Checking if a number occurs in a list of numbers - scheme

Write a procedure called direct-num-occurs? that checks whether a number occurs in a list of numbers. Examples:
> (direct-num-occurs? 1 '(2 3 1 4))
;=> #t
> (direct-num-occurs? 1 '(2 3 5 4))
;=> #f
This is what I tried:
(define direct-num-occurs?
(lambda (num ws)
(cond
[(null? ws) #f]
[(equal? num (car ws)) #t]
[else (direct-num-occurs? (cdr ws) num)])))
But I'm getting an error that says expected a pair.

For future reference, you're re-implementing the member procedure:
(define (direct-num-occurs? n lst)
(if (member n lst) #t #f))
... But I guess you're trying to write it from scratch. The implementation shown is basically correct, except that you passed the arguments in the wrong order in the last line. This should fix it:
(define direct-num-occurs?
(lambda (num ws)
(cond
[(null? ws) #f]
[(equal? num (car ws)) #t]
[else (direct-num-occurs? num (cdr ws))])))
Of course, it works as expected:
(direct-num-occurs? 1 '(2 3 1 4))
=> #t
(direct-num-occurs? 1 '(2 3 5 4))
=> #f

Related

How to design a function that subtracts 2 from each number in a given list?

Here is my code. My test result are always wrong and I don't know where the mistakes are and how to correct them.
(define (calculator op num lst)
(cond [(empty? lst) empty]
[else (cons (op num (first lst))
(calculator op num (rest lst)))]))
(define (sb lst)
(calculator - 2 lst))
(define (calculator op num lst)
; test result:
(sb (list 2 3))
-->(list 0 -1)
(sb (list 5 6))
-->(list -3 -4)
(sb (list -1 -2))
-->(list 3 4)
The problem is caused by (op num (first lst)). When you run your code, it is essentially equivalent to (- 2 (first lst)). You are not subtracting 2 from every item in the list. Instead you are subtracting every item in the list from 2. You are doing 2 - x instead of x - 2. To get the desired results, the arguments given to - should be flipped.
You could solve the problem by defining a "flipped subtraction" function that takes its arguments in a different order. For example:
(define (flipped-sub b a)
(- a b))
(define (sb lst)
(calculator flipped-sub 2 lst))
Or just use an anonymous lambda:
(define (sb lst)
(calculator (lambda (num x) (- x num)) 2 lst))

Scheme Double All List Values and Write Mapping Function

I have a question on a homework assignment that is as follows:
I have the first part (double-list-elements) complete
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
but I honestly have absolutely no idea how to proceed with double-list-elements-one. Any pointers would be greatly appreciated.
Close But No Cigar:
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
(define (custom-map proc lst)
(if (null? lst)
'()
(cons (proc lst)
(custom-map proc (cdr lst)))))
(define (double-list-elements-one func s)
(custom-map double-list-elements s))
(double-list-elements-one double-list-elements '(1 2 3 4 5 6))
Output = (list (list 2 4 6 8 10 12) (list 4 6 8 10 12) (list 6 8 10 12) (list 8 10 12) (list 10 12) (list 12))
I need to pass double-list-elements to double-list-elements-one as a parameter as well as the list.
You just have to write your own map, it's very very similar to what you already have, simply pass the part that changes as a procedure parameter, and invoke it on the right place:
(define (mymap proc lst)
(if (null? lst)
'()
(cons <invoke proc on current element>
(mymap proc (cdr lst)))))
(define (double-list-elements-one s)
(mymap <pass a proper lambda> s))
(double-list-elements-one '(1 2 3 4 5))
=> '(2 4 6 8 10)

How to check if a given list is divisible by 4 in scheme

I need to check if a given list of numbers(all of them) are divisible by 4
(divisible4 '(4,12,20))
#t
(divisible4 '(12 5 13))
#f
I have written this but it does not return #f. How can i fix this
(define (div2? list)
(if (= (modulo (car list) 4) 0)
#t
(div2? cdr list)))
A simple way would be to use built-ins, such as andmap that checks whether a condition holds for all elements in a list:
(define (divisible4 lst)
(andmap (lambda (e) (zero? (modulo e 4)))
lst))
We can do the same process by hand, albeit less elegantly:
(define (divisible4 lst)
(if (null? lst)
#t
(and (zero? (modulo (car lst) 4))
(divisible4 (cdr lst)))))
Equivalently:
(define (divisible4 lst)
(or (null? lst)
(and (zero? (modulo (car lst) 4))
(divisible4 (cdr lst)))))
Anyway, it works as expected:
(divisible4 '(4 12 20))
=> #t
(divisible4 '(12 5 13))
=> #f
Named let recursion may be more easy to understand:
(define (div4 L)
(let loop ((ll L)) ; set up recursion and initial value;
(cond
[(empty? ll) #t] ; if full list tested, return true;
[(not(= 0 (modulo (car ll) 4))) #f] ; if first item is not divisible, return false;
[else (loop (rest ll))] ; else goto rest of list;
)))

Counting elements of a list and sublists

I'm trying to create a function to count all the elements in a list, including the elements of its sublists. initially, to get started, i came up with a basic function myList:
(define myLength
(lambda (L)
(cond
((null? L) 0)
(else (+ 1 (myLength (cdr L)))))))
However, it doesn't help me account for function calls like:
(numAtoms '()) "...should be 0"
(numAtoms '(())) "...should be 0"
(numAtoms '(1 1)) "...should be 2"
(numAtoms '(1 (1 1) 1)) "...should be 4"
(numAtoms '(1 (1 (1 1)) 1)) "...should be 5"
I'm trying to use basic functions like length, null?, and list?.
I think the trick here is to imagine how you can transform your input into the code that you'd want to use to compute the sum. Let's write each of your inputs in the fully expanded form, in terms of cons and '() and whatever other atoms appear in your data:
'() == '()
'(()) == (cons '() '())
'(1 1) == (cons 1 (cons 1 '()))
'(1 (1 1) 1) == (cons 1 (cons 1 (cons 1 '())) (cons 1 '()))
'(1 (1 (1 1)) 1) == ...
Now, look what would happen if you replaced each occurrence of cons with +, and each occurrence of '() with 0, and each occurrence of something that's not '() with 1. You'd have:
'() => 0 == 0
(cons '() '()) => (+ 0 0) == 0
(cons 1 (cons 1 '())) => (+ 1 (+ 1 0)) == 2
(cons 1 (cons 1 (cons 1 '())) (cons 1 '())) => (+ 1 (+ 1 (+ 1 0)) (+ 1 0)) == 4
... => ... == ...
Notice that those sums are exactly the values that you want! Based on this, it seems like you might not want to treat your input as a list so much as a tree built from cons cells. In general, you can map over a tree by specifying a function to apply to the recursive results of processing a pair, and a function to process the atoms of the tree:
(define (treeduce pair-fn atom-fn tree)
(if (pair? tree)
(pair-fn (treeduce pair-fn atom-fn (car tree))
(treeduce pair-fn atom-fn (cdr tree)))
(atom-fn tree)))
You could then implement that mapping of cons to + and everything else to 1 if it's a list and 0 if it's not by:
(define (non-null-atoms tree)
(treeduce +
(lambda (atom)
(if (not (null? atom))
1
0))
tree))
This yields the kinds of results you'd expect:
(non-null-atoms '()) ;=> 0
(non-null-atoms '(())) ;=> 0
(non-null-atoms '(1 1)) ;=> 2
(non-null-atoms '(1 (1 1) 1)) ;=> 4
(non-null-atoms '(1 (1 (1 1)) 1)) ;=> 5
Here is a recursive template you can use:
(define (num-atoms lst)
(cond ((pair? lst) (+ (num-atoms <??>)
(num-atoms <??>)))
((null? lst) <??>) ; not an atom
(else <??>))) ; an atom
This next example uses a helper that has the accumulated value (num) as an argument.
(define (num-atoms lst)
;; locally defined helper
(define (helper num lst)
(cond ((pair? lst) (helper (helper <??> <??>) <??>)) ; recurse with the sum of elements from car
((null? lst) <??>) ; return accumulated value
(else (helper <??> <??>)))) ; recurse with add1 to num
;; procedure starts here
(helper 0 lst))
Hope it helps
Make my-length work for any argument type, list or 'atom'; then the recursive algorithm becomes almost trivial:
(define (my-length l)
(cond ((null? l) 0)
((list? l) (+ (my-length (car l)) (my-length (cdr l))))
(else 1))) ; atom
> (my-length '(1 (1 (1 1)) 1)))
5

What is wrong with my scheme code?

The function I wrote for SICP 2.20 is:
(define (same-parity x . y)
(if (null? (car y)
'()
(if (= (even? (car y)) (even? x))
(cons (car y) (same-parity (cons x (cdr y))))
(same-parity (cons x (cdr y))))))
And then I try to call it with
(same-parity 1 2 3 4 5 6 7)
The error I get is:
"The object #t, passed as the first argument to integer-equal? is not the correct type."
I thought that equal works with #t and #f...
An example of code I found online is the following, I ran it and it works. But, what am I doing wrong?
(define (same-parity a . rest)
(define (filter rest)
(cond ((null? rest) '())
((= (remainder a 2) (remainder (car rest) 2))
(cons (car rest) (filter (cdr rest))))
(else
(filter (cdr rest)))))
(filter (cons a rest)))
The = procedure accepts numbers. But even? returns a boolean not a number.
Use equal? instead of =.
equal? works with booleans.
For instance at the REPL:
> (even? 2)
#t
> (= (even? 2) (even? 2))
=: expects type <number> as 1st argument, given: #t; other arguments were: #t
> (equal? (even? 2) (even? 2))
#t

Resources