Generating a quiz in Common Lisp? - common-lisp

I want to teach myself Spanish and Lisp. I've got several word lists like
the data show below. How can I generate a quiz from the data that looks like this?
amarillo? [ ] blue [ ] yellow [ ] gray [ ] pink
azul? [ ] red [ ] blue [ ] green [ ] orange
.
.
.
verde? [ ] purple [ ] gold [ ] green [ ] black
The idea is to randomly include the answer with 3 randomly chosen
incorrect answers. Ideally, the incorrect answers would not be too
repetitive.
amarillo|yellow
azul|blue
blanco|white
dorado|golden
gris|gray
marrón|brown
naranja|orange
negro|black
oro|gold
púrpura|purple
rojo|red
rosa|pink
verde|green

Using LispWorks, with support for Unicode.
The color translations.
(defparameter *word-data*
"amarillo|yellow
azul|blue
blanco|white
dorado|golden
gris|gray
marrón|brown
naranja|orange
negro|black
oro|gold
púrpura|purple
rojo|red
rosa|pink
verde|green")
a few top-level variables: a translation table and two lists with color names
(defvar *translation* (make-hash-table :test #'equalp))
(defvar *all-english-colors* nil)
(defvar *all-spanish-colors* nil)
Parsing the translation data and filling the table and the lists:
(defun parse-word-data (&optional (data *word-data*))
(with-input-from-string (stream data)
(loop for line = (read-line stream nil nil)
while line
do (let ((pos (position #\| line)))
(setf (gethash (subseq line 0 pos) *translation*)
(subseq line (1+ pos)))
(pushnew (subseq line 0 pos) *all-spanish-colors*
:test #'equalp)
(pushnew (subseq line (1+ pos)) *all-english-colors*
:test #'equalp)))))
Find the translation for a spanish word:
(defun translate-s->e (word)
(gethash word *translation*))
Choose n random elements from a list:
(defun random-elements (list &optional (n 1))
(let ((elements nil)
(all-elements list))
(loop repeat n
for r = (random (length all-elements))
for e = (elt all-elements r)
do (push e elements)
do (setf all-elements (remove e all-elements :test #'equal)))
elements))
Choose three random english colors:
(defun random-english-colors (answer &optional (n 3))
(random-elements (remove answer *all-english-colors* :test #'equal) n))
Compute the choices -
(defun compute-choices (answer answers &optional (n 3))
(let ((pos (random (1+ n))))
(append (subseq answers 0 pos)
(list answer)
(subseq answers pos))))
The test:
(defun test ()
(loop for sc in *all-spanish-colors*
for ec = (translate-s->e sc)
do (apply #'format
t
"~%~a~1,16#T[ ] ~a~1,16#T[ ] ~a~1,16#T[ ] ~a~1,16#T[ ] ~a"
sc
(compute-choices ec (random-english-colors ec))))
(terpri))
Compute the data:
(parse-word-data)
The test:
CL-USER 212 > (test)
verde [ ] green [ ] yellow [ ] orange [ ] brown
rosa [ ] yellow [ ] orange [ ] pink [ ] golden
rojo [ ] gold [ ] golden [ ] brown [ ] red
púrpura [ ] gold [ ] red [ ] orange [ ] purple
oro [ ] orange [ ] gold [ ] red [ ] white
negro [ ] gold [ ] black [ ] golden [ ] purple
naranja [ ] red [ ] gray [ ] orange [ ] gold
marrón [ ] orange [ ] pink [ ] brown [ ] red
gris [ ] brown [ ] green [ ] gray [ ] orange
dorado [ ] golden [ ] pink [ ] blue [ ] gray
blanco [ ] blue [ ] red [ ] white [ ] gold
azul [ ] brown [ ] blue [ ] green [ ] purple
amarillo [ ] red [ ] yellow [ ] brown [ ] black

Related

iterate over two lists in NetLogo: Big picture context :R extension. Assign patch values to specific patches from R

I need to pass some data to R from NetLogo using the R-extension, do some computations and then assign the R output to specific patches.
I have tried every combination of map and foreach in NetLogo that I can imagine. I have been trying to change colors based on a patch id because it is visible. Setting all of the patches blue works.
observer> foreach [1 2 3] [ x -> ask patches with [id = x] [ set pcolor blue ] ]
When I add the second list nothing I have tried works. I also tried assigning values to the patches to no avail. This turned patches 4, 5, and 6 red...
observer> foreach [4 5 6] [ x -> ask patches with [id = x] [ set pcolor [blue red green] ]]
The next approach did not work.
observer> set list-a (list blue red green)
observer> set list-b (list 7 8 9)
observer> ask patches with [id = list-b] [ set pcolor list-a]
Attempting a foreach with two lists like this:
observer> foreach list-b list-b ask patches with [id = list-b] [set pcolor list-a]
observer> show map list-b list-b ask patches with [id = list-b] [set pcolor list-a]
redefining list-a and then trying the original approach again sets those patches blue.
observer> set list-a r:get "df1[[1]]"
observer> show list-a
observer: [1 5 8]
observer> foreach list-a [ x -> ask patches with [id = x] [ set pcolor blue ] ]
If I could just understand how to work through two lists I would be set.
for example
list-a [1 2 3]
list-b [blue green red]
; effectively do the following
ask patch with [id = 1] [set pcolor blue]
ask patch with [id = 2] [set pcolor green]
ask patch with [id = 3] [set pcolor red]
The actual problem is I have activity variables (all the patches below are planting corn).
> a
id a_corn a_crp a_soy
1 1 0 1 0
2 2 0 1 0
3 3 0 1 0
4 4 0 1 0
5 5 0 1 0
6 6 0 1 0
7 7 0 1 0
8 8 0 1 0
9 9 0 1 0
10 10 0 1 0
>
I know with the r extension dataframes come into netlogo as unnamed nested lists. So if I avoid the nesting by:
set list-id r:get "a$id"
set list-a r:get "a$a_corn"
; then netlogo iterates through the lists:
ask patch with [id = 1] [set a_corn 0]
ask patch with [id = 2] [set a_corn 0]
; and so on
I am open to suggestions for better ways. But the ids need to match, may not be sequential, and the a dataframe above will vary in size and contents.
UPDATE:
As I continue working the problem I am documenting the steps here so I can find them later.
I have found anonymous-commands.
observer> set procedure [[x y] -> ask patches with [id = x] [set pcolor y]]
observer> show is-anonymous-command? procedure
observer: true
observer> set list-a (list blue red green)
observer> set list-b (list 7 8 9)
observer> (foreach list-b list-a procedure) ; does nothing
I cleared all, set up again and the following worked:
observer> ask patches with [id = 7] [set pcolor red]
observer> set procedure [[x y] -> ask patches with [id = x] [set pcolor y]]
observer> set list-b (list 7 8 9)
observer> set list-a (list blue red green)
observer> (foreach list-b list-a procedure)
Now for the application portion of the problem:
observer> set procedure [[x y] -> ask patches with [id = x] [set a_corn y]]
observer> set list-a (list 1 1 1)
observer> (foreach list-b list-a procedure)
and it works!

Netlogo Get a pushing force from all neighbours within a distance

For each turtle, I got an agentset called visible-neighbors which are the turtles within a distance.
I wanna get a pulling force on this turtle from each of visible-neighbors. And then sum the forces. For each single pulling force from one neighbor is following the equation force = 1 / distance ^ 2. My idea is to decompose the force to x and y components and then sum the forces on x and y, finally compose the force again.
Here is the code I have at the moment. It's runnable, but for some reasons it doesn't work.
to get-direction-naive
set visible-neighbors (other turtles) in-radius 75 with [ distance myself > 0 ]
ifelse any? visible-neighbors
[let distance-list [distance myself] of visible-neighbors
let x-cors [xcor] of visible-neighbors
let x-diff map [? -> ? - xcor] x-cors
let x-forces (map [ [a b] -> a / (b ^ 3) ] x-diff distance-list)
let x-sum sum x-forces
let y-cors [ycor] of visible-neighbors
let y-diff map [? -> ? - ycor] y-cors
let y-forces (map [ [a b] -> a / (b ^ 3) ] y-diff distance-list)
let y-sum sum y-forces
ifelse y-sum = 0
[ifelse x-sum > 0
[set heading 0]
[set heading 180] ]
[set heading atan x-sum y-sum]
]
[right random 360]
end
Any advices would be appreciated.
What are you finding that isn't working? You want the turtles to be pulled towards each other, is that correct? This seems to set turtles' headings as needed- I think you can drop the two nested ifelse statements, though. Check out this toy version:
to setup
ca
crt 20 [
setxy random-xcor random-ycor
pd
]
reset-ticks
end
to force-pull
ask turtles [
let visible-neighbors other turtles in-radius 10
ifelse any? visible-neighbors [
let distance-list [distance myself] of visible-neighbors
let x-cors [xcor] of visible-neighbors
let x-diff map [ ? -> ? - xcor] x-cors
let x-forces force-calc x-diff distance-list
let x-sum sum x-forces
let y-cors [ycor] of visible-neighbors
let y-diff map [? -> ? - ycor] y-cors
let y-forces force-calc y-diff distance-list
let y-sum sum y-forces
set heading atan x-sum y-sum
let hyp sqrt ( ( x-sum ^ 2 ) + ( y-sum ^ 2 ) )
fd e ^ ( -0.5 * hyp )
] [
right random 360
]
]
tick
end
to-report force-calc [ dif-list dist-list ]
report ( map [ [ a b ] -> a / ( b ^ 3 ) ] dif-list dist-list )
end
It seems to me that the turtles face the calculated heading properly and get drawn together.

Converting a recursive formula back to the original explicit formula?

There is a generic formula Z^N = A(Z)^N+1 + B(Z)^N+1 . This formula is used to convert a given recursive function back to its original explicit form :
Recursive Formulas :
1) R(0) = 1, R(n) = (1/3) R(n-1), n = 1, 2, ...
2) P(0) = 1, P(1) = 1/3, P(n) = (4/3) P(n-1) - (1/3) P(n-2), n = 2, 3, ...
3) Q(0) = 1, Q(1) = 1/3, Q(n) = (10/3) Q(n-1) - Q(n-2), n = 2, 3, ...
Then, it suggests that "difference formulas" of the form :
2) P(n) = A(1/3^n) + B
3) Q(n) = A(1/3^n) + B * 3^n
represent the general solution.
Then the "difference functions" are to be substituted into the "recursive functions" to obtain root of A, B which completes the proof that the recursive function is indeed a representation of the original sequence {Xn} = {1/3^n} = 1, 1/3, 1/9, ...
My Question is where the difference formulas come from? I would appreciate a reference to the subject in any major text-book in calculus or numerical methods like Swokowski, Fink, or Chapra.
It's just a bit of freshman algebra. Let's take example 3 for instance:
Q(n+2) = (10/3)Q(n+1) + (-1)Q(n)
Q(n+1) = ( 1)Q(n+1) + ( 0)Q(n)
That second equation seems silly, but it allows us to write the following matrix equation:
[ Q(n+2) ] = [ 10/3 -1 ][ Q(n+1) ]
[ Q(n+1) ] = [ 1 0 ][ Q(n) ]
This is the 2-dimensional analogue of a recurrence like v(n+1) = a*v(n) which has an easy solution v(n) = a^n * v(0). We can apply the same logic to our matrix equation to obtain:
[ Q(n+1) ] = [ 10/3 -1 ]^n [ 1/3 ]
[ Q(n) ] = [ 1 0 ] [ 1 ]
Let's call that 2 x 2 matrix in the middle that we're raising to the nth power, A.Now how do we quickly compute powers of square matrices? When they're diagonalizable, it's easy. The eigenvalues of that 2x2 matrix are the roots of its characteristic polynomial:
det(A - xI) = (10/3 - x)(0 - x) - (1)(-1) = (x - 1/3)(x - 3)
This tells us that there's some invertible 2 x 2 matrix P (consisting of the eigenvectors of A) such that:
[ Q(n+1) ] = P [ 1/3 0 ]^n P^-1 [ 1/3 ]
[ Q(n) ] = [ 0 3 ] [ 1 ]
and so:
[ Q(n+1) ] = P [ 1/3^n 0 ] P^-1 [ 1/3 ]
[ Q(n) ] = [ 0 3^n ] [ 1 ]
From this we easily deduce that for some constants a and b:
Q(n) = a(1/3^n) + b(3^n)
We could explicitly figure out what they are by finding the eigenvectors of A, constructing the matrices P and P^-1, multiplying those three 2 x 2 matrices with the 2 x 1 vector on the right, and actually extracting the expression for Q(n) from that. But it's easier to just look at the equation, realize that it'll result in something of the form Q(n) = a(1/3^n) + b(3^n) and actually just solve for a and b via back-substitution.

Netlogo : change patch color of one patch if orthogonal neighbors have the same color

I'm new to netlogo and I need some help.
I am trying to grow a continuous patch of one color (green on a black background). However, I will sometimes have a black patch that is completely surrounded by green patches. I would like to change the color of those black patches to green.
I tried :
ask patches [
if neighbors4 with [pcolor = 55]
[set pcolor 55]
]
but it gives me an error, as does
ask patches [
if any? neighbors4 [pcolor = 55]
[set pcolor 55]
]
Here is the code that works that will sometimes leave black patches surrounded by green patches :
to setup
clear-all
set-patch-size 4
resize-world -50 50 -50 50
ask patches[set pcolor black]
grow-cell
reset-ticks
end
to grow-cell
ask patch 0 0 [
set pcolor 55
ask neighbors [
set pcolor 55
]
]
repeat 45
[ ask patches with [pcolor = black]
[ set pcolor [pcolor] of one-of neighbors4 ] ]
end
Here is an ugly/barely clever hack.
Ask patches[
if mean [pcolor] of neighbors4 = green[set pcolor green]
]
Or alternately:
Ask patches with [ count neighbors4 with [pcolor = green] = 4 ]
[set pcolor green]

Get the coordinates of a matrix from its flatten index

How can we get the coordinates of a n dimensions matrix from its shape and its flatten index?
I mean, if for example I have the following (2,3) matrix of 2 dimensions:
[ [ 0, 1 ],
[ 2, 3 ],
[ *4*, 5 ] ]
...and I want to find the value of the index in bold from the coordinates [0,2], how can I do?
Or if I have this (2,2,5) matrix of 3 dimensions:
[ [ [ nil, nil ],
[ nil, nil ] ],
[ [ nil, nil ],
[ nil, nil ] ],
[ [ nil, *9* ],
[ nil, nil ] ],
[ [ nil, nil ],
[ nil, nil ] ],
[ [ nil, nil ],
[ nil, nil ] ] ]
...and I know the coordinates that I want have a flatten index value of 9, how can I find the relative coordinates are: [1,0,2]?
If possible, I would like to know a general and simple method, which work on matrix of any shape.
Many thanks for your help.
You can use this simple algorithm:
Let's say you have the matrix A[a][b][c][d] (where a,b,c,d are the dimensions) and the index X.
To get the first coordinate of the index X you simply divide X by b*c*d.
Let it be this next matrix, having the sizes [2][5] and the index X=7
0 1 2 3 4
5 6 7 8 9
You first divide X by the last dimension to find the first coordinate. X/5=1 . Then, from there you move forward and give X the value X%=5 . So you'll have X = 7%5 =2. Now you have to search the coordinates for the remaining dimensions using the same algorithm. If you reach the last dimension , the coordinate will be the remaining X, in this case 2. So the coordinates for X=7 are [1][2] , which is actually the answear.
Again, for the general case, where you have a,b,c,d dimensions.
I'll note with (yd) the y'th dimension.
X=index
(1d)=X/b*c*d
X gets value X % b*c*d
(2d)=X/c*d
X gets value X % c*d
(3d)=X/d
X gets value X % d
(4d)=X
If you had the dimensions [2][2][5] you would get:
X=9;
(1d) = 9/2*5 = 0
X = 9%10 = 9
(2d) = 9/5 = 1
X = 9%5 = 4
(3d) = 4
Result: [0][1][4] is the 9th element.
To get from [0][1][4] to the index 9 , you do the reverse algorithm by multiplying:
X=(1d)*b*c + (2d)*c + 3d = 0 + 1*5 +4 =9

Resources