Is there a way to specify bias in a random generator in lisp?
For instance if I had a range of numbers. How can I specify that the numbers in the first half of the range are 3× more likely than those in the last half?
I like Barmar's answer, and it handles arbitrary weights very well. However, it does require two calls to random, and that might be undesirable. Another approach would be to create a vector with elements that occur according to their intended frequency. E.g., if you have elements a and b that should be chosen with probability 1/3 and 2/3, then you can create an array (a b b) and select randomly from that.
(defun biased-generator (values weights)
(multiple-value-bind (total values)
(loop for v in values
for w in weights
nconc (make-list w :initial-element v) into vs
sum w into total
finally (return (values total (coerce vs 'vector))))
(lambda ()
(aref values (random total)))))
CL-USER> (defparameter *gen* (biased-generator '(a b) '(1 2)))
*GEN*
CL-USER> (loop for i from 1 to 100 collect (funcall *gen*))
(A A B A B A A B B A B B A A A B A A B A A A B A A A B B B B B A B B B B A A B
A B B A A A A B B B A A A A B A A B B B A A B B B A B B B B B B B B B B A B A
A A A B B B B A B A A B B A B A A B B B B B)
CL-USER> (let ((abs (loop for i from 1 to 10000 collect (funcall *gen*))))
(list (count 'a abs)
(count 'b abs)))
(3293 6707)
Do it in 2 steps:
First, select a random number in some arbitrary range, and determine if it's in the first 3/4 of the range. If it is, select a random number in the first half of the given range, otherwise select a random number in the second half:
(defun biased_random(low high) {
(let ((temp (random 1.0))
(middle (floor (+ high low) 2)))
(if (< temp 0.75)
(+ low (random (- middle low)))
(+ middle (random (- high middle)))))
Related
I'm doing some problems from Structure and Interpretation of Computer Programs
My case outputs #f as a valid result in the repl.it interpreter. I'm applying (and (not (max a b c)) (not (min a b c))) to get mid value.
I've tried rearranging the values for the mid function. The max and min functions work alright.
(define (max a b c)
(cond
((and(>= a b)(>= a c)) a)
((and(>= b a)(>= b c)) b)
((and(>= c a)(>= c b)) c)
))
(define (min a b c)
(cond
((and(<= a b)(<= a c)) a)
((and(<= b a)(<= b c)) b)
((and(<= c a)(<= c b)) c)
))
(define (mid a b c)
(and
(not (max a b c))
(not (min a b c))
))
(mid 10 8 6)
The output in the repl.it scheme interpreter is:
=> #f
I'd expect an error of some sort or a number value but this code returns a green #f so I'm assuming it means something is false? How can I fix this code to return a mid using conditional expressions?
I think it's worth thinking about how many tests you have to do to compute these things: to compute the extremum of three elements under any ordering operator you need to do no more than three comparisons:
(define (extremum/3 ordered? a b c)
;; find the extremum of three elements under ordered?
(cond ((and (ordered? a b) (ordered? a c)) a)
((ordered? b c) b)
(else c)))
And given this general function you can now define max/3 and min/3 easily:
(define (max/3 a b c)
(extremum/3 >= a b c))
(define (min/3 a b c)
(extremum/3 <= a b c))
Computing the mid point of three elements also requires no more than three tests:
(define (mid/3 a b c)
(if (>= a b)
(if (>= a c)
;; a is greatest, so we need to pick b or c
(if (>= b c) b c)
;; a is the mid point
a)
(if (>= a c)
;; a is the mid point
a
;; a is the minimum, pick b or c
(if (>= c b) b c))))
It's interesting to consider how many comparisons you need to find the mid point of n items.
I realized that I was passing a NOT from max AND min which is why it was evaluating false every time since there's always a false result from those expressions. I continued using comparisons to get the correct solution and adjusted the exceptions to take the mid to be a value which is either repeated three times or twice if it's not less than max or greater than min. The only thing that is unsettling is that I had to essentially express all conditions that are valid to isolate a mid number and couldn't explicitly define mid as NOT the max number AND NOT the min number. That being said there's got to be a better way to reduce these functions and eliminate the bulk of the comparisons...
(define (mid a b c)
(cond
((and(< a (max a b c))(> a (min a b c))) a)
((and(< b (max a b c))(> b (min a b c))) b)
((and(< c (max a b c))(> c (min a b c))) c)
(else (cond
((= (min a b c) (max a b c)) a)
((= a b) a)
((= a c) a)
((= b c) b)
))
))
Hello I have this function that makes randomly: a, b, c or d.
(define random-abcd
(let ([n (random 4)])
(cond [(equal? n 0) 'A]
[(equal? n 1) 'B]
[(equal? n 2) 'C]
[else 'D])))
That means I have 4 possible random outputs. But I would like to build a recusrsive function that gives an output between a number I give as parameter.
For example:
random-my 3 -> gives and output between: a b or c
random-my 5 -> gives and output between: a b c d or e
Thank you!
You could pass a number n and you can do (random n) to get a random number r in the range [0,n>. Now The char number for #\a is 97 so if you do (integer->char (+ 97 r)) you get #\a for 0, #\b for 1, ...
You can get a string with (list->string (list #\a)) ; ===> "a".
You can get a symbol with (string->symbol "a") ; ==> a
I leave it to you to put it all together, however it's not recursive.
Try:
(list-ref '(a b c d e f) (random 6))
fun problem. one way i can think of to do this is to use a vector (since it's zero-indexed and random-access) and given a number, choose a random number smaller than that value. once you have the number, then use that as the index into the vector to get the character in the vector at that index. in essence, you're just randomly indexing into 'slices' of the vector and slice size is determined by input argument.
Recursive fn to produce a random list of n letters till nth letter:
(define (f n (ol '()))
(if (= n (length ol))
ol
(f n (cons (string (integer->char (+ 97 (random n)))) ol))))
Testing:
(f 5)
Output:
'("b" "d" "b" "e" "e") ; list will have random letters;
(rearrange-this '(4 (4 2) 1) '(a b c d)) -> (d (d b) a)
So I need this to recurse into the sub-lists and rearrange those.
(define (rearrange-this list1 list2) ;Initial function
(rearrange-r list1 list2 (count list1) '() list1))
;list 1 holds numbers, list2 hold letters
(rearrange-this '(4 3 2 1) '( a b c d )) ;-> outputs (d c b a)
(rearrange-this '(2 3 4 1 3 2 1 4) '(a b c d)) ;-> outputs (b c d a c b a d)
You want to use higher order functions whenever possible. The most important ones for list operations are: map, fold, filter, and list-tabulate. Learning these will save so much time.
map is incredibly useful in this situation. I used it to write a deep-map function which delves into sublists and applies an operation to the objects within, although it will not work if you want to map lists to something else since deep-map will delve into those lists. You would have to wrap such lists in something to make the list? check fail.
After writing deep-map, I use it with list-ref to select the appropriate element from value-list and replace the number in arrangement.
(define (deep-map operator deep-list)
(map
(lambda (element)
(if (list? element)
(deep-map operator element)
(operator element)))
deep-list))
(define (rearrange-this arrangement value-list)
(deep-map
(lambda (element)
(list-ref value-list element))
arrangement))
Here is a quick test of the code. Note that unlike your code, the list positions start at 0. You could map the input arrangement list if you want to have input references starting at 1. I will leave that as an exercise to you.
> (rearrange-this '(3 2 (1 0)) '(a b c d))
;Value 16: (d c (b a))
The following function computes the Fibonacci series by tail recursive and squaring:
(defun fib1 (n &optional (a 1) (b 0) (p 0) (q 1))
(cond ((zerop n) b)
((evenp n)
(fib1 (/ n 2)
a
b
(+ (* p p) (* q q))
(+ (* q q) (* 2 p q))))
(t
(fib1 (1- n)
(+ (* b q) (* a (+ p q)))
(+ (* b p) (* a q))
p
q))))
Basically it reduces every odd input to a even one, and reduces every even input by half. For example,
F(21)
= F(21 1 0 0 1)
= F(20 1 1 0 1)
= F(10 1 1 1 1)
= F(5 1 1 2 3)
= F(4 8 5 2 3)
= F(2 8 5 13 21)
= F(1 8 5 610 987)
= F(0 17711 10946 610 987)
= 10946
When I saw this I thought it might be better to combine the even and odd cases (since odd minus one = even), so I wrote
(defun fib2 (n &optional (a 1) (b 0) (p 0) (q 1))
(if (zerop n) b
(fib2 (ash n -1)
(if (evenp n) a (+ (* b q) (* a (+ p q))))
(if (evenp n) b (+ (* b p) (* a q)))
(+ (* p p) (* q q))
(+ (* q q) (* 2 p q)))))
and hoping this will make it faster, as the equations above now becomes
F(21)
= F(21 1 0 0 1)
= F(10 1 1 1 1)
= F(5 1 1 2 3)
= F(2 8 5 13 21)
= F(1 8 5 610 987)
= F(0 17711 10946 1346269 2178309)
= 10946
However, it turned out to be much slower (takes about 50% more time in e.g. Clozure CL, CLisp and Lispworks) when I check the time needed for Fib(1000000) by the following code (Ignore the progn, I just don't want my screen filled with numbers.)
(time (progn (fib1 1000000)()))
(time (progn (fib2 1000000)()))
I can only see fib2 may do more evenp than fib1, so why is it that much slower?
EDIT: I think n.m. get it right, and I edited the second group of formulae. E.g. in the example of F(21) above, fib2 actually computes F(31) and F(32) in p and q, which is never used. So in F(1000000), fib2 computes F(1048575) and F(1048576).
Lazy evaluation rocks, that's a very good point. I guess in Common Lisp only some macro like "and" and "or" are evaluated lazily?
The following modified fib2 (defined for n>0) actually runs faster:
(defun fib2 (n &optional (a 1) (b 0) (p 0) (q 1))
(if (= n 1) (+ (* b p) (* a q))
(fib2 (ash n -1)
(if (evenp n) a (+ (* b q) (* a (+ p q))))
(if (evenp n) b (+ (* b p) (* a q)))
(+ (* p p) (* q q))
(+ (* q q) (* 2 p q)))))
Insert printing of the intermediate results. Pay attention to p and q towards the end of the computation.
You will notice that fib2 computes much larger values for p and q at the last step. These two values account for all the performance difference.
The ironic thing is that these expensive values are unused. This is why Haskell doesn't suffer from this performance problem: the unused values are not actually computed.
If nothing else, fib2 has more conditionals (while computing the arguments). That may well change how the code flow is done. Conditionals imply jumps, implies pipeline stalls.
It would probably be instructive to look at the generated code (try (disassemble #'fib1) and (disassemble #'fib2) and see if there's any blatant differences). It might also be worth to change the optimization settings, there's usually a fair few optimizations that are not done unless you request heavy optimization for speed.
I'm making a game, and I have this:
(define b "black piece") (define w "white piece")
(define (board)
(lambda (matrix)
(list ((b w b w b w b w)
(w b w b w b w b)
(b w b w b w b w)
(w b w b w b w b)
(b w b w b w b w)
(w b w b w b w b)
(b w b w b w b w)
(w b w b w b w b)))))
board makes a list with 8 lines and 8 columns of black and white pieces.
How do I access and change elements of the board? How do I do the procedure matrix with recursion?
first a few notes:
(define f (lambda (x) l ))
is the same as
(define (f x) l ))
You however are combining them with
(define (board) (lambda (matrix) l ))
which is the same as
(define board (lambda () (lambda (matrix) l )))
The distinction is important. The first two I have listed bind f to a function that take one parameter and return l. I'm guessing this is what you want to do. In the second two, you're binding board to a function that takes no parameters and returns a function that takes 1 parameter, matrix, (which it doesn't seem to do anything with), and returns a l.
second issue, (list ((b w....) ...)) isn't going to work because it will try to evaluate (b w ...). you need to have list in the function application position for each row of your board like so (list (list b w ...) (list w b ...) ...) in order for you code to even compile.
On to your question. link-ref is included in racket/base and is used for referencing elements in a list when you know the index into the list.
(list-ref 2 (list 'a 'b 'c 'd))
will return 'c. The index starts at 0. Since you have a list of lists, you will need to apply list-ref twice to retrieve a 'b or 'w.
As for changing it, well, you can't. As of r6rs, pairs (which make up lists) are immutable. The recommended way of doing things when possible is to return a new list with your change. you can use this somewhat inefficient version of list-set which returns a copy of the list with your new value at an index.
(define (list-set lis idx val)
(map (lambda (e i)
(if (= i idx) val e))
lis
(iota (length lis))))
In this case however, I would recommend switching to a different data structure more appropriate to the task at hand since you probably want O(1) access to the elements in the board. Look into vectors which behave much like lists but are used for constant lookups and updates. there is a built in vector-ref and vector-set! operations, which you should use instead of my above function.
Incase this is part of a larger problem and you're already using lists everywhere, you can use the vector->list and list->vector functions to go back and forth. Also, you can use mutable lists but don't.
Better still is the multidimensional array library offered in srfi/25, but that might be more complicated that you want to get.
The second part of your question was how to construct the board recursively. Well, here's a version using map.
(require (lib "1.ss" "srfi"))
(define (board)
(map (lambda (x)
(map (lambda (y)
(if (odd? (+ x y)) b w))
(iota 8)))
(iota 8)))
and here's a recursive version
(define (board)
(letrec ((board-helper
(lambda (x)
(if (eq? x 8) '()
(cons (row-helper x 0) (board-helper (+ 1 x))))))
(row-helper
(lambda (x y)
(if (eq? y 8) '()
(cons (if (odd? (+ x y)) b w) (row-helper x (+ 1 y)))))))
(board-helper 0)))