Extracting only numbers within a list - scheme

Is there a way to extract only numbers within a list?
I'm using the beginner language package so I cannot use filter which is a bummer.
(list a 1 2 b d 3 5) => 1 2 3 5 etc
I want to use this as a part of my helper function but I cannot figure it out!
thanks!

Ideally this problem should be solved using the filter higher-order procedure, like this:
(filter number? '(a 1 2 b d 3 5))
=> '(1 2 3 5)
... But because this looks like a homework, I'll give you some hints on how to solve the problem by hand, just fill-in the blanks:
(define (only-numbers lst)
(cond (<???> ; is the list empty?
<???>) ; return the em´pty list
(<???> ; is the 1st element in the list a number?
(cons <???> ; then cons the first element
(only-numbers <???>))) ; and advance the recursion
(else ; otherwise
(only-numbers <???>)))) ; simply advance the recursion
Notice that this solution follows a well-known template, a recipe of sorts for recursively processing a list and in turn creating a new list as output. Don't forget to test your procedure:
(only-numbers '(a 1 2 b d 3 5))
=> '(1 2 3 5)
(only-numbers '(1 2 3 4 5))
=> '(1 2 3 5)
(only-numbers '(a b c d e))
=> '()

Related

How to represent the following data structure in scheme r5rs

In Python the data structure looks like this: [([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
How would I represent the same in Scheme r5rs?
This is what I tried: (list (cons `(1 2 3) `(8 9 10)))
But running (display (list (cons `(1 2 3) `(8 9 10)))) gives (((1 2 3) 8 9 10)) whereas I want (((1 2 3) (8 9 10)))
Edit
Using only lists (as per #Will Ness answer here):
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
works.
And I can access the 2nd element of the tuple by
(cadr (car x)) which gives (8 9 10) (which is correct)
I was just thinking how would I build this up using cons since my tuple will only contain 2 elements and from what I know cons are used to represent a pair in Scheme. Any ideas on how to do this using cons?
[([1 2 3], [8 9 10])] (a list of tuple, where tuple is of size 2, and each tuple element is a list again)
(list ; a list of
(list ; a pair of elements,
(list 1 2 3) ; 1 each is itself
(list 8 9 10))) ; 2 a list
Scheme is untyped, so we can just use lists for tuples. It is simpler that way -- the access is uniform. The first is car, the second cadr.
Your way is correct as well. What really determines whether it is or not is how you can access your data to retrieve its constituents back. And with your way you can indeed, too: the first element will be car and the second -- cdr.
(update to the question edit:) whether you use (cons 1 (cons 2 '())) or (list 1 2) is immaterial. the resulting structure in memory is the same.
There is an infinity of ways to represent data. You have been presented a way. Here is other way:
(define mk/data
(lambda (a b)
(lambda (?)
(cond ((eq? ? 'repr) (list (list a b)))
((eq? ? 'first) a)
((eq? ? 'second) b)))))
(define data/test (mk/data '(1 2 3) '(8 9 10)))
(data/test 'repr)
(data/test 'first)
(data/test 'second)
This is another way how the big systems actually represent data.

How to solve this Racket problem using higher order functions?

I am stuck on Q2.
Q1. Write a function drop-divisible that takes a number and a list of numbers, and returns a new list containing only those numbers not "non-trivially divisible" by the the number.
This is my answer to Q1.
(define (drop-divisible x lst)
(cond [(empty? lst) empty]
; if the number in the list is equal to the divisor
; or the number is not divisible, add it to the result list
[(or (= x (first lst))(< 0 (remainder (first lst) x))) (cons (first lst) (drop-divisible x (rest lst)))]
[else (drop-divisible x (rest lst))]))
(module+ test
(check-equal? (drop-divisible 3 (list 2 3 4 5 6 7 8 9 10)) (list 2 3 4 5 7 8 10)))
Q2. Using drop-divisible and (one or more) higher order functions filter, map, foldl, foldr. (i.e. no explicit recursion), write a function that takes a list of divisors, a list of numbers to test, and applies drop-divisible for each element of the list of divisors. Here is a test your code should pass
(module+ test
(check-equal? (sieve-with '(2 3) (list 2 3 4 5 6 7 8 9 10)) (list 2 3 5 7)))
I can come up with a snippet that only takes the second list, which does the same work as the solution to Q1.
(define (sieve-with divisors lst)
(filter (lambda (x) ((lambda (d)(or (= d x)(< 0 (remainder x d)))) divisors)) lst))
I tried to modify the snippet with 'map' but couldn't make it work as intended. I also can't see how 'foldr' may possibly be used here.
In this case, foldl is the right tool to use (foldr will also give a correct answer, albeit less efficiently, when the divisors are in increasing order). The idea is to take the input list and repeatedly applying drop-divisible on it, once per each element in the divisors list. Because we accumulate the result between calls, in the end we'll obtain a list filtered by all of the divisors. This is what I mean:
(define (sieve-with divisors lst)
; `e` is the current element from the `divisors` list
; `acc` is the accumulated result
(foldl (lambda (e acc) (drop-divisible e acc))
lst ; initially, the accumulated result
; is the whole input list
divisors)) ; iterate over all divisors
I used a lambda to make explicit the parameter names, but in fact you can pass drop-divisible directly. I'd rather write this shorter implementation:
(define (sieve-with divisors lst)
(foldl drop-divisible lst divisors))
Either way, it works as expected:
(sieve-with '(2 3) '(2 3 4 5 6 7 8 9 10))
=> '(2 3 5 7)

Scheme - Adding a list to a list of lists?

I am trying to answer a scheme question, for a part of this question I have to make a list of lists:
(define (join a b (result '()))
(cons (list a b) result))
So I am taking in two characters, and placing them in a list, then I need to place each sublist into a list of lists, this function is being called recursively with two characters each time, so it is supposed to work like this:
join 1 4
=> ((1 4))
join 2 5
=> ((1 4) (2 5))
join 3 6
=> ((1 4) (2 5) (3 6))
However, I am getting ((3 6) (2 5) (1 4)), so the elements need to be reversed, I tried reversing my cons function to (cons result (list a b)) but then I get (((() 1 4) 2 5) 3 6), how can I get the list the right way around, or is there an easier way to do what I'm doing?
If you need to add elements at the end of a list use append; cons is for adding elements at the head. Try this:
(define (join a b (result '()))
(append result (list (list a b))))
Notice that append combines two lists, that's why we have to surround the new element inside its own list. Also, it's not a good idea to add elements at the end, using append is more expensive than using cons - if possible, rethink your algorithm to add elements at the head, and reverse the result at the end.
This can easily be done like this:
(define (group-by-2 lst)
(let loop ((lst lst) (rlst '()))
(if (or (null? lst) (null? (cdr lst)))
(rcons->cons rlst)
(loop (cdr lst)
(rcons (list (car lst)
(cadr lst))
rlst)))))
(group-by-2 '(1 2 3 4 5 6 7 8))
; ==> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8))
Now rcons is like cons but it makes a reverse list. (rcons 1 (rcons 2 (rcons 3))) ; ==> {3 2 1} however it is not a list so you have to convert it to a list (rcons->list (rcons 1 (rcons 2 (rcons 3))) ; ==> (3 2 1)
The magic functions are really not that magical:
(define rcons cons)
(define rcons->cons reverse)
So in fact I didn't really have to make that abstraction, but hopefully I made my point. It doesn't matter how you organize the intermediate data structure in your programs so why not make the best for the job you are doing. For lists it's always best to iterate from beginning to end and make from end to beginning. Every insert O(1) per element and you do a O(n) reverse in the end. It beats doing append n times that would make it O(n²)

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

removing list with a list

I understand how to remove elements when there are list and a variable, but is there a way to remove elements from a list using another list? EXAMPLE: (list 1 2 3 4 5)(list 1 2 3) yields (list 4 5)
It's the same as with a variable, but you need to use the member function instead of equal?:
#lang racket
; remove every element included in rlist from flist
(define (remove-list rlist flist)
(if (empty? flist)
'()
(let ((c (car flist)))
(if (member c rlist) ; <====
(remove-list rlist (cdr flist))
(cons c (remove-list rlist (cdr flist)))))))
(remove-list (list 1 2 3) (list 1 2 3 4 5))
=> '(4 5)
In Racket this is pretty simple, just use the remove* built-in procedure:
(remove* (list 1 2 3) (list 1 2 3 4 5))
=> '(4 5)

Resources