Archive for the 'Uncategorized' Category

lissajous figures

Thursday, October 22nd, 2009

enter the x and y values (ratio is important), then phase, the RGB values
call: (lissajous x y phase R G B)

After the “better draw”, place this!

(define lissajous
  (lambda (Horizontal Vertical phase (Red 0) (Green 0) (Blue 0))
    (show-window)
    (for ((t (in-range 0 1000)))
      (let ((y (+ 230 (* 225 (sin (/ t Vertical)))))
            (x (+ 230 (* 225 (sin (/ (+ t phase ) Horizontal))))))
        (ellipse x y 12 12 Red Green Blue 1)
        (sleep/yield .00001)))))

Haz movement :3

Thursday, October 22nd, 2009

You *must* click on the new window before attempting to move, or it won’t move.

Have fun finding the rest of the keycodes.

touhou-scheme

luls, I has a arow kees.

Recursion for a certain amount of time

Tuesday, October 20th, 2009

I was asked about whether it was possible to use the time to terminate an otherwise endless recursion, and I thought the answer might interest other people as well:


Sure. There are a couple of ways.

If you are flexible enough in your interpretation of “time” and “how long it’s been running” then you could do something very simple by setting up a step counter, something like this:

(define ticks 0)

(define my-function
 (lambda ()
   (unless (>= ticks 40)
     (print '*) ;; or whatever else you want to do
     (set! ticks (+ ticks 1))
     (my-function))))

(my-function)

If you really mean clock time then you can use the function current-seconds. This takes no arguments and it “Returns the current time in seconds. This time is always an exact integer based on a platform-specific starting date (with a platform-specific minimum and maximum value).”

The upshot of this is that (current-seconds) will return a big number but the differences between its values in subsequent calls will reflect the number of seconds called. So you could do something like this:

(define starting-time (current-seconds))

(define print-stuff-for-5-seconds
 (lambda ()
   (print '*)
   (unless (> (- (current-seconds) starting-time) 4)
     (print-stuff-for-5-seconds))))

(print-stuff-for-5-seconds)

If you need more resolution there’s also (current-milliseconds).

Simple animation

Friday, October 16th, 2009

Once you have defined the better-draw stuff (see this post) you can do some simple animation by first doing some drawing, then erasing, then drawing again, etc. You should call sleep/yield between each draw and the next erase, both to allow the OS to actually draw the image and to make it stay visible for a bit before you erase it and redraw it elsewhere. Something like (sleep/yield 0.001) might be a good first stab (that’s supposed to sleep for 1/1000 of a second). There are of course fancier ways to make animations that will be smoother, etc., but this is simple and can be fun.

As an example, let’s first define a procedure that draws a guy:

(define draw-guy
  (lambda (x y)
    (ellipse x y 50 50 88 156 174 1.0)
    (ellipse (+ x 15) (+ y 10) 10 10 20 50 150 1.0)
    (ellipse (+ x 30) (+ y 10) 10 10 20 50 150 1.0)
    (ellipse (+ x 12) (+ y 25) 30 15 220 50 50 1.0)))

To run this you first want to show the window — (show-window) — and if you’ve previously drawn in it clear it — (clear). Then call (draw-guy).

Now let’s write a procedure to erase the guy. Notice that I make this circle a little bigger, because the “smoothing” in the drawing code, which gets rid of jaggies around circles, etc., “leaks” a little bit of color into adjacent pixels:

(define erase-guy
  (lambda (x y)
    (ellipse (- x 5) (- y 5) 60 60 255 255 255 1.0)))

Now I can make a guy move in a diagonal line using a “for” loop like this:

(define move-guy
  (lambda ()
    (for ((n (in-range 0 100)))
      (draw-guy (* n 2) (* n 3))
      (sleep/yield 0.01)
      (unless (>= n 99)
        (erase-guy (* n 2) (* n 3))))))

Again, you should show and clear the window, and then call (move-guy).

Of course we can move him in fancier ways too, by doing something like this:

(define wavy-guy
  (lambda ()
    (for ((x (in-range 0 500)))
      (let ((y (+ 200 (* 200 (sin (/ x 50.0))))))
      (draw-guy x y)
      (sleep/yield 0.0005)
      (unless (>= x 499)
        (erase-guy x y))))))

Better draw code (with bitmaps and lines)

Friday, October 16th, 2009

Here is a better version of the drawing code, with Adria’s bitmap contribution (which should help with the unwanted window-clearing on some systems and also make the window redraw when resized, etc.), some enhancements that I made to the bitmap code because it wasn’t working right with iterative drawing, plus two other changes:

  • A “line” procedure to draw a line that takes 9 arguments — x1 y1 x2 y2 width r g b a — and draws a line from (x1, y1) to (x2, y2) that’s width pixels wide, with color red=r, green=g, blue=b, and transparency alpha=a.
  • I changed the name of “make-window” to “show-window” because that’s really what it does.

Here it is: better-draw

Let me know if you have any problems with it.

A Scheme “while loop”

Thursday, October 15th, 2009

There was a question in class about whether Scheme has an iteration construct like the “while loops” of other languages, in which there is a condition and a body and the body is executed repeatedly until the condition becomes false. I showed how to do this using “do”, but noted that it was a little awkward because you have to specify an empty variable list, the negation of the condition, etc. I also said that one could define a syntax transformation that would give you a real, more natural “while.” Here’s a version of what I was talking about:

(define-syntax (while stx)
  (syntax-case stx ()
      ((_ condition expression ...)
       #`(do ()
           ((not condition))
           expression
           ...))))

If you haven’t previously seen “define-syntax” then this will look quite odd, but you can use it without understanding it. Just include it in your code and then you can do something like this:

(define x 0)

(while (< x 5)
       (printf "~A\n" x)
       (set! x (+ x 1)))

That will print:

0
1
2
3
4

The first thing after “while” is the condition. It will be evaluated and if it is true (producing anything other than #f) then everything else in the expression will be evaluated. Then the condition will be evaluated again and, if it is true, it everything else in the expression will be evaluated again. And so on, until the condition evaluates to false (#f), at which point the whole “while” expression will be done (and won’t return anything).

modification of lee’s drawing code

Thursday, October 15th, 2009

It works exactly the same in terms of what you do, except that it works smoothly on all platforms (e. g. , it will not clear when you resize on a Mac.)

Attached is the modified file. Now go have unlawful fun, y’all!

leesdrawing

Simple loops in Scheme

Saturday, October 10th, 2009

After that post on memoization, which used very fancy features of Scheme, I thought I’d post some answers to questions I’ve received on much less fancy stuff, for creating iterative (non-recursive) loops in Scheme. Here’s about the simplest kind of iterative loop:

(for ((x (in-range 3 12)))
 (printf "~A\n" x))

The thing after the variable name can be anything that produces a sequence or list, so this also works:

(for ((x '(fee fi fo fum)))
 (printf "~A\n" x))

Those loops just execute their bodies for “side effects,” but there are related procedures that will return a result of all of the looping, like:

(for/list ((x (in-range 3 12)))
 (* x 2))

This returns a list of whatever was returned from each time through the body of the loop.

“for” and friends can also loop over more than one variable at a time and do some other somewhat fancy things. The “do” procedure is sort of the most powerful variant of all of these, making it easy (among other things) to leave the loop whenever a condition is met, instead of keeping going through as many times as indicated at the beginning. Because of its generality the syntax is also a little confusing at first, but here’s a fairly simple example:

(do ((car1-position 0 (+ car1-position 5))
     (car2-position 100 (- car2-position 4)))
  ((> car1-position car2-position)
   (printf "Crash detected, Car1: ~A, Car2: ~A\n"
           car1-position car2-position)
   (abs (- car1-position car2-position)))
  (printf "Cruising along, Car1: ~A, Car2: ~A\n"
          car1-position car2-position))

Other procedures that loop in some sense, and that are worth checking out, are “map” and the various versions of “fold”.

-Lee

Memoization

Friday, October 9th, 2009

In class I talked about “memoization” as a strategy for improving the efficiency of recursive functions like the Fibonacci function we were experimenting with. The idea is to store each value as you calculate it, so that later calls with the same arguments can immediately return the previously calculated value instead of re-calculating it. In the half-implemented version we produced in class the previously calculated values were stored in a list with the value for argument 1 being in position 1 of the list, the value for argument 2 being in position 2, etc. But a more general strategy is to store pairs of (argument value) so that calculated answers can be added to the “memo” in arbitrary order,  so that you can memoize functions that take arguments other than positive integers, etc.

Scheme allows us to abstract this idea in a particularly powerful way. Using the definition of memoize provided below — which uses some fancy stuff that we haven’t covered in class — one can first define fibonacci in the totally normal, non-memoized way, and then do this:

(set! fibonacci (memoize fibonacci))

Henceforth fibonacci will be memoized, meaning that it will first check to see if it has previously calculated the answer and return the previously-calculated answer if it has. If it hasn’t then it will calculate it from scratch (but using any previously-calculated answers that it needs in its recursive calls) and store the new value (and return it).

To try this out first use my definition of memoize:

(define memoize
  (lambda (f) ;; returns a memoized version of function f
    (let ((memo '()))
      (lambda args
        (let ((match (assoc args memo)))    ;; look up args
          (if match
              (cadr match)                  ;; return stored value
              (let ((value (apply f args))) ;; or calculate if necessary
                (set! memo                  ;; and store new value
                      (cons (list args value) memo))
                value)))))))

Then define fibonacci in the ordinary, unmemoized way that most directly reflects the way we describe the function in English:

(define fibonacci
  (lambda (n)
    (cond ((< n 2) 0)
          ((= n 2) 1)
          (else (+ (fibonacci (- n 2))
                   (fibonacci (- n 1)))))))

Now if you test this version without memoizing, using “time” to see how long it takes, you get something like:

> (time (fibonacci 30))
cpu time: 500 real time: 518 gc time: 0
514229

But if you add the following after your ordinary definition of fibonacci:

(set! fibonacci (memoize fibonacci))

Then you get:

> (time (fibonacci 30))
cpu time: 0 real time: 1 gc time: 0
514229

And you can easily go up to inputs of many thousand now.

Some improvements that someone might want to make to my memoize function: 1) It already works for functions that take any number of arguments, but make it work for functions that return any number of values (something we haven’t yet covered), 2) Make it use a more efficient memo data structure, like a hashtable.

BTW my idea for this was based on Paul Graham’s similar function in Common Lisp, but the Scheme version is pretty different.

-Lee

Update: I had a bug in the fibonacci definition in my first post of this, (= n 3) instead of (= n 2); I’ve fixed it and rerun the timings.

code-immersion software overview (part 2) — architecture

Thursday, October 8th, 2009

This post will talk about the general architecture of the code-immersion system. That is, it will give a general idea of how all the parts interact with each other, which should elucidate how the entire system works. Read the rest of this entry »