search through nested list in scheme to find a number - scheme

How would I search through the nested list to find a certain number?
For example, the list is:
((1 2) (2 3) (3 4) (3 5) (4 5))
and I'm looking for 1.
Expected output:
(1 2)
since 1 is in the sub list (1 2).

First of all create function to flatten list. Something like this:
> (flatten '((8) 4 ((7 4) 5) ((())) (((6))) 7 2 ()))
(8 4 7 4 5 6 7 2)
And then search your number in the ordinary list.
This quesion looks like the homework so try to develop this function on your own and if you can not do it - post your code here and I'll try to help you.
Updated
Ok. As I understand we need to create function which get the list of pairs and return another list of pairs, where first element of pair equal some number.
For example:
(define data '((1 2)(2 3)(3 4)(3 5)(4 5)))
(solution data 3)
-> '((3 4) (3 5))
(define data '((1 2)(2 3)(3 4)(3 5)(4 5)))
(solution data 1)
-> '((1 2))
In the other words we need to filter our list of pairs by some condition. In the Scheme there is a function to filter list. It takes a list to filter and function to decide - to include or not the element of list in the result list.
So we need to create such function:
(define (check-pair num p)
(cond
[(= (first p) num) #t]
[else #f]))
This function get a pair (element of list), number and decide - incude or not this pair to result list. This function have 2 parameters, but the filter function require the function with only one parameter, so we rewrite our function such way:
(define (check-pair num)
(lambda (p)
(cond
[(= (first p) num) #t]
[else #f])))
I have created function wich produce another function. It is currying.
So, we have all to create our solution:
(define (check-pair num)
(lambda (p)
(cond
[(= (first p) num) #t]
[else #f])))
(define (solution list num)
(local
((define check-pair-by-num (check-pair num)))
(filter check-pair-by-num list)))
(define data '((1 2)(2 3)(3 4)(3 5)(4 5)))
(solution data 1)

Flattening isn't the approach I'd prefer here, but that doesn't mean it's incorrect. Here's an alternative:
(define (solve lst num)
(cond
[(null? lst) null]
[(cons? (first lst)) (solve (first lst) num)]
[(member num lst) (cons lst (solve (rest lst) num))]
[#t (solve (rest lst) num)]))
This just recursively deals with nested listing as needed, so I prefer it a little bit stylistically. In addition, the call to member can be replaced with check-pair from above, but member will let you grab values from cdrs as well as cars, if you want that.

Use find to select a member of a list meeting a condition:
(find contains-1? '((1 2)(2 3)(3 4)(5 6)))
How to implement contains-1? Hint: consider the member function:
(member 1 '(1 2)) => #t
(member 1 '(3 4)) => #f

Related

Pair combinations in scheme

I'm trying to find the various combinations that can be made with a list of N pairs in scheme. Here is where I'm at thus far:
(define (pair-combinations list-of-pairs)
(if (null? list-of-pairs)
nil
(let ((first (caar list-of-pairs))
(second (cadar list-of-pairs))
(rest (pair-combinations (cdr list-of-pairs))))
(append
(list (cons first rest))
(list (cons second rest))
))))
Now, I'm not sure if the logic is correct, but what I notice immediately is the telescoping of parentheticals. For example:
(define p1 '( (1 2) (3 4) (5 6) ))
(pair-combinations p1)
((1 (3 (5) (6)) (4 (5) (6))) (2 (3 (5) (6)) (4 (5) (6))))
Obviously this is from the repetition of the list (... within the append calls, so the result looks something like (list 1 (list 2 (list 3 .... Is there a way to do something like the above in a single function? If so, where am I going wrong, and how would it be properly done?
The answer that I'm looking to get would be:
((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
That is, the possible ways to choose one element from N pairs.
Here is one way to think about this problem. If the input is the empty list, then the result is (). If the input is a list containing a single list, then the result is just the result of mapping list over that list, i.e., (combinations '((1 2 3))) --> ((1) (2) (3)).
Otherwise the result can be formed by taking the first list in the input, and prepending each item from that list to all of the combinations found for the rest of the lists in the input. That is, (combinations '((1 2) (3 4))) can be found by prepending each element of (1 2) to each of the combinations in (combinations '((3 4))), which are ((3) (4)).
It seems natural to express this in two procedures. First, a combinations procedure:
(define (combinations xss)
(cond ((null? xss) '())
((null? (cdr xss))
(map list (car xss)))
(else
(prepend-each (car xss)
(combinations (cdr xss))))))
Now a prepend-each procedure is needed:
(define (prepend-each xs yss)
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
yss))
xs)))
Here the procedure prepend-each takes a list xs and a list of lists yss and returns the result of prepending each x in xs to the lists in yss. The inner map takes each list ys in yss and conses an x from xs onto it. Since the inner mapping produces a list of lists, and the outer mapping then produces a list of lists of lists, append is used to join the results before returning.
combinations.rkt> (combinations '((1 2) (3 4) (5 6)))
'((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
Now that a working approach has been found, this could be converted into a single procedure:
(define (combinations-2 xss)
(cond ((null? xss) '())
((null? (cdr xss))
(map list (car xss)))
(else
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
(combinations-2 (cdr xss))))
(car xss))))))
But, I would not do that since the first version in two procedures seems more clear.
It might be helpful to look just at the results of prepend-each with and without using append:
combinations.rkt> (prepend-each '(1 2) '((3 4) (5 6)))
'((1 3 4) (1 5 6) (2 3 4) (2 5 6))
Without using append:
(define (prepend-each-no-append xs yss)
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
yss))
xs))
combinations.rkt> (prepend-each-no-append '(1 2) '((3 4) (5 6)))
'(((1 3 4) (1 5 6)) ((2 3 4) (2 5 6)))
It can be seen that 1 is prepended to each list in ((3 4) (5 6)) to create a list of lists, and then 2 is prepended to each list in ((3 4) (5 6)) to create a list of lists. These results are contained in another list, since the 1 and 2 come from the outer mapping over (1 2). This is why append is used to join the results.
Some Final Refinements
Note that prepend-each returns an empty list when yss is empty, but that a list containing the elements of xs distributed among as many lists is returned when yss contains a single empty list:
combinations.rkt> (prepend-each '(1 2 3) '(()))
'((1) (2) (3))
This is the same result that we want when the input to combinations contains a single list. We can modify combinations to have a single base case: when the input is '(), then the result is (()). This will allow prepend-each to do the work previously done by (map list (car xss)), making combinations a bit more concise; the prepend-each procedure is unchanged, but I include it below for completeness anyway:
(define (combinations xss)
(if (null? xss) '(())
(prepend-each (car xss)
(combinations (cdr xss)))))
(define (prepend-each xs yss)
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
yss))
xs)))
Having made combinations more concise, I might be tempted to go ahead and write this as one procedure, after all:
(define (combinations xss)
(if (null? xss) '(())
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
(combinations (cdr xss))))
(car xss)))))

If a list is found in another list?

I started to learn Racket and I don't know how to check if a list is found in another list. Something like (member x (list 1 2 3 x 4 5)), but I want that "x" to be a a sequence of numbers.
I know how to implement recursive, but I would like to know if it exists a more direct operator.
For example I want to know if (list 3 4 5) is found in (list 1 2 3 4 5 6 )
I would take a look at this Racket Object interface and the (is-a? v type) -> boolean seems to be what you are looking for?, simply use it while looping to catch any results that are of a given type and do whatever with them
you may also want to look into (subclass? c cls) -> boolean from the same link, if you want to catch all List types in one go
should there be a possiblity of having a list inside a list, that was already inside a list(1,2,(3,4,(5,6))) i'm afraid that recursion is probally the best solution though, since given there is a possibility of an infinit amount of loops, it is just better to run the recursion on a list everytime you locate a new list in the original list, that way any given number of subList will still be processed
You want to search for succeeding elements in a list:
(define (subseq needle haystack)
(let loop ((index 0)
(cur-needle needle)
(haystack haystack))
(cond ((null? cur-needle) index)
((null? haystack) #f)
((and (equal? (car cur-needle) (car haystack))
(loop index (cdr cur-needle) (cdr haystack)))) ; NB no consequence
(else (loop (add1 index) needle (cdr haystack))))))
This evaluates to the index where the elements of needle is first found in the haystack or #f if it isn't.
You can use regexp-match to check if pattern is a substring of another string by converting both lists of numbers to strings, and comparing them, as such:
(define (member? x lst)
(define (f lst)
(foldr string-append "" (map number->string lst)))
(if (regexp-match (f x) (f lst)) #t #f))
f converts lst (a list of numbers) to a string. regexp-match checks if (f x) is a pattern that appears in (f lst).
For example,
> (member? (list 3 4 5) (list 1 2 3 4 5 6 7))
#t
One can also use some string functions to join the lists and compare them (recursion is needed):
(define (list-in-list l L)
(define (fn ll)
(string-join (map number->string ll))) ; Function to create a string out of list of numbers;
(define ss (fn l)) ; Convert smaller list to string;
(let loop ((L L)) ; Set up recursion and initial value;
(cond
[(empty? L) #f] ; If end of list reached, pattern is not present;
[(string-prefix? (fn L) ss) #t] ; Compare if initial part of main list is same as test list;
[else (loop (rest L))]))) ; If not, loop with first item of list removed;
Testing:
(list-in-list (list 3 4 5) (list 1 2 3 4 5 6 ))
Output:
#t
straight from the Racket documentation:
(member v lst [is-equal?]) → (or/c list? #f)
v : any/c
lst : list?
is-equal? : (any/c any/c -> any/c) = equal?
Locates the first element of lst that is equal? to v. If such an element exists, the tail of lst starting with that element is returned. Otherwise, the result is #f.
Or in your case:
(member '(3 4 5) (list 1 2 3 4 5 6 7))
where x is '(3 4 5) or (list 3 4 5) or (cons 3 4 5)
it will return '(3 4 5 6 7) if x ( searched list '(3 4 5) ) was found in the list or false (#f) if it was not found
or you can use assoc to check if your x is met in one of many lists, or :
(assoc x (list (list 1 2) (list 3 4) (list x 6)))
will return :
'(x 6)
There are also lambda constructions but I will not go in depth since I am not very familiar with Racket yet. Hope this helps :)
EDIT: if member gives you different results than what you expect try using memq instead

finding subsets of length N of a list in scheme

I wrote a function which finds all the subsets of a list already and it works. I'm trying to write a second function where I get all the subsets of N length, but it's not working very well.
This is my code:
(define (subset_length_n n lst)
(cond
[(empty? lst) empty]
[else (foldr (lambda (x y) (if (equal? (length y) n) (cons y x) x)) empty (powerset lst))]
))
where (powerset lst) gives a list of all the subsets.
Am I misunderstanding the purpose of foldr?
I was thinking that the program would go through each element of the list of subsets, compare the length to n, cons it onto the empty list if there the same, ignore it if it's not.
But (subset_length_n 2 (list 1 2 3)) gives me (list (list 1 2) 1 2 3) when I want (list (list 1 2) (list 1 3) (list 2 3))
Thanks in advance
When using foldr you don't have to test if the input list is empty, foldr takes care of that for you. And this seems like a job better suited for filter:
(define (subset_length_n n lst)
(filter (lambda (e) (= (length e) n))
(powerset lst)))
If you must, you can use foldr for this, but it's a rather contrived solution. You were very close to getting it right! in your code, just change the lambda's parameters, instead of (x y) write (y x). See how a nice indentation and appropriate parameter names go a long way toward writing correct solutions:
(define (subset_length_n n lst)
(foldr (lambda (e acc)
(if (= (length e) n)
(cons e acc)
acc))
empty
(powerset lst)))
Anyway, it works as expected:
(subset_length_n 4 '(1 2 3 4 5))
=> '((1 2 3 4) (1 2 3 5) (1 2 4 5) (1 3 4 5) (2 3 4 5))

How to write SUM function in Scheme?

How to write a function in scheme that sums the numbers in embedded lists?
i.e. ((1) (2 3) (4) (5 6))
I wrote this to sum the regular list:
(define (sum list)
(if (null? list)
0
(+ (car list) (sum (cdr list)))))
but I'm not sure how to do the embedded one.
You have 3 cases:
(define (my-sum lst)
(cond
; 1. the list is empty, so finish of by adding 0
([empty? lst] 0)
; 2. the first element is a list, so recurse down on the sublist, then do the rest
([list? (car lst)] (+ (my-sum (car lst)) (my-sum (cdr lst))))
; 3. add the first element to the sum, then do the rest
(else (+ (car lst) (my-sum (cdr lst))))))
so you were just missing the middle case.
This will work regardless of the nesting depth:
(my-sum '((1) (2 3) (4) (5 6)))
=> 21
(my-sum '((1) (2 3) (4) (5 6 (7 8 (9)))))
=> 45
Please note that you should not use the names "sum" and "list" in order not to shadow the build-in procedures.
Here is the simplest answer.
(define (sum list-of-lists)
(apply + (apply append list-of-lists)))
and the 'proof':
> (sum '((1) (2 3) (4) (5 6)))
21
In a more functional way
; this sums the elements of a not-embedded list
(define (sum-list* l)
(foldl + 0 l))
; this sums the elements of an embedded list
(define (sum-embedded-list* el)
(foldl + 0 (map sum-list* el)))
It covers the case of a list so formed: ((a1...an) (b1...bn)...), where ai and bj are atoms.
Foldl and map are two important functions in scheme (and other languages). If you don't know how to use them you should learn. Take a look here

How to count individual elements in a pair - scheme ?

(cons 2 (cons ( cons 2 3 ) (cons 4 5 )))
This gives me a list that looks like this : (2 (2 . 3) 4 . 5) when I try to count the number of elements in this list the output is 3 as exepected.
How do I calculate the number of individual elements of a pair ? The output in this case should be 5 for example.
Here's a possible solution, the question is essentially asking for the number of atoms in a list structure (not necessarily null-terminated proper lists):
(define (count-all seq)
(cond ((null? seq) 0)
((not (pair? seq)) 1)
(else (+ (count-all (car seq))
(count-all (cdr seq))))))
It works on sequences of elements like this:
If the sequence is empty, it has zero elements
If the sequence is not a cons cell (a pair of elements), it's because it's a single element - an atom
Otherwise add the elements of both the car and the cdr of the sequence
It works as expected for arbitrarily nested list structures:
(count-all '(2 (2 . 3) 4 . 5))
=> 5
(count-all '(1 (2 . (3 (4 . 5) 6)) 7 . 8))
=> 8
We can solve this problem recursively for arbitrarily deeply nested lists.
(define (atom? x) (not (pair? x)))
(define (count-atoms lst)
(cond ((null? lst) 0) ; nothing to count, return 0
((atom? lst) 1) ; lst contains only one thing, return 1
(else ; otherwise, lst contains multiple elements
(+ (count-atoms (car lst)) ; add the number of atoms in the first position
(count-atoms (cdr lst)))))) ; to the number of atoms in the rest of the list
EDIT: This is a duplicate to Oscar's answer. I did not see that he had answered when I hit submit, but will leave this here since I feel the comments are useful.

Resources