List calling with car and cdr in scheme/lisp - list

Currently setting cells in list notation using scheme. My question is how to make scheme(Dr Racket) list pair correctly using cons. My code accounts for the right location I want but creates a list by adding on the front. I am currently only working on the column = 1, 2, 3 or 4 aspect of this, and when row = 1 ONLY... Any help would be greatly appreciated.
(define KMMgame 0)
(define (KMMStartGame)
( begin
(set! KMMgame '( 1(4 9 0 0)(99 0 0 0)(88 0 0 0)(11 0 0 1)
(3 8 0 0)(77 0 0 0)(66 0 0 0)(55 0 0 2)
(2 0 0 0)(44 0 0 0)(33 0 0 0)(22 0 0 3)
(1 0 0 0)(43 0 0 0)(34 0 0 0)(87 0 0 4)))
(display "Starting Game Now!" ) (newline)
#t))
;Passes list without the one on front (That is for my player state, irrelevant to my question)
(define ( KMMmove KMMgame Plane Row Column Token)
(KMMMove (car(cdr KMMgame)) (cdr (cdr KMMgame)) Plane Row Column Token) )
;Set the cell to token.
(define (KMMMove KMMgame KMMend Plane Row Column Token)
(if (= Row 1)
(if (= Column 1)
(cons (cons Token (cdr KMMgame)) KMMend)
(cons (car KMMgame) (KMMMove (cdr KMMgame) KMMend Plane Row (- Column 1) Token))
)
;Next line accounts for rows greater than one, not working yet so please disregard. Exists to compile.
(cons (cons (car(cdr (cdr KMMgame))) (KMMMove (car KMMgame) Plane (- Row 1) Column Token)) (cdr(cdr KMMgame))
)
)
)
(KMMMove KMMgame 4 1 1 999)
Plane 4, Row 1, Column 1, Token to be added instead of current number 999, will print the desired output but inside an extra set of parenthesis:
((999 9 0 0)
(99 0 0 0)
(88 0 0 0)
(11 0 0 1)
(3 8 0 0)
(77 0 0 0)
(66 0 0 0)
(55 0 0 2)
(2 0 0 0)
(44 0 0 0)
(33 0 0 0)
(22 0 0 3)
(1 0 0 0)
(43 0 0 0)
(34 0 0 0)
(87 0 0 4))
( KMMmove KMMgame 4 1 2 999)
Plane 4, Row 1, Column 2, Token 999, gives the correct location for column but is pairing the front of the list outside.
(4
(999 0 0)
(99 0 0 0)
(88 0 0 0)
(11 0 0 1)
(3 8 0 0)
(77 0 0 0)
(66 0 0 0)
(55 0 0 2)
(2 0 0 0)
(44 0 0 0)
(33 0 0 0)
(22 0 0 3)
(1 0 0 0)
(43 0 0 0)
(34 0 0 0)
(87 0 0 4))
Desired output for column 2:
(4 999 0 0)
(99 0 0 0)
(88 0 0 0)
(11 0 0 1)
(3 8 0 0)
(77 0 0 0)
(66 0 0 0)
(55 0 0 2)
(2 0 0 0)
(44 0 0 0)
(33 0 0 0)
(22 0 0 3)
(1 0 0 0)
(43 0 0 0)
(34 0 0 0)
(87 0 0 4)

To get a list like that, I'd suggest helper functions!
(define (newGameState KMMgame Row Column Plane Token)
(if (= Plane 4)
(steptwo KMMgame Row Column Plane Token)
(newGameState KMMgame (+ 4 Row) (+ Plane 1) Column Token)
)
)
(define (steptwo KMMgame Row Column Plane Token)
(if (= Row 1)
(cons (stepthree (car (cdr KMMgame)) Row Column Plane Token) (cdr (cdr KMMgame)))
(cons (car (cdr KMMgame))(steptwo (cdr KMMgame) (- Row 1) Column Plane Token))
)
)
(define (stepthree KMMgame Row Column Plane Token)
(if (= Column 1)
(cons Token (cdr KMMgame))
(cons (car KMMgame) (stepthree (cdr KMMgame) Row (- Column 1) Plane Token))
)
)
This should give desired output!

Related

Unexplained behaviour in atom

I have an atom which stores current and historical event counts.
(def buckets (atom (list)))
It starts as 20 empty values.
(reset! buckets (apply list (repeat 20 0)))
=> (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
The head bucket gets incremented for each event.
(defn- inc-bucket [buckets]
(conj (rest buckets) (inc (first buckets))))
(defn event-happened [] (swap! buckets inc-bucket))
=> (event-happened)
(1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
It gets shifted once a second to give a history of counts.
(defn- shift-buckets [buckets]
(conj (drop-last buckets) 0))
(once-a-second-run (swap! buckets shift-bucket))
=> (swap! buckets shift-bucket)
(0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
This all works fine most of the time. But occasionally (say once a week) I find that the length of buckets has been reset to 5, not the correct value (20 in this example).
=> #buckets
(0 1 0 0 0)
The only place buckets is used is in these functions and with a deref to observe the value.
Something went wrong, and I can't work out how or where. The only place buckets is modified is during the two above swap!s and as I think they're being used correctly. Any ideas?
I found the answer. Laziness and unhandled exceptions in atoms. There is no magic.
user=> (reset! buckets (apply list (repeat 20 0)))
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
user=> (dotimes [_ 99999] (swap! buckets shift-buckets))
nil
user=> #buckets
StackOverflowError clojure.core/map/fn--4557 (core.clj:2627)
user=> (type #buckets)
clojure.lang.Cons
This had showed up in the log, but I hadn't seen it (there's a lot else going on). But here's the crazy thing:
user=> #buckets ; again
(0 0)
I don't know why it would give that value. It's not because a cons cell has a head and a tail, because in production that was (0 0 0 0 0). Either way it's undefined behaviour so there's no point guessing.
To fix it, the list must be realised each time.
user=> (defn- shift-buckets-nonlazy [buckets]
#_=> (apply list (conj (drop-last buckets) 0)))
#'user/shift-buckets-nonlazy
user=> (reset! buckets (apply list (repeat 20 0)))
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
user=> (dotimes [_ 999999] (swap! buckets shift-buckets-nonlazy))
nil
user=> (type #buckets)
clojure.lang.PersistentList
user=> #buckets
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
The problem has to be in code you haven't posted: everything in your question looks perfectly correct, and can't cause the behavior you describe.

how to split a vector on a delimiter

I have a vector that contains numbers.
The structure of the vector is the following:
items of arbitrary length
a separator [0 0 0 0 0] (0 repeated 5 times) between the items
I want to write a function split that retrieves the list of the items (without the separator): It is similar to string/split.
For instance:
(split [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 199])
; => [[123 0 1] [1 1] [1 0 1] [0 0 1 199]]
Remark: the code has to be effective as the length of the vector is around 1 million.
Thanks for your help.
Here:
(defn the-split [coll]
(let [part (partition-by identity coll)
ppart (partition-by #(= [0 0 0 0 0] %) part)
almost (map #(apply concat %) ppart)]
(filter (partial not= [0 0 0 0 0]) almost)))
(the-split [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 199])
=> ((123 0 1) (1 1) (1 0 1) (1 199))
Here's one approach -- with the [0 0 0 0 0] separator hardwired, but straightforward to generalize:
(defn split5z [xs]
(let [delim [0 0 0 0 0]
step (fn step [xs seg]
(lazy-seq
(if-let [xs (seq xs)]
(let [window (take 5 xs)]
(if (= window delim)
(cons seg (step (drop 5 xs) []))
(step (rest xs) (conj seg (first xs)))))
(list seg))))]
(step xs [])))
Applying it to your sample input:
(split5z [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 199])
;= ([123 0 1] [1 1] [1 0 1] [1 199])
Wrap in vec if you'd like the output to be a vector rather than a seq of vectors.
Another approach -- this time eagerly consuming the input with loop/recur:
(defn split5z [sep xs]
(let [scnt (count sep)]
(loop [xs (seq xs)
out []
seg []]
(if xs
(if (= (take scnt xs) sep)
(recur (nthnext xs scnt)
(conj out seg)
[])
(recur (next xs)
out
(conj seg (first xs))))
(if (seq seg)
(conj out seg)
seg)))))
At the REPL:
(split5z [0 0 0 0 0]
[123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 199])
;= [[123 0 1] [1 1] [1 0 1] [1 199]]
A lazy solution:
(defn split [v]
(let [delim (repeat 5 0)
i (->> v (partition 5 1) (take-while #(not= delim %)) count)]
(if (zero? i) [v] (lazy-seq (cons (subvec v 0 i)
(split (subvec v (+ i 5))))))))
For example
(split [123 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 199])
; ([123 0 1] [1 1] [1 0 1] [0 0 1 199])

duplicating and modifying the head of a list of list, in Lisp

I'm learning Lisp. I wish to add a new list to a list of list, say ((1 1 1) (0 0 0)), where the new head of this list collection is computed based on the previous head.
Here's what I tried, in the REPL environment in Slimv with sbcl:
> (defvar *ll* (list (list 1 1 1) (list 0 0 0)))
*LL*
> *ll*
((1 1 1) (0 0 0))
> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *ll*)) 2)
2
> *ll*
((1 1 2) (1 1 2) (0 0 0))
As shown above, I only wanted to modify the last element of the first list, but somehow the last element of the second list was also changed.
I noticed that if instead I push into a brand-new list, then the result is different:
> (defvar *lll* (list (list 1 1 1) (list 0 0 0)))
*LLL*
> (push '(1 1 1) *lll*)
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *lll*)) 2)
2
> *lll*
((1 1 2) (1 1 1) (0 0 0))
I'd like to know what causes these different results, and how to achieve the result that "adds a new list to the list of list, where the new head of resulting list collection is computed based on the previous head." Thanks!
(car *ll*) and (cadr *ll*) are the same list
> (defvar *ll* (list (list 1 1 1) (list 0 0 0)))
*LL*
> *ll*
((1 1 1) (0 0 0))
> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *ll*)) 2)
2
> *ll*
((1 1 2) (1 1 2) (0 0 0))
As shown above, I only wanted to modify the last element of the first
list, but somehow the last element of the second list was also
changed.
There's only one object there, and you modified it. It's not really any different than if you had some sort of structured data type (and really, what is a cons cell but a structured datatype with just two fields). If you have a list of people, and then you add the first person to the list again, there's still just one person; the person just appears two places in the list. If you change the name of the person, you'll see it in both places. You can actually see the shared structure if you set *print-circle* to t.
CL-USER> (defvar *ll* (list (list 1 1 1) (list 0 0 0)))
*LL*
CL-USER> *ll*
((1 1 1) (0 0 0))
CL-USER> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
CL-USER> *ll*
((1 1 1) (1 1 1) (0 0 0))
CL-USER> (setf *print-circle* t)
T
CL-USER> *ll*
(#1=(1 1 1) #1# (0 0 0))
The notation using #1=… and #1# indicates that the same object is the first and second element of the list.
If you want a copy, make a copy
I wish to add a new list to a list of list, say ((1 1 1) (0 0 0)),
where the new head of this list collection is computed based on the
previous head. …
> (push (car *ll*) *ll*)
((1 1 1) (1 1 1) (0 0 0))
You said that you wanted to add a new list to a list of lists, but you're not adding a new list; you're adding (car *ll*) which is the list you created at the beginning with (list 1 1 1). If you want to copy the list, you'll need to copy it explicitly, e.g., with copy-list:
> (push (copy-list (car *ll*)) *ll*)
((1 1 1) (1 1 1) (0 0 0))
Don't modify literal data!
As an aside, what you're doing in your second code block is actually undefined behavior, since you're modifying the literal list '(1 1 1).
> (defvar *lll* (list (list 1 1 1) (list 0 0 0)))
*LLL*
> (push '(1 1 1) *lll*) ; '(1 1 1) is literal data.
((1 1 1) (1 1 1) (0 0 0))
> (setf (nth 2 (car *lll*)) 2) ; (car *lll*) is literal data, and you're modifying it!
2
> *lll*
((1 1 2) (1 1 1) (0 0 0))
See my answer to Unexpected persistence of data for more about why this can be problematic.

Scheme: 3 numbers in a row, implementation [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Currently I have a list of elements (1 2 1 2 2 0 0 1 0).
The point of the function I'm trying to write is that it should display a possibility that would show 3 of the same number in a row (which would be a 'winning' case).
The output I would want is (1 2 1 2 2 2 0 1 0).
The function, when called, would be in the format of
(display (next 2 (list)))
I'd assume I'd take the car of the list and if there's a way to store/remember the car I got (in case I call for it again and want to check if it matches).
The closest thing to a basic loop is the named let construct. Here's a simple implementation that works for your problem:
(define (next e lst)
; l1 : part of the list already processed (reversed)
; l2 : part of the list still to be processed
; c-2: element before previous
; c-1: previous element
; res: result (list of winning cases
(let loop ((l1 null) (l2 lst) (c-2 null) (c-1 null) (res null))
(if (null? l2)
(reverse res)
(let ((ca (car l2)) (cd (cdr l2)))
(loop (cons ca l1) cd c-1 ca
(if (and (= ca 0) (= c-2 e) (= c-1 e))
(cons (append (reverse l1) (cons c-1 cd)) res) ; build winning case
res))))))
then
> (next 2 '(1 2 1 2 2 0 0 1 0))
'((1 2 1 2 2 2 0 1 0))
> (next 2 '(1 2 1 2 2 0 2 2 0))
'((1 2 1 2 2 2 2 2 0) (1 2 1 2 2 0 2 2 2))
> (next 1 '(1 2 1 2 2 0 1 1 0))
'((1 2 1 2 2 0 1 1 1))

Using Clojure vector to model a 7 card poker hand

I have a vector that represents a 7 card poker hand and I want to find the next hand using the following method:
values are from 0 to 12 and are sorted (e.g. [0 0 7 11 11 12 12])
A valid vector has atmost 4 of one value
The first valid vector is [0 0 0 0 1 1 1]
If the values at index and index + 1 are different then increment the value at index and set all the values from 0 to index - 1 to zero
Repeat the last step until the vector is valid
For example, (next-hand [0 0 0 0 1 1 1]) would return [0 0 0 1 1 1 1] directly. However, (next-hand [0 0 0 1 1 1 1]) would loop through,
[0 0 1 1 1 1 1] (invalid)
[0 1 1 1 1 1 1] (invalid)
[1 1 1 1 1 1 1] (invalid)
[0 0 0 0 0 0 2] (invalid)
[0 0 0 0 0 1 2] (invalid)
and return this valid hand:
[0 0 0 0 1 1 2]
Here is the sudo code I have, but need to convert this to clojure. Note how I'm adding a really large integer to the end of the hand to make the last comparison always true. Thus, in the case of [1 1 1 1 1 1 1 99] the first loop would end at i=6 with 1 < 99 == true.
let hand = [hand 99]
while hand is invalid
for i in range(0,6)
if hand[i] < hand[i+1]
increment hand[i]
break
for j in range(0,i-1)
hand[j] = 0
Edit Friday, Mar 29, 2013:
In order for the select solution to work with the poker hand model I added an is-valid function like so:
(defn is-valid [v]
(let [distinct-ranks (partition-by identity v)
count-distinct (map count distinct-ranks)
max-count (apply max count-distinct)]
(<= max-count 4)))
and updated to (filter #(is-valid %) in next-hand.
One possible solution:
(defn next [v]
(let [i (->> (map < v (rest v))
(map-indexed vector)
(filter #(% 1))
first)
index (if i (i 0) 6)]
(for [[i x] (map-indexed vector v)]
(cond (= i index) (inc x)
(< i index) 0
:else x))))
(defn next-hand [v]
(->> (iterate next (next v))
(filter #(= 4 (apply + %)))
first
vec))
(next-hand [0 0 0 1 1 1 1])