Add dolist variables to a list in LISP - list

I have two dolists. The first dolist has a variable i and the inner dolist has a variable j.
I want to make a final list li look like ((00)(01)(10)(11))
(setq mm '(0 1))
(setq li '())
(dolist (i mm)
(dolist (j mm)
(progn
(setq ans (cons ans (list (nth i mm)
(nth j mm)))))))
gives me
((((NIL 0 0) 0 1) 1 0) 1 1)

CL-USER 68 > (let ((ans ()))
(dolist (i mm (reverse ans))
(dolist (j mm)
(setq ans (cons (list (nth i mm)
(nth j mm))
ans)))))
((0 0) (0 1) (1 0) (1 1))

Got it.
The keyword "List" does the trick.
(dolist (i mm) (dolist(j mm) (progn (setq ans (append ans (list(list(nth i mm )(nth j mm))))))))

Related

Stackoverflow in Common Lisp Mergesort

I've written my first ever Common Lisp function and I'm having trouble tracking down where my error is being produced. How do I trouble shoot the following error:
Error: Stack overflow on value stack. While executing: TRUNCATE
Here is my code:
(defun mergelist (alist low mid high)
(setq i1 low)
(setq i2 (+ mid 1))
(setq i low)
(setq blist `())
(loop while (and (<= i1 mid) (<= i2 high)) do
(if (<= (nth i1 alist) (nth i2 alist))
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist))
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist))
)
)
(loop while (<= i1 mid) do
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist))
)
(loop while (<= i2 high) do
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist))
)
(setq j low)
(loop for j from j to high do
(setf (nth i alist) (nth i blist))
)
)
(defun mergesort (alist low high)
(when (< low high)
(mergesort alist low (/ (+ low high) 2))
(mergesort alist (/ (+ low high) (+ 2 1)) high)
(mergelist alist low (/ (+ low high) 2) high)
)
)
The following is how I'm testing the function:
(setq dlist `(5 1 4 2 3))
(mergesort dlist 0 4)
My expected return is:
(1 2 3 4 5)
There are quite a few things we can do to improve this code.
1. Indenting
Lisp has relatively little syntax, but we use indenting to help highlight the structure of the code. Most Lisp aware editors help manage that. The most obvious departure from the conventional indenting approach is closing parentheses on following lines. I've Indented the mergelist function to show a more readable function body - well, at least to me.
(defun mergelist (alist low mid high)
(setq i1 low)
(setq i2 (+ mid 1))
(setq i low)
(setq blist `())
(loop while (and (<= i1 mid) (<= i2 high)) do
(if (<= (nth i1 alist) (nth i2 alist))
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist))
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist))))
(loop while (<= i1 mid) do
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist)))
(loop while (<= i2 high) do
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist)))
(setq j low)
(loop for j from j to high do
(setf (nth i alist) (nth i blist))))
2. Setq's, setf's vs Let.
The code above creates variables in the top level environment by setq'ing them ( unless of course, you have defparametered them elsewhere). This can have some undesirable side effects as programs get larger ( what if two functions use "i" at the same time?) . Its better to use LET to create local lexical variables so something like
(defun mergelist-2 (alist low mid high)
(let ((i1 low)
(i2 (+ mid 1)
i (low)
blist '()))
(loop while (and (<= i1 mid) (<= i2 high)) do
(if (<= (nth i1 alist) (nth i2 alist))
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist))
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist))))
(loop while (<= i1 mid) do
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist)))
(loop while (<= i2 high) do
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist)))
(setq j low)
(loop for j from j to high do
(setf (nth i alist) (nth i blist))) ))
3. Forms can return values
A lisp form often returns a value. If we type in (+ 1 2) at the repl we will see 3. A defun will normally return a value usually as the last form in its body.
If we look at mergelist we see that it is not explicility returning any value but is instead trying to use the variable alist to communicate the return values. This does not work!
Lisp provides the trace facility which lets us understand what is going on inside
This is the first 16 lines of trace. My system craps out at line 600
0: (MERGESORT (5 1 4 2 3) 0 4)
1: (MERGESORT (5 1 4 2 3) 0 2)
2: (MERGESORT (5 1 4 2 3) 0 1)
3: (MERGESORT (5 1 4 2 3) 0 1/2)
4: (MERGESORT (5 1 4 2 3) 0 1/4)
5: (MERGESORT (5 1 4 2 3) 0 1/8)
6: (MERGESORT (5 1 4 2 3) 0 1/16)
7: (MERGESORT (5 1 4 2 3) 0 1/32)
8: (MERGESORT (5 1 4 2 3) 0 1/64)
9: (MERGESORT (5 1 4 2 3) 0 1/128)
10: (MERGESORT (5 1 4 2 3) 0 1/256)
11: (MERGESORT (5 1 4 2 3) 0 1/512)
12: (MERGESORT (5 1 4 2 3) 0 1/1024)
13: (MERGESORT (5 1 4 2 3) 0 1/2048)
14: (MERGESORT (5 1 4 2 3) 0 1/4096)
15: (MERGESORT (5 1 4 2 3) 0 1/8192)
16: (MERGESORT (5 1 4 2 3) 0 1/16384)
at line 600 you see
600: (MERGESORT (5 1 4 2 3) 0
1/1037378892220248239628101965922790287753111558060609224998914332422663202853227036599926762236775948572049471652825197295598787768852943826971718708528490921765295450850377380921344)
This is a very small number and explains the error message about truncate.
You can see that the alist array is not changing as we proceed down the call stack. Thats because the alist function parameter is local to each invocation of mergelist.
What we need to do is have mergelist return a value explicility each time its called.
(defun mergelist-3 (alist low mid high)
(let ((i1 low)
(i2 (+ mid 1)
i (low)
j
blist '()))
(loop while (and (<= i1 mid) (<= i2 high)) do
(if (<= (nth i1 alist) (nth i2 alist))
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist))
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist))))
(loop while (<= i1 mid) do
(setf (nth (+ i 1) blist) (nth (+ i1 1) alist)))
(loop while (<= i2 high) do
(setf (nth (+ i 1) blist) (nth (+ i2 1) alist)))
(setq j low)
(loop for j from j to high do
(setf (nth i alist) (nth i blist)))
*;return value here*
))
As a further hint , the last loop in the function is not needed.
Additionally, you will have to capture that return value in mergesort and have mergesort return an explicit value as well.
I would also recommend that you read a bit about the loop macro - google for "Practical Common Lisp Loop for Black belts" which will help you grasp the syntax and the sort of things you can do with loop.
Now, there are still a few things to fix in the code but I hope I've given you enough to get through this iteration
There is too much wrong with the code:
treats lists as vectors: if you want a Lisp data structure with random access, then use a vector. Not a list.
doesn't declare variables
while loops don't work at all
imperative, instead of functional
wrong code layout
Best to start from scratch and to avoid above mistakes. If you want Lisp lists, then use a different way to write a mergesort. Hint: lists are not like vectors. They might be used like that, but usually it's a mistake to do so.

Making a list from the position number of another list in Racket Advanced Student

I am currently trying to write a function that gives me a list with the position numbers of the position that contains the element 1 as elements.
Unfortunately, when I execute the following function it gives me '()which is the initial value of lst.
So I am not sure what to write for the case (< pos 0).
(define lst '())
(define (posj pos) (if (< pos 0)
lst
(begin (cond ((equal? (list-ref l pos) 1) (begin (set! lst (append (list* pos) '()))
(posj (- pos 1))))
(else (posj (- pos 1)))))))
(define l '(1 3 1 2 1 5 1))
(posj (- (length l) 1))
What you probably meant to write was this, with list instead of list*, lst instead of '(): (and with more standard indentation)
(define lst '())
(define (posj pos)
(if (< pos 0)
lst
(cond [(equal? (list-ref l pos) 1)
(begin
(set! lst (append (list pos) lst))
(posj (- pos 1)))]
[else
(posj (- pos 1))])))
(define l '(1 3 1 2 1 5 1))
(posj (- (length l) 1))
That works, but it relies on global variables (l and lst), which isn't a very good way of doing things. Then you can translate that from global variables into function arguments. The (set! lst (append ...)) can be replaced by passing the (append ...) as an argument:
(define (posj l lst pos)
(if (< pos 0)
lst
(cond [(equal? (list-ref l pos) 1)
(posj l (append (list pos) lst) (- pos 1))]
[else
(posj l lst (- pos 1))])))
(define l '(1 3 1 2 1 5 1))
(posj l '() (- (length l) 1))
So far l has just been the same list every time, when the part that you actually need shrinks every time. To fix that, you can iterate from front-to-back instead of back-front, and use first and rest in the recursion. Also the order of the arguments to append has to be switched because we're iterating in the other direction now, and the (< pos 0) check can be replaced by an (empty? l) check:
(define (posj l lst pos)
(if (empty? l)
lst
(cond [(equal? (first l) 1)
(posj (rest l) (append lst (list pos)) (+ pos 1))]
[else
(posj (rest l) lst (+ pos 1))])))
(define l '(1 3 1 2 1 5 1))
(posj l '() 0)
Now instead of using append it's much more efficient if you can use cons instead. That reverses lst, so rename it to rev-lst, and when you return it, reverse it again:
(define (posj l rev-lst pos)
(if (empty? l)
(reverse rev-lst)
(cond [(equal? (first l) 1)
(posj (rest l) (cons pos rev-lst) (+ pos 1))]
[else
(posj (rest l) rev-lst (+ pos 1))])))
(define l '(1 3 1 2 1 5 1))
(posj l '() 0)
Now it's starting to look a lot like the template for list functions, especially if you replace that if with a cond. Also, if you wanted to avoid passing '() and 0 as extra arguments, you could use either a helper function or a named let.
Your code doesn't work (append expects only lists) and is not the way to do it in Scheme for more than one reason.
I would suggest using a named let (classic Scheme):
(define (posj lst val)
(let loop ((lst lst) (pos 0) (res null))
(if (null? lst)
(reverse res)
(loop (cdr lst)
(add1 pos)
(if (= (car lst) val) (cons pos res) res)))))
or the more "rackety"
(define (posj lst val)
(reverse
(for/fold ((res null)) (((elt pos) (in-indexed lst)))
(if (= elt val) (cons pos res) res))))
then
> (posj '(1 3 1 2 1 5 1) 1)
'(0 2 4 6)
Since you're using Racket and presumably Dr Racket (the IDE),
use the automatic indentation feature, it helps a lot to make your code readable
in order to understand how this code works, use the build-in debugger to execute it step by step
read a Scheme tutorial which will teach you the common looping constructs, among other useful things.

Decimal to Binary in Lisp - make a non-nested list

When reaching my recursion cases, I use list to append the future result with the current one, but I end up with a nested list because of recursion. This causes an error when I have a number that causes recursion for more than five times.
Any ideas how I can get results in a single plain non-nested list, e.g.:
CL-USER 100 : 8 > (BINARY_LIST 4)
(1 0 0)
Code & Example output:
CL-USER 99 : 8 > (defun binary_list (i)
(COND
((= i 0) 0)
((= i 1) 1)
((= (mod i 2) 0) (list (binary_list (truncate i 2)) 0))
(t (list (binary_list (truncate i 2)) 1))
)
)
BINARY_LIST
CL-USER 100 : 8 > (BINARY_LIST 4)
((1 0) 0)
CL-USER 101 : 8 > (BINARY_LIST 104)
((((# 1) 0) 0) 0)
You are almost there. All you need to do is to replace list with nconc:
(defun binary-list (n)
(cond ((= n 0) (list 0))
((= n 1) (list 1))
(t (nconc (binary-list (truncate n 2)) (list (mod n 2))))))
You can avoid calling both truncate and mod by collecting both values in integer division:
(defun binary-list (n)
(assert (>= n 0))
(multiple-value-bind (q r) (floor n 2)
(if (zerop q)
(list r)
(nconc (binary-list q) (list r)))))
Note that this algorithm is quadratic because nconc has to traverse the result on each iteration. This can be avoided by passing an accumulator:
(defun binary-list (n &optional acc)
(assert (>= n 0))
(multiple-value-bind (q r) (floor n 2)
(if (zerop q)
(cons r acc)
(binary-list q (cons r acc)))))
Now we have a tail-recursive function which can be compiled to iteration by a modern compiler.
One more optimization trick you could use (which, in fact, should be done by the compiler - try disassemble to check!) is using ash and logand instead of the much more general and expensive floor:
(defun binary-list (n &optional acc)
(cond ((zerop n) (or acc (list 0)))
((plusp n)
(binary-list (ash n -1) (cons (logand 1 n) acc)))
(t (error "~S: non-negative argument required, got ~s" 'binary-list n))))
Incidentally, lispers usually use dash instead of underscores in symbols, so your binary_list should be binary-list if you do not want to offend our tender aesthetics.
this seems to me to be the most direct, least roundabout manner to achieve the desired results every time:
(defun mvp-binary-from-decimal (n r)
(if (zerop n)
r
(multiple-value-bind (a b)
(floor n 2)
(mvp-binary-from-decimal a (cons b r)))))
(defun binary-from-decimal (n)
(if (and (numberp n) (plusp n))
(mvp-binary-from-decimal n '())
(if (eql n 0) '(0) nil)))
tested in slime, sbcl, clisp - used as follows:
CL-USER> (binary-from-decimal 100)
(1 1 0 0 1 0 0)
CL-USER> (binary-from-decimal 10)
(1 0 1 0)
CL-USER> (binary-from-decimal 0)
(0)
there are some advanced reasons as to why this might be the most desirable manner in which to implement such functionality, but for now, suffice to say that it is clean, polite, readable and always works.

Create list from 2 numbers and 2 for loops

I have 2 numbers let's say number1=5 and number2=3 and I want to create a list in this form
((1(1 2 3)) (2(1 2 3)) (3(1 2 3)) (4(1 2 3)) (5(1 2 3)))
So the number1 indicates the number of the elements in the list and number2 indicates the total elements that will be as the second part of every element..
I have smth like this untill now
(define mylist '())
(define (pushlist item item2)
(do ((j 1 (+ j 1))) ((> j item2))
(set! mylist(list mylist (list item j)))))
(define (createlist number number2)
(do ((j 1 (+ j 1))) ((> j number))
(pushlist j number2)
))
(createlist 5 3)
Unfortunately it doesn't work.. It doesn't give the result I want.. It gives me this (((((((((((((((() (1 1)) (1 2)) (1 3)) (2 1)) (2 2)) (2 3)) (3 1)) (3 2)) (3 3)) (4 1)) (4 2)) (4 3)) (5 1)) (5 2)) (5 3))
There are many ways to solve this problem - for example, using explicit recursion, or using higher-order procedures. Your approach is not recommended, in Scheme you should try to avoid thinking about loops and mutation operations. Although it is possible to write such a solution, it won't be idiomatic. I'll try to explain how to write a more idiomatic solution, using explicit recursion first:
; create a list from i to n
(define (makelist i n)
(if (> i n)
'()
(cons i (makelist (add1 i) n))))
; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist i m n)
(if (> i m)
'()
(cons (list i (makelist 1 n))
(makenumlist (add1 i) m n))))
; call previous functions
(define (createlist number1 number2)
(makenumlist 1 number1 number2))
Now, an even more idiomatic solution would be to use higher-order procedures. This will work in Racket:
; create a list from i to n
(define (makelist n)
(build-list n add1))
; create a list from i to m, together with
; a list returned by makelist from 1 to n
(define (makenumlist m n)
(build-list m
(lambda (i)
(list (add1 i) (makelist n)))))
; call previous functions
(define (createlist number1 number2)
(makenumlist number1 number2))
See how we can avoid explicit looping? that's the Scheme way of thinking, the way you're expected to solve problems - embrace it!
I don't think that your pushlist procedure is doing what you you expect it to.
(define (pushlist item item2)
(do ((j 1 (+ j 1)))
((> j item2))
(set! mylist (list mylist (list item j)))))
If you have a list (x y z) and you want to push a new value v into it, you'd do
(set! lst (cons v lst))
because (cons v (x y z)) == (v x y z). By doing
(set! mylist (list mylist (list item j)))
you're making mylist always have exactly two elements, where the first is a deeper and deeper nested list. Óscar López's answer gives a more idiomatic approach to this problem. Here's a similar idiomatic approach:
(define (range n)
; returns a list (1 ... n)
(let rng ((n n) (l '()))
(if (zero? n)
l
(rng (- n 1) (cons n l)))))
If the sublists (1 ... n) can all be the same list (i.e., the actual list object is the same), then you can create it just once:
(define (createlist m n)
(let ((sublist (range n)))
(map (lambda (main)
(list main sublist))
(range m))))
Otherwise, if they need to be distinct, you can generate one for each of 1 ... m:
(define (createlist m n)
(map (lambda (main)
(list main (range n)))
(range m)))

Scheme split operation not working

I'm new to scheme and am having some trouble debugging my code.
; returns number of elements in a list
(define (length L)
(cond ((null? L) 0)
(else (+ (length (cdr L)) 1))))
; split the list in half:
; returns ((first half)(second half))
(define (split L)
(cond
((= (length L) 0) (list L L) )
((= (length L) 1) (list L '() ))
(else
(list (sublist L 1 (/ (length L) 2) 1)
(sublist L (+ (/ (length L) 2) 1) (length L) 1)))))
; extract elements start to end into a list
(define (sublist L start end counter)
(cond ((null? L) L)
((< counter start) (sublist (cdr L) start end (+ counter 1)))
((> counter end) '())
(else (cons (car L) (sublist (cdr L) start end (+ counter 1))))))
To me, this feels like it would split a single list into two sub lists. There may be an easier way to do this, and so I apologize if this seems cumbersome.
Anyway, the results:
Expected: (split '(1 2 3 4 5)) = ('(1 2) '(3 4 5))
Actual: (split '(1 2 3 4 5)) = ('(1 2) '(4 5))
It's clear that the length or split is losing the middle value, but I've checked it again and again and it seems to lose the middle value. It seems like an easy solution would be to get rid of the (+ 1) of (+ (/ (length L) 2) 1) but this seems counter intuitive to me, as:
Assume L = '(1 2 3 4 5), (/ (length L) 2) = 2, and (+ (/ (length L) 2) 1) = 3
(sublist L 1 (2) 1) = '(1 2)
(sublist L (3) 5 1) = '(3 4 5)
** I put parens around the 2 and 3 to indicate that they were length calculations.
Clearly an assumption I am making is false, or I am overlooking something trivial.
Thanks in advance!
Do you know the tortoise-and-hare algorithm? The tortoise walks the list, the hare runs the list at double speed. The split occurs at the position of the tortoise when the hare reaches the end of the list. Here's most of the code; I'll let you figure out the rest:
(define (split xs)
(let loop ((ts xs) (hs xs) (zs (list)))
(if (or (null? hs) (null? (cdr hs)))
(values (reverse zs) ts)
(loop ...))))
Here ts is the remaining list of items to be examined by the tortoise, hs is the remaining list of items to be examined by the hare, and zs is the list of items already examined by the tortoise, in reverse order.
Note that you never need to count the items in the input list.
I'm not going to debug your code for you. Instead, here's a simpler definition of split:
(define (split l)
(let ((n (length l)))
(list (take (/ n 2) l)
(drop (+ (/ n 2) (mod n 2)) l))))
Exercise for the reader: implement take and drop. The latter is just recursion on n while taking the cdr of l in the recursive case; the former takes slightly more effort to get right in the base case (stopping condition).
Here is almost your solution (Racket Scheme):
#lang racket
(define (length lst)
(cond [(empty? lst) 0]
[else (+ (length (rest lst)) 1)]))
(define (first-length lst)
(quotient (length lst) 2))
(define (second-length lst)
(- (length lst) (first-length lst)))
(define (sublist lst start end counter)
(cond [(empty? lst) lst]
[(< counter start) (sublist (rest lst) start end (+ counter 1))]
[(> counter end) '()]
[else (cons (first lst) (sublist (rest lst) start end (+ counter 1)))]))
(define (first-half-of-list lst)
(sublist lst 1 (first-length lst) 1))
(define (second-half-of-list lst)
(sublist lst (second-length lst) (length lst) 1))
(define (split lst)
(cond
[(= (length lst) 0) (list lst lst)]
[(= (length lst) 1) (list lst '())]
[else (list (first-half-of-list lst)
(second-half-of-list lst))]))
(split '(1 2 3 4 5))
=> '((1 2) (3 4 5))
Thank you for good brain exercise.
The key moment is 'second-length'-function.