Starting with an empty 5-gallon jug and an empty 11-gallon jug, how can we end up with exactly 3 gallons of water in the 11-gallon jug and with the 5-gallon jug empty?
I want to write a function in Lisp that computes a list of successor states for any state in this puzzle
my solution
(0 0) > (5 0) > (0 5) > (5 5) > (0 10 ) > (5 10)>(4 11)>(4 0)>(0 4)>(5 4)>(0 9)>(5 9)>(3 11)>(3 0)>(0 3)
How can I implement successors function?
(setq initial-state '(0 0))
(setq fill-jug1-state '(5 0))
(setq fill-jug2-state '(0 11))
(setq full '(5 11))
(defparameter *jug-1* 5)
(defparameter *jug-2* 11)
(defun successors (initial-state)
)
please help !!!!
Here is a hint to start:
(defun successors (state) ; for each state
(let ((jug1 (first state)) ; gallons in jug1 for state
(jug2 (second state)) ; gallons in jug2 for state
(new-states nil)) ; successor states of state
(when (< jug1 5) ; if jug1 is not full
(push (list 5 jug2) new-states)) ; then fill jug1
; do the same for jug2
; ...
(when (> jug1 0) ; if jug1 has some water
;... empty jug1, that is, new-state = (0 jug2)
; do the same for jug2 if jug2 has some water
;...
(when (and (> jug2 0) (< jug1 5)) ; if jug2 can give water to jug1
; then pour the water of jug2 in jug1
(push (list (min 5 (+ jug1 jug2))
(max (- jug2 (- 5 jug1)) 0)) new-states))
; do the same for the opposite situation
;...
new-states)) ; finally return the set of new states
Related
I'm trying to write a program that returns the Pell numbers sequence based on a given number.
For example (pellNumb 6) should return a list (0 1 2 5 12 29 70)
This is my code so far.
I am able of calculating the numbers, but I am not able of skipping the double recursion.
(defun base (n)
(if (= n 0)
0
(if (= n 1)
1)))
(defun pellNumb (n)
(if (or (= n 0) (= n 1))
(base n)
(let ((x (pellNumb (- n 2))))
(setq y (+ (* 2 (pellNumb (- n 1))) x))
(print y))))
The output for (pellNumb 4) is 2 2 5 12, and this is because i'm recursing to (pellNumb 2) twice.
Is there a way to skip that, and store these values in a list ?
Thanks!
Get the nth number
Yes, there is a way - use multiple values:
(defun pell-numbers (n)
"Return the n-th Pell number, n-1 number is returned as the 2nd value.
See https://oeis.org/A000129, https://en.wikipedia.org/wiki/Pell_number"
(check-type n (integer 0))
(cond ((= n 0) (values 0 0))
((= n 1) (values 1 0))
(t (multiple-value-bind (prev prev-1) (pell-numbers (1- n))
(values (+ (* 2 prev) prev-1)
prev)))))
(pell-numbers 10)
==> 2378 ; 985
This is a standard trick for recursive sequences which depend on several previous values, such as the Fibonacci.
Performance
Note that your double recursion means that (pell-numbers n) has exponential(!) performance (computation requires O(2^n) time), while my single recursion is linear (i.e., O(n)).
Moreover, Fibonacci numbers have a convenient property which allows a logarithmic recursive implementation, i.e., taking O(log(n)) time.
Get all the numbers up to n in a list
If you need all numbers up to the nth, you need a simple loop:
(defun pell-numbers-loop (n)
(loop repeat n
for cur = 1 then (+ (* 2 cur) prev)
and prev = 0 then cur
collect cur))
(pell-numbers-loop 10)
==> (1 2 5 12 29 70 169 408 985 2378)
If you insist on recursion:
(defun pell-numbers-recursive (n)
(labels ((pnr (n)
(cond ((= n 0) (list 0))
((= n 1) (list 1 0))
(t (let ((prev (pnr (1- n))))
(cons (+ (* 2 (first prev)) (second prev))
prev))))))
(nreverse (pnr n))))
(pell-numbers-recursive 10)
==> (0 1 2 5 12 29 70 169 408 985 2378)
Note that the recursion is non-tail, so the loop version is probably more efficient.
One can, of course, produce a tail recursive version:
(defun pell-numbers-tail (n)
(labels ((pnt (i prev)
(if (= i 0)
prev ; done
(pnt (1- i)
(cond ((null prev) (list 0)) ; n=0
((null (cdr prev)) (cons 1 prev)) ; n=1
(t
(cons (+ (* 2 (or (first prev) 1))
(or (second prev) 0))
prev)))))))
(nreverse (pnt (1+ n) ()))))
(pell-numbers-tail 10)
==> (0 1 2 5 12 29 70 169 408 985 2378)
So i have this macro (basically a for loop):
(defmacro for ((parameter start-value end-value &optional (step 1)) &body e)
(let ((func-name (gensym))
(end (gensym)))
`(labels ((,func-name (,parameter ,end)
(if (<= ,parameter ,end)
(progn ,#e
(,func-name (+ ,parameter ,step) ,end)))))
(,func-name ,start-value ,end-value))))
And i want to test it with this:
(print (let ((j 0) (k 1))
(for (i 1 10 (incf k)) (print i))))
What i get now is:
1, 3, 6, 10, NIL.
which means that my step increments after each iteration, but i want it to increment only once in the beginning for this output:
1, 3, 5, 7, 9, NIL.
What's wrong with my macro and what should i do?
You need to compute the step value outside the loop:
CL-USER 12 > (defmacro for ((parameter start-value end-value
&optional (step 1))
&body e)
(let ((func-name (gensym))
(step-name (gensym))
(end (gensym)))
`(labels ((,func-name (,parameter ,end ,step-name)
(when (<= ,parameter ,end)
,#e
(,func-name (+ ,parameter ,step-name)
,end
,step-name))))
(,func-name ,start-value ,end-value ,step))))
FOR
CL-USER 13 > (pprint (macroexpand-1 '(for (i 1 10 (incf k)) (print i))))
(LABELS ((#:G954 (I #:G956 #:G955)
(WHEN (<= I #:G956) (PRINT I) (#:G954 (+ I #:G955) #:G956 #:G955))))
(#:G954 1 10 (INCF K)))
CL-USER 14 > (let ((j 0) (k 1))
(for (i 1 10 (incf k))
(print i)))
1
3
5
7
9
NIL
If you don't want to pass the step-value all the time, you need an outer LET binding its value.
Note: some Lisp implementations (many interpreters and some compilers) don't support TCO (tail call optimisation).
i am new to racket. I tried to do lab work, but...
#lang scheme
(define lab2
(lambda (currentList counter result)
((let countdown ((i (- (length currentList) 1)))
(if (= i 0) (display result)
(begin
(if (pair? (list-ref currentList i)) ;1 if element is list
(if (> (+ 1 counter) result) ;1 if counter > currentResult
((set! counter (+ 1 counter)) (set! result (+ 1 result)) (countdown(- i 1))) ;2 then counter++, result++
((set! counter (+ 1 counter)) (countdown(- i 1)))) ;2 else counter++
((set! counter 0) (countdown(- i 1)))) ;1 else counter=0
))))))
testing: (lab2 '(9 9 9 (0) (0) (0) (0) 9 9 9 9 9 9 (0)9 9 (0) 9 9 9 9 9 9) 0 0)
but getting this : application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments.:
#<void>
How fix it?
Please help me((
Assuming your indentation expresses what you want, this would be the working version of your code:
(define lab2
(lambda (currentList counter result)
(let countdown ((i (- (length currentList) 1)))
(if (= i 0)
(display result)
(begin
(if (pair? (list-ref currentList i)) ;1 if element is list
(if (> (+ 1 counter) result) ;1 if counter > currentResult
(begin
(set! counter (+ 1 counter))
(set! result (+ 1 result))
(countdown(- i 1))) ;2 then counter++, result++
(begin
(set! counter (+ 1 counter))
(countdown(- i 1)))) ;2 else counter++
(begin
(set! counter 0)
(countdown(- i 1))))))))) ;1 else counter=0
Lessons learned:
indent properly; especially don't put 2 consecutive forms on one single line
in an if form, if you need to use a begin form if you have more than one form in the then or else part and not double parentheses
if you use many beginwith if you should try and see if using cond instead of if wouldn't make your code more readable (left as an exercise to you)
if you have many set! forms you're probably not thinking the Scheme way; seriously, post another question where you explain what you want to do and a working version of this code!
What I have to do is removing some elements from the list,the 1st,2nd,4th,8th,elements on positions power of 2.I figured out that the easyest way for me to solve this is to construct how the result list should look like without destroying the original list.Here's my code but it doesn't work yet,I'm getting a type error.I'm using contor to know with which element of the list I'm working with an counter to specify only the position from which the elements should be removed.My question is what am I doing wrong and how can it be fixed?
(defun remo(l)
(defparameter e ())
(setq contor 0)
(setq counter 0)
(dolist (elem l) (
(cond
(
((or (< (expt 2 contor) counter) (> (expt 2 contor) counter))
((push elem e) (setq contor (+ 1 contor))))
))
(setq counter (+1 counter))
)
)
(print e)
)
(defun remo (l)
(do ((power-of-2 1)
(counter 1 (1+ counter))
(result ())
(sublist l (cdr sublist)))
((null sublist) (nreverse result))
(if (= counter power-of-2)
(setq power-of-2 (* 2 power-of-2))
(push (car sublist) result))))
(remo '(1 2 3 4 5 6 7 8 9 10))
=> (3 5 6 7 9 10)
I already improved another of your attempts at https://stackoverflow.com/a/20711170/31615, but since you stated the real problem here, I propose the following solution:
(defun remove-if-index-power-of-2 (list)
(loop :for element :in list
:for index :upfrom 1 ; correct for language: "1st" is index 0
:unless (power-of-2-p index)
:collect element))
(defun power-of-2-p (number)
"Determines whether number, which is assumed to be a nonnegative
integer, is a power of 2 by counting the bits."
(declare (type (integer 0 *) number))
(= 1 (logcount number)))
Is there a way to do this:
(defvar long-list ((1 1 1 1) (2 2 2 2) (3 3 3 3)
(4 4 4 4) (5 5 5 5) (6 6 6 6))
(format t "magic" long-list)
To output something like:
(1 1 1 1) (2 2 2 2) (3 3 3 3)
(4 4 4 4) (5 5 5 5) (6 6 6 6)
Where I would define the number of columns to print?
I know about (format t "~/my-function/" long-list) option, but maybe there's something built-in?
The reference is being highly unhelpful on this particular topic.
OK, sorry, I actually found it: http://www.lispworks.com/documentation/lw51/CLHS/Body/f_ppr_fi.htm#pprint-tabular but before I found it, I wrote this:
(defun pplist-as-string (stream fmt colon at)
(declare (ignore colon at))
(dolist (i fmt)
(princ i stream)))
(defun ppcolumns (stream fmt colon at cols)
(declare (ignore at colon))
(when (or (not cols) (< cols 1)) (setq cols 1))
(let* ((fmt-length (length fmt))
(column-height (floor fmt-length cols))
(remainder (mod fmt-length cols))
(printed 0)
columns
column-sizes)
(do ((c fmt (cdr c))
(j 0 (1+ j))
(r (if (zerop remainder) 0 1) (if (zerop remainder) 0 1))
(i 0 (1+ i)))
((null c))
(when (or (= j (+ r column-height)) (zerop i))
(setq columns (cons c columns)
column-sizes
(cons
(+ r column-height) column-sizes))
(unless (zerop remainder)
(unless (zerop i) (decf remainder)))
(setq j 0)))
(setq columns (reverse columns)
column-sizes (reverse column-sizes))
(when (/= fmt-length (* column-height cols))
(incf column-height))
(dotimes (i column-height)
(do ((c columns (cdr c))
(size column-sizes (cdr size)))
((or (null c)))
(when (> printed (1- fmt-length))
(return-from ppcolumns))
(when (< 0 (car size))
(pplist-as-string stream (caar c) nil nil)
(when (caar c) (incf printed))
(unless (null c) (princ #\ ))
(rplaca c (cdar c))))
(princ #\newline))))
which prints it in another direction. In case you would need it.