I'm trying to write a function in Common Lisp to convert a base 10 number into a base 8 number, represented as a list, recursively.
Here's what I have so far:
(defun base8(n)
(cond
((zerop (truncate n 8)) (cons n nil))
((t) (cons (mod n 8) (base8 (truncate n 8))))))
This function works fine when I input numbers < 8 and > -8, but the recursive case is giving me a lot of trouble. When I try 8 as an argument (which should return (1 0)), I get an error Undefined operator T in form (T).
Thanks in advance.
Just for fun, here's a solution without recursion, using built-in functionality:
(defun base8 (n)
(reverse (coerce (format nil "~8R" n) 'list)))
It seems you have forgotten to (defun t ...) or perhaps it's not the function t you meant to have in the cond? Perhaps it's t the truth value?
The dual namespace nature of Common Lisp makes it possible for t to both be a function and the truth value. the difference is which context you use it and you clearly are trying to apply t as a function/macro.
Here is the code edited for the truth value instead of the t function:
(defun base8(n)
(cond
((zerop (truncate n 8)) (cons n nil))
(t (cons (mod n 8) (base8 (truncate n 8))))))
(base8 8) ; ==> (0 1)
Related
I am writing a recursive function. But the question requires you not to use the exponential function. Can anyone show me how to get larger powers by multiplying smaller powers by a?
Input a=2 n=4. Then get[2, 4, 8, 16]
Input a=3 n=4. Then get[3 9 27 81].
I was trying to multiply a by a each time, so when I input 2 and 4. I get [2 4 16 256]. So what should I do?
Here is what I have written:
(define (input a n)
(if (= n 0)
'()
(append (cdr (list [* a a] a))
(let ((a (* a a)))
(input a (- n 1))))))
You are approaching the problem wrong, you really need two recursive functions (one to build the list and one to build each element). I am assuming you are allowed to use local, but if you aren't you could move that into a helper function.
(define (build-sqr-list a n)
(local [(define (sqr-recurse a n)
(if (= n 0)
1
(* a (sqr-recurse a (sub1 n)))))]
(if (= n 0)
'()
(cons (sqr-recurse a n) (build-sqr-list a (sub1 n))))))
As part of some Eulerian travails, I'm trying to code a Sieve of Eratosthenes with a factorization wheel. My code so far is:
(defun ring (&rest content)
"Returns a circular list containing the elements in content.
The returned list starts with the first element of content."
(setf (cdr (last content)) content))
(defun factorization-wheel (lst)
"Returns a circular list containing a factorization
wheel using the list of prime numbers in lst"
(let ((circumference (apply #'* lst)))
(loop for i from 1 to circumference
unless (some #'(lambda (x) (zerop (mod i x))) lst)
collect i into wheel
finally (return (apply #'ring
(maplist
#'(lambda (x) ; Takes exception to long lists (?!)
(if (cdr x)
(- (cadr x) (car x))
(- circumference (car x) -1)))
wheel))))))
(defun eratosthenes (n &optional (wheel (ring 4 2)))
"Returns primes up to n calculated using
a Sieve of Eratosthenes and a factorization wheel"
(let* ((candidates (loop with s = 1
for i in wheel
collect (setf s (+ i s))
until (> s n))))
(maplist #'(lambda (x)
(if (> (expt (car x) 2) n)
(return-from eratosthenes candidates))
(delete-if
#'(lambda (y) (zerop (mod y (car x))))
(cdr x)))
candidates)))
I got the following result for wheels longer than 6 elements. I didn't really understand why:
21 > (factorization-wheel '(2 3 5 7 11 13))
(16 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 ...)
21 > (factorization-wheel '(2 3 5 7 11 13 17))
> Error: Too many arguments.
> While executing: FACTORIZATION-WHEEL, in process listener(1).
The algorithm seems to be working OK otherwise and churns out primes with wheels having 6 or fewer elements.
Apparently apply or ring turn up their noses when long lists are passed to them.
But shouldn't the list count as a single argument? I admit I'm thoroughly flummoxed. Any input is appreciated.
ANSI Common Lisp allows implementations to constrain the maximum number of arguments which can be passed to a function. This limit is given by call-arguments-limit can be as small as 50.
For functions which behave like algebraic group operators obeying the
associative property (+, list, and others), we can get around the limit by using reduce to decimate the input list while treating the function as binary.
For instance to add a large list of numbers: (reduce #'+ list) rather than (apply #'+ list).
Notes on reduce
In Common Lisp, reduce will appear to work even if the list is empty. Few other languages give you this, and it doesn't actually come from reduce: it won't work for all functions. But with + we can write (reduce #'+ nil) and it calculates zero, just like (apply #'+ nil).
Why is that? Because the + function can be called with zero arguments, and when called with zero arguments, it yields the identity element for the additive group: 0. This dovetails with the reduce function.
In some other languages the fold or reduce function must be given an initial seed value (like 0), or else a nonempty list. If it is given neither, it is an error.
The Common Lisp reduce, if it is given an empty list and no :initial-value, will call the kernel function with no arguments, and use the return value as the initial value. Since that value is then the only value (the list is empty), that value is returned.
Watch out for functions with special rules for the leftmost argument. For instance:
(apply #'- '(1)) -> -1 ;; same as (- 1), unary minus semantics.
(reduce #'- '(1)) -> 1 ;; what?
What's going on is that when reduce is given a one-element list, it just returns the element without calling the function.
Basically it is founded on the mathematical assumption mentioned above that if no :initial-value is supplied then f is expected to support (f) -> i, where i is some identity element in relation to f, so that (f i x) -> x. This is used as the initial value when reducing the singleton list, (reduce #'f (list x)) -> (f (f) x) -> (f i x) -> x.
The - function doesn't obey these rules. (- a 0) means "subtract zero from a" and so yields a, whereas (- a) is the additive inverse of a, probably for purely pragmatic, notational reasons (namely, not making Lisp programmers write (- 0 a) just to flip a sign, just for the sake of having - behave more consistently under reduce and apply). The - function also may not be called with zero arguments.
If we want to take a list of numbers and subtract them all from some value x, the pattern for that is:
(reduce #'- list-of-numbers :initial-value x)
(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1))))))
This program is designed to take a number and a function as inputs and do the following..
f(1) + f(2) + f(3)+ … + f(N).
An example input would be:
(generalized-triangular square 3)
The Error message:
if: bad syntax;
has 4 parts after keyword in: (if (= n 1) 1 (+ (input n) (generalized-triangular (- n 1))) input)
The error is quite explicit - an if form can only have two parts after the condition - the consequent (if the condition is true) and the alternative (if the condition is false). Perhaps you meant this?
(if (= n 1)
1
(+ (input n) (generalized-triangular input (- n 1))))
I moved the input from the original code, it was in the wrong place, as the call to generalized-triangular expects two arguments, in the right order.
For the record: if you need to execute more than one expression in either the consequent or the alternative (which is not the case for your question, but it's useful to know about it), then you must pack them in a begin, for example:
(if <condition> ; condition
(begin ; consequent
<expression1>
<expression2>)
(begin ; alternative
<expression3>
<expression4>))
Alternatively, you could use a cond, which has an implicit begin:
(cond (<condition> ; condition
<expression1> ; consequent
<expression2>)
(else ; alternative
<expression3>
<expression4>))
Literal answer
The code you posted in your question is fine:
(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1))))))
The error message in your question would be for something like this code:
(define generalized-triangular
(lambda (input n)
(if (= n 1)
1
(+ (input n) (generalized-triangular (- n 1)))
input)))
The problem is input. if is of the form (if <cond> <then> <else>). Not counting if itself, it has 3 parts. The code above supplies 4.
Real answer
Two tips:
Use DrRacket to write your code, and let it help you with the indenting. I couldn't make any sense of your original code. (Even after someone edited it for you, the indentation was a bit wonky making it still difficult to parse mentally.)
I don't know about your class, but for "real" Racket code I'd recommend using cond instead of if. Racket has an informal style guide that recommends this, too.
here's the tail-recursive
(define (generalized-triangular f n-max)
(let loop ((n 1) (sum 0))
(if (> n n-max)
0
(loop (+ n 1) (+ sum (f n))))))
Since you're using the racket tag, I assume the implementation of generalized-triangular is not required to use only standard Scheme. In that case, a very concise and efficient version (that doesn't use if at all) can be written with the racket language:
(define (generalized-triangular f n)
(for/sum ([i n]) (f (+ i 1))))
There are two things necessary to understand beyond standard Scheme to understand this definition that you can easily look up in the Racket Reference: how for/sum works and how a non-negative integer behaves when used as a sequence.
I've attempted to solve Euler Problem 2 with the following tail recursive functions:
(defun fib (num)
(labels ((fib-helper (num a b)
(cond ((or (zerop num)
(eql num 1))
a)
(t (fib-helper (decf num)
(+ a b)
a)))))
(fib-helper num 1 1)))
(defun sum-even-fib (max)
(labels ((helper (sum num)
(cond ((oddp num) (helper sum (decf num)))
((zerop num) sum)
(t (helper (+ sum (fib num))
(decf num))))))
(helper 0 max)))
Now, when I try to print the result using the function
(defun print-fib-sum (max dir file)
(with-open-file
(fib-sum-str
(make-pathname
:name file
:directory dir)
:direction :output)
(format fib-sum-str "~A~%" (sum-even-fib max))))
with a max value of 4000000, I get the error
("bignum overflow" "[Condition of type SYSTEM::SIMPLE-ARITHMETIC-ERROR]" nil)
from *slime-events*. Is there any other way to handle the number and print to the file?
First, a few small issues:
Use time instead of top.
Common Lisp standard does not require tail recursion optimization. While many implementation do it, not all of them optimize all cases (e.g., labels).
Your algorithm is quadratic in max because it computes the nth Fibonacci number separately for all indexes. You should make it linear instead.
You are computing the sum of even-indexed numbers, not even-valued numbers.
Now, the arithmetic error you are seeing: 4,000,000th Fibonacci number is pretty large - about 1.6^4M ~ 10^835951. Its length is about 2,776,968.
Are you sure your lisp can represent bignums this big?
So I've solved Euler #2 with the following tail recursive code:
(defun rev-sum-even-fib (max-val)
(labels ((helper (sum a b)
(cond ((oddp a)
(helper sum (+ a b) a))
((> a max-val)
sum)
(t
(helper (+ sum a) (+ a b) a)))))
(helper 0 1 0)))
Here, the algorithm is linear in max and evaluates in
(time (rev-sum-even-fib 4000000))
Real time: 3.4E-5 sec.
Run time: 0.0 sec.
Space: 0 Bytes
Where I've omitted the numerical answer for obvious reasons.
Since CL does not promise that it supports TCO (for example ABCL on the JVM does not support TCO - tail call optimization), it makes sense to write it portably as a loop:
(defun rev-sum-even-fib (max-val)
(loop for a = 1 then (+ a b) and b = 0 then a
until (> a max-val)
when (evenp a) sum a))
I want to calculate the sum of digits of a number in Scheme. It should work like this:
>(sum-of-digits 123)
6
My idea is to transform the number 123 to string "123" and then transform it to a list '(1 2 3) and then use (apply + '(1 2 3)) to get 6.
but it's unfortunately not working like I imagined.
>(string->list(number->string 123))
'(#\1 #\2 #\3)
Apparently '(#\1 #\2 #\3) is not same as '(1 2 3)... because I'm using language racket under DrRacket, so I can not use the function like char->digit.
Can anyone help me fix this?
An alternative method would be to loop over the digits by using modulo. I'm not as used to scheme syntax, but thanks to #bearzk translating my Lisp here's a function that works for non-negative integers (and with a little work could encompass decimals and negative values):
(define (sum-of-digits x)
(if (= x 0) 0
(+ (modulo x 10)
(sum-of-digits (/ (- x (modulo x 10)) 10)))))
Something like this can do your digits thing arithmetically rather than string style:
(define (digits n)
(if (zero? n)
'()
(cons (remainder n 10) (digits2 (quotient n 10))))
Anyway, idk if its what you're doing but this question makes me think Project Euler. And if so, you're going to appreciate both of these functions in future problems.
Above is the hard part, this is the rest:
(foldr + (digits 12345) 0)
OR
(apply + (digits 1234))
EDIT - I got rid of intLength above, but in case you still want it.
(define (intLength x)
(define (intLengthP x c)
(if (zero? x)
c
(intLengthP (quotient x 10) (+ c 1))
)
)
(intLengthP x 0))
Those #\1, #\2 things are characters. I hate to RTFM you, but the Racket docs are really good here. If you highlight string->list in DrRacket and hit F1, you should get a browser window with a bunch of useful information.
So as not to keep you in the dark; I think I'd probably use the "string" function as the missing step in your solution:
(map string (list #\a #\b))
... produces
(list "a" "b")
A better idea would be to actually find the digits and sum them. 34%10 gives 4 and 3%10 gives 3. Sum is 3+4.
Here's an algorithm in F# (I'm sorry, I don't know Scheme):
let rec sumOfDigits n =
if n<10 then n
else (n%10) + sumOfDigits (n/10)
This works, it builds on your initial string->list solution, just does a conversion on the list of characters
(apply + (map (lambda (d) (- (char->integer d) (char->integer #\0)))
(string->list (number->string 123))))
The conversion function could factored out to make it a little more clear:
(define (digit->integer d)
(- (char->integer d) (char->integer #\0)))
(apply + (map digit->integer (string->list (number->string 123))))
(define (sum-of-digits num)
(if (< num 10)
num
(+ (remainder num 10) (sum-of-digits (/ (- num (remainder num 10)) 10)))))
recursive process.. terminates at n < 10 where sum-of-digits returns the input num itself.