Permutation of list of lists of booleans in Racket - list

I'd like to create a function that: given a natural number, returns a list of lists with all the possible values for n propositional variables.
e.g, given n = 3, it should return:
(list
(list #false #false #false)
(list #false #false #true)
(list #false #true #false)
(list #false #true #true)
(list #true #false #false)
(list #true #false #true)
(list #true #true #false)
(list #true #true #true))
I know the amount of possible combinations is 2^n, but i am clueless about how to solve it on racket.

You can use the cartesian-product function. (cartesian-product (list #false #true) (list #false #true) (list #false #true)) returns the same thing as your n = 3 example. The number of copies of (list #false #true) in the arguments should come from n.
(cartesian-product (list #false #true) ...n)
To do this, you can use cartesian-product with apply to give an arbitrary number of arguments in a list, and make-list to make a list of N elements:
(define (permutation-of-lists n)
(apply cartesian-product (make-list n (list #false #true))))
Using it:
> (permutation-of-lists 0)
(list '())
> (permutation-of-lists 1)
(list (list #false) (list #true))
> (permutation-of-lists 2)
(list (list #false #false)
(list #false #true)
(list #true #false)
(list #true #true))
> (permutation-of-lists 3)
(list (list #false #false #false)
(list #false #false #true)
(list #false #true #false)
(list #false #true #true)
(list #true #false #false)
(list #true #false #true)
(list #true #true #false)
(list #true #true #true))

You can potentially do something like:
(define (permutation-of-lists n)
(if (= 1 n)
'((#t) (#f))
(append
(map (λ (p) (cons #t p)) (permutation-of-lists (sub1 n)))
(map (λ (p) (cons #f p)) (permutation-of-lists (sub1 n))))))
This works for any n >= 1. You can also optionally add a case to handle n = 0.
This essentially builds up these lists by appending both possible copies to the lists generated for n - 1 - one appends #true and the other appends #false to the front (and we keep both copies).

Related

Racket: Check if there is a list in a list

this is my first question here! :)
I need a function that checks if there is a list inside a list. It should give false when there is a list inside a list. I tried simple things like:
(define (list-inside-list? ls)
(if (or (list? (first ls)) (list? (rest ls))) false true))
I probably need lambda but I just don't know how?
Would appreciate a lot for help!
There is no list inside the empty list.
Otherwise, there is a list inside a list if
its first element is a list,
or if there is a list inside the rest of the list.
The trick is then to turn this into code, thinking particularly hard about how to express the last case: to do it you might want to write a function which determines if there is a list inside a list ... well, what's the function you're writing do?
a warm welcome to StackOverflow.
I haven't heavily tested, but maybe this approache helps you:
(check-expect (contains-no-sublist? (list )) #true)
(check-expect (contains-no-sublist? (list "red" "green" "blue")) #true)
(check-expect (contains-no-sublist? (list (list "light red" "dark red") "green" "blue")) #false)
;; contains-no-sublist? checks if any element in the list is a list itself and returns #false, if it finds a list in the list (nested list).
(define contains-no-sublist? ;; define a function with the name "contains-no-sublist?"
(lambda [L] ;; define the function as a lambda expression over a given input list L
(cond ;; the function returns either #t or #f
[(empty? L) #true] ;; an empty list doesn't contain a sublist, so #t = #true can be returned
[(cons? L) ;; else still a list is given
(cond
[(list? (first L)) #false] ;; either the first element of the list is a list itself, then return false.
[else (contains-no-sublist? (rest L))] ;; or the first element is not a list itself, then check for the rest of the list if it contains any sublist
)
]
)
)
)
use cond
#lang racket
(define (no-list-inside?-by-cond ls)
(cond
[(empty? ls) #t]
[(list? (first ls))
#f]
[else
(no-list-inside?-by-cond (rest ls))]))
;;; TEST
(no-list-inside?-by-cond '(1 2 3)) ; should be #t
(no-list-inside?-by-cond '(1 2 3 '(3) 4)) ; should be #f
(no-list-inside?-by-cond '(1 2 3 '() 5)) ; should be #f
use andmap
#lang racket
(define (no-list-inside?-by-andmap ls)
(andmap (lambda (x) (not (list? x))) ls))
;;; TEST
(no-list-inside?-by-andmap '(1 2 3 2)) ; should be #t
(no-list-inside?-by-andmap '(1 2 3 '(3) 4)) ; should be #f
(no-list-inside?-by-andmap '(1 2 3 '() 5)) ; should be #f
use filter
#lang racket
(define (no-list-inside?-by-filter lst)
(empty? (filter list? lst)))
;;; TEST
(no-list-inside?-by-filter '(1 2 3)) ; should be #t
(no-list-inside?-by-filter '(1 2 3 '(3) 4)) ; should be #f
(no-list-inside?-by-filter '(1 2 3 '() 5)) ; should be #f

Edit A Nested List In Scheme

I will keep this short and simple.
Want: To edit elements in a nested list. This nested list will have an unlimited number of elements but the list inside the list will always have 2 elements, like (list (list 1 2) (list 3 4)). I wanted to add a specific value 'x' to the first element of each nested list using recursion. e.g., (change (list (list 1 2) (list 10 20) 3), where 3 is the 'x' value => (list (list 4 2) (list 13 23))
Code:
(define (change lst x)
(cond
[(empty? lst) empty]
[else (cons (+ (first (first lst)) x)
(cons (second (first lst)) (change (rest lst) x)))]))
Output: an input such as (change (list (list 12 2) (list 1 2)) 100) will produce (list 112 2 101 2).
Problem: The x value is added, but it should produce (list (list 112 2) (list 101 2)). Itt is not nested.
try this:
(define +n
(lambda (n)
(lambda (l)
(fold-right
(lambda (x a)
(cons (+ (car x) n)
(cons (cadr x)
a)))
'()
l ))))
(define 100+ (+n 100))
(100+ (list (list 12 2) (list 1 2)))

Creating a list of of structurs from another list of structures in Racket

I have a task to solve and unfortunately came to a point where I am not sure If I am on the right path at all.
The setting is a phone, where you have a list of calls each with the structure (make-call Date Phone Duration) and I have to summarize all calls from a certain number (Phone) and create a list of contacts with each number, that summarizes the duration (make-contact Phone Duration).
So the question is how do I e.g. get from
(list (make-call Date1 "123" 1.5) (make-call Date2 "123" 4) (make-call Date3 "456" 2))
to
(list (make-contact "123" 5.5) (make-contact "456" 2))
My plan is to first filter a list of calls for a certain name:
;(define CALL1 (make-call "18.01." "101010" 4.5))
;(define CALL2 (make-call "01.01." "222222" 1.0))
;(define CALL3 (make-call "13.01." "123456" 20.2))
;(define CALL4 (make-call "05.01." "999999" 10))
; (list-of-Call) Name -> (List-of-Call)
; filters all calls with a certain name from a list of calls
(check-expect (filter-by-number empty "101010") empty)
(check-expect (filter-by-number (list CALL1 CALL1) "101010") (list CALL1 CALL1))
(check-expect (filter-by-number (list CALL1 CALL2) "Jonas") empty)
(define (filter-by-number lst nam)
(if (empty? lst)
empty
(if (string=? (call-callee (first lst)) nam)
(append (filter-by-number (first lst) nam) (filter-by-number (rest lst) nam))
empty)))
Unfortunately this function doesn't work properly yet.
In a second step, my plan is to put this togehter somehow to create the required list of contacts, and that where I am stuck:
;(List-of-Call) -> (List-of-Contact)
;computes the total duration of all calls of a certain number
(check-expect (compute-contacts empty) empty)
(check-expect (compute-contacts (list CALL1)) (list (make-contact "101010" 4.5)))
(check-expect (compute-contacts (list CALL1 CALL2 CALL3)) (list (make-contact "101010" 4.5) (make-contact "222222" 1.0) (make-contact "123456" 20.2)))
(check-expect (compute-contacts (list CALL4 CALL4)) (list (make-contact "999999" 20)))
(check-expect (compute-contacts (list CALL4 CALL4 CALL1) (list (make-contact "999999" 20))) (make-contact "101010" 4.5))
(define (summarize-contacts lst)
(if (empty? lst)
empty
(append (make-contact ...) (make-contact ...))))
How would you do proceed from here? Or would you do it a totally different way?
Any hints welcome :)
Cheers!

SCHEME - Count number of procedures that are not primitive

I have to make a function where I have to count the number of procedures that are not primitive inside a list.
Here are some examples:
(nprocs '(+ (cuadrado 1) (* 2 (inc1 3)))) => 0
(nprocs (+ (cuadrado 1) (* 2 (inc1 3)))) => ERROR
(nprocs (list + (list cuadrado 1) (list * 2 (list inc1 3)))) => 2
I tried this:
(define (cuadrado x) (* x x))
(define inc1 (lambda (x) (+ x 1)))
(define nprocs
(lambda (fun)
(if (list? fun)
(if(procedure? (car fun))
(+ 1 (nprocs (cdr fun)))
(nprocs (cdr fun)))
0)
)
)
This code isn't working, hope someone can help.
Thanks in advance!
A list is composed of cons cells and atoms. Here's the canonical way of processing a list, counting non-primitive procedures on your way:
(define (nprocs sxp)
(cond
; cons cell -> process car and cdr
((pair? sxp) (+ (nprocs (car sxp)) (nprocs (cdr sxp))))
; atom -> is it a procedure that is not a primitive?
((and (procedure? sxp) (not (primitive? sxp))) 1)
; atom, not or procedure or a primitive
(else 0)))
Testing:
> (nprocs '(+ (cuadrado 1) (* 2 (inc1 3))))
0
> (nprocs (list + (list cuadrado 1) (list * 2 (list inc1 3))))
2
The nprocs procedure must traverse a list of lists, testing whether each atom is a procedure that is not primitive, and adding the results of all sublists. This is simpler if we use a cond for the conditions, and use the standard template for traversing a list of lists:
(define (nprocs fun)
(cond ((null? fun) 0)
((not (pair? fun))
(if (and (procedure? fun) (not (primitive? fun))) 1 0))
(else (+ (nprocs (car fun))
(nprocs (cdr fun))))))
It works as long as we pass actual procedures in the list (not just symbols):
(nprocs (list + (list cuadrado 1) (list * 2 (list inc1 3))))
=> 2
If the same non-primitive procedure appears more then once, it'll be counted several times. If that's a problem, it'll be easier to remove the duplicates if we use a more idiomatic solution leveraging built-in higher-order procedures. For example, in Racket:
(define (nprocs fun)
(count (lambda (e) (and (procedure? e) (not (primitive? e))))
(remove-duplicates (flatten fun))))

Scheme language: merge two numbers

How can I merge two integers from a list into one? (in Scheme)
Example:
'(11 223) -> 11223
Assuming that the list has exactly two elements, and that both are numbers:
(define (merge-numbers lst)
(let ((1st (number->string (first lst)))
(2nd (number->string (second lst))))
(string->number (string-append 1st 2nd))))
It works as expected:
(merge-numbers '(11 223))
> 11223
Alternatively, without using a let:
(define (merge-numbers lst)
(string->number
(string-append
(number->string (first lst))
(number->string (second lst)))))
This is my original answer from Jan 25 '12 at 3:05. It only handles the given test. It was a mindless answer, sorry.
(define (merge ls) 11223)
(merge '(11 223))
This is my new answer that handles all cases when passed a list of numbers. Thank you blubberdiblub for the pointer!
; list of zero or more strings -> string
(define (merge-numbers ns)
(if (null? ns) ""
(let ((first-n (number->string (car ns)))
(rest-ns (cdr ns)))
(string-append first-n (merge-numbers rest-ns)))))
(merge-numbers '(11 223))
(merge-numbers '())
(merge-numbers '(1))
(merge-numbers '(1 2))
(merge-numbers '(1 2 3))
(merge-numbers '(1 2 3 4))
(merge-numbers '(1 2 3 4 5))
"11223"
""
"1"
"12"
"123"
"1234"
"12345"
Since the original question probably meant that the result should be a number, and this results in a string, then string->number needs to be used to get the final answer. Thank you again blubberdiblub for an explanation of what the poster probably meant, I had missed it.
There are many ways to write this procedure, depending on what you plan for it. For example, if the list might contain more than two numbers (in the future?) then you can write it as follows:
(define merge-numbers
(lambda (s)
(string->number
(apply string-append
(map number->string s)))))
So now you can type:
> (merge-numbers '(4 9 66 33 555 1))
4966335551
If there's a real reason why you want the number two, then I think the use of the procedure format would be more readable:
(define merge-two-numbers
(lambda (s)
(string->number
(format "~a~a"
(car s)
(cadr s)))))
etc.