Common Lisp - Gentle introduction to symbolic computation: Excercise 4.4 - lisp

I am learning Common Lisp using clisp and have entered following code:
(defun ordered (x y)
(if (< x y)
(list x y)
(list y x)))
(setq l (ordered 28 49))
(print l)
(setq l (ordered 49 28))
(print l)
Expected these answers:
(28 49)
(49 28)
Got these answers:
(28 49)
(28 49)
In the solutions of this book I have found the same function definition.
What could be wrong?

Your code
(defun
defines a function,
ordered
named "ordered",
(x y)
that expects two arguments which will be known as "x" and "y" in its body, whereupon on receiving the arguments (i.e. having been called with two values, e.g. (ordered 49 28))
(if (< x y)
it will compare them, and in case the first was smaller than the second, it will produce
(list x y)
the same two values repackaged in a list (i.e. '(49 28)); or otherwise, if the first value was not smaller than the second,
(list y x)))
it will produce the list containing the second value first, and then the first argument value (i.e. '(28 49)).
So, which was the case here, of comparing the 49 and 28?
Reading this code generally, we can say that if it receives the smaller number as its first argument, it will produce the smaller number first and the bigger number second, in the result list;
and in case it receives the smaller number as its second argument, it will produce the smaller number first and the bigger number second, in the result list.
Reading this back, we can see that this description can be simplified further into one simple statement: it will always produce ______ number first, and ______ second, in the resulting list.
Another way to attack this, is to write down the function created by that definition,
( lambda (x y) (if (< x y) (list x y) (list y x) ) )
Then follow its application symbolically:
( ( lambda (x y) (if (< x y) (list x y) (list y x) ) )
49
28 )
==
(let ( (x 49)
(y 28)
)
(if (< x y) (list x y) (list y x) ) )
==
(let ( (x 49)
(y 28)
)
(if (< 49 28) (list x y) (list y x) ) )
==
(let ( (x 49)
(y 28)
)
(if FALSE (list x y) (list y x) ) )
==
(let ( (x 49)
(y 28)
)
(list y x) )
==
(let ( (x 49)
(y 28)
)
(list 28 49) )
==
(list 28 49)

Related

Scheme Helper Function and always returning zero

I am trying to write a Scheme function that takes in a list of letters, hashes them with another function, multiplies each one iteratively by 5^i, and sums them together. I am new to Scheme and this is what I have written:
(define (key w)
keyhelper w 0)
(define (keyhelper w i)
(cond ((null? w) '())
(else (+ (* (hashchar(car w) (expt 5 i)) (keyhelper(cdr w) (+ i 1)))))))
So for example, doing (key '(h e l l o)) should do hashchar(h)*5^0 + hashchar(e)*5^1 + hashchar(l)^5^2 ... etc. The function is only returning 0 for any list that is sent in. Could anyone please tell me where I am going wrong?
My implementation of hashchar is:
(define hashchar
(lambda (x)
(cond
((eq? x 'a) 1)
((eq? x 'b) 2)
((eq? x 'c) 3)
((eq? x 'd) 4)
((eq? x 'e) 5)
((eq? x 'f) 6)
((eq? x 'g) 7)
((eq? x 'h) 8)
((eq? x 'i) 9)
((eq? x 'j) 10)
((eq? x 'k) 11)
((eq? x 'l) 12)
((eq? x 'm) 13)
((eq? x 'n) 14)
((eq? x 'o) 15)
((eq? x 'p) 16)
((eq? x 'q) 17)
((eq? x 'r) 18)
((eq? x 's) 19)
((eq? x 't) 20)
((eq? x 'u) 21)
((eq? x 'v) 22)
((eq? x 'w) 23)
((eq? x 'x) 24)
((eq? x 'y) 25)
((eq? x 'z) 26))))
key returns zero all the time because you defined it that way. You had:
(define (key w)
keyhelper
w
0)
thus, it evaluates keyhelper (discarding its value), then w (discarding its value), then 0 (returning its value). So the answer is always 0.
You should instead define it this way:
(define (key w)
(keyhelper w 0))
Notice the extra parentheses.
Also, the base-case value for keyhelper is wrong. It shouldn't be '(), it should be i.
If your definition of hashchar is similar to this one:
(define (hash:hash-char-ci char n)
(modulo (char->integer (char-downcase char)) n))
(define hash:hash-char hash:hash-char-ci)
Then hashchar will return 0 when i = 0 is passed to (expt 5 i) because (expt 5 i) is one, and the one-modulo of any integer is zero.
Once you multiply zero into your hash function, then you'll always get zero out...since + isn't doing anything but returning identity because it is only passed one argument:
(* (hashchar(car w) (expt 5 i)) (keyhelper(cdr w) (+ i 1)))
Maybe string-hash is a better choice of library function?

lisp - should be a lambda expression

I'm trying to return (values str ((+ x 3) y)) from the function it resides in.
code snippet:
(if (<my condition>)
(values str ((+ x 3) y))
(values str ((+ x 2) y)))
gives error:
(+ X 3) SHOULD BE A LAMBDA EXPRESSION
but (values str (y (+ x 3))) works fine.
why?
The S-expression ((+ x 3) y) cannot be evaluated because the first list element is not funcallable (it should name a function or be a lambda expression).
So, to avoid evaluation, you need to quote it:
(if (<my condition>)
(values str '((+ x 3) y))
(values str '((+ x 2) y)))
Then you will return a list of length 2 (containing a list of length 3 and a symbol y) as your second value. If, however, you want to return the values of (+ x 2) and y in the list, you will want to do something like
(values str (list (+ x (if <condition> 3 2)) y))
or maybe return 3 values instead of 2:
(values str
(+ x (if <condition> 3 2))
y)
On the other hand, y is a symbol, which, apparently, names a function in your image, so (y (+ x 3)) evaluates fine (it calls function y on the result of adding 3 to x).

Lisp function call syntax

I am trying to write a recursive code to do x^y but the problem no mater how I update the code it gives me an error.
The Code:
(defun power(x y) (if(> y 0) (* x (power(x (- y 1)))) (1)))
Error:
CL-USER 11 : 5 >Power 2 3
Error: Undefined operator X in form (X (- Y 1)).
Error:
CL-USER 11 : 5 >power(2 3)
Illegal argument in functor position: 2 in (2 3).
You're calling the function in the wrong way. In lisps function calls have the form:
(f a b c)
not
f(a b c)
You had (power (x (- y 1))) in your recursive definition, which in turn had (x (- y 1)) hence the error: x is not a function.
Use (power x (- y 1)) so your definition becomes:
(defun power (x y)
(if (> y 0)
(* x
(power x (- y 1)))
1))
and call it as (power 2 3)
To expand slightly on the previous (correct) answer, this version uses some idiomatic functions:
(defun power (x y)
(if (plusp y)
(* x (power x (1- y)))
1))
You cannot use parenthesis for grouping since CL thinks you want to call function x and function 1. Remove the excess like this:
(defun power(x y)
(if (> y 0)
(* x (power x (- y 1)))
1))
Parenthesis goes on the outside, just as in your function:
(power 2 3) ;==> 8
When you write (X ...) in a Lisp expression, you are asserting that X is a function to be called on the arguments ....
Your problem is you have too many parentheses in your expression. When you write (power (x ..
you've made this assertion. Write (power x ... instead.
You're calling, among others, this code:
(power (x (- y 1)))
So power is called with (x (- y 1)) as a parameter. Are you sure you want to call x as a function?

Deconstructing a recursive process - SICP

Consider the following definition:
(define foo
(lambda (x y)
(if (= x y)
0
(+ x (foo (+ x 1) y)))))
What is the test expression? (write the actual expression, not its value)
I would think it is just (if (= x y) but the MIT 6.001 On Line Tutor is not accepting that answer.
The test would be:
(= x y)
That's the expression that actually returns a boolean value, and the behaviour of the if conditional expression depends on it - if it's #t (or in general: any non-false value) the consequent part will be executed: 0. Only if it's #f the alternative part will be executed: (+ x (foo (+ x 1) y)).

Lisp List Printing

I am having some troubles regarding the lisp format function. I have the following list:
((X X X)(X X X X X X)(X X X X X X X X X))
and I need to print it in the following format:
X X X
XX XX XX
XXXXXXXXX
Any thoughts on how to achieve this? The format function is kinda confusing and the HyperSpec documentation doesn't seem to do anything for me. Thanks.
Like every tool format has its limitations and it's not suited for such problems very well. Probably the best you can get with plain format without resorting to black magic tricks with ~? or ~/, that you or anyone else probably won't understand in the future, is this code:
CL-USER> (format t "~{~{~A ~}~%~}"
'((X X X) (X X X X X X) (X X X X X X X X X)))
X X X
X X X X X X
X X X X X X X X X
If you want to get your sophisticated output structure, try to do some pre-processing.
Like, if the format of the list is hard-coded, you can use this:
(format t "~{~{~6A~} ~%~}"
(mapcar (lambda (l)
(loop :for i :from 0 :to (1- (length l)) :by (/ (length l) 3)
:collect (format nil "~{~A ~}"
(subseq l i (+ i (/ (length l) 3))))))
'((X X X) (X X X X X X) (X X X X X X X X X))))
Here we first collect the items of a list into same number of groups for each list, print them and this way get 3 lists with the same number of elements, which can then be processed by format.
You can find out more about format in the appropriate chapter of Peter Seibel's excelent Lisp book: http://gigamonkeys.com/book/a-few-format-recipes.html
EDIT
If you have a variable number of lists, with each one being twice bigger than the previous one, you'll also need to prepare the format string beforehand:
CL-USER> (defun format-custom-list (list)
(format t (format nil "~~{~~{~~~DA~~} ~~%~~}" (* 2 (length list)))
(mapcar (lambda (l)
(let* ((len (length l))
(len/3 (/ len 3)))
(loop :for i :from 0 :to (1- len) :by len/3
:collect (format nil "~{~A ~}"
(subseq l i (+ i len/3))))))
list)))
CL-USER> (format-custom-list '((X X X) (X X X X X X) (X X X X X X X X X)
(X X X X X X X X X X X X)))
X X X
X X X X X X
X X X X X X X X X
X X X X X X X X X X X X
NIL
(The trailing nil is the output of format, which isn't printed to the output stream t. If you want to get a string out of this function use nil as format's output stream.)
I'm assuming you want to print each list, inserting spaces to make elements fit max list length.
Though I believe it is possible to print this with nearly single format call, it is better to split printing into several functions:
(defun format-list (stream lst space-count)
(let ((spaces (make-string 5 :initial-element #\Space))) ;; create string of spaces to insert
(let ((fmt (concatenate 'string "~{~a" spaces "~}~%")) ;; create formatting string
(format stream fmt lst)))))
(defvar full-list '((X X X)(X X X X X X)(X X X X X X X X X)))
(defvar max-list-length (max (mapcar length full-list))) ;; find length
(mapcar
#'(lambda (lst) (format-list t lst (/ (- max-list-length (length lst)) (length lst))))
full-list)
UPD.
For X + Space * (NumRows - CurrentRowNumber) condition you can next function instead of 2 last lines in my original code (in functional style, you can also use loop instead of reduce to make it less functional and more CL-like):
(format-list-of-lists (lst)
(let ((num-rows (length lst)))
(reduce #(lambda (cur-row sub-list) (format-list t sub-list (- num-rows cur-row)) (1+ cur-row))
lst)))