(define (list-ref items n)
(cond ((null? items) "Out of range exception")
((= n 0) (car items))
(list-ref (cdr items) (- n 1))))
(list-ref (list 1 2 3) 6)
5
Why it always return value of (- n 1)? Why it doesn't execute (list-ref (cdr items) (- n 1)) ?
You forgot an else in the final clause.
Instead, it used list-ref as the condition (which is always truthy, since all procedures are truthy), and evaluated your other two subforms and returned the last one.
Related
I have been writing a code that returns a list with all prime numbers less than or equal to n in the Scheme language.
Example,3 -> 2,3 10 -> 1,3,5,7 11->2,3,5,7,11
Actually, the codes below works.However, when I put 1 for n, the code should show (), but it shows 2. I think that it is because I put 2 on the second line. But I put the 2 for the other test case.
I tried to fix the code, but it did not work.
Are there any points where I can fix?
(define (primes n)
(let loop((result `(2))
(i 3))
(cond ((> i n)(reverse result))
(else (loop
(if (divide-any? i result) result (cons i result))
(+ i 2))))))
(define (divide? n1 n2)
(zero? (modulo n1 n2)))
(define (divide-any? n ls)
(do ((ls ls (cdr ls)))
((or (null? ls)
(divide? n (car ls)))
(not (eqv? '() ls)))))
Yes, the function primes is partial - it only works for certain values.
You can fix it quite simply:
(define (primes n)
(if (<= n 1)
'()
(let loop((result `(2))
(i 3))
(cond ((> i n)(reverse result))
(else (loop
(if (divide-any? i result) result (cons i result))
(+ i 2)))))))
I'm trying to write a function in Scheme that returns the first n elements in a list. I'm want to do that without loops, just with this basic structure below.
What I've tried is:
(define n-first
(lambda (lst n)
(if (or(empty? lst) (= n 0))
(list)
(append (car lst) (n-first (cdr lst) (- n 1))))))
But I'm getting an error:
append: contract violation
expected: list?
given: 'in
I've tried to debug it and it looks that the tail of the recursion crashes it, meaning, just after returning the empty list the program crashes.
When replacing "append" operator with "list" I get:
Input: (n-first '(the cat in the hat) 3)
Output:
'(the (cat (in ())))
But I want to get an appended list.
A list that looks like (1 2 3) i constructed like (1 . (2 . (3 . ()))) or if you're more familiar with cons (cons 1 (cons 2 (cons 3 '()))). Thus (list 1 2 3)) does exactly that under the hood. This is crucial information in order to be good at procedures that works on them. Notice that the first cons cannot be applied before the (cons 2 (cons 3 '())) is finished so a list is always created from end to beginning. Also a list is iterated from beginning to end.
So you want:
(define lst '(1 2 3 4 5))
(n-first lst 0) ; == '()
(n-first lst 1) ; == (cons (car lst) (n-first (- 1 1) (cdr lst)))
(n-first lst 2) ; == (cons (car lst) (n-first (- 2 1) (cdr lst)))
append works like this:
(define (append lst1 lst2)
(if (null? lst1)
lst2
(cons (car lst1)
(append (cdr lst1) lst2))))
append is O(n) time complexity so if you use that each iteration of n parts of a list then you get O(n^2). For small lists you won't notice it but even a medium sized lists of a hundred thousand elements you'll notice append uses about 50 times longer to complete than the cons one and for large lists you don't want to wait for the result since it grows exponentially.
try so
(define first-n
(lambda (l)
(lambda (n)
((lambda (s)
(s s l n (lambda (x) x)))
(lambda (s l n k)
(if (or (zero? n)
(null? l))
(k '())
(s s (cdr l) (- n 1)
(lambda (rest)
(k (cons (car l) rest))))))))))
(display ((first-n '(a b c d e f)) 4))
(display ((first-n '(a b)) 4))
In scheme you must compute mentally the types of each expression, as it does not have a type checker/ type inference included.
I'm stuck on a homework question and could use any hints or suggestions. I need to find the n largest numbers in a list using Scheme. I am trying to do this by creating helper functions that are called by the main function. So far I have this:
(define (get_max_value L)
(if (null? L)
'()
(apply max L)
)
(define (biggest_nums L n)
(if (null? n)
'()
(cons (get_max_value L) (biggest_nums L (- n 1)))
)
)
When I type (biggest_num '(3 1 4 2 5) 3) at the command prompt drRacket just hangs and doesn't even return an error message. Where am I going wrong?
The simplest solution is to first sort the numbers in ascending order and then take the n first. This translates quite literally in Racket code:
(define (biggest_nums L n)
(take (sort L >) n))
It works as expected:
(biggest_nums '(3 1 4 2 5) 3)
=> '(5 4 3)
Two mains problems with your code:
L always stays the same. L doesn't decrease in size when you make the recursive call, so the max will always be the same number in every recursive call.
You don't ever check n to make sure it contains the correct amount of numbers before returning the answer.
To solve these two problems in the most trivial way possible, you can put a (< n 1) condition in the if, and use something like (cdr L) to make L decrease in size in each recursive call by removing an element each time.
(define (biggest-nums n L)
(if (or (empty? L)
(< n 1))
'()
(cons (apply max L) (biggest-nums (- n 1) (cdr L)))))
So when we run it:
> (biggest-nums 3 '(1 59 2 10 33 4 5))
What should the output be?
'(59 33 10)
What is the actual output?
'(59 59 33)
OK, so we got your code running, but there are still some issues with it. Do you know why that's happening? Can you step through the code to figure out what you could do to fix it?
Just sort the list and then return the first n elements.
However, if the list is very long and n is not very large, then you probably don't want to sort the whole list first. In that case, I would suggest something like this:
(define insert-sorted
(lambda (item lst)
(cond ((null? lst)
(list item))
((<= item (car lst))
(cons item lst))
(else
(cons (car lst) (insert-sorted item (cdr lst)))))))
(define largest-n
(lambda (count lst)
(if (<= (length lst) count)
lst
(let loop ((todo (cdr lst))
(result (list (car lst))))
(if (null? todo)
result
(let* ((item (car todo))
(new-result
(if (< (car result) item)
(let ((new-result (insert-sorted item result)))
(if (< count (length new-result))
(cdr new-result)
new-result))
result)))
(loop (cdr todo)
new-result)))))))
I am a beginner in scheme and I want to know how you find the location of an element in a list. For example, in this given list,
(list 1 2 13)
I found the maximum using accumulative recursion, but I need to also find the location of the maximum, so if the function is:
(max-with-location (list 1 2 13)), I need to get: (list 13 (list 3))
Please help me out.
This sounds like homework, and if this is the case then any of these solutions won't help. What you're likely expected to do is to revise the code that you wrote to find the maximum: instead of a single accumulator input to the loop, add one more for the position of the maximum-so-far. That will not be too hard given that you already have implemented max.
I don't use Scheme, but in CL it's (position 13 (list 1 2 13))
Maybe it's the same...
So for your code, you'd want something like this:
(list (max (list 1 2 13)) (position (max (list 1 2 13)))
which would return (13 2)
edit: max is supposed to be your max algorithm, though I imagine there might already be a function for this
double edit: if that still doesn't work, you could always use a counter that increments each time through your recursive function, then return that as well...
first you have to determinate the max number:
(define max_list1
(lambda (l)
(cond
((empty? (rest l)) l)
(else (max_aux_list (first l) (rest l))))))
(define (max_aux_list n lista)
(cond
((empty? lista) n)
((> n (first lista)) (max_aux_list n (rest lista)))
(else (max_aux_list (first lista) (rest lista)))))
then you have to count the position number of an element.
(define find_in_position
(lambda (n lista)
(cond
((empty? lista) 0)
((= n (first lista)) 1)
(else (+ 1 (find_in_position n (rest lista)))))))
finally, list both resoults.
(define (the_max_in_position lista)
(list (max_list1 lista)
(list (find_in_position (max_list1 lista) lista))))
This should do the trick:
(define (find-position list element #!optional (pred eq?))
(letrec ((loop (lambda (list count)
(if (null? list) #f ;No such element found
(if (pred (car list) element) count
(loop (cdr list) (+ count 1)))))))
(loop list 0)))
Then:
(find-position (list 1 3 13) 13)
>>> 2
Use list-ref like so:
(define tlist '(a b c d))
(list-ref tlist 2)
>> c
I'd like to add the even items in a list and have the following algorithm I wrote to achieve the objective.
The error I am getting is:
+: expects type <number> as 2nd argument, given: #<void>; other arguments were: 4
The code:
(define (mylength alist cnt)
(if (null? alist)
0
(if (= (modulo cnt 2) 0)(+ (car alist) (mylength (cdr alist) (+ cnt 1)))))
(if (= (modulo cnt 2) 1)(mylength (cdr alist) (+ cnt 1))))
Could you please advise on the
i) error
ii) logic of the algorithm
Thanks!
First, indent your code properly:
(define (mylength alist cnt)
(if (null? alist) ;
0 ; this section is wasted because
(if (= (modulo cnt 2) 0) ; it's not the last expression
(+ (car alist) (mylength (cdr alist) (+ cnt 1))))) ;
(if (= (modulo cnt 2) 1) ; this if is the last expression, but
(mylength (cdr alist) (+ cnt 1)))) ; if it's false you get #<void>
You shouldn't have if expressions that don't have both the true and false branches. You have to remember that this isn't C, and anything that's not the last expression will be run and then thrown away.
Combine the last two if statements into one if statement:
(define (mylength alist cnt)
(if (null? alist)
0
(if (= (modulo cnt 2) 0)
(+ (car alist) (mylength (cdr alist) (+ cnt 1)))
(mylength (cdr alist) (+ cnt 1)))))
Edit: When I wrote "anything that's not the last expression will be run and then thrown away", I meant:
(begin
(+ 2 2)
(+ 4 1)
(+ 1 0)
(+ 1 1)) => 2
(let ((x 5))
(add1 x)
(+ x 2)
(* x 2)) => 10
((lambda ()
(if #t 3)
(if #f 0 4)
(if #t 2))) => 2
The other answer is completely right, but your interface is not very scheme-y. This is a more common form with tail recursion.
; Assumes given a list of numbers. Returns sum of even indices.
(define (mylength alist)
(let helper ((alist alist) (acc 0))
(cond
((null? alist) acc)
((null? (cdr alist)) (+ acc (car alist)))
(else (helper (cddr alist) (+ acc (car alist)))))))