Treating a part of program as data in Racket - racket

I must say that I don't know really know how to call what I'm looking for, so perhaps the title isn't that accurate.
I have a program that plots some points. The generate-list function produces a list of n (x,y) coordinates and get-points produces another list that has every x (from (x,y)) divisible by n.
I can definitely call points how many times I need, but I'm trying to reduce the process by writing the points function only once).
#lang racket
(require plot)
(define (generate-list n)
(if (= n 0)
empty
(cons (list (random 0 100) (random 0 100))
(generate-list (- n 1)))))
(define (get-points lst n)
(if (empty? lst)
empty
(if (= (remainder (caar lst) n) 0)
(cons (car lst) (get-points (cdr lst) n))
(get-points (cdr lst) n))))
(plot (list
(axes 0 0)
(points (get-points (generate-list 1000) 2)
#:color 2)
(points (get-points (generate-list 1000) 3)
#:color 3)
(points (get-points (generate-list 1000) 4)
#:color 4)
(points (get-points (generate-list 1000) 5)
#:color 5)))
Bellow is an example that doesn't produce anything useful, but I'm looking for something that simplifies the code in a similar manner.
(plot (list
(axes 0 0)
(for ([i (in-range 2 5)])
(points (get-points (generate-list 1000) i)
#:color i))))
Of course any alternative that only writes the points function once would help a lot.

Try for/list instead of for there:
(plot (list
(axes 0 0)
(for/list ([i (in-range 2 5)])
(points (get-points (generate-list 1000) i)
#:color i))))
A for loop throws away the values the body-expression produces on each iteration, while the for/list loop puts them into a list, and returns the list so that all the points are included in the input to plot.
(By the way, this nested list is okay because plot allows a renderer-tree as input.)

Related

Unbound identifier racket operators

This is my first time working with racket, and I am getting an error message (*: unbound identifier;) when trying to evaluate a list in Dr. Racket.
#lang racket
(define (randop)
(define x(random 3))
(cond
((= x 0) '+)
((= x 1) '-)
((= x 2) '*)
)
)
(define (randexp ht)
(define x(random 10))
(define y(random 10))
(define z(randop))
(eval (list z y x))
)
(randexp 1)
When executing racket in the console, (eval lst) works fine, though when I execute this code, it comes up with an unbound identifier. Any help is appreciated.
You don't need eval here. Instead of returning the symbols return the procedures instead:
#lang racket
(define (randop)
(define x (random 3))
(cond ((= x 0) +) ; + not quoted means if will return what + evaluates to
((= x 1) -) ; which is the procedures they represent
((= x 2) *)))
(define (randexp)
(define x (random 10))
(define y (random 10))
(define z (randop))
(z y x))) ; call z (the procedure returned by randop) with arguments x and y.
(randexp)
There's a problem with the way you're calling eval, in Racket you have to do this in a file:
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(define (randop)
(define x (random 3))
(cond
((= x 0) '+)
((= x 1) '-)
((= x 2) '*)))
(define (randexp ht)
(define x (random 10))
(define y (random 10))
(define z (randop))
(eval (list z y x) ns))
(randexp 1)
Also, you're not actually using the ht parameter, consider deleting it.

Bignum overflow error after Euler #2 attempt

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

looping through two lists while updating one of the lists

I have two lists as follows:
(x y z) & (2 1)
and I want to have a result like:
((x y) (z))
The relation of the lists is quite clear. So basically I want to rearrange the members of the first list into a list of lists with two (length of second list) lists.
I have tried running two dotimes iterations to do this:
(let ((result) (list1* list1))
(dotimes (n (length list2) result)
(progn (setq result
(append result
(list (let ((result2))
(dotimes (m (nth n list2) result2)
(setq result2
(append result2
(list (nth m list1*)))))))))
(setq list1*
(subseq list1* 0 (nth n list2))))))
The idea is that I make the first list of the expected result (x y), and then I want to update the (x y z) list so that the x any y are removed and I only have (z). Then the loop runs again to get the (z) list in the expected result. This does not work correctly and results in:
((x y) (x))
which means apparently the second command for progn which is basically updating the list1* is not working. Clearly there must be a correct and better way of doing this and I was wondering whether anyone can help with this. Also explain why it is not possible to have the solution explained?
If I see that right, your problem is in (subseq list1* 0 (nth n list2)), which returns the part of the list that you do not want.
I have the following to offer:
(defun partition-list (list lengths)
(mapcar (lambda (length)
(loop :repeat length
:collect (pop list)))
lengths))
This is a bit simplistic, of course, as it does not handle unexpected input, such as (length list) being smaller than (reduce #'+ lengths), but it can be expanded upon.
Just for the sake of example, an alternative using iterate:
(defun partition-list (list by)
(iter:iter
(iter:for element in list)
(iter:for i from 1)
(iter:generating measure in by)
(iter:collect element into sublist)
(when (= (or measure (iter:next measure)) i)
(iter:collect sublist)
(iter:next measure)
(setf i 0 sublist nil))))

Recursing Through Nested List LISP

How would I recurse through nested lists?
For example, given: '((A 1 2) (B 3 4))
How would I add 2 to the second element in each nested sublist?
(defun get-p0 (points)
(loop for x from 0 to
(- (list-length points) 1) do
(+ 2 (cadr (nth x points)))
)
)
I'm not really sure why (get-p0 '((A 1 2) (B 3 4))) returns NIL.
I'd go with something like this:
(loop for (letter x y) in '((A 1 2) (B 3 4))
collect (list letter (+ 2 x) y))
The reason: it's shorter and you don't measure the length of the list in order to iterate over it (why would you do that?)
Since you ask for a recursive solution:
(defun get-p0 (lst &optional (n 0))
(if (null lst)
nil
(let ((elt1 (first lst)) (eltn (cdr lst)))
(if (listp elt1)
(cons (get-p0 elt1) (get-p0 eltn))
(cons (if (= n 1) (+ elt1 2) elt1) (get-p0 eltn (+ n 1)))))))
so
? (get-p0 '((A 1 2) (B 3 4)))
((A 3 2) (B 5 4))
and it recurses further down if necessary:
? (get-p0 '((A 0 2) ((B -4 4) (C 10 4))))
((A 2 2) ((B -2 4) (C 12 4)))
The way you put it, you can consider the problem as a basic recursion pattern: you go through a list using recursion or iteration (mapcar, reduce, etc.; dolist, loop, etc.) and apply a function to its entries. Here is a functional solution:
(defun get-p0 (points)
(mapcar #'add-2 points))
where the auxiliary function can be defined as follows:
(defun add-2 (lst)
"Add 2 to the 2nd item"
(let ((res '()))
(do ((l lst (cdr l))
(i 1 (1+ i)))
((null l) (nreverse res))
(push (if (= 2 i)
(+ 2 (car l))
(car l))
res))))
As written your 'loop' use does not return anything; thus NIL is returned. As is your code is simply iterating over x and computing something; that something isn't stored anywhere.
So, how to get your desired result? Assuming you are willing to modify each point in points, this should work:
(defun get-p0 (points)
(loop for x from 0 to (- (list-length points) 1) do
(let ((point (nth x points)))
(setf (cadr point) (+ 2 (cadr point)))))
points)

Sum of Squares in Lisp

I need to write a non-recursive version of the function sum-squares and Use a do-loop that is based on the length of the argument list.
Here's how it's done generally:
(defun sum-squares (list) (loop for x in list
for y = (* x x)
summing y into total
finally (return total)))
A do loop solution is even simpler, but not half as elegant:
(defun sum-squares (list)
(let ((sum 0)) (do ((i 0 (1+ i)))
((>= i (length list)))
(setq sum (+ sum (* (nth i list) (nth i list)))))
sum))