I was writing some code that outputs a list of factorials given a list of natural numbers. So (list 1 4 3) would give (list 1 24 6). Currently Racket is giving me the error "first: expects a non-empty list; given: empty" when on the line with the (cons ......). I used the debugger to check and the code never reaches empty, is there a way to fix this?
(define (factorialize arr)
(cond
[(empty? arr) empty]
[else (cons (factorial (first arr)) (factorialize (factorial (first (rest arr)))))]))
;;helper function
(define (factorial num)
(cond
[(= 0 num) 1]
[else (* num (factorial (- num 1)))]))
The recursive step isn't right, why do you call (factorialize (factorial (first (rest arr))))? that's trying to apply factorialize on the result of factorial, which is a number and not the list expected by factorialize. You just need to advance the recursion by invoking the procedure on the rest of the list! Try this:
(define (factorialize arr)
(cond
[(empty? arr) empty]
[else (cons (factorial (first arr))
(factorialize (rest arr)))]))
FYI, a simpler and more idiomatic implementation would use the built-in map higher-order procedure:
(define (factorialize arr)
(map factorial arr))
Either way, it works as expected:
(factorialize '(1 4 3))
=> '(1 24 6)
Related
Im trying to write a small program that will take a list as an input and the first function is supposed to remove values that are greater than 4 and the other one is supposed to remove values that are lower than 4 in the check-expects. I figure this is a simple solution but I cant seem to figure it out as Im still new to lists and data structures. Any help would be appreciated, here is the code:
(define (removehigher lon n)
(cond [(> n lon)(remove (lon))]
[(< n lon) true]))
(define (removelower lon n)
(cond [(> n lon) true]
[(< n lon) (remove(lon))]))
(check-expect(removehigher(list 0 1 2 3 4 5 6)4)(list 0 1 2 3))
(check-expect(removelower(list 0 1 2 5 6 7) 3)(list 5 6 7))
There is a function called filter which would do this.
(define (my-filter pred lst (acc '()))
(cond [(null? lst) (reverse acc)]
[(pred (car lst)) (my-filter pred (cdr lst) (cons (car lst) acc))]
[else (my-filter pred (cdr lst) acc)]))
It is actually an in-built function filter. I use my- as prefix to not to overwrite this in-built function.
Once you have the function filter (or my-filter), you can write your desired functions easily - it is then about to define the predicate function (pred) correctly for each of the cases:
(define (remove-higher lst n)
(filter (lambda (x) (<= x n)) lst))
(define (remove-lower lst n)
(filter (lambda (x) (<= n x)) lst))
Alternatively, one could also use append-map:
(define (remove-higher lst n)
(append-map (lambda (x) (if (<= x n) (list x) '())) lst))
(define (remove-lower lst n)
(append-map (lambda (x) (if (<= n x) (list x) '())) lst))
Or define filter using append-map:
(define (my-filter pred lst)
(append-map (lambda (x) (if (pred x) (list x) '())) lst))
append-map in turn can be defined:
(define (my-append-map func lst)
(apply append (map func lst)))
Having nested lists as the input, I'm trying to find how to output the number of 'siblings' an element has. In terms of trees, how many other leaf nodes belong to the same parent/root node.
My code is giving the wrong outputs (it's a really bad code) and I'm not sure how to entirely approach the question
(define (siblings lst n)
(cond
[(empty? lst) false]
[(member? n lst) (sub1 (length lst))]
[else (siblings (rest lst) n)]))
sample outcomes: if given (list (list 2 1) 3 (list 4)) and 3, produce 0
(list (list 1 2 3) (list (list 4 5 6 ))) and 5 -> 2
Your code has to do two separate things:
Find the branch that contains n
Count the number of siblings in that branch, accounting for the possibility of other branches starting there.
Finding the branch that contains n, assuming that n can only appear once:
(define (find-branch root n)
(cond ((empty? root) empty)
((memq n root)
root)
((list? (first root))
(let ((subresult (find-branch (first root) n)))
(if (not (empty? subresult))
subresult
(find-branch (rest root) n))))
(else (find-branch (rest root) n))))
Since you're using "Beginning Student," that takes all the tools out of your toolbox. Fortunately, it still has number?, so if it's safe to assume that anything that isn't a number in this assignment is a list, you can define list? like this:
(define (list? n) (not (number? n)))
Given your example tree as input, it would return:
(4 5 6)
The above example unnecessarily uses memq repeatedly on the rest of the
input list as a result of using recursion to iterate over the same list.
Here's a more efficient version of the above, but you can't implement it in Beginning Student:
(define (find-branch root n)
(cond ((empty? root) false)
((memq n root) root)
(else (foldl (λ (a b)
(if (empty? a) b a))
empty
(map (λ (sublist)
(find-branch sublist n))
(filter list? root))))))
You pass the result of that to a function to count the siblings. I previously provided a version that would work in the real Racket, but not the Beginning Student version used by teachers:
(define (count-siblings root mem)
(count (λ (sib)
(and (not (eq? sib mem))
(not (list? sib)))) root))
Here's a version that's compatible with Beginning Student:
(define (count-siblings lst n counter)
(cond
[(empty? lst) counter]
[(and (not (list? (first lst)))
(not (eq? n (first lst))))
(count-siblings (rest lst) n (add1 counter))]
[else (count-siblings (rest lst) n counter)]))
Finally, put the two together:
(define (find/count-siblings root n)
(count-siblings (find-branch root n) n 0))
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)
First off, scheme: return a lst that only contains the first element of the lst did not help much, as the question was never really answered, and I followed the contributor's suggestions to no success. Furthermore, I am approaching this with a do loop, and have almost achieved the solution.
I need to make a procedure that will return the first n items in a passed list. For example, (first-n 4 '(5 8 2 9 4 0 8 7)) should give (5 8 2 9).
Here is my approach, the display is there to make sure that the loop is working, which it is:
(define (front-n n list)
(do ((i 0 (+ i 1)))
((> i (- n 1)))
(display (list-ref list i))))
How do I go about making that return a list, or output a list?
Your do-loop, and #Penguino's recursive function, both fail if there are less than n items in the input list. Here is a simple version based on named-let, renamed take which is the normal name for this function:
(define (take n xs)
(let loop ((n n) (xs xs) (zs (list)))
(if (or (zero? n) (null? xs))
(reverse zs)
(loop (- n 1) (cdr xs)
(cons (car xs) zs)))))
Or, if you prefer the recursive function version:
(define (take n xs)
(if (or (zero? n) (null? xs))
(list)
(cons (car xs) (take (- n 1) (cdr xs)))))
The named-let version is preferable to the recursive version, because the recursion isn't in tail position, so it builds a large intermediate stack.
You said that you wanted a version using do. That's harder, because the test that terminates the loop is performed after the action of the loop, and you need to perform the test before the action. You can either test one-ahead, which is awkward, or use this loop that delays the action until after the test has succeeded:
(define (take n xs)
(let ((zs (list)))
(do ((n n (- n 1)) (xs xs (cdr xs)))
((or (zero? n) (null? xs)) (reverse zs))
(set! zs (cons (car xs) zs)))))
The set! isn't particularly Schemely, but at least it shares with the named-let version the property that it doesn't build an intermediate stack.
How about
(define (front-n n list)
(cond ((= 0 n) '())
(else (cons (car list) (front-n (- n 1) (cdr list))))))
with a little pseudo-error-trapping added.
Testing with:
(front-n 4 '(5 8 2 9 4 0 8 7))
(front-n 8 '(5 8 2 9 4 0 8 7))
produces the expected output:
'(5 8 2 9)
'(5 8 2 9 4 0 8 7)
>
Note that the error checking may be useful.
Here is a tail recursive version:
(define (take n a-list)
(define (iter counter result sublist)
(cond
[(empty? sublist) result]
[(< counter n)
(iter
(+ counter 1)
(append result (list (car sublist)))
(cdr sublist))]
[else result]))
(cond
[(= n 0) '()]
[else (iter 0 '() a-list)]))
It differs slightly from the library procedure, because the library procedure throws an error, if you give a take count which is larger than the length of the list, while this function returns the whole list in that case.
Note however, that it makes use of append. I could not figure out a way around that yet.
Trying to learn lisp, want to delete every nth. I only managed to delete the first (nth) element
(defun delete-nth (n list)
(if (zerop n)
(cdr list)
(let ((cons (nthcdr (1- n) list)))
(if cons
(setf (cdr cons) (cddr cons))
cons))))
I'd like to delete the next nth and so on
Also I tried this:
(defun remove-nth (list n)
(remove-if (constantly t) list :start n :end (+ 1 n)))
No idea how to start again
What I was thinking was concatenating, but I have no idea of how to keep track of my position.
Counting from 1 (changing to 0 is trivial):
(defun remove-every-nth (n list)
(loop for element in list
for index from 1
unless (zerop (rem index n))
collect element))
Also: Please indent your code correctly.
An alternative way to do the same thing:
(defun remove-all-nth (list period)
(remove-if
(let ((iterator 0))
(lambda (x)
(declare (ignore x))
(= 0 (mod (incf iterator) period)))) list))
(remove-all-nth '(1 2 3 4 5 6 7 8 9 0) 3)
; (1 2 4 5 7 8 0)
Perhaps a more academic recursive solution here:
(defun delete-nth (n list)
(labels ((rec (i list)
(cond ((null list) nil)
((= i 1) (rec n (cdr list)))
(t (cons (car list) (rec (1- i) (cdr list)))))))
(rec n list)))
But in real life I'd use the loop option above.