How would I go about coding a lotto in Lisp where the user randomly generates 6 numbers (non repetitive) between 1- 45, then input their own selection of lotto numbers to see if they match, and then tell them if they've won or not ?
(defun shuffle (list)
(let ((len (length list)))
(loop repeat len
do (rotatef (nth (random len) list)
(nth (random len) list))
finally (return list))))
(defun lottery ()
(sort (subseq (shuffle (loop for i from 1 to 49 collect i))
0 6)
#'<))
(lottery)
(The code was actually taken from other authors from this question: Get numbers for the lottery)
This outputs the random numbers I need but I'm having a lot of trouble getting the user input of 6 numbers and comparing them to these numbers to see if they have 'won'.
Let's start with getting n non repeating random numbers.
(defun get-n-rand (n)
(loop :for i = (adjoin (1+ (random 44)) i)
:when (= (length i) n) :return i))
Now if we want 6 of them is simple enough to write (get-n-rand 6)
Next we want to check if every member of one list can be found in another.
(defun check-user-guess (guess-list actual-list)
(equal (sort guess-list #'<) (sort actual-list #'<)))
Hopefully this covers the core logic. Input I will leave for now as it was covered in the other answer.
If your problem is the input this should be a (unsafe) solution:
(defun play-lotto (&aux list)
(dotimes (i 6)
(loop
(princ "Write a Integer between 0 and 50: ")
(let ((number (read)))
(if (and (integerp number) (< 0 number 50))
(if (member number list)
(progn
(princ "You can only choose a number once")
(terpri))
(progn
(push number list)
(return)))
(progn
(princ "Not a Integer between 0 and 50")
(terpri))))))
(if (equal (sort list #'<) (lottery))
(princ "You won!")
(princ "You lost...")))
Related
(princ "ENTER ANY NUMBER : ")
(setq n (read))
(setq flag 0)
(loop for i from 2 to n-1
(if (=(mod n i)0)
(setq flag 1)))
(if (= flag 0)
(format t "~d IS A PRIME NUMBER"n)
(format t "~d IS NOT A PRIME NUMBER"n))
It would make your code much easier for other people to read if you
would start each top-level form on a new line.
n-1 is not lisp. Try (- n 1)
You need a do in your loop. That is:
(loop for i from 2 to (- n 1) do ...
In other words:
(princ "ENTER ANY NUMBER : ")
(setq n (read))
(setq flag 0)
(loop for i from 2 to (- n 1) do
(if (= (mod n i) 0)
(setq flag 1)))
(if (= flag 0)
(format t "~d IS A PRIME NUMBER"n)
(format t "~d IS NOT A PRIME NUMBER"n))
n-1 is a symbol, and in your case it's an unbound symbol (that is, it does not have a value, as such). You probably mean one of (- n 1) or (1- n) (they both have the value of "one subtracted from n").
In general, you do not need to loop through all the numbers lower than n, only to (isqrt n) (the integer square root of the number, this is the positive square root if you're looking at a square number and is always at least as large as a factor for a non-prime number).
Instead of using flag variables and setting them, wrap your primality checker in a function and return early of you find a factor.
(defun primep (n)
(loop for i from 2 upto (isqrt n)
if (zerop (mod n i))
do (return-from primep nil))
'prime)
I need a function that will check if all digits in some number on even positions are even. The least significant digit is on position 1, starting from right to left. The function need to be written in lisp.
Examples:
245 -> true, since 4 is even
238456 -> false, since 5 is odd and 8 and 2 are even
and so on...
Here`s what I got:
(defun check(number fac)
(cond
((= (/ number fac) 0) t)
((= (mod (/ number fac) 2 ) 0) (check number (* 100 fac) ) )
(nil)))
The initial value for fac is 10, we divide the number with 10, extract the second digit, check if it is even, if so proceed and divide number with 1000 to extract the 4-th digit and so on until we get over all digits, than the function returns true, meanwhile if some digit is odd the function should return nil.
But something is wrong and the function return nil all the time , when I call it like (check 22 10) for example.
Any thoughts?
Here is a non recursive solution that checks for the correctness of the parameter:
(defun check(num)
(assert (integerp num))
(loop for i = (truncate num 10) then (truncate i 100) until (zerop i)
always (evenp i)))
Just another variant. Basicly I'm converting number to list (through string though, maybe not the best way), then reverse it, select every second element and check it all for being even.
;; Helper for getting every
(defun get-all-nth (list period)
"Get all NTH element in the list"
(remove-if-not
(let ((iterator 0))
(lambda (x)
(declare (ignore x))
(= 0 (mod (incf iterator) period)))) list))
(defun check-evens (num)
"Checks if all digits in some number on even positions are even.
Goes Rigth-to-left."
(assert (integerp num))
(every #'evenp
(get-all-nth
(reverse
(map 'list #'digit-char-p
(prin1-to-string num))) 2)))
Some test cases:
CL-USER> (check-evens 123)
T
CL-USER> (check-evens 238456)
NIL
CL-USER> (check-evens 238446)
T
CL-USER> (check-evens 23844681)
T
I want to test this list whether it's palindrome or not by comparing first element with last element , second element with before the last element and so on
(setq l '(1 5 7 8 8 7 5 1))
(defun f (l)
(cond ((null l) 0)
((atom l) l)
(if (equal (car l) (car(cdr l))))
Is there a reason for this way of comparing them? If not, it would be easier to use the reverse function:
(defun palindrome-p (l)
(equal l (reverse l)))
The #Pascal solution reverses the entire list to check if it is palindrome, but this is not necessary. Why not reverse only half of it?
(defun palindrome-p (l)
(let* ((half (floor (length l) 2))
(secondhalf (reverse (nthcdr half l))))
(loop for x in l
for y in secondhalf
always (eq x y))))
This solution (which, I have to admit, is more “common-lispy” and less “lispy”) allocates only half of memory of the solution that reverses the entire list, and in CCL, on my laptop, for long lists uses less then half time.
Another option that conses only half the list:
(defun palindrome-p (list)
(let* ((length (length list))
;; The following lists will NOT include the middle element if length is odd
(half-length (ceiling length 2))
(tail (nthcdr half-length list))
(reversed-head (nreverse (butlast list half-length))))
(equal tail reversed-head)))
The thing about this option is that you get two lists of similar length, you don't have to worry about whether iteration stops at the smallest one, and it's easier to adapt and debug later for other purposes.
Yet another option that is usually disregarded is to copy the whole list into a vector. Most implementations take 1 or 2 architecture words (32-bit/64-bit) to represent a cons, thus the worst case for a list is:
2 × length words
These same implementations take about 1 to 2 words for the vector's header, plus 1 word per element, thus the worst case for a vector is:
2 + length words
What I mean is, you'll have about the same memory allocation cost for consing half of the list compared to copying the whole list into a vector.
The compromise is to find out when the header is no longer much of an overhead compared to consing and (n)reversing the list, or from accessing the nth element of a not-that-small list.
If this threshold is found, I'd redefine it as follows, making it accept a sequence:
;; Mere example, I did not research this on any implementation
(defconstant +list-to-vector-overhead-threshold+ 8)
(defun palindrome-p (sequence)
(if (and (consp sequence)
(not (null (nthcdr +list-to-vector-overhead-threshold+ sequence))
(palindrome-p (concatenate 'vector sequence)
(let ((length (length sequence)))
(dotimes (i (floor length 2))
(when (not (equal (elt sequence i) (elt sequence (- length i 1))))
(return nil)))
t)))
PS: Here's some implementations' object sizes found by experimentation (meaning, I might be wrong about these numbers) with 32-bit implementations:
Allegro CL
List: 2 × length words
Vector: 2 + length words, 2 words aligned (i.e. in 32-bit, 8-byte aligned)
Clozure CL
List: 2 × length words
Vector: 1 + length words, 2 words aligned (i.e. in 32-bit, 8-byte aligned)
LispWorks
List: 3 × length words
Vector: 2 + length words
SBCL
List: 2 × length words
Vector: 2 + length words
; Get the reverse of a list
(defun revList (l)
(cond
((null (cdr l)) l)
(t (append (revList (cdr l)) (list(car l) ) ))
)
)
; Check whether a given a list is a palindrome
(defun palindrome (l)
(cond ((null l) t)
((equal (car l) (car (last l)))(palindrome (cdr (revList (cdr l)))))
)
)
This implements a recursive function that returns (t) if a string (represented as a flat list of atoms) is a palindrome and (nil) otherwise. you can use the built-in "reverse" lisp function instead of "revList".
(defun palind (l1)
(if (equal l1 (reverse l1))
'palindrome
'no-palindrome))
Right now I"m working on a program that should be able to pick 3 people out of a list of 7 ( a b c d e f g) and assign them to be criminals. This "game" then picks 3 random peolpe out of the 7, tells you how many of those people are criminals and asks if you want to guess who the three criminals are, having one guess ( "two of these three are crimnals would you like to guess who the criminals are). However, I currently have a program that pulls 3 random criminals from the list, however the struggle I"m having is initially assigning who's a criminal or not ( randomly picking 3 out of a list and assigning them to values that can be recalled later ) and then being able to print that back out. This is my code so far and I was hoping somebody could point me in the right direction, I'm still very new to functional programming as a whole.
;allows us to use prompt to ask the user for input
(defun prompt-read (prompt)
(format *query-io* "~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
;allows you to add elements in needed spots
(defun element-at (org-list pos &optional (ini 1))
(if (eql ini pos)
(car org-list)
(element-at (cdr org-list) pos (+ ini 1))))
(defun element-at (lista n)
(if (= n 1)
(first lista)
(element-at (rest lista) (1- n))))
;allows for the removal of unneeded elements
(defun remove-at (org-list pos &optional (ini 1))
(if (eql pos ini)
(cdr org-list)
(cons (car org-list) (remove-at (cdr org-list) pos (+ ini 1)))))
;returns a chosen number of random elements from a list
(defun rnd-select (org-list num &optional (selected 0))
(if (eql num selected)
nil
(let ((rand-pos (+ (random (length org-list)) 1)))
(cons (element-at org-list rand-pos) (rnd-select (remove-at org-list rand-pos) num (+ selected 1))))))
;returns 3 random criminals from a list of 7
(defun rnd-criminals ()
(rnd-select '(a b c d e f g) 3))
(defun game ()
(prompt-for-players))
;allows for the storing of number of players
(defun num-of-players(number)
(list :number number))
;prompts for the amount of players you want to play
(defun prompt-for-players ()
(num-of-players
(or (parse-integer (prompt-read "How many players are there?"
:junk-allowed t) 0))))
This is a sampling without replacement problem (since, I'd assume, you wouldn't want to "pick three criminals" by picking the same person from the list each time). There are lots of ways to do this. One way is to generate indices until you've got enough distinct ones. How about something like this:
(defun pick (sequence n)
"Return n elements chosen at random from the sequence."
(do ((len (length sequence)) ; the length of the sequence
(indices '()) ; the indices that have been used
(elements '())) ; the elements that have been selected
((zerop n) ; when there are no more elements to select,
elements) ; return the elements that were selectd.
(let ((i (random len))) ; choose an index at random
(unless (member i indices) ; unless it's been used already
(push i indices) ; add it to the list of used indices
(push (elt sequence i) elements) ; and grab the element at the index
(decf n))))) ; and decrement n.
If you're not so familiar with do, you could use a recursive approach, e.g., with a local recursive function:
(defun pick2 (sequence n &aux (len (length sequence)))
(labels ((pick2 (indices elements n)
(if (zerop n) ; if no more elements are needed,
elements ; then return elements.
(let ((i (random len))) ; Otherwise, pick an index i.
;; If it's been used before,
(if (member i indices)
;; then continue on with the same indices,
;; elements, and n.
(pick2 indices elements n)
;; else, continue with it in the list of
;; indices, add the new element to the list of
;; elements, and select one fewer elements
;; (i.e., decrease n).
(pick2 (list* i indices)
(list* (elt sequence i) elements)
(1- n)))))))
;; Start the process off with no indices, no elements, and n.
(pick2 '() '() n)))
Another approach would one based on Efficiently selecting a set of random elements from a linked list which suggests Reservoir Sampling.
I have a problem with some part of my lisp code. It is a sudoku table generator. It works fine until this part:
(loop for e in entries do
(if (and (not (member e sub))
(not (member e col)))
(progn (setq choices (nconc choices (list e)))
(print choices)))
(if (= (length choices) 1)
(setq pick (car choices))
(if (not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
Basically, I am on a row x and a column y, and I need to insert an element. I watch the submatrix for this element and for column, and I choose the number that isn't appearing in any of the above and put it there. That's the "pick" variable. The problem is that sometimes the "choices" variable gets NIL value although in entries loop it has the right value. When it gets NIL, the pick value stays the same as it was in last loop (I am looping in columns and rows, above this snippet), making my final table have invalidated output (double values in a row, for example). How can I track where the choices variable changes? I work with it only in this snippet and I don't understand why it changes suddenly to nil.
For instance, I usually have:
in entries loop: choices (5)
Out of entries loop: choices (5)
in entries loop: choices (6 7)
Out of entries loop: choices (6 7) and after that this one:
in entries loop: choices nil.
Thank you.
First, some reformatting:
(loop for e in entries do
(if (and (not (member e sub))
(not (member e col)))
(progn (setq choices (nconc choices (list e)))
(print choices)))
(if (= (length choices) 1)
(setq pick (car choices))
(if (not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
Then, if you don't need the alternative clause of if, but want a progn, you can use when:
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(if (= (length choices) 1)
(setq pick (car choices))
(if (not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
The last two if clauses are mutually exclusive, so either cond or case would be appropriate (I'll use cond for now):
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (= (length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
There is a zerop predicate:
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (+ 0 (length choices))) choices))))
I don't see what adding 0 to some value should accomplish:
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices))))
Unless you are sure that pick is set to a sensible default to begin with, you should perhaps have a default case (this may be one of your problems):
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(setq choices (nconc choices (list e)))
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil))
Instead of using setq and nconc, you can use push (this puts the new element at the start of the list, but since you pick randomly anyway, this shouldn't be a concern):
(loop for e in entries do
(when (and (not (member e sub))
(not (member e col)))
(push e choices)
(print choices))
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil))
I suspect that at the start of this snippet, choices is supposed to be (), that you don't need choices after this snippet, and that printing choices is just for debugging, so you could do this in a different way by using remove-if and changing the condition:
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(cond ((= (length choices) 1)
(setq pick (car choices)))
((not (zerop (length choices)))
(setq pick (nth (random (length choices)) choices)))
(t
(setq pick nil)))
If choices is printed as () now, it means that there are no choices left here, so you will have to do some backtracking then (or whatever your algorithm does when a dead end is reached).
Finally, since (length choices) can only be non-negative integers, you can use case instead of cond if you test the cases in different order:
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(case (length choices)
(0 (setq pick nil))
(1 (setq pick (car choices)))
(otherwise (setq pick (nth (random (length choices)) choices)))))
Update by request.
As Rainer points out, this is basically the body of a pick function, so we can get rid of all the free variables. Also, instead of car, you can use the (for lists) more descriptive name first:
(defun pick (entries sub col)
(let ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries)))
(print choices)
(case (length choices)
(0 nil)
(1 (first choices))
(otherwise (nth (random (length choices)) choices)))))
This function would be defined elsewhere, and in the snippet's place, it would be called like this:
(pick entries sub col)
In order not to compute (length choices) twice, we can put that into the let (which needs to become let* for serial evaluation):
(defun pick (entries sub col)
(let* ((choices (remove-if (lambda (e)
(or (member e sub)
(member e col)))
entries))
(choices-length (length choices)))
(print choices)
(case choices-length
(0 nil)
(1 (first choices))
(otherwise (nth (random choices-length) choices)))))
A final step (really optional, but perhaps you discover that you have more sequences reducing your choices, e.g. row) would be a little generalization:
(defun pick (entries &rest exclusion-sequences)
(let* ((choices (remove-if (lambda (e)
(some #'identity
(mapcar (lambda (seq)
(member e seq))
exclusion-sequences)))
entries))
(choices-length (length choices)))
(print choices)
(case choices-length
(0 nil)
(1 (first choices))
(otherwise (nth (random choices-length) choices)))))
The call to this function is of the same shape, but you can now use any number of exclusion sequences:
(pick entries col sub row ver ima fou)
A potential source of trouble is NCONC.
nconc is destructively modifying the first list. If that is unwanted, use APPEND instead.
A second source of problem with NCONC is the use of literal lists.
Example:
(defun foo (bar) (let ((l '(1 2 3))) ...))
Here '(1 2 3) is a literal list. The effects of destructively modifying such a list is undefined in Common Lisp. Thus it should be avoided. What to do instead?
cons the list: (list 1 2 3)
copy the literal list: (copy-list l)
use non destructive operations (APPEND instead of NCONC, ...)
My Lisp is quite rusty, but I don't see any backtracking there... and I think you cannot just start putting numbers randomly and expect that they will make a proper sudoku game.
It seems that the list is nil because there are no possible options and thus is not created. You should handle that.
This is not a proper answer, but I did fix the indentation to make the code a bit more legible to myself and other answerers:
(loop for e in entries do
(if (and (not (member e sub)) (not (member e col)))
(progn (setq choices (nconc choices (list e)))
(print choices) ))
(if (= (length choices) 1) (setq pick (car choices))
(if (not (=(length choices) 0))
(setq pick (nth (random (+ 0 (length choices))) choices))))
Questions:
Is entries a list of lists? Does each list represent a row?
What are the values 'sub' and 'col' set to?