Well, I am trying to add two elements to become a list, and from the video of Prof. Colleen Lewis at minute 4 and 53 secs, and from the official racket site I saw that the best practice is to use "cons".
When I did:
(cons (Listof Number) (Listof (Listof Number)))
It worked perfectly well but it gave me a mirror to what I am suppose to get. Therefore I tried:
(cons (Listof (Listof Number)) (Listof Number) )
This resulted in:
Type Checker: Polymorphic function `cons' could not be applied to
arguments:
Argument 1:
Expected: a
Given: (Listof (Listof Real))
Argument 2:
Expected: (Listof a)
Given: (Listof Real)
Result type: (Listof a)
Expected result: (Listof (Listof Real))
in: (cons acc (get-min&max-from-mixed-list (first lol)))
This is weird, since the official site says that:
The cons function actually accepts any two values, not just a list
for the second argument.
Here is my actual code:
(: min&max-lists (-> (Listof (Listof Any)) (Listof (Listof Number))))
(: tail-min&max-lists (-> (Listof (Listof Any)) (Listof (Listof Number)) (Listof (Listof Number))))
(: get-min&max-from-mixed-list (-> (Listof Any) (Listof Number)))
(define (min&max-lists lol)
(tail-min&max-lists lol '()))
(define (tail-min&max-lists lol acc)
(if (null? lol)
acc
(tail-min&max-lists (rest lol) (cons acc (get-min&max-from-mixed-list (first lol))))))
(define (get-min&max-from-mixed-list mixedList)
(if (null? (sublist-numbers mixedList))
'()
(min&maxRec (sublist-numbers mixedList) (first (sublist-numbers mixedList)) (first (sublist-numbers mixedList)))))
(test (min&max-lists '((any "Benny" 10 OP 8) (any "Benny" OP (2 3)))) => '((8 10) ()))
Here is the code for all kinds of functions that my code uses. These work fine, so there should be no reason to check them:
#lang pl
(require rackunit)
(require racket/trace)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Question 1
(: min&maxRec (-> (Listof Number) Number Number (Listof Number)))
(: min&max (-> Number Number Number Number Number (Listof Number) ))
(define (min&max number1 number2 number3 number4 number5) ; gets all numbers and sends to the min&max recursive part
(min&maxRec (list number2 number3 number4 number5) number1 number1)) ; made all numbers to become a list and has max and min numbers
(define (min&maxRec myList max min)
;; logic: 1) if finished list give back result 2) else check if head of list max or min and recall the function with a shorter list and the new max or min
(if (null? myList)
;return the min and max from myList when finished looking at all numbers
(list min max)
(if (> (first myList) max); is the head max?
(min&maxRec (rest myList) (first myList) min)
(if (< (first myList) min) ; is the head min?
(min&maxRec (rest myList) max (first myList) )
(min&maxRec (rest myList) max min)))))
(test (min&max 2 3 2 7 1) => '(1 7))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Question 2 a
(: sublist-numbers (-> (Listof Any) (Listof Number)))
(: tail-sublist-numbers (-> (Listof Any) (Listof Number) (Listof Number)))
;;This func calls a diff func since the tail-recursion needs an accumelator.
(define (sublist-numbers myList)
(tail-sublist-numbers myList `()))
;;this uses tail-recursion (all calculations are dont before the recursion and are sent with an accumelator)
(define (tail-sublist-numbers myList acc)
(if (null? myList)
acc ; if finished all vars in list
(if (number? (first myList))
(tail-sublist-numbers (rest myList) (cons (first myList) acc)) ; if the head of list is a number add it to acc, and continue working on the rest of the list
(tail-sublist-numbers (rest myList) acc)))) ; else throw this var and work on rest of list
Note that when you link to cons in #lang racket it is not the same as cons in other languages, like #lang pl. Same names functions in different languages can be the same but often are they different. Eg. cons and friends in #!r6rs are mapped from mcons and friends in #lang racket
I have no idea what #lang pl is but it seems like it is typed in some way. I assume that when you say you do:
(cons (Listof Number) (Listof (Listof Number)))
You mean that you do:
(cons a b)
Where a is of type (Listof Number) and b is of type (Listof (Listof Number)). I notice that the type of the second is Listof whatever was type on the first. In your trial the types don't have that relationship but the other way around. It's likely that you have switched the arguments and that the correct code for the acc is:
(cons (get-min&max-from-mixed-list (first lol)) acc)
I assume type specification of cons might require the second list to be lists of the same type as the type of the first argument. For the untyped languages like Scheme and #lang racket you can have any type in the two arguments.
#lang racket
(cons 3 #f) ; ==> (3 . #f)
Related
How can I sort and merge two lists based on the operator in Racket-Plait? > ascending, < descending order. This is what I have so far, but I do not have any idea what to do next.
(define (merge [op : (Number Number -> Boolean)]
[int-list1 : (Listof Number)]
[int-list2 : (Listof Number)]) : (Listof Number)
(cond
[(equal? op <) "something"]
[(equal? op >) "do something"]))
(test (merge < '(1 4 6) '(2 5 8))
'(1 2 4 5 6 8))
I think you're assuming that this is more complicated than it is.
You're not supposed to do different things depending on the value of op - op is the ordering predicate you should use for merging and the predicate that the input lists are ordered by.
(In contrast to many other languages, symbols like < or > are not "special" in any way, they are identifiers just like less, or greater, or op)
Here is a skeleton special case to get you started; the interesting bits are left as an exercise:
(define (merge [l1 : (Listof Number)]
[l2 : (Listof Number)]) : (Listof Number)
(cond [(empty? l1) l2] ;; If either list is empty,
[(empty? l2) l1] ;; the result is the other list.
[(< (first l1) (first l2)) ... fill this in ...]
[else ... fill this in ...]))
then, notice that this is equivalent to the code above:
(define op <)
(define (merge [l1 : (Listof Number)]
[l2 : (Listof Number)]) : (Listof Number)
(cond [(empty? l1) l2] ;; If either list is empty,
[(empty? l2) l1] ;; the result is the other list.
[(op (first l1) (first l2)) ... fill this in ...]
[else ... fill this in ...]))
and then you pass op as a parameter instead, and you're done.
Working on this program that's supposed to take a vector of integers as input and return the one with the longest integer. Example (vector 20 738 5942 125) and would return 4 as its the longest one. I'm pretty sure I have most of this done the only issue I have is in the conditional as I have to call an outside function (count-integers), this is what I have so far:
(require while)
(define (empty-VINT? low high) (> low high))
(define (count-integers n)
(cond [(< n 10) 1]
(else(+ 1 (count-integers [/ n 10])))))
(define (count-digits V)
(local [
(define x (void))
(define accum (void))
(define largest 0)]
(begin
(set! x (vector-length V))
(set! accum 0)
(while (< accum (vector-length V))
(cond [(empty-VINT? x accum) accum]
[(> (count-integers (vector-ref V accum) largest)
(add1 x) accum(vector-ref V accum))]
[else add1 accum])))))
Right now when its run, I get this message: cond: expected a clause with a question and an answer, but found a clause with only one part. Any suggestions would be great, thanks
First of all, it's not clear what do you want to return. 4 isn't the longest integer (that's 5942), 4 is a maximal digit count among integers in given vector.
Secondly, your code isn't idiomatic and without your comment, it's very hard to say what's going on. Programming in functional languages requies functional way of thinking. Forget about while, set!, void, local and nested define and instead spend some time learning about apply, map, filter and foldl.
I would solve this problem like this:
(define (digits number)
(string-length (number->string number)))
(define (max-digit-count vec)
(apply max (map digits (vector->list vec))))
(max-digit-count (vector 20 738 5942 125))
=> 4
From comments:
Design and implement a function to find the number of digits in the longest integer in a (vectorof integer) ...
use ... while loops
So a plan (design) might be:
count-digits: integer -> natural
max-digit-count: (vectorof integer) -> natural
..something while something max count-digits something ???
Implementing count-digits seems straightforward (but
integers can be negative, and in Racket (integer? 123.000) is true).
#lang racket
(define (count-digits int) ;; Integer -> Natural
;; produce count of digits in int
(string-length (number->string (abs (exact-truncate int)))))
As #Gwang-Jin Kim mentions, while could be defined:
(define-syntax-rule (while condition body ...)
;; From: https://stackoverflow.com/questions/10968212/while-loop-macro-in-drracket
(let loop ()
(when condition
body ...
(loop))))
and then one could use it:
(define (max-digit-count vec) ;; VectorOfInteger -> Natural
;; produce maximum of digit counts of vec elements
(define vx 0)
(define acc 0)
(while (< vx (vector-length vec))
(set! acc (max accum (count-digits (vector-ref vec vx))))
(set! vx (add1 vx)))
acc)
(max-digit-count (vector 20 -738.00 5942 125)) ;=> 4
One of the problems with while is that it can't produce a value (where would it come
from if the condition is false on entry?)
If one "enhanced" while a bit:
(define-syntax-rule (while< x-id limit a-id a-init update)
;; "while loop" incrementing x-id from 0 to limit-1, updating a-id
(let loop ([x-id 0] [a-id a-init])
(if (< x-id limit)
(loop (add1 x-id) update)
a-id)))
max-digit-count could be neater:
(define (max-digit-count vec) ;; VectorOfInteger -> Natural
;; produce maximum of digit counts of vec elements
(while< vx (vector-length vec)
acc 0 (max acc (count-digits (vector-ref vec vx)))))
#MartinPuda's answer is quite good.
I would have defined:
(define (digits n (acc 0))
(if (< n 1)
acc
(digits (/ n 10) (+ acc 1))))
(define (max-digits lst)
(digits (car (sort lst >))))
To apply it:
(max-digits (vector->list (vector 20 738 5942 125)))
Why you should not use while
Using while would force you to mutate variable values. It is much more "natural" for lisp languages to follow the functional style (recursive functions instead of while loops or other loops) rather than the imperative style with mutation of variables.
That is why while is not in the lisp languages.
But if you want to use it:
(define-syntax-rule (while condition body ...)
;; From: https://stackoverflow.com/questions/10968212/while-loop-macro-in-drracket
(let loop ()
(when condition
body ...
(loop))))
(define (digits n (acc 0))
(cond ((< n 1) acc)
(else (digits (/ n 10) (+ acc 1)))))
(define (max-digits lst)
(let ((max-digit 0))
(while (not (null? lst))
(let ((digit (digits (car lst))))
(when (< max-digit digit)
(set! max-digit digit))
(set! lst (cdr lst))))
max-digit))
Then you can try:
> (max-digits (vector->list v))
4
> (max-digits '(1111 123456 2345 34))
6
Prefer let over define
Why? Because if you use let, you can control the scope of the to-be-mutated variable very precisely. You can define in your definition, from where on your variable canNOT have any effect on your code (since its scope ended at some point). While with define you don't have this fine-grained control. (Or this control is implicit not explicite like with let). You could delete/unbind the variable explicitely but that is rarely done in real life.
Therefore, in Lisp, for variable declarations use whenever possible let, especially whenever you deal with mutated variables.
All imperative = declarations should be in Lisp languages let expressions!
You can use function arguments instead of let-definitions, because they are anyway implemented using lets
Just you save syntactically some lines - and the fewer lines you occupy the cleaner the code.
#lang racket
(define (digits n)
(string-length (number->string n)))
(define (max-digit a b)
(if (< (digits a) (digits b)) b a))
(define (max-digits lst (res ""))
(while (not (null? lst))
(set! res (max-digit res (car lst)))
(set! lst (cdr lst)))
(digits res))
I am trying to write a function that take a list and iterates over each element in the list if the number is even I want that number to be added to the previous number in the list.
I was thinking an accumulator will count up from 0 with each iteration giving a position for each element in the list.
If the number in the list is even I want to add that number to the previous number in the list.
Hence why I am trying to use the accumulator as an index for list-ref. I don't know how to write it to get the accumulator value for the previous iteration (+ i (list-ref a-list(- acc 1)))?
(define loopl (lambda (l)
(for/fold
([acc 0])([i l])
(cond
[(even? i)(+ i (list-ref (- acc 1) l))]
enter image description here
The question is not quite clear about the value to be returned by this function:
this answer assumes that it is a total of even elements together with their previous elements.
The function is developed using the
HtDF (How to Design Functions)
design method with a BSL (Beginning Student language) in DrRacket.
Start with a stub, incorporating signature and purpose, and a minimal "check-expect" example:
(Note: layout differs slightly from HtDF conventions)
(define (sum-evens-with-prev xs) ;; (Listof Integer) -> Integer ; *stub define* ;; *signature*
;; produce total of each even x with its previous element ; *purpose statement*
0) ; *stub body* (a valid result)
(check-expect (sum-evens-with-prev '()) 0) ; *minimal example*
This can be run in DrRacket:
Welcome to DrRacket, version 8.4 [cs].
Language: Beginning Student with List Abbreviations
The test passed!
>
The next steps in HtDF are template and inventory. For a function with one list
argument the "natural recursion" list template is likely to be appropriate;
(define (fn xs) ;; (Listof X) -> Y ; *template*
(cond ;
[(empty? xs) ... ] #|base case|# ;; Y ;
[else (... #|something|# ;; X Y -> Y ;
(first xs) (fn (rest xs))) ])) ;
With this template the function and the next tests become:
(define (sum-evens-with-prev xs) ;; (Listof Number) -> Number
;; produce total of each even x with its previous element (prev of first is 0)
(cond
[(empty? xs) 0 ] #|base case: from minimal example|#
[else (error "with arguments: " #|something: ?|#
(first xs) (sum-evens-with-prev (rest xs))) ]))
(check-expect (sum-evens-with-prev '(1)) 0)
(check-expect (sum-evens-with-prev '(2)) 2)
These tests fail, but the error messages and purpose statement suggest what is required:
the (... #|something|# from the template has to choose whether to add (first xs):
(define (sum-evens-with-prev xs) ;; (Listof Integer) -> Integer
;; produce total of each even x with its previous element (prev of first is 0)
(cond
[(empty? xs) 0 ]
[else
(if (even? (first xs))
(+ (first xs) (sum-evens-with-prev (rest xs)))
(sum-evens-with-prev (rest xs))) ]))
Now all 3 tests pass! Time for more check-expects (note: careful introduction of
check-expects is a way of clarifying ones understanding of the requirements, and
points one to the code to be added):
(check-expect (sum-evens-with-prev '(1 1)) 0)
(check-expect (sum-evens-with-prev '(1 2)) 3)
Ran 5 tests.
1 of the 5 tests failed.
Check failures:
Actual value 2 differs from 3, the expected value.
sum-evens-with-prev needs the prev value to include in the even? case:
make it available by introducing it as an argument (renaming the function), add
the appropriate arguments to the recursive calls, the function now just calls
sum-evens-and-prev:
(define (sum-evens-and-prev xs prev) ;; (Listof Integer) Integer -> Integer
;; produce total of each even x and prev
(cond
[(empty? xs) 0 ]
[else
(if (even? (first xs))
(+ prev (first xs) (sum-evens-and-prev (rest xs) (first xs)))
(sum-evens-and-prev (rest xs) (first xs))) ]))
(define (sum-evens-with-prev xs) ;; (Listof Integer) -> Integer
;; produce total of each even x with its previous element (prev of first is 0)
(sum-evens-and-prev xs 0))
(just add some more tests, and all is well :)
(check-expect (sum-evens-with-prev '(0 2)) 2)
(check-expect (sum-evens-with-prev '(2 1)) 2)
(check-expect (sum-evens-with-prev '(1 3)) 0)
(check-expect (sum-evens-with-prev '(2 2)) 6)
(check-expect (sum-evens-with-prev '(1 2 3 4)) 10)
(check-expect (sum-evens-with-prev '(1 2 3 3 5 6 6)) 26)
Welcome to DrRacket, version 8.4 [cs].
Language: Beginning Student with List Abbreviations.
All 11 tests passed!
>
The (for/fold) form requires a (values) clause, and it is in that which you would put the conditional form.
Assuming you want only the new list as the return value, you would also want a #:result clause following the iteration variables.
(define loopl
(lambda (l)
(for/fold
([index 0]
[acc '()]
#:result acc)
([i l])
(values [+ index 1]
[append acc
(if (and (> index 0)
(even? i))
(list (+ i (list-ref l (- index 1))))
(list i))]))))
This should give the correct answer.
You almost never want to repeatedly call list-ref in a loop: that makes for horrible performance. Remember that (list-ref l i) takes time proportional to i: in your case you're going to be calling list-ref with the index being, potentially 0, 1, ..., and that going to result in quadratic performance, which is bad.
Instead there's a neat trick if you want to iterate over elements of a list offset by a fixed amount (here 1): iterate over two lists: the list itself and its tail.
In addition you need to check that the first element of the list is not even (because there is no previous element in that case, so this is an error).
Finally I'm not entirely sure what you wanted to return from the function: I'm assuming it's the sum.
(define (accum-even-previouses l)
(unless (not (even? (first l)))
;; if the first elt is even this is an error
(error 'accum-even-previouses "even first elt"))
(for/fold ([accum 0])
([this (in-list (rest l))]
[previous (in-list l)])
(+ accum (if (even? this)
(+ this previous)
0))))
I need to create a recursive method in LISP that takes the numbers in a list and finds the sum. Anything in the list that is not a number is skipped (For example, if the list contains "Cheese 12 Dog 8 Shoe 5", the output would be 25).
Right now my code finds the sum, but throws an error if there is anything in the list that is not a number. What can be changed to fix that?
(defun adder (lis)
(cond
((null lis) 0)
(t (eval (cons '+ lis)) )
)
)
This would do:
(defun adder (lis)
(if (null lis)
0
(let ((c (car lis)))
(if (numberp c)
(+ c (adder (cdr lis)))
(adder (cdr lis))))))
Your version is not recursive (you don't call adder inside of adder), maybe you meant something like this (which is non-recursive)?
(defun adder (lis)
(apply '+ (remove-if-not 'numberp lis)))
Using apply on lists that can be long is a bit dangerous. If the list is longer than call-arguments-limit, then (apply '+ list) won't work. Now, call-arguments-limit is typically pretty big in modern Lisps, but it's allowed to be as small as 50. For more information about this, see:
Common lisp: How many argument can a function take? (this answer uses (reduce '+ …))
In Lisp, how many inputs can the + function actually have?
I think your best bet would be to use reduce '+ list with a key function that takes each number to itself and each non-number to 0. (This key function is what abiessu mentioned in a comment.)
(reduce '+ list :key (lambda (x) (if (numberp x) x 0)))
CL-USER> (let ((list '(cheese 12 dog 8 shoe 5)))
(reduce '+ list :key (lambda (x) (if (numberp x) x 0))))
25
CL-USER> (let ((list '()))
(reduce '+ list :key (lambda (x) (if (numberp x) x 0))))
0
Instead of using a more complex key function, you could also use (remove-if-not 'numberp list) to get rid of the non-numbers (or (remove-if (complement 'numberp) list)):
CL-USER> (let ((list '(cheese 12 dog 8 shoe 5)))
(reduce '+ (remove-if-not 'numberp list)))
25
CL-USER> (let ((list '()))
(reduce '+ (remove-if-not 'numberp list)))
0
I like creating functions which take an unlimited number of arguments, and being able to deal with them as a list. It's been useful to me when creating binary trees & I'm using it for a variation on the nearest-neighbor algorithm right now. My method, however, is really horrible: since I can't think of a way to iterate over an improper list (which may well be improper & degenerate), I tried using various list functions to force the improper list into list form.
This is my best attempt in a simple function to determine difference between map-nodes (works, just not sure why it works):
(define distance-between
(lambda xs
(let ([input-list (list* xs null)])
(letrec
([f (lambda (xs acc)
(if (null? (cdr xs))
acc
(f (cdr xs)
(+ (abs (- (map-node-x (car xs))
(map-node-x (cadr xs))))
(abs (- (map-node-y (car xs))
(map-node-y (cadr xs))))
acc))))])
(f (car input-list) 0)))))
As you can see, it's an ugly solution and involves some of what seems like magic to me - why is the improper list coerced into list form when I include it in a list*? (note: this sentence is misleading, this does not occur).
I'd rather have a pretty solution and no magic. Can anyone help?
For example a typical input would be:
(distance-between (map-node 1 2) (map-node 2 3) (map-node 3 4))
with the expected result:
4
(a distance of 2 between map-node (a) and m-n (b), plus a distance of 2 between map-node (b) and map-node (c)).
Alternatively one might simply input:
(distance-between (map-node 1 2) (map-node 2 2))
and get an answer of:
1
If I attempted this on the raw input, without my (let ([input-list...])...) statement, it would cause an error as (? not actually sure why given response to this question).
The function works as expected.
There's nothing improper about the list received as a variadic argument list (meaning: variable number of arguments). For example:
(define test-list
(lambda xs
(length xs))) ; xs is a normal list, use it like any other list
(test-list 1 2 3 4)
=> 4
In the above example, the xs parameter is a normal, plain, vanilla list, there's nothing improper about it. You can iterate over it as you would over any other list. There's no need to car it, it's already a list! Also, notice that the same function can be written like this:
(define (test-list . xs)
(length xs)) ; xs is a normal list, use it like any other list
Just for reference: an improper list is one that does not end with the null list. For example: '(1 2 3 . 4). Again, that's not how a variadic argument list looks.
I also don't understand how your variadic argument list could be improper.
But to answer your original question (how to iterate over a possibly improper list, somewhat more elegantly), here is one way using match:
#lang racket
(define (properly-sum-improper-list xs)
(let loop ([acc 0]
[xs xs])
(match xs
[(list) acc]
[(cons x more) (loop (+ acc x) more)]
[x (+ acc x)]))) ;last item of improper list
(require rackunit)
(check-equal? (properly-sum-improper-list '(1 2 3 4)) 10)
(check-equal? (properly-sum-improper-list '(1 2 3 . 4)) 10)
However needing to do this, at all, is probably an indication you want to fix or change something else.
Your list is not improper. When your argument is not a pair, like (lambda xs body ...) or (define (fun . xs) body ...) all your arguments gets slurped into a list. Eg.. (fun 1 2 3) would make xs '(1 2 3). Doing (list* '(1 2 3) '()) makes '((1 2 3) which you undo right away by calling your loop with car which makes it '(1 2 3) again.
Other than that your procedure works as intended. You might clean up your procedure a little, but since there is no list comprehensions that glides over a list folding over the two next elements it won't become much smaller. Below is basically the same code, but abstracting out the procedure that does the work (which if existed a foldl-pair you could have used) and with a named let as a iterator loop (which is syntactic sugar for a letrec+call).
(define (distance-between e1 . lst)
(define (add-diff-acc e1 e2 acc)
(+ (abs (- (map-node-x e1) (map-node-x e2)))
(abs (- (map-node-y e1) (map-node-y e2)))
acc))
(let iterate ((e1 e1) (lst lst) (acc 0))
(if (pair? lst)
(let ((e2 (car lst)))
(iterate e2 (cdr lst) (add-diff-acc e1 e2 acc)))
acc)))
EDIT: About syntax sugar, named let and letrec.
(let ((x 10) (y 19))
body)
is syntactic sugar for a anonymous procedure call
((lambda (x y)
body)
10 19)
A named let is just giving that procedure a name, though as if by letrec, making a recursive binding. you call it with the name you give and the arguments will be what you supply instead of the initial value in the let. I'm used to them and prefer them today. It might take some time to get used to though.
Most of the code we write is syntactic sugar for some lower level stuff. The macros are nested so that your letrec form could get reduced down lambdas eventually. The whole procedure without syntactic sugar would look like this:
(define distance-between
(lambda (e1 . lst)
((lambda (add-diff-acc)
((lambda (iterate e1 lst acc) ; emulate Y to substitute `letrec`
(iterate iterate e1 lst acc))
(lambda (iterate e1 lst acc)
(if (pair? lst)
((lambda (e2)
(iterate iterate e2 (cdr lst) (add-diff-acc e1 e2 acc)))
(car lst))
acc))
e1 lst 0))
(lambda (e1 e2 acc)
(+ (abs (- (map-node-x e1) (map-node-x e2)))
(abs (- (map-node-y e1) (map-node-y e2)))
acc)))))