Racket: Check if there is a list in a list - 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

Related

Scheme Inverse List Function

I defined a function called zip which took two lists as parameters and returned a list of pairs.
(define (zip list1 list2)
(if (null? list1)
'()
(cons (list (cons (car list1) (car list2)))
(zip (cdr list1) (cdr list2)))))
(zip (list 1 3 5) (list 2 4 6))
> (((1 . 2)) ((3 . 4)) ((5 . 6)))
Now I'm basically having trouble writing the inverse function of this. This is what I have so far. This function needs to output a list of two lists. I only attempted at making the first of the two lists to make it easier for myself but the output is not what I want.
(define (unzip u-list)
(if (null? u-list)
'()
(list (car (car (car u-list))) (unzip(cdr u-list)))))
(unzip (zip (list 1 3 5) (list 2 4 6)))
> (1 (3 (5 ())))
Any help would be appreciated...
I believe there's a problem with your implementation of zip, did you notice that you're returning a list of single-element lists of pairs? returning a list of pairs makes more sense:
(define (zip lst1 lst2)
(if (null? lst1)
'()
(cons (cons (car lst1) (car lst2))
(zip (cdr lst1) (cdr lst2)))))
Or even better, let's use the map higher-order function for a shorter, more idiomatic solution:
(define (zip lst1 lst2)
(map cons lst1 lst2))
Regarding unzip: it's easier if we split the problem in parts - let's get the first element of each pair, then the second element of each pair, and finally build a list with the answer. Try this:
(define (unzip lst)
(define (firsts lst)
(if (null? lst)
'()
(cons (caar lst)
(firsts (cdr lst)))))
(define (seconds lst)
(if (null? lst)
'()
(cons (cdar lst)
(seconds (cdr lst)))))
(list (firsts lst) (seconds lst)))
But once again, we're reinventing the wheel. Let's just use built-in functions to write a simpler answer:
(define (unzip lst)
(list (map car lst) (map cdr lst)))
Anyway, now unzip is the inverse of zip:
(zip '(1 3 5) '(2 4 6))
=> '((1 . 2) (3 . 4) (5 . 6))
(unzip '((1 . 2) (3 . 4) (5 . 6)))
=> '((1 3 5) (2 4 6))
As you make it with pairs it's somewhat more difficult but not much:
(define (zip-pair a b)
(map cons a b))
(define (unzip-pair zipped-pair)
(list (map car zipped-pair)
(map cdr zipped-pair)))
zip is usually implemented with apply and map and takes list and produce list of lists, like this:
(define (zip . lists)
(apply map list lists))
(zip '(1 2 3) '(a b c)) ; ==> ((1 a) (2 b) (3 c))
Though this will make lists and not pairs. However a unzip is almost the same except that you will take a list of lists instead of variable number of arguments:
(define (unzip1 zipped-list)
(apply map list zipped-list))
; or reuse zip
(define (unzip1 zipped-list)
(apply zip zipped-list))
(unzip1 '((1 a) (2 b) (3 c))) ; ==> ((1 2 3) (a b c))

Duplicate every found element in a list in Scheme

I want to duplicate every found element in a list. I have the idea but i can't make it right. Sample input is >(pass '(1 2 3 4 4)) will have the output (1 1 2 2 3 3 4 4 4 4). Anyone out there help me. Here is my code ..
(define duplicate
(lambda (mylist n)
(cond ((null? mylist) "Not found")
((< n 2) (cons (car mylist)
(duplicate mylist (+ n 1))))
(else
(duplicate (cdr mylist) 0)))))
(define pass
(lambda (mylist)
(duplicate list 0)))
I will appreaciate all valuable comments.
Just a couple of fixes (see the comments) and we're good to go:
(define duplicate
(lambda (mylist n)
(cond ((null? mylist) '()) ; base case must return the empty list
((< n 2) (cons (car mylist)
(duplicate mylist (+ n 1))))
(else
(duplicate (cdr mylist) 0)))))
(define pass
(lambda (mylist)
(duplicate mylist 0))) ; pass myList, not list
Notice that the procedure can be simplified a bit:
(define (pass lst)
(if (null? lst)
'()
(cons (car lst)
(cons (car lst)
(pass (cdr lst))))))
Or even better, using higher-order procedures for a more idiomatic solution:
(define (pass lst)
(foldr (lambda (ele acc) (list* ele ele acc))
'()
lst))
Yet another alternative:
(define (pass lst)
(append-map (lambda (ele) (list ele ele))
lst))
Anyway, it works as expected:
(pass '(1 2 3 4 4))
=> (1 1 2 2 3 3 4 4 4 4)
I would do it so:
(define (dup l)
(define (iter l co)
(if (null? l)
(co '())
(iter (cdr l)
(lambda (x)
(co (cons (car l) (cons (car l) x)))))))
(iter l (lambda (x) x)))
(dup '(1 2 3))
It may be simpler to treat duplicate as zipping a list with itself. Then flattening the resulting list.
In Scheme or Racket:
(require srfi/1)
(define (duplicate-list-members lox)
(flatten (zip lox lox)))
Though it runs in O(n) time, profiling may indicate that passing through the list twice is a bottleneck and justify rewriting the function. Or it might not.
Try using map and list
(define (duplicate my-list)
(flatten
(map
(lambda (x)
(list x x))
my-list)))`
Gives requested format:
> (duplicate (list 1 2 3 4 4))
'(1 1 2 2 3 3 4 4 4 4)

Comparing individual elements of two lists of the same length in DrRacket

I am trying to write a function that takes two lists (must be of equal length) and then goes through each list comparing individual items.
For example: (1 2 3) and (2 4 5) would return true because each element of list 2 is greater than the corresponding element in list 1. (1 2 3) and (0 4 1) would return false as would (1 2 3) and (1 2 3 4) since they are of different size. Using Dr Racket
(define (each-bigger? a-lon another-lon)
(cond
(if
[(= (length a-lon) (length another-lon))true]
(then
[(> (first a-lon) (first another-lon))true]
(then
[(> (rest a-lon) (rest another-lon))true]
[else false])))))
this didn't work.
Unfortunately you've got both your syntax and your logic wrong. I believe your intention was to write something like this:
(define (each-bigger? lst1 lst2)
(cond
((and (null? lst1) (null? lst2)) #t) ; both lists are empty => true
((or (null? lst1) (null? lst2)) #f) ; only one is empty => not the same length => false
((>= (car lst1) (car lst2)) #f) ; first element of lst1 >= first element of lst2 => false
(else (each-bigger? (cdr lst1) (cdr lst2))))) ; recur on the rest of the list
which can be shortened to
(define (each-bigger? lst1 lst2)
(or (and (null? lst1) (null? lst2)) ; EITHER both lists are empty
(and (not (or (null? lst1) (null? lst2))) ; OR 1) none of them is empty
(< (car lst1) (car lst2)) ; 2) AND first element of lst1 < first element of lst2
(each-bigger? (cdr lst1) (cdr lst2))))) ; 3) AND each-bigger? is true for the rest of both lists
Hope this helps!
Clearly you want to implement a solution from scratch, and #uselpa's advice is spot-on. But in a non-academic context you should use existing procedures for solving this kind of problem, in particular andmap is your best friend here:
(define (each-bigger? lst1 lst2)
(and (= (length lst1) (length lst2))
(andmap < lst1 lst2)))
The trick is that andmap applies a predicate on elements of both lists, passing as parameters the first element of lst1 and the first element of lst2, then the second element of lst1 and the second element of lst2, and so on (BTW, andmap accepts one or more lists as parameters, as long as the predicate receives the same number of parameters).
If all the applications of the predicate return #t then #t is returned, if a single predicate returns #f then evaluation stops and #f is returned. In the above example, the predicate is just <, applied pair-wise between the two lists. It works as expected:
(each-bigger? '(1 2 3) '(2 4 5))
=> #t
(each-bigger? '(1 2 3) '(0 4 1))
=> #f
(each-bigger? '(1 2 3) '(2 4 5 6))
=> #f

Search in a list with argument

I`m trying to implement a function that given an argument and a list, find that argument in the first element of the pair in a list
Like this:
#lang scheme
(define pairs
(list (cons 1 2) (cons 2 3) (cons 2 4) (cons 3 1) (cons 2 5) (cons 4 4)))
;This try only gets the first element, I need to runs o every pair on pairs
((lambda (lst arg)
(if (equal? (car (first lst)) arg) "DIFF" "EQ"))
pairs 2)
;This try below brings nok for every element, because Its not spliting the pairs
(define (arg) (lambda (x)2))
(map
(lambda (e)
(if (equal? arg (car e)) "ok" "nok"))
pairs)
The idea is simple, I have pair elements, and a given number. I need to see if the first element of the pairs (they are in a list) starts with that number
Thanks in advance
In Racket, this is easy to implement in terms of map. Simply do this:
(define (find-pair lst arg)
(map (lambda (e)
(if (equal? (car e) arg) "ok" "nok"))
lst))
Alternatively, you could do the same "by hand", basically reinventing map. Notice that in Scheme we use explicit recursion to implement looping:
(define (find-pair lst arg)
(cond ((null? lst) '())
((equal? (car (first lst)) arg)
(cons "ok" (find-pair (rest lst) arg)))
(else
(cons "nok" (find-pair (rest lst) arg)))))
Either way, it works as expected:
(find-pair pairs 2)
=> '("nok" "ok" "ok" "nok" "ok" "nok")
(find-pair pairs 7)
=> '("nok" "nok" "nok" "nok" "nok" "nok")
In Scheme, you should usually approach algorithms with a recursive mindset - especially when lists are involved. In your case, if you find the element in the car of the list then you are done; if not, then you've got the same problem on the cdr (rest) of the list. When the list is empty, you've not found the result.
Here is a solution:
(define (find pred list)
(and (not (null? list)) ; no list, #f result
(or (pred (car list)) ; pred on car, #t result
(find pred (cdr list))))) ; otherwise, recurse on cdr
With this your predicate function 'match if car of argument is n' is:
(define (predicate-if-car-is-n n)
(lambda (arg)
(eq? n (car arg))))
The above stretches your understanding; make sure you understand it - it returns a new function that uses n.
With everything together, some examples:
> (find (predicate-if-car-is-n 2) '((1 . 2) (2 . 3) (4 . 5)))
#t
> (find (predicate-if-car-is-n 5) '((1 . 2) (2 . 3) (4 . 5)))
#f

Recursively creating list in scheme

I come up again with my strange Scheme questions.
I have a definition that remove subelement(based on search occurrence) from a list and generate new list without it (based on this answer here).
(func '1 mylist) ; will return mylist without all sublists containing 1
All was working fine until I realized that I need to repeat my definition for each element in another list.
I call it recursively, but with every call I use the original list not the previous filtered.
Or with another words I want to achieve this:
(define filterList '(1 2 3))
(func '3 (func '2 (func '1 mylist) ); list without all sublists containig 1 2 3
I'm tottaly stuck. Thanks everyone for the help.
This is a basic loop over the lists of elements (elts) to remove from the initial list (lst):
(define (func2 elts lst)
(if (null? elts)
lst
(func2 (cdr elts) (func (car elts) lst))))
then
(func2 '(1 3) '(1 2 3))
=> '(2)
or, in Racket:
(define (func2 elts lst)
(for/fold ((res lst)) ((e (in-list elts)))
(func e res)))