I'm a beginner learner of dr.racket. I'm asked to write a function that does the following:
Write a function "readnum" that consumes nothing,and each time it is called, it will produce the Nth number of a defined list.
Example:
(define a (list 0 2 -5 0))
readnum --> 0 (first time readnum is called)
readnum --> 2 (second time readnum is called)
readnum --> -5 (third time readnum is called)
You dont have to worry about the case where the list does have numbers or no numbers left to be read.
Dr.racket is a functional language and it is very inconvinient to mutate variables and use them as counters, and in this problem I am not allowed to define other global functions and variables (local is allowed though).
Here is my attempt but it does not seems to work:
(define counter -1)
(define lstofnum (list 5 10 15 20 32 3 2))
(define (read-num)
((begin(set! counter (+ 1 counter)))
(list-ref lstofnum counter)))
Not only I defined global variable which is not allowed, the output is not quite right either.
Any help would be appreciated, thanks!
The trick here is to declare a local variable before actually defining the function, in this way the state will be inside a closure and we can update it as we see fit.
We can implement a solution using list-ref and saving the current index, but it's not recommended. It'd be better to store the list and cdr over it until its end is reached, this is what I mean:
(define lstofnum (list 0 2 -5 0))
(define readnum
(let ((lst lstofnum)) ; list defined outside will be hardcoded
(lambda () ; define no-args function
(if (null? lst) ; not required by problem, but still...
#f ; return #f when the list is finished
(let ((current (car lst))) ; save the current element
(set! lst (cdr lst)) ; update list
current))))) ; return current element
It works as expected:
(readnum)
=> 0
(readnum)
=> 2
(readnum)
=> -5
(readnum)
=> 0
(readnum)
=> #f
Related
I have the following function "change" which takes a certain amount of money to be paid, the size of the bill/coin used to pay, and returns a list with the number of "coins" ($50, $20 $10 $5 $2 and $1) one would receive after completing the transaction:
(define (change total payment)
(let [(x (- payment total))]
(change-aux x '(50 20 10 5 2 1))))
(define (change-aux change coins)
(cond
[(empty? coins) empty]
[else (let [(num-coins (floor (/ change (car coins))))]
(append (list num-coins)
(change-aux (- change (* (car coins) num-coins)) (cdr coins))))]))
So, if I input these parameters:
> (change 44 200)
It returns the output:
'(3 0 0 1 0 1)
That's 200-44 = 156, which corresponds to 3 coins worth $50, 1 worth $5 and 1 worth $1.
My question would be if there's a more elegant, simplified way to write a similar procedure without relying on auxiliary functions, and rather use lambda, filter, map, foldr, foldl etc?
Thanks in advance.
Here is a solution in a different Lisp dialect which shows how to do it with a left fold (reduce) without any mutation of an accumulator variable, as a kind of functional counterpoint to the existing solution.
(defun change (amount coins)
(reduce-left (tb ((counts . rem) next-coin)
(let* ((coin-count (floor rem next-coin))
(coin-value (* coin-count next-coin)))
(cons (cons coin-count counts)
(- rem coin-value))))
coins
(cons '() amount)))
3> (change 156 '(50 20 10 5 2 1))
((1 0 1 0 0 3) . 0)
4> (change 88 '(50 20 10 5 2 1))
((1 1 1 1 1 1) . 0)
Note that the values end up reported in reverse order and wrapped in an extra cons cell; a "porcelain" function could be used around this "plumbing" to report the result in the expected form.
The idea is that we have an accumulator which looks like this: (counts . remainder). The counts part of the accumulator stored in the car is the list of coins accumulated so far. When the reduce is done, this holds the final list. The cdr field holds the remaining amount to be processed; since the last coin is 1, this will always emerge as zero.
Using this accumulator structure, we process the list of coins.
On each call to our reduce kernel function, the left argument is the accumulator, and the right argument, next-coin, is the next coin denomination value.
I used a macro called tb ("tree bind") macro, which is a kind of lambda that provides built-in destructuring, to make it look like we have three parameters.
The initial value for the reduce job is the starting accumulator, which has an empty list of coins, and the full original amount: (cons nil amount) (which I rewrote to (cons '() amount) for better Scheme compatibility).
The reduce function is very simple: greedily calculate how many of the next coin value are needed to represent the remainder, and then calculate the new remainder, packaging these up into a new accumulator cons cell that is returned, and is passed to the next invocation of the function, or returned when the list of coin values has been processed.
Hopefully this points the way to "a more elegant, simplified way to write a similar procedure without relying on auxiliary functions, and rather use lambda, filter, map, foldr, foldl etc" that you can work out in Racket. Good luck!
Sure, you can.
Final solution
(define (change total payment (coins '(50 20 10 5 2 1)))
(let ((rest-diff (- payment total)))
(map (lambda (coin)
(let ((num-coins (floor (/ rest-diff coin))))
(set! rest-diff (- rest-diff (* num-coins coin)))
num-coins))
coins)))
Step by step
First of all, using inner define, you can get rid of the auxiliary function from the global namespace.
(define (change total payment)
(define (change-aux change coins)
(cond
[(empty? coins) empty]
[else (let [(num-coins (floor (/ change (car coins))))]
(append (list num-coins)
(change-aux (- change (* (car coins) num-coins)) (cdr coins))))]))
(let [(x (- payment total))]
(change-aux x '(50 20 10 5 2 1))))
Then, you can pull some variables of the helper function's to the global function's lambda list.
(define (change total payment (coins '(50 20 10 5 2 1)))
(define (change-aux change) ;; eliminate coins in the inner lambda list
(cond
[(empty? coins) empty] ;; coins in function body looked up from outer arguments
[else (let [(num-coins (floor (/ change (car coins))))]
(append (list num-coins)
(change-aux (- change (* (car coins) num-coins)) (cdr coins))))]))
(let [(x (- payment total))]
(change-aux x))) ;; eliminate coins in the call
Then, looking at the code of change-aux, one understands this is actually
a looping through and trying to fit maximal multiples of current value
into the rest of the difference remaining - and collecting those reults. One could loop using map and use set! to mutate the rest.
(define (change total payment (coins '(50 20 10 5 2 1)))
(let ((rest-diff (- payment total)))
(map (lambda (coin)
(let ((num-coins (floor (/ rest-diff coin))))
(set! rest-diff (- rest-diff (* num-coins coin)))
num-coins))
coins)))
Then, you call like above:
(change 44 200)
;; '(3 0 0 1 0 1)
I am struggling to find the right approach to solve the following function
(FOO #'– '(1 2 3 4 5))
=> ((–1 2 3 4 5) (1 –2 3 4 5) (1 2 –3 4 5) (1 2 3 –4 5) (1 2 3 4 –5))
The first Parameter to the foo function is supposed to be a function "-" that has to be applied to each element returning a list of list as shown above. I am not sure as to what approach I can take to create this function. I thought of recursion but not sure how I will preserve the list in each call and what kind of base criteria would I have. Any help would be appreciated. I cannot use loops as this is functional programming.
It's a pity you cannot use loop because this could be elegantly solved like so:
(defun foo (fctn lst)
(loop
for n from 0 below (length lst) ; outer
collect (loop
for elt in lst ; inner
for i from 0
collect (if (= i n) (funcall fctn elt) elt))))
So we've got an outer loop that increments n from 0 to (length lst) excluded, and an inner loop that will copy verbatim the list except for element n where fctn is applied:
CL-USER> (foo #'- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
Replacing loop by recursion means creating local functions by using labels that replace the inner and the outer loop, for example:
(defun foo (fctn lst)
(let ((len (length lst)))
(labels
((inner (lst n &optional (i 0))
(unless (= i len)
(cons (if (= i n) (funcall fctn (car lst)) (car lst))
(inner (cdr lst) n (1+ i)))))
(outer (&optional (i 0))
(unless (= i len)
(cons (inner lst i) (outer (1+ i))))))
(outer))))
Part of the implementation strategy that you choose here will depend on whether you want to support structure sharing or not. Some of the answers have provided solutions where you get completely new lists, which may be what you want. If you want to actually share some of the common structure, you can do that too, with a solution like this. (Note: I'm using first/rest/list* in preference to car/car/cons, since we're working with lists, not arbitrary trees.)
(defun foo (operation list)
(labels ((foo% (left right result)
(if (endp right)
(nreverse result)
(let* ((x (first right))
(ox (funcall operation x)))
(foo% (list* x left)
(rest right)
(list* (revappend left
(list* ox (rest right)))
result))))))
(foo% '() list '())))
The idea is to walk down list once, keeping track of the left side (in reverse) and the right side as we've gone through them, so we get as left and right:
() (1 2 3 4)
(1) (2 3 4)
(2 1) (3 4)
(3 2 1) (4)
(4 3 2 1) ()
At each step but the last, we take the the first element from the right side, apply the operation, and create a new list use revappend with the left, the result of the operation, and the rest of right. The results from all those operations are accumulated in result (in reverse order). At the end, we simply return result, reversed. We can check that this has the right result, along with observing the structure sharing:
CL-USER> (foo '- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
By setting *print-circle* to true, we can see the structure sharing:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((l '(1 2 3 4 5)))
(list l (foo '- l)))
((1 . #1=(2 . #2=(3 . #3=(4 . #4=(5))))) ; input L
((-1 . #1#)
(1 -2 . #2#)
(1 2 -3 . #3#)
(1 2 3 -4 . #4#)
(1 2 3 4 -5)))
Each list in the output shares as much structure with the original input list as possible.
I find it easier, conceptually, to write some of these kind of functions recursively, using labels, but Common Lisp doesn't guarantee tail call optimization, so it's worth writing this iteratively, too. Here's one way that could be done:
(defun phoo (operation list)
(do ((left '())
(right list)
(result '()))
((endp right)
(nreverse result))
(let* ((x (pop right))
(ox (funcall operation x)))
(push (revappend left (list* ox right)) result)
(push x left))))
The base case of a recursion can be determined by asking yourself "When do I want to stop?".
As an example, when I want to compute the sum of an integer and all positive integers below it, I can do this recusively with a base case determined by answering "When do I want to stop?" with "When the value I might add in is zero.":
(defun sumdown (val)
(if (zerop val)
0
(+ (sumdown (1- val)) val)))
With regard to 'preserve the list in each call', rather than trying to preserve anything I would just build up a result as you go along. Using the 'sumdown' example, this can be done in various ways that are all fundamentally the same approach.
The approach is to have an auxiliary function with a result argument that lets you build up a result as you recurse, and a function that is intended for the user to call, which calls the auxiliary function:
(defun sumdown1-aux (val result)
(if (zerop val)
result
(sumdown1-aux (1- val) (+ val result))))
(defun sumdown1 (val)
(sumdown1-aux val 0))
You can combine the auxiliary function and the function intended to be called by the user by using optional arguments:
(defun sumdown2 (val &optional (result 0))
(if (zerop val)
result
(sumdown2 (1- val) (+ val result))))
You can hide the fact that an auxiliary function is being used by locally binding it within the function the user would call:
(defun sumdown3 (val)
(labels ((sumdown3-aux (val result)
(if (zerop val)
result
(sumdown3-aux (1- val) (+ val result)))))
(sumdown3-aux val 0)))
A recursive solution to your problem can be implemented by answering the question "When do I want to stop when I want to operate on every element of a list?" to determine the base case, and building up a result list-of-lists (instead of adding as in the example) as you recurse. Breaking the problem into smaller pieces will help - "Make a copy of the original list with the nth element replaced by the result of calling the function on that element" can be considered a subproblem, so you might want to write a function that does that first, then use that function to write a function that solves the whole problem. It will be easier if you are allowed to use functions like mapcar and substitute or substitute-if, but if you are not, then you can write equivalents yourself out of what you are allowed to use.
I am bad at Lisp. Help me please to find a syntax error. I need to write a function which swaps two elements in list. This function must consist loop-cycle. Here is what if have so far.
(defun swap-two-element(z x y)
(let ((newlist nil) (newlist2 nil) (copyz z) (copyz2 z) (newx nil))
(loop
(when (= (- (length z) (length copyz2)) y)
(return (set newx car z)))
(setq newlist2 (append newlist2(car copyz2))
copyz2 (cdr copyz2)))))
Call example: (swap-two-element '(a b c d) 2 3)
Replace the word set with the word values and you are good to go.
PS. You need to address the warnings though, and explain what the function is supposed to do so that we could help you with the algorithm.
You really need to tidy up your question. The title says nothing, the code is badly formatted and you really need to play around with loop to get started. I won't give you your solution since you need to learn this by trying. Here is an example you can make use of to do your assignment.
;; this orders a list by their odd index
;; NB: index starts at zero so first element is even
(defun order-odd-index (list)
(loop :for element :in list ; iterates your list
:for index :from 0 ; starts from 0 and goes on
:if (oddp index) ; if in a loop
:collect element :into odd-list ; variable is automatically created
:else ; else in a loop
:collect element :into even-list
:finally (return (append odd-list even-list)))) ; what to do in the end
(order-odd-index '(4 67 3 2 7 9)) ; ==> (67 2 9 4 3 7)
I use keywords (like :for instead of for) to indicate what symbols are loop keywords and what are not. It's optional but I think it looks a lot cleaner.
Now your problem can be solved with collecting element into 5 variables. Two of them is when index is equal to one of the places (given as arguments) to be switched the other 3 are before, in between and greater. In the finally you can just append those variables in the correct order and you're done.
I'm writing a simple function that needs to remove a certain element from a list. The list has 3 lists inside, and I want to search the 2nd one for a given value. This 2nd list's elements are also lists (id x y).
My function receives a list and and id as arguments, and it has to remove the element from the second list that has that id.
(defun rem (list id)
(dolist (var (nth 1 list))
(cond (equal id (nth 0 var))
(delete var (nth 1 list))))
)
I search the second list of the given list, and when I find the element with id, I delete it. The problem is that I'm always getting NIL. I tried with function remove as well, but the result is the same.
There are a number of issues with this code, and describing them is actually longer than constructing a working example, so I'll show a working version first, and then walk through the code that you provided. Please read through that second section and be sure you understand the issues in the original code, though.
A working version
Based on your description, you want to remove each element of the second element of list whose first element is id. I'm not sure exactly what it is that you want to return, but assuming that it's like list, but with the new second element, you can do something like the following. I emphasized certain words in that paragraph, because they're important for solving this problem. You have an id, and you want to remove things from a sequence that have that id. You can do that with remove (or delete) by calling (remove id sequence :key <key>), where key is a function that extracts a value from the sequence elements to compare against id. You want to remove those elements from (second list) whose first is id. You'd use
(remove id (second list) :key 'first)
to do that. In context, you'd get a function like this:
(defun bex-remove (list id)
(list (first list)
(remove id (second list) :key 'first)
(third list)))
Here's an example:
(bex-remove '((1 2 3 4) ; values don't matter
((id-a x1 y1)
(id-b x2 y2)
(id-a x3 y3)
(id-b x4 y4))
(5 6 7 8)) ; values don't matter
'id-a)
;=> ((1 2 3 4) ((ID-B X2 Y2) (ID-B X4 Y4)) (5 6 7 8))
Issues with your code
There are a few issues:
You shouldn't try to define a function named rem.
You've got syntax errors in your code.
delete doesn't necessarily have the side effects that your code presupposes that it does.
dolist, by default, returns nil.
In more detail:
There's already a function named REM in the Common Lisp package that computes a remainder. Trying to evaluate your definition in SBCL signals an error:
Lock on package COMMON-LISP violated when setting fdefinition of
REM while in package COMMON-LISP-USER.
[Condition of type SYMBOL-PACKAGE-LOCKED-ERROR]
See also:
SBCL Manual, Package Locks [:node]
Common Lisp Hyperspec, 11.1.2.1.2 [:section]
You get a similar error in CLISP (with which you've tagged the question, so I assume it's the implementation that you're using):
[1]> (defun rem (x) x) ; not the same as your definition, but still a function named rem
** - Continuable Error
DEFUN/DEFMACRO(REM): #<PACKAGE COMMON-LISP> is locked
If you continue (by typing 'continue'): Ignore the lock and proceed
The following restarts are also available:
ABORT :R1 Abort main loop
We'll rename your function %rem so that we can continue, and we'll see what happens. When try compile the adjusted definition in SBCL, we get a warnings about undefined variables delete and equal.
; --> IF COND
; ==>
; (IF DELETE
; (PROGN VAR (NTH 1 LIST))
; NIL)
;
; caught WARNING:
; undefined variable: DELETE
; ==>
; (IF EQUAL
; (PROGN ID (NTH 0 VAR))
; (COND (DELETE VAR (NTH 1 LIST))))
;
; caught WARNING:
; undefined variable: EQUAL
;
; compilation unit finished
; Undefined variables:
; DELETE EQUAL
; caught 2 WARNING conditions
In CLISP you'll have to compile before you get similar warnings:
CL-USER> (defun %rem (list id)
(dolist (var (nth 1 list))
(cond (equal id (nth 0 var))
(delete var (nth 1 list))))
)
%REM
CL-USER> (compile '%rem)
WARNING: in %REM : EQUAL is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
WARNING: in %REM : DELETE is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
%REM
2
2
The syntax of cond is (cond (test expr*)*), which means that each test and its associated expressions need to be wrapped in parentheses. Updated to fix that, we now have:
(defun %rem (list id)
(dolist (var (nth 1 list))
(cond
((equal id (nth 0 var))
(delete var (nth 1 list))))))
When we compile that, we still get some warnings in SBCL, but CLISP doesn't generate similar warnings, even during compilation:
; in: DEFUN %REM
; (DELETE VAR (NTH 1 LIST))
;
; caught STYLE-WARNING:
; The return value of DELETE should not be discarded.
;
; caught STYLE-WARNING:
; The return value of DELETE should not be discarded.
;
; compilation unit finished
; caught 2 STYLE-WARNING conditions
What this is telling us is that you really need to save the results from delete. delete can modify a list in arbitrary ways, and yet isn't required to modify anything at all. For instance, in the following code, the value of the variable x isn't modified, although (delete 1 x) does return a list (2 3).
CL-USER> (let ((x (list 1 2 3)))
(delete 1 x) ; could return, e.g, (cdr x)
x)
;=> (1 2 3)
So what you're probably trying to write is:
(defun %rem (list id)
(dolist (var (nth 1 list))
(cond ; or (when (equal id (nth 0 var))
((equal id (nth 0 var)) ; (setf (nth 1 list) ...))
(setf (nth 1 list)
(delete var (nth 1 list)))))))
This code isn't likely to do much that's useful. One, you're modifying (nth 1 list) while you're iterating over it, which is unlikely to have good results. I'm not sure what the code is supposed to do, exactly. Since you're iterating over (nth 1 list), list must have the form
(<first-element> (var1 var2 ...) ...)
and since you take (nth 0 var), then each vari must also be a list, so list has the form
(<first-element> ((<elt10> ...) (<elt20> ...) ...) ...)
Regardless, your dolist will still return nil. The syntax for dolist is
dolist (var list-form [result-form]) declaration* {tag | statement}*
and that optional result-form defaults to nil. I'm not sure exactly what you want to return, but maybe it's list, in which case you'd do
(dolist (var list list)
…)
For instance:
(let ((list (list 1 2 3)))
(dolist (x list) ; return default (nil)
(+ x x)))
;=> NIL
(let ((list (list 1 2 3)))
(dolist (x list (reverse list)) ; return something
(+ x x)))
;=> (3 2 1)
Im really having problems understanding how I can create variable that would act as an accumulator in racket. This is definitely a really stupid question....but racket's documentation is pretty difficult for me to read.
I know I will use some kind of define statement or let statement.
I want to be able to pass a number to a variable or function and it adds the current value with the new value keeps the sum...How would I do this....?? Thank you..
(define (accumulator newvalue) "current=current+newvalue"
something like this..
An accumulator is generally just a function parameter. There are a few chapters in How to Design Programs (online, starting here) that cover accumulators. Have you read them?
For example, the reverse function is implemented using an accumulator that remembers the prefix of the list, reversed:
;; reverse : list -> list
(define (reverse elems0)
;; reverse/accum : list list -> list
(define (reverse/accum elems reversed-prefix)
(cond [(null? elems)
reversed-prefix]
[else
(reverse/accum (cdr elems)
(cons (car elems) reversed-prefix))]))
(reverse/accum elems null))
Note that the scope of the accumulator reversed-prefix is limited to the function. It is updated by calling the function with a new value for that parameter. Different calls to reverse have different accumulators, and reverse remembers nothing from one call to the next.
Perhaps you mean state variable instead. In that case, you define it (or bind it with let or lambda) at the appropriate scope and update it using set!. Here's a global state variable:
;; total : number
(define total 0)
;; add-to-total! : number -> number
(define (add-to-total! n)
(set! total (+ total n))
total)
(add-to-total! 5) ;; => 5
(add-to-total! 31) ;; => 36
Here's a variation that creates local state variables, so you can have multiple counters:
;; make-counter : -> number -> number
(define (make-counter)
(let ([total 0])
(lambda (n)
(set! total (+ total n))
total)))
(define counterA (make-counter))
(define counterB (make-counter))
(counterA 5) ;; => 5
(counterB 10) ;; => 10
(counterA 15) ;; => 20
(counterB 20) ;; => 30
But don't call state variables accumulators; it will confuse people.
Do you mean something like this?
(define (accumulator current newvalue)
(let ((current (+ current newvalue)))
...)
You can close over the accumulator variable:
(define accumulate
(let ((acc 0))
(λ (new-val)
(set! acc (+ acc new-val))
acc)))
(accumulate 10) ;=> 10
(accumulate 4) ;=> 14