Im a noob in Racket, and I am trying to figure out how to print the elements of one list vertically, thus:
(printv '(1 2 3 4))
1
2
3
4
T
I try with if and cond, thus:
(define (delete x lst)
(cond [(member x lst)(append(reverse(rest(member x(reverse lst))))(rest(member x lst)))]
[else "Error"]
))
(define (printv lst)
(cond [(< 0 (length lst)) ((printf "~a ~%" (first lst))(printv (delete (first lst) lst)))]
[else "T"]))
But I got this error in the moment the list becomes empty
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
Help is appreciated
You should use built-in procedures to make your life easier. And why do you want to delete the elements? just iterate over the list. Try this:
(define (printv lst)
(for-each displayln lst)
(displayln "T"))
Just removing the extra parentheses fixes your problem:
(define (printv lst)
(cond [(< 0 (length lst))
(printf "~a ~%" (first lst))
(printv (delete (first lst) lst))]
[else "T"]))
Some hints:
Doing length at each iteration makes makes your function exponential time. Eg. doubling the list to display squares the time it takes. A beter approach to check if a list is empty is using (empty? lst)
How you get the rest of the list using delete is perhaps the most complicated I've seen. Since you know you are removing the first element you can just replace it with (rest lst).
Just printing with a linefeed has a function: displayln
All combined:
(define (printv lst)
(cond [(empty? lst) "T"]
[else
(displayln (first lst))
(printv (rest lst))]))
Pure Scheme version:
(define (printv lst)
(cond [(null? lst) "T"]
[else
(display (car lst))
(newline)
(printv (cdr lst))]))
Related
I am trying to define the rule 3 of "MIU System" of "Gödel, Escher, Bach" (Douglas Hofstadter), which says:
Replace any III with a U
Example:
MIIIIU → MUIU and MIIIIU → MIUU
Main code:
(define (rule-tree lst)
(if (<= 3 (counter lst #\I))
(append (delete #\I lst) (list #\U))
(append lst empty)))
(define (delete x lst)
(cond [(empty? lst) lst]
[(eq? (first lst) x) (delete x (rest lst))]
[else (append (list (first lst)) (delete x (rest lst)))]))
(define (counter lst target)
(if (empty? lst)
0
(+ (counter (rest lst) target)
(let ((x (first lst)))
(if (list? x)
(counter x target)
(if (eqv? x target) 1 0))))))
With this expression there is no problem:
>(rule-tree '(#\M #\I #\I #\I))
'(#\M #\U)
But I don't know how to determine the position that the "U" should take when finding the 3 "I".
Any suggestion will be very helpful :)
Here is an alternative recursive version, where repl2 encodes the information “we have just encountered one #\I”, while repl3 encodes the information “we have just encountered two #\I”:
(define (repl lst)
(cond ((empty? lst) lst)
((eqv? (first lst) #\I) (repl2 (rest lst)))
(else (cons (first lst) (repl (rest lst))))))
(define (repl2 lst)
(cond ((empty? lst) (list #\I))
((eqv? (first lst) #\I) (repl3 (rest lst)))
(else (cons #\I (cons (first lst) (repl (rest lst)))))))
(define (repl3 lst)
(cond ((empty? lst) (list #\I #\I))
((eqv? (first lst) #\I) (cons #\U (repl (rest lst))))
(else (cons #\I (cons #\I (cons (first lst) (repl (rest lst))))))))
Of course this solution is some kind of hack and cannot scale to a greater number of repetitions. But looking at the structure of this solution and simply generalizing the three functions we can produce a general solution:
(define (repl lst n from to)
(define (helper lst k)
(cond ((empty? lst) (repeat from (- n k)))
((eqv? (first lst) from)
(if (= k 1)
(cons to (helper (rest lst) n))
(helper (rest lst) (- k 1))))
(else (append (repeat from (- n k))
(cons (first lst) (helper (rest lst) n))))))
(define (repeat x n)
(if (= n 0)
'()
(cons x (repeat x (- n 1)))))
We define a function repl that takes a list, the number of copies to replace (n), the element to replace (from) and the element that must be substituted (to). Then we define a helper function to do all the work, and that has as parameters the list to be processed and the number of copies that must be still found (k).
Each time the function encounters a copy it checks if we have finished with the number of copies and substitutes the element, restarting its work, otherwise it decrements the number of copies to find and continues.
If it founds an element different from from it recreates the list with the elements “consumed” until this point (maybe 0) with repeat and then continues its work.
Note that the previous version of the helper function had an error in the final case, when lst is null. Instead of returning simply the empty list, we must return the possibly skipped from elements.
Essentially I am trying to remove the first and last element in a list. I have currently been able to determine how to remove the last element in the list but i'm struggling how to remove the first element in the list with the last element in the list.
Here is the code I have so far. Is there a way I can modify my code so I am able to include removing the first element in the list.
(define (rid L)
(cond
[(empty? L) '()]
[(empty? (rest L)) '()]
[(cons (first L) (rid (rest L)))]))
Here is the results I am expecting with my code
(check-expect (rid (list 1 2 3 4 5)) (list 2 3 4))
(check-expect (rid (list "cat" "dog" "giraffe")) (list "dog"))
Just for fun - In Racket you can solve this problem without using explicit recursion. Always try to use existing procedures to solve your problems:
(define (rid L)
(rest (drop-right L 1)))
(rid '(1 2 3 4 5 6))
=> '(2 3 4 5)
With many recursive algorithms, it is not uncommon to actually implement them with two procedures: one to set up the initial conditions and a second one to do the actual recursion, like so:
(define (rid-inner li)
(cond
[(empty? li) '()]
[(empty? (rest li)) '()]
[(cons (first li) (rid-inner (rest li)))]))
(define (rid1 L)
(define r (if (empty? L) '() (rest L)))
(rid-inner r))
With (define r (if (empty? L) '() (rest L))) we strip off the first element of the list; no recursion is actually necessary for this step. Then we define the same procedure you had before with a different name and call it with our new list that already has the first element stripped off. If you want the first element stripped off, just strip off the first element; don't overthink it :) .
In a language like Racket that allows closures and nested procedures, you don't actually even need to define both procedures at the top "global" module scope; just define your recursive procedure inside your initial procedure and call it from there. Example:
(define (rid2 L)
(define r (if (empty? L) '() (rest L)))
(define (rid-inner li)
(cond
[(empty? li) '()]
[(empty? (rest li)) '()]
[(cons (first li) (rid-inner (rest li)))]))
(rid-inner r))
Another, somewhat cleaner, way to do the above is to use a named let, which allows us to simultaneously set up our initial conditions, create a named procedure, and then call that procedure immediately from within itself. We do that like so:
(define (rid3 L)
(let rid-inner ([li (if (empty? L) '() (rest L))])
(cond
[(empty? li) '()]
[(empty? (rest li)) '()]
[(cons (first li) (rid-inner (rest li)))])))
To those unfamiliar with Racket, Scheme, or a related Lisp, the named let in rid3 may be more cryptic at first since it is really doing two or three things at once. You can find the docs for it here. Don't be fooled though, it works exactly the same as rid2. Named let exists precisely because this pattern is so common.
(define (rid L)
(if (< (length L) 3)
'()
(reverse (rest (reverse (rest L))))))
;;; recursion inside and more general
;;; you can setting which position 0~n-1 you want to remove
(define (rid-v2 L)
(local ((define remove-index-list (list 0 (- (length L) 1)))
(define (auxf L k)
(cond
[(empty? L) '()]
[(memq k remove-index-list) (auxf (rest L) (+ k 1))]
[else (cons (first L)
(auxf (rest L) (+ k 1)))])))
(auxf L 0)))
tail call recursive version
(define (rid lst (acc '()))
(cond ((empty? lst) acc)
((empty? (cdr lst)) (cdr (reverse acc)))
(else (rid (cdr lst) (cons (car lst) acc)))))
with elementar lisp (not the most efficient)
(define (rid1 lst)
(cdr (reverse (cdr (reverse lst))))
I have created the following expression which I would like to graph parabolas based on the last two elements in a list. It looks like this:
#lang racket
(require plot)
(define list-sqr-graph
(lambda (lst)
(cond
[(null? lst) (plot (function sqr 0 0))]
[(<= (car lst) 0) (list-sqr-graph (cdr lst))]
[(not (equal? (length lst) 2)) (list-sqr-graph (cdr lst))]
[else (plot (function sqr (car lst) (cdr lst)))])))
The first conditional statement checks if the list is null, and returns a blank graph if true. The second conditional statement skips past numbers from the list which are less than or equal to 0. The third conditional statement checks if the length of the list is equal to 2, and goes down the list until the length is equal to 2.
The else statement is where I get trouble when running an expression such as:
(list-sqr-graph '(1 2 3))
Which will result in an error reading:
function: contract violation
expected: (or/c rational? #f)
given: '(4)
From this error I am led to believe that the first element of the list is being read as a number, but that the second element is having trouble. Why is this?
Thank you in advance!
You are passing a list when ploting. Remember cdr returns a list and not an element (like car does).
You want to use cadr.
#lang racket
(require plot)
(define list-sqr-graph
(lambda (lst)
(cond
[(null? lst) (plot (function sqr 0 0))]
[(<= (car lst) 0) (list-sqr-graph (cdr lst))]
[(not (equal? (length lst) 2)) (list-sqr-graph (cdr lst))]
[else (plot (function sqr (car lst) (cadr lst)))]))) <- HERE
Let's say we have this list '( (4 (1 2)) (5 (5 5)) (7 (3 1)) (1 (2 3)))
I am trying to write smth in Scheme in order to get the second element for every element in the list.. So the result will look like '( (1 2) (5 5) (3 1) (2 3))
I have this code so far..
(define (second list1)
(if (null? (cdr list1))
(cdr (car list1))
((cdr (car list1))(second (cdr list1)))))
Here's a straightforward solution:
(define (seconds lst)
(map cadr lst))
In general, when you want to transform every element of a list, map is the way to go.
All you need to do is map the built-in function second onto the list lst:
(map second lst)
Your error is that you lack an operator, perhaps cons. If you look at the consequent:
((cdr (car list1))(second (cdr list1)))
So Scheme expects (cdr (car list)) to be a procedure since it's in operator position in the form, but since it isn't you get an error. In addition (cdr (car x)) == cdar wont take the second element in every element but the tail of each element. cadar is what you're lookig for.
(define (second list1)00+
(if (null? (cdr list1))
(cons (cadar list1) '())
(cons (cadar list1) (second (cdr list1)))))
It will fail for the empty list. To fix this you let the consequemt take care of every element and the base case only to stop:
(define (second list1)
(if (null? list1)
'()
(cons (cadar list1) (second (cdr list1)))))
The result for a list will be the same. There is a procedure called map. It supports several list arguments, but the implementation for one is:
(define (map fun lst)
(if (null? lst)
'()
(cons (fun (car lst)) (map fun (cdr lst)))))
Looks familiar? Both make a list based on each element, but map is generic. Thus we should try to make (fun (car lst)) do the same as (cadar lst).
(define (second lst)
(map cadr lst)) ; (cadr (car x)) == (cadar x)
There you have it. Chris beat me to it, but I'd like to comment one of the other answers that uses the abbreviation second. It's defined in racket/base and the library SRFI-1, but it's not mentioned in the last Scheme reports. I.e. some implementations might require an extra library to be imported for it to work.
I'd like to create a Scheme function that yields true if it is passed a list that is composed entirely of identical elements. Such a list would be '(1 1 1 1). It would yield false with something like '(1 2 1 1).
This is what I have so far:
(define (list-equal? lst)
(define tmp (car lst))
(for-each (lambda (x)
(equal? x tmp))
lst)
)
Clearly this is incorrect, and I'm new to this. I guess I'm unable to express the step where I'm supposed to return #t or #f.
Thanks in advance!
EDIT:
I fiddled a bit and found a solution that seems to work very well, and with a minimal amount of code:
(define (list-equal? lst)
(andmap (lambda (x)
(equal? x (car lst)))
lst))
Thanks again for the help everyone.
Minimal amount of code, if you don't care that it only works for numbers:
(define (list-equel? lst)
(apply = lst))
Examples:
> (list-equel? '(1 1 2 1))
#f
> (list-equel? '(1 1 1 1))
#t
> (list-equel? '(1))
#t
The andmap solution is nice, but if andmap is not available, you can use this. It uses basic operations (and, or, null check, equality check) and handles empty lists and one element lists. Similar to Sean's implementation, but no helper definition is necessary.
(define (list-equal? args)
(or (or (null? args)
(null? (cdr args)))
(and (eq? (car args) (cadr args))
(list-equal? (cdr args)))))
Try something like this:
(define (list-equal? lst)
(define (helper el lst)
(or (null? lst)
(and (eq? el (car lst))
(helper (car lst) (cdr lst)))))
(or (null? lst)
(helper (car lst) (cdr lst))))
This might not be the cleanest implementation, but I think it will correctly handle the cases of empty lists and one-element lists.
In R6RS there's the for-all function, which takes a predicate and a list, and returns #t if the predicate returns true for all elements in the list and #f otherwise, which is exactly what you need here.
So if you're using R6RS (or any other scheme dialect that has the for-all function), you can just replace for-each with for-all in your code and it will work.
(define (list-equal? lst)
(if (= (cdr lst) null)
true
(and (equal? (car lst) (cadr lst))
(list-equal? (cdr lst)))))
Something like this should work:
(define (list-equal? lst)
(cond ((< (length lst) 2) #t)
(#t (and (equal? (car lst) (cadr lst))
(list-equal? (cdr lst))))))
The other answers in this thread all seem too complicated (I read through them all), so here's my take on it:
(define (all-equal? lst)
(define item (car lst))
(let next ((lst (cdr lst)))
(cond ((null? lst) #t)
((equal? item (car lst)) (next (cdr lst)))
(else #f))))
(It does not work with an empty list, by design. It's easy to add a (if (null? lst) #t ...) if necessary.)
A short, concise solution:
#lang racket
(define (all-equal? lst)
(for/and
([i (in-permutations lst)])
(equal? (first i) (second i))))
; TEST CASES
(require rackunit)
(check-false (all-equal? '(1 2 3)))
(check-true (all-equal? '(1 1 1)))
(check-true (all-equal? '()))
Note that this uses racket, so this may not work with your scheme implementation.
Yet another solution:
(define (all-same ls)
(cond
((or (null? ls)
(null? (cdr ls))) #t)
(else (and (equal? (car ls) (next ls))
(all-same (cdr ls)))))))
(define (next ls)
(cond
((or (null? ls)
(null? (cdr ls))) '())
(else (cadr ls)))))
For is bad in these languages. Try
(define list-equal?
(lambda (lst)
(if (= lst null)
(true)
(foldr = (car lst) (cdr lst))
)))