I have a list called hand and another one called deck, the main goal here is to take the first card (or element ) in the list deck and put it in the list hand when i call the fnction draw...
> (draw hand deck)
(2 C)
> (draw hand deck)
(2 C) (3 H)
> (draw hand deck)
(2 C) (3 H) (K D)
but everytime i call it the hand never changes value...
I'm clueless is there a way like in O-Object to change the content of hand permenantly?
and i initialy define hand empty because the player has no card to start.
(define hand '())
A functional solution, with draw being side-effect free:
;; Returns a cons whose car will be the new hand and cdr being the
;; rest of the original deck
(define (draw deck hand)
(if (not (null? deck))
(cons (cons (car deck) hand) (cdr deck))
(cons hand ())))
;; Gets the new hand from the cons returned by draw.
(define (hand cards) (car cards))
;; Gets the new deck from the cons returned by draw.
(define (deck cards) (cdr cards))
;; test
(define cards (draw '(1 2 3 4 5) ()))
cards
=> ((1) 2 3 4 5)
(hand cards)
=> (1)
(deck cards)
=> (2 3 4 5)
;; draw again
(set! cards (draw (deck cards) (hand cards)))
cards
=> ((2 1) 3 4 5)
(hand cards)
=> (2 1)
(deck cards)
=> (3 4 5)
You cannot change the contents of a list, but you can change which list a name refers to. So:
(let ((some-list '("post")))
(display "initially: ")
(display some-list)
(newline)
(set! some-list (cons "first" some-list))
(display "added first: ")
(display some-list)
(newline)
(set! some-list '(a completely new list))
(display "finally: ")
(display some-list)
(newline)
some-list)
Now each of the lists '("post") '("first" "post") and '(a completely new list) are unchangeable ("immutable") lists, but the name some-list first points to one, then another, then the third.
Caveat: For many problems, you will want to avoid set! and try to think about the problem a different way. For example, if you work with worlds and universes for your game,
http://pre.plt-scheme.org/plt/doc/teachpack/2htdpuniverse.html
then you'll want your updaters to return a new state of the world rather than using set! to modify the old one.
Oh, and next you will find that changing what list a name refers to inside a function will not change what the name refers to from the perspective of whoever called the function. So:
(define (foo lst)
(set! lst '(hi))
(display "within foo: ")
(display lst)
(newline)
lst)
(define my-list '(hello))
(foo my-list)
(display "after foo: ")
(display my-list)
(newline)
(set! my-list (foo my-list))
(display "using the result of foo: ")
(display my-list)
(newline)
Vijay has the best solution for Scheme. However, if you really want to make this work by changing the lists permanently, you'll need to use set-car! and set-cdr!. This is not natural in Scheme, and requires a couple of hacks to make it work:
First define hand and deck:
(define hand '(dummy))
(define deck '((2 C) (3 H) (K D)))
hand has to start with an existing element so that it has some existing list structure to modify. You can't use set-car! and set-cdr! with nil ( '() ).
Now write draw:
(define (draw from to)
; push the top element of `from` onto `to`
(set-cdr! to (copy to))
(set-car! to (car from))
; pop the top element of `from` off
(set-car! deck (cadr deck))
(set-cdr! deck (cddr deck)))
; also we need to define copy
(define (copy l)
(map (lambda (x) x) l))
This means the last element of your hand will always be dummy. It would be better to add a check for the initial case and overwrite it instead of pushing:
(define (draw from to)
; push the top element of `from` onto `to` (just overwrite the first time)
(when (pair? (cdr to))
(set-cdr! to (copy to)))
(set-car! to (car from))
; pop the top element of `from` off
(set-car! deck (cadr deck))
(set-cdr! deck (cddr deck)))
Also you should check that from isn't empty before doing anything.
Related
I'm trying to take in user input and add it to a list but I have not been able to get it working. I'm still new to scheme and have been browsing around to try to figure it out but I haven't had any luck.
(display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(define (intlist number)
(define number(read-line))
(cond (number? number)
(cons lst (number))
(else
(display lst)
done')))
this is what I have so far. Any help or direction to where I can learn a bit more is appreciated.
Your solution is almost correct, but it doesn't work, because:
Variable lst doesn't exist and with this expression (number), you are calling some undefined function number.
done' is badly written 'done.
Function cons expects element as first argument and other element or list as second argument.
See these examples:
> (cons 1 2)
'(1 . 2)
> (cons 1 '())
'(1)
> (cons 1 (cons 2 (cons 3 '())))
'(1 2 3)
Last example is important here- your function will be recursive and it will return a cons cell in each step. If I will follow your solution, this can be enough:
(define (list-from-user)
(let ((number (read)))
(if (number? number)
(cons number (list-from-user))
'())))
(Note that I used read instead of read-line, because read-line returns string, and let instead of define.)
If you really want to wait for e, you must decide, what happens if user enters something that isn't number and isn't e- maybe just ignore it?
(define (list-from-user)
(let ((user-input (read)))
(cond ((number? user-input) (cons user-input (list-from-user)))
((eq? user-input 'e) '())
(else (list-from-user)))))
Then just add some wrapping function with output:
(define (my-fn)
(begin (display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(list-from-user)))
and call it
> (my-fn)
Note that my function returns list with numbers, instead of some useless 'done, so I can use that function in other functions.
(define (sum-of-list)
(let ((lst (my-fn)))
(format "Sum of given list is ~a." (apply + lst))))
> (sum-of-list)
For my programming languages class I'm supposed to write a function in Scheme to reverse a list without using the pre-made reverse function. So far what I got was
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (CONS (reverseList(CDR lst)) (CAR lst)))
))
The problem I'm having is that if I input a list, lets say (a b c) it gives me (((() . c) . b) . a).
How am I supposed to get a clean list without multiple sets of parenthesis and the .'s?
The problem with your implementation is that cons isn't receiving a list as its second parameter, so the answer you're building isn't a proper list, remember: a proper list is constructed by consing an element with a list, and the last list is empty.
One possible workaround for this is to use a helper function that builds the answer in an accumulator parameter, consing the elements in reverse - incidentally, this solution is tail recursive:
(define (reverse lst)
(reverse-helper lst '()))
(define (reverse-helper lst acc)
(if (null? lst)
acc
(reverse-helper (cdr lst) (cons (car lst) acc))))
(reverse '(1 2 3 4 5))
=> '(5 4 3 2 1)
You are half way there. The order of the elements in your result is correct, only the structure needs fixing.
What you want is to perform this transformation:
(((() . c) . b) . a) ; input
--------------------
(((() . c) . b) . a) () ; trans-
((() . c) . b) (a) ; for-
(() . c) (b a) ; mation
() (c b a) ; steps
--------------------
(c b a) ; result
This is easy to code. The car and cdr of the interim value are immediately available to us. At each step, the next interim-result is constructed by (cons (cdr interim-value) interim-result), and interim-result starts up as an empty list, because this is what we construct here - a list:
(define (transform-rev input)
(let step ( (interim-value input) ; initial set-up of
(interim-result '() ) ) ; the two loop variables
(if (null? interim-value)
interim-result ; return it in the end, or else
(step (car interim-value) ; go on with the next interim value
(cons ; and the next interim result
(... what goes here? ...)
interim-result )))))
interim-result serves as an accumulator. This is what's known as "accumulator technique". step represents a loop's step coded with "named-let" syntax.
So overall reverse is
(define (my-reverse lst)
(transform-rev
(reverseList lst)))
Can you tweak transform-rev so that it is able to accept the original list as an input, and thus skip the reverseList call? You only need to change the data-access parts, i.e. how you get the next interim value, and what you add into the interim result.
(define (my-reverse L)
(fold cons '() L)) ;;left fold
Step through the list and keep appending the car of the list to the recursive call.
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR lst))))
))
Instead of using cons, try append
(define (reverseList lst)
(if (null? lst)
'()
(append (reverseList (cdr lst)) (list (car lst)) )
)
)
a sample run would be:
1]=> (reverseList '(a b c 1 2 + -))
>>> (- + 2 1 c b a)
car will give you just one symbol but cdr a list
Always make sure that you provide append with two lists.
If you don't give two lists to the cons it will give you dotted pair (a . b) rather than a list.
See Pairs and Lists for more information.
So I am familiar with the algorithm for creating a power set using Scheme that looks something like this:
(define (power-set set)
(if (null? set) '(())
(let ((power-set-of-rest (power-set (cdr set))))
(append power-set-of-rest
(map (lambda (subset) (cons (car set) subset))
power-set-of-rest)))))
So this, for (1, 2, 3, 4), would output:
(() (4) (3) (3 4) (2) (2 4) (2 3) (2 3 4) (1) (1 4) (1 3) (1 3 4) (1 2) (1 2 4)
(1 2 3) (1 2 3 4))
I need to figure out how to output the power set "in order", for example:
(() (1) (2) (3) (4) (1 2) (1 3) (1 4) (2 3) (2 4) (3 4) (1 2 3) (1 2 4) (1 3 4)
(2 3 4) (1 2 3 4))
Doing a little research, it seems as if the best option would be for me to run a sort before outputting. I am NOT allowed to use built in sorts, so I have found some example sorts for sorting a list:
(define (qsort e)
(if (or (null? e) (<= (length e) 1))
e
(let loop ((left null) (right null)
(pivot (car e)) (rest (cdr e)))
(if (null? rest)
(append (append (qsort left) (list pivot)) (qsort right))
(if (<= (car rest) pivot)
(loop (append left (list (car rest))) right pivot (cdr rest))
(loop left (append right (list (car rest))) pivot (cdr rest)))))))
I cannot figure out how I would go about sorting it based off of the second, or third element in one of the power sets though. Can anyone provide an example?
Here's a powerset function that returns the items in the correct order, without sorting. It requires Racket and uses its queues to implement breadth-first processing:
(require srfi/1 data/queue)
(define (powerset items)
(define fifo (make-queue))
(enqueue! fifo (cons '() items))
(let loop ((result '()))
(if (queue-empty? fifo)
(reverse result)
(let* ((head-entry (dequeue! fifo))
(subset (car head-entry))
(rest-items (cdr head-entry)))
(pair-for-each (lambda (next-items)
(enqueue! fifo (cons (cons (car next-items) subset)
(cdr next-items))))
rest-items)
(loop (cons (reverse subset) result))))))
We maintain a FIFO queue of pairs, each consisting of a subset (in reversed order) and a list of items not included in it, starting with an empty subset so all the original items are still not included in it.
For each such pair, we collect the subset into the result list, and also extend the queue by extending this subset by each item from the not-included items. Processing stops when the queue is empty.
Because we extend subsets each time by one element only, and in order, the result is ordered too.
Here's a compare function that should work for your needs. It assumes that the numbers in the two input arguments are sorted already.
(define (list-less? lst1 lst2)
;; Compare the contents of the lists.
(define (helper l1 l2)
;; If two lists are identical, the answer is false.
;; This scenario won't be exercised in the problem.
;; It's here only for the sake of completeness.
(if (null? l1)
#f
;; If the first item of the second list is greater than
;; the first item, return true.
(if (> (car l2) (car l1))
#t
(or (< (car l1) (car l2)) (helper (cdr l1) (cdr l2))))))
;; First compare the lengths of the input arguments.
;; A list of smaller length are assumed to be "less"
;; than list of greater length.
;; Only when the lists are of equal length, do we
;; compare the contents of the lists.
(let ((len1 (length lst1)) (len2 (length lst2)))
(if (> len1 len2)
#f
(or (< len1 len2) (helper lst1 lst2)))))
So I have to remove the last element of a list in scheme.
For example, let's say I have a list (1 2 3 4). I need to return:
(1 2 3)
My idea:
reverse(list)
car(list)
reverse(list)
Is there a reverse function in scheme(racket)?
You wrote: "reverse, car, reverse". I believe you meant to write "reverse, cdr, reverse". There's nothing wrong with this solution; it's linear in the size of the list, just like any solution to this that uses the standard lists.
As code:
;; all-but-last: return the list, not including the last element
;; list? -> list?
(define (all-but-last l) (reverse (cdr (reverse l))))
If the multiple traversal of the list or the needless construction of another list copy bothers you, you can certainly avoid it, by writing the thing directly.
Given your almost-solution, I'm going to assume that this isn't homework.
Here's what it would look like, in racket:
#lang racket
(require rackunit)
;; all-but-last : return the list, except for the last element
;; non-empty-list? -> list?
(define (all-but-last l)
(cond [(empty? l) (error 'all-but-last "empty list")]
[(empty? (rest l)) empty]
[else (cons (first l) (all-but-last (rest l)))]))
(check-equal? (all-but-last '(3 4 5))
'(3 4))
There is a reverse, but using it would not be very efficient. I suggest the following recursive function.
(define (remove-last lst)
(if (null? (cdr lst))
'()
(cons (car lst) (remove-last (cdr lst)))))
(remove-last '(1 2 3 4)) ; returns '(1 2 3)
The if checks whether it is at the last element of the list.
SRFI 1 (activate in Racket using (require srfi/1)) has a drop-right function:
(drop-right '(1 2 3 4) 1) ; => (1 2 3)
I would do a recursive function that goes down the list and attaches the element (using cons) if the element after it is not the last, and appends nothing if it isn't.
I haven't done scheme for years though so that's as far as I can go.
Someone can run with how to implement it (unless it's homework then they probably shouldn't!)
I've done something simpler than: reverse(list), car(list), reverse(list) to get the last element, check out:
(define (last-one liste)
(if(null? (cdr liste))
null
(cons (car liste) (last-one (cdr liste)))
)
)
Those who are looking for another way can check this out:
(define (removing-last xx)
(remove (list-ref xx (- (length xx) 1)) xx))
I would write a simple recursion, altering the typical "empty? mylist" base case to "empty? (rest mylist)," so that I can return empty when the input list is only 1 element.
(define (removelast mylist)
(cond
[(empty? (rest mylist)) empty]
[(cons? mylist) (cons (first mylist) (removelast (rest mylist)))]))
(removelast (list 1 2 3 4 5))
By the way, this code is in Racket/PLT Scheme, a subset of Scheme.
I have the following items
(define itemslist
(list 'a1 'b2 'c3 (list 'z1 'z2) 'd5 'e6))
My method to find items is below
(define find-item
(lambda (item itemslist)
(cond ((null? itemslist) #f)
((list? (car itemslist))
(cond ((null? itemslist) #f)
(else (find-item item (car itemslist)))))
((equal? stn (car itemslist)) (display "found"))
(else (find-stn stn (cdr itemslist)))
)
)
)
With my method above I can find a1, b2, c3, z1, z2. But when I want to find d5 onwards, it returns nothing. It seems to have skip the stack. Btw, I am just starting to learn Scheme so simple explanation would be better.
One more qns, how about if I have this
(list 'a1 'b2 'c3 (list 'z1 (list 'y1 'y2) 'z2) 'd5 'e6)
does this works as well? Thanks!
Yes, you skip lists.
Example:
'(1 '(2 3) 4)
If (list? '(2 3)) is true, the else part (outer cond) wont be evaluated so 4 is skipped.
So, either you place the else part inside list? block or you redesign your code.
If the itemlist is a list/pair you can pass it right away in a recursive call so
you can avoid writing code like (car itemslist) inside predicates thus make the code simple.
Here is a redesigned (simplified) version:
(define (find-item item l)
(cond ((equal? item l) #t)
((pair? l) (or (find-item item (car l)) (find-item item (cdr l))))
(else #f)))
Tip: you can also can write lists with '(...) notation instead of (list ...), ie
(find-item 'z2 '('a1 'b2 'c3 '('z1 '('y1 'y2) 'z2) 'd5 'e6))
#t
(find-item 'e6 '('a1 'b2 'c3 '('z1 '('y1 'y2) 'z2) 'd5 'e6))
#t
To write more for the sake of writing more... This is usually called a "tree-walk" because a nested list like that is really a binary tree. Lists are really made up of binary pairs, so when you have a pair (l . r), l is the left branch of the tree and r is the right branch of the tree.
For example, '(1 (2 3) 4) is short for '(1 . ((2 . (3 . ())) . (4 . ()))) which can be drawn as
.
/ \
1 .
/ \
/ .
/ / \
. 4 ()
/ \
2 .
/ \
3 ()
and at any pair (l . r), car gets you the left tree and cdr gets you the right. So, when you write (pair? ls), you're really asking if you're at a branch in the tree, at which point you should recur on both the left branch (car) and the right branch (cdr). Hope that helps you understand lists.
Even though you got your [specific] answer, here's something that might help you with similar questions.
(define describe
(lambda (e)
(cond #;((list? e)
`(list ,#(map describe e)))
((pair? e)
`(cons ,(describe (car e))
,(describe (cdr e))))
((vector? e)
`(vector ,#(map describe (vector->list e))))
((or (null? e) (symbol? e)) `',e)
(else e))))
This procedure prints the code that generates a given sexpr. For example:
> (describe '(a 2 b 3))
(cons 'a (cons 2 (cons 'b (cons 3 '()))))
It will also place the quotes where needed, so it places them before symbols or () but not before numbers. When you are comfortable with nested pairs, you may want to remove the #; on the third line, to generate more compact output:
> (describe '(a 2 b 3))
(list 'a 2 'b 3)
This code can teach you many things about quote. For example:
> (describe ''''a)
(list 'quote (list 'quote (list 'quote 'a)))