End of file (character) in Common Lisp - lisp

Basically im trying to read lines from a file recursively (because i can't use any loop cycle), but i don't know where the file ends.
This is my function:
;; (get-problemas 0)
(defun get-problemas (indice &optional file (problemas '()))
(cond
((null file) (with-open-file (open "C:/Users/nunor/Desktop/problemas.dat" :direction :input :if-does-not-exist nil)
(get-problemas (1+ indice) open (cons (read open) nil))
)
)
(t (cond
((= indice 6) problemas)
(t (get-problemas (1+ indice) file (append problemas (cons (read file) nil))))
)
)
)
)
I'm using a counter 'indice' to stop de recursion because i dont kow how to stop when i reached the end of the file.
And i'm putting the lists that the file contains in to a list called 'problemas'.
The file looks like this:
(a (((0 0 0) (0 0 1) (0 1 1) (0 0 1)) ((0 0 0) (0 1 0) (0 0 1) (0 1 1))) 3)
(b (((0 0 0) (0 0 1) (0 1 1) (0 0 1)) ((0 0 0) (0 1 0) (0 0 1) (0 1 1))) 3)
(c (((0 0 0) (0 0 1) (0 1 1) (0 0 1)) ((0 0 0) (0 1 0) (0 0 1) (0 1 1))) 3)
(d (((0 0 0) (0 0 1) (0 1 1) (0 0 1)) ((0 0 0) (0 1 0) (0 0 1) (0 1 1))) 3)
(e (((0 0 0) (0 0 1) (0 1 1) (0 0 1)) ((0 0 0) (0 1 0) (0 0 1) (0 1 1))) 3)
(f (((0 0 0) (0 0 1) (0 1 1) (0 0 1)) ((0 0 0) (0 1 0) (0 0 1) (0 1 1))) 3)
I hope you can help me.

Look at some solutions that use loop and rewrite them into recursion. Take for example this one:
(defun get-file (filename)
(with-open-file (stream filename)
(loop for line = (read-line stream nil)
while line
collect line)))
Note the usage of (read-line stream nil), which returns nil at the end of the file. You can just repeatedly call it and save the result of each call until you will get nil:
(defun read-until-null (f)
(let ((result (read-line f nil)))
(unless (null result)
(cons result (read-until-null f)))))
(defun file-to-lines (path)
(with-open-file (f path :direction :input :if-does-not-exist nil)
(read-until-null f)))

This works for me:
(defun get-problemas (&optional file (problemas nil))
(if file
(let ((prob (read file nil)))
(if prob
(get-problemas file (cons prob problemas))
(nreverse problemas)))
(with-open-file (stream (open "problemas.dat" :direction :input))
(get-problemas stream))))
Notes:
We pass arguments to read so that it doesn't throw an error, but returns nil. We detect this nil to terminate the recursion.
Your tail recursion with explicit accumulator is good; I improved it by avoiding append and accumulating the output in reverse. When we terminate the recursion, we nreverse the reversed list of "problemas".
I got rid of the :if-does-not-exist nil. If the file doesn't exist, we want to bail, and not recurse.

Rather than all the hair about the file argument it's natural to split this into two functions. One deals with opening the file:
(defun get-problemas (&optional (file "C:/Users/nunor/Desktop/problemas.dat"))
(with-open-file (in file :direction :input)
(with-standard-io-syntax
(let ((*read-eval* nil))
(get-problemas/accumulate in '())))))
Note this uses with-standard-io-syntax and binds *read-eval* to nil which are both elementary safety precautions which far too few Lisp programmers use.
The second, recursive, function builds the list of problems. It uses a trick which also seems to be unknown to too many Lisp programmers: to detect the end of file you return the stream itself since this is an object which can't (without great heroics) be in data read from the file:
(defun get-problemas/accumulate (in accumulation)
(let ((got (read in nil in)))
(if (eql got in)
(reverse accumulation)
(get-problemas/accumulate in (cons got accumulation)))))

I managed to solve my problem.
To know if i reached the end of the file i used "(read file nil 'eof)", if it reached the end of the file 'line' is going to be 'eof, and in cond i verify if 'line' is equal to 'eof so the recursion can stop.
This is how my function looks like now:
(defun get-problemas (&optional file (problemas '()))
(cond
((null file) (with-open-file (open "C:/Users/nunor/Desktop/problemas.dat" :direction :input :if-does-not-exist nil)
(get-problemas open (cons (read open) nil))
)
)
(t (let
(
(line (read file nil 'eof))
)
(cond
((eq line 'eof) problemas)
(t (get-problemas file (append problemas (cons line nil))))
)
)
)
)
)
Thank you for your help.

Related

Usage of DEFSETF

It is just really hard to understand from a standard description, so:
For instance, I'm trying to set a k-th position of some list (ls) to a specific value. Even have a function of my own, that gives acces to k-th elt.
(defun kth-elt (lst k)
(cond ((> 0 k) nil)
((equal 0 k) (car lst))
((< 0 k) (kth-elt (cdr lst) (- k 1))))).
Also made a function, that updates that value.
(defun kth-upd (lst k new)
(cond ((> 0 k) nil)
((equal 0 k) (setf (car lst) new))
((< 0 k) (kth-upd (cdr lst) (- k 1) new))))
Now i can actually use that, but i wanna understand the difference between it and DEFSETF. Also I still do not understand. how to "teach" defsetf to use these. Thx for help.
Based on your definitions, it is simply:
(defsetf kth-elt kth-upd)
Instead of using kth-upd, you can now use kth-elt and (setf kth-elt).
For example:
(let ((list (copy-list '(a b c d e f))))
(setf (kth-elt list 3) nil)
list)
=> (A B C NIL E F)
But the real benefits of using SETF consistently is that you can combine this setter with other ones. Just consider incrementing a value:
(let ((list (make-list 10 :initial-element 0)))
(incf (kth-elt list 3))
(incf (kth-elt list 5) 20)
list)
=> (0 0 0 1 0 20 0 0 0 0)
See also this answer from Rainer Joswig for more background on places and SETF.
Setf expander
Note that you are doing the list traversal twice: you first get the current value, then computes the new one; only then, you store the new value, starting from the beginning of the list:
0: (KTH-ELT (0 0 0 0 0 0 0 0 0 0) 3)
1: (KTH-ELT (0 0 0 0 0 0 0 0 0) 2)
2: (KTH-ELT (0 0 0 0 0 0 0 0) 1)
3: (KTH-ELT (0 0 0 0 0 0 0) 0)
3: KTH-ELT returned 0
2: KTH-ELT returned 0
1: KTH-ELT returned 0
0: KTH-ELT returned 0
0: (KTH-UPD (0 0 0 0 0 0 0 0 0 0) 3 1)
1: (KTH-UPD (0 0 0 0 0 0 0 0 0) 2 1)
2: (KTH-UPD (0 0 0 0 0 0 0 0) 1 1)
3: (KTH-UPD (0 0 0 0 0 0 0) 0 1)
3: KTH-UPD returned 1
2: KTH-UPD returned 1
1: KTH-UPD returned 1
0: KTH-UPD returned 1
This can also be seen by macroexpansion:
(incf (kth-elt list 3))
... is macroexpanded as:
(LET* ((#:LIST796 LIST) (#:NEW1 (+ 1 (KTH-ELT #:LIST796 3))))
(KTH-UPD #:LIST796 3 #:NEW1))
Another possible approach might be to use DEFINE-SETF-EXPANDER:
(define-setf-expander kth (list index)
(alexandria:with-gensyms (store cell)
(values `(,cell)
`((nthcdr ,index ,list))
`(,store)
`(setf (car ,cell) ,store)
`(car ,cell))))
The function returns 5 different code parts that can be assembled to access and modify a place. cell and store are local variables introduced using GENSYM.
The variable cell (i.e. the variable named after the fresh symbol bound to cell) will be bound to (nthcdr index list). store contains the value to set in the place. Here, it will be put at the appropriate place by using (setf (car cell) store). Also, the existing value in the place is (car cell). As you can see, we need to manipulate, under the hood, the cons cell we mutate (of course, an error is raised with empty lists).
The macroexpansion for (incf (kth list 3)) is:
(LET* ((#:CELL798 (NTHCDR 3 LIST)) (#:STORE797 (+ 1 (CAR #:CELL798))))
(SETF (CAR #:CELL798) #:STORE797))
The setter function knows how to access the place that holds the value we want to change, and can change it directly, which is more efficent than just a pair of reader/writer functions.
Remark about mutability
SETF is designed around mutable data. If you write an accessor for a key/value store on the network, so that (remote host key) will connect and retrieve a value, and (setf (remote host key) value) sends the new value back, then it is not guaranteed that the remote value is always updated when (remote host key) is used as an intermediate place.
For example, if the value is a list, (push val (remote host key)) will push on the local list created on your host, there is no obligation for setf to actually ensure the result is sent back to the network when it is part of a larger expression. That allows SETF to be efficient by mutating places, at the small cost of requiring you to be more explicit. In the preceding example, you have to write (setf (remote host key) new-list) directly (not as a nested place) to effectively send the new data back.
As an addendum to coredump's answer, it's worth noting that the following works, and is, in my opinion, much better than using defsetf:
(defun kth-elt (lst k)
(cond ((> 0 k) nil)
((= 0 k) (car lst))
((< 0 k) (kth-elt (cdr lst) (- k 1)))))
(defun (setf kth-elt) (new lst k)
(cond ((> 0 k) nil)
((= 0 k) (setf (car lst) new))
((< 0 k) (setf (kth-elt (cdr lst) (- k 1)) new))))
There are cases when you need defsetf but they are not that common.
(kth-elt itself is just a special-case of elt of course: in real life you don't need to write any of this.)

Test if all elements of a list are different from each other

I have a list of lists and want to test if all elements are different from each other, i.e. equal should return nil for all combinations of list elements.
E.g.
(defparameter feld '((1 0 0 5 5 0)
(0 0 0 0 0 0)
(1 1 5 5 0 0)
(0 1 0 1 5 5)
(5 5 1 0 1 0)
(1 0 1 0 5 5)))
I thought of using reduce but as far as I understand it only tests the equality of neighbors, as would do a loop construct like:
(loop for i below (length feld)
for j from 1
if (equal (nth i feld) (nth j feld)) return t)
Is there a simple way using a standard construct which I do not see at the moment or do I have to create a recursive function?
The whole data structure represents a "board game" where every list is a line on the board and each element in the inside-lists is a value of this very field. The three numerical values (0, 1 and 5) are something like empty, Symbol A and Symbol B. A valid board cannot have two identical lines. This is why I want to identify those.
Basically, it is like remove-duplicates without removing. In the meantime I was thinking about something like this:
(defun duplicates-p (lst)
(cond ((null lst) '())
((member (car lst) (cdr lst)) t)
(t (duplicates-p (rest lst)))))
Something like this:
(defun unique (lsts &aux (h (make-hash-table :test 'equal)))
(loop :for lst :in lsts
:never (gethash lst h)
:do (setf (gethash lst h) t)))

Explanation of Racket function using map, append, and a recursive call

This procedure takes a non-negative integer n and creates a list of all lists of n 0's or 1's in the specific order required for a truth table. I am just trying to understand how the map portion of the procedure works. I am particularly confused as to how append, map, and the recursive call to all-lists are working together in the second argument of the if. Any help would be greatly greatly appreciated!
(define all-lists
(lambda (n)
(if (= n 0)
'(())
(append (map (lambda (k) (cons 0 k)) (all-lists (- n 1)))
(map (lambda (k) (cons 1 k)) (all-lists (- n 1)))
))))
The best strategy to understand a recursive function is to try it with the case sligthly more complex than the terminal one. So, let's try it with n=1.
In this case, the function becomes:
(append (map (lambda (k) (cons 0 k)) (all-lists 0))
(map (lambda (k) (cons 1 k)) (all-lists 0))
that is:
(append (map (lambda (k) (cons 0 k)) '(()))
(map (lambda (k) (cons 1 k)) '(())))
So, the first map applies the function (lambda (k) (cons 0 k)) to all the elements of the list '(())), which has only an element, '(), producing '((0)) (the list containing an element obtained by the cons of 0 and the empty list), and in the same way the second map produces '((1)).
These lists are appended together yielding the list '((0) (1)), in other words, the list of all the lists of length 1 with all the possible combinations of 0 and 1.
In the case of n=2, the recursive case is applied to '((0) (1)): so the first map puts a 0 before all the elements, obtaining '((0 0) (0 1)), while the second map produces '((1 0) (1 1)). If you append together these two lists, you obtain '((0 0) (0 1) (1 0) (1 1)), which is the list of all the possible combinations, of length 2, of 0 and 1.
And so on, and so on...
Actually, the function is not well defined, since it calculates unnecessarily the value of (all-lists (- n 1)) two times at each recursion, so doubling its work, which is already exponential. So it could be made much more efficient by computing that value only once, for instance in the following way:
(define all-lists
(lambda (n)
(if (= n 0)
'(())
(let ((a (all-lists (- n 1))))
(append (map (lambda (k) (cons 0 k)) a)
(map (lambda (k) (cons 1 k)) a))))))
Separating statements along with 'println' can help understand what is happening:
(define (all-lists n)
(if (= n 0)
'(())
(let* ((a (all-lists (- n 1)))
(ol1 (map (λ (k) (cons 0 k)) a))
(ol2 (map (λ (k) (cons 1 k)) a))
(ol (append ol1 ol2)))
(println "---------")
(println ol1)
(println ol2)
(println ol)
ol)))
(all-lists 3)
Output:
"---------"
'((0))
'((1))
'((0) (1))
"---------"
'((0 0) (0 1))
'((1 0) (1 1))
'((0 0) (0 1) (1 0) (1 1))
"---------"
'((0 0 0) (0 0 1) (0 1 0) (0 1 1))
'((1 0 0) (1 0 1) (1 1 0) (1 1 1))
'((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))
'((0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1))
One can clearly see how outlists (ol1, ol2 and combined ol) are changing at each step.

Elements removal from list

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)))

Print long list split into X columns

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.