Day 40/100: Some more slides

Craig Maloney - Mon, 07/10/2017 - 22:37

Still more slides for the presentation. Also downloaded some tutorials from GDQuest for the Godot Engine to see how that works.

Categories: LugNut Blogs

Day 39/100: More slidea dn lambda calculus

Craig Maloney - Sun, 07/09/2017 - 22:42

Putting more spit and polish on my slides for the MUG Meeting (July 11th is when the presentation is). Did some reading on Lambda Calculus just so I can speak somewhat intelligently about it and how it relates to Scheme.

Categories: LugNut Blogs

Day 38/100: eqv? in guile

Craig Maloney - Sat, 07/08/2017 - 22:58

Was working more on my slides when I ran into something a little curious with the implementation of guile.

(eqv? "5" "5")

Apparently in certain versions of guile this returns #f (2.0.9). However in later versions (2.0.13) this returns #t. It also returns #t in Racket. I'm not 100% sure what's going on (I think it has something to do with how strings are handled in the earlier versions, and how they do comparisons) but it was interesting to me to see that even in later implementations of the same Scheme interpreter there was disagreement over how certain bits were handled.

I'll likely hand-wave this as part of the presentation, but it was interesting nonetheless.

Categories: LugNut Blogs

Day 37/100: Nothing to report

Craig Maloney - Fri, 07/07/2017 - 22:57

Worked a little more on my slides, but didn't get to any programming of note.

Categories: LugNut Blogs

Day 36/100: More and more slides

Craig Maloney - Thu, 07/06/2017 - 23:10

Still more work on the slides. Added bits about scheme types. More fun times.

Categories: LugNut Blogs

Day 35/100: More Slides

Craig Maloney - Wed, 07/05/2017 - 23:12

Wrote up more slides for my talk. Did a quick demo of them to explain what scheme was and realized I might need to go a little more basic. Apparently not everyone knows what a Lisp is (shock! horror!) Ah well.

Categories: LugNut Blogs

Day 34/100: July 4th - no progress

Craig Maloney - Tue, 07/04/2017 - 23:51

Today was July 4th so I didn't get a chance to sit down and do any coding. Hopefully tomorrow will offer better opportunities to code.

Categories: LugNut Blogs

Day 33/100: Busy day / Closures

Craig Maloney - Mon, 07/03/2017 - 23:35

Today was a bit busier than I thought it would be. I did some playing around with trying to better understand closures. I think I understand them a little better but one of things I'm having trouble with is figuring out how something magically becomes a closure.

Take this for instance:

(define (make-serial-number-generator) (let ((current-serial-number 0)) (lambda () (set! current-serial-number (+ current-serial-number 1)) current-serial-number))) (define entry-sn-generator (make-serial-number-generator))

I understand that in this case a new instance of the procedure make-serial-number-generator needs to be wrapped in entry-en-generator otherwise it won't work properly (it gets reset each time). However:

(define counter (let ((count 0)) (lambda (x) (set! count (+ x count)) count)))

This doesn't need the wrapping and I can use (counter 3) to increment the counter by 3. Worse, I can't seem to replicate the need for the generator wrapper.

So confused.

Any help on what the difference is would be appreciated. Thanks!

Categories: LugNut Blogs

Day 32/100: More work on slides and closures

Craig Maloney - Sun, 07/02/2017 - 22:49

Today I did a little more work on my slides for the MUG presentation, but I also read some more of the (excellent) manual. The section on Closures really helped me understand better what was going on.

For those playing along at home, a closure is when a function is called in such a way that the local state is preserved. So, for example:

(define (silly-function x) (let ((y (/ x 2))) y))

This defines a lexical scope for y where y does not exist outside of the scope of the function. If I did the following:

(define y "moo") (silly-function 8) => 4 y => "moo"

"y" is not overwritten.

What makes closure so powerful is best described in this example (taken from the Guile documentation):

(define (make-serial-number-generator) (let ((current-serial-number 0)) (lambda () (set! current-serial-number (+ current-serial-number 1)) current-serial-number))) (define entry-sn-generator (make-serial-number-generator)) (entry-sn-generator) => 1 (entry-sn-generator) => 2 ...

In this case current-serial-number is initialized with 0 and the lambda function turns the function into a variable. Since the function as a whole is saved as a variable you can assign it to another variable and that variable holds the address of the instantiated function. So when you call that variable as a function it looks up the address of the function, brings up the current state of where it left off, and then (in this case) increments the value of current-serial-number.

Simple, no?

I'm pretty sure I'm not explaining this right, but I'll hopefully explain it better for the slides. Closure is one of the important concepts of JavaScript and it's nice to see a clear example of this in Scheme.

Onward!

Categories: LugNut Blogs

Day 31/100: More work on slides

Craig Maloney - Sat, 07/01/2017 - 23:38

Did some more work on my slides for the MUG presentation, but that was it. Lost some momentum today. Going to find it tomorrow.

Categories: LugNut Blogs

Day 30/100: Marking time

Craig Maloney - Fri, 06/30/2017 - 22:25

Did a little reading but today was not as productive as it could be. Not a great finish to the first 30 days, but tomorrow will be better.

Categories: LugNut Blogs

Day 29/100: Hint System and Shut the Box fin

Craig Maloney - Thu, 06/29/2017 - 18:09

I think I'm done with Shut the Box, for now.

I added a hint system where you can type "hint" and get hints on which tiles can be shut. Also fixed a few bugs and cleaned up the output so it looks better.

#lang racket #| Init Block |# (define tiles '()) (define die1 0) (define die2 0) (define turn-number 1) (define took-turn #f) (define end-of-game #f) (define (start-game) (set! tiles '(1 2 3 4 5 6 7 8 9))) (define (dice) (+ 1 (random 6))) (define (dice-roll) (set! die1 (dice)) (set! die2 (dice))) (define (sum-of-dice) (+ die1 die2)) (define (sum-of-tiles tilelist) (apply + tilelist)) (define (list-check l1 l2) (andmap (lambda (x) (not (boolean? (memq x l2)))) l1)) (define (shut-tiles tilelist) (if (not took-turn) (if (list-check tilelist tiles) (for ([i tilelist]) (if (index-of tiles i) (begin (set! tiles (remove i tiles)) (set! took-turn #t)) (error "Tile already shut"))) (println "Tile not available to be shut")) (println "Already took your turn"))) (define (check-roll dice-sum tile-sum) (= dice-sum tile-sum)) (define (player-turn tilelist) (if (member "hint" tilelist) (hint (sum-of-dice)) (if (check-roll (sum-of-dice) (sum-of-tiles tilelist)) (shut-tiles tilelist) (println "Roll does not equal shut tiles. Try again.")))) (define (my-read-line) (let ([contents (read-line)]) (if (string=? contents "") (read-line) contents))) (define (input) (let ((input-line (my-read-line))) (if (string=? input-line "hint") '("hint") (map string->number (string-split input-line))))) (define (next-turn) (set! turn-number (+ 1 turn-number)) (set! took-turn #f) (dice-roll) (show-turn)) (define (show-turn) (printf "Turn: ") (println turn-number) (println tiles) (printf "Dice roll ~v ~v = ~v\n" die1 die2 (sum-of-dice) )) (define (tile-combinations sum) (filter (lambda (x) (eq? (apply + x) sum)) (cdr ( combinations tiles)))) (define (hint sum) (println sum) (println (tile-combinations sum))) (define (end-of-game-test sum) (let ((combinations (tile-combinations sum))) (empty? combinations) )) #| Main Loop |# (start-game) (dice-roll) (show-turn) (let loop() (define tilelist (input)) (player-turn tilelist) (cond [took-turn (next-turn)]) (when (not (end-of-game-test (sum-of-dice))) (loop))) (if (empty? tiles) (println "Congratulations! You shut the box!") (println "No more moves available. Try again?"))

Code is available on github as well.

Categories: LugNut Blogs

Day 28/100: Better end-game

Craig Maloney - Wed, 06/28/2017 - 12:21

This morning I played around with the end-game solution for Shut the Box. Part of the issue I had was the way I determined the end game in other languages was iterative. It would iterate through the list of tiles, subtract the current tile it was using, and then recurse through the list to find combinations that worked. eg: If the tiles [1 2 3 5 9] were present and I wanted to find out if the sum 6 could still be shut then it would check 9 (which is too big). It would then check 5 (which wasn't larger than 6) and then subtract 5 from the sum (to get 1) and then find the tiles that were equal to 1 (which is 1). So there was one solution in there, so it would exit upon finding the one solution).

Unfortunately in Racket this algorithm was a bit of a pain to generate. You can look at yesterday's end-game to see how well I did (hint: not great).

So I needed a different way to figure out if there was a solution. I happened upon the "Count the Coins" solution, which seemed to work. Unfortunately it assumes replacement so a list of tiles [1 2 3] would generate combinations for 6 that weren't correct ([2 2 2] and [1 1 1 1 1 1] for instance).

Back to the drawing board I went, and I happened upon this solution:

#lang racket (define tiles '(1 2 3 4 )) (filter (lambda (x) (eq? (apply + x) 6)) (cdr ( combinations tiles)))

What this does is creates combinations of the tiles (combinations tiles) and removes the first combination (which is '(), or the empty set. So (cdr (combinations tiles)) contain a list of the non-empty combinations.) it then filters out the combinations that sum up to the number we're looking for (6 in this case). That leaves us with the following output:

'((1 2 3) (2 4))

which are the combination of tiles that will get us to 6.

With that in mind the code now looks like this:

#lang racket #| Init Block |# (define tiles '()) (define die1 0) (define die2 0) (define turn-number 1) (define took-turn #f) (define end-of-game #f) (define (start-game) (set! tiles '(1 2 3 4 5 6 7 8 9))) (define (dice) (+ 1 (random 6))) (define (dice-roll) (set! die1 (dice)) (set! die2 (dice))) (define (sum-of-dice) (+ die1 die2)) (define (sum-of-tiles tilelist) (apply + tilelist)) (define (list-check l1 l2) (andmap (lambda (x) (not (boolean? (memq x l2)))) l1)) (define (shut-tiles tilelist) (if (not took-turn) (if (list-check tilelist tiles) (for ([i tilelist]) (if (index-of tiles i) (begin (set! tiles (remove i tiles)) (set! took-turn #t)) (error "Tile already shut"))) (println "Tile not available to be shut")) (println "Already took your turn"))) (define (check-roll dice-sum tile-sum) (= dice-sum tile-sum)) (define (player-turn tilelist) (if (check-roll (sum-of-dice) (sum-of-tiles tilelist)) (shut-tiles tilelist) (println "Roll does not equal shut tiles. Try again."))) (define (my-read-line) (let ([contents (read-line)]) (if (string=? contents "") (read-line) contents))) (define (input) (map string->number (string-split (my-read-line)))) (define (next-turn) (set! turn-number (+ 1 turn-number)) (set! took-turn #f) (dice-roll) (show-turn)) (define (show-turn) (printf "Turn: ") (println turn-number) (println tiles) (printf "Dice roll ~v ~v = ~v\n" die1 die2 (sum-of-dice) )) (define (tile-combinations sum) (filter (lambda (x) (eq? (apply + x) sum)) (cdr ( combinations tiles)))) (define (end-of-game-test sum) (let ((combinations (tile-combinations sum))) (println combinations) (empty? combinations) )) #| Main Loop |# (start-game) (dice-roll) (let loop() (show-turn) (define tilelist (input)) (player-turn tilelist) (next-turn) (when (not (end-of-game-test (sum-of-dice))) (loop)))

I need to clean up the game loop some, but it actually plays a game of "Shut the Box" to completion. Better still, I could instrument the "tile-combinations" to provide a hint functionality so you can see which tile sets can be shut for a particular roll.

Ever onward!

Categories: LugNut Blogs

Day 27/100: Buggy end-game

Craig Maloney - Tue, 06/27/2017 - 23:13

Getting closer to calling this version of "Shut the Box" done. There are still a few bugs that I'm running into that I hope to resolve tomorrow.

One of the things that is a little annoying to me about scheme is the absence of a "return" statement. Several bugs that I ran into with the end game checker were related to not having an explicit way to say "no, I'm done with this function; please return #t or #f as needed". If someone knows how to make something like this work better I'm all ears.

#lang racket #| Init Block |# (define tiles '()) (define die1 0) (define die2 0) (define turn-number 1) (define took-turn #f) (define end-of-game #f) (define (start-game) (set! tiles '(1 2 3 4 5 6 7 8 9))) (define (dice) (+ 1 (random 6))) (define (dice-roll) (set! die1 (dice)) (set! die2 (dice))) (define (sum-of-dice) (+ die1 die2)) (define (sum-of-tiles tilelist) (apply + tilelist)) (define (list-check l1 l2) (andmap (lambda (x) (not (boolean? (memq x l2)))) l1)) (define (shut-tiles tilelist) (if (not took-turn) (if (list-check tilelist tiles) (for ([i tilelist]) (if (index-of tiles i) (begin (set! tiles (remove i tiles)) (set! took-turn #t)) (error "Tile already shut"))) (println "Tile not available to be shut")) (println "Already took your turn"))) (define (check-roll dice-sum tile-sum) (= dice-sum tile-sum)) (define (player-turn tilelist) (if (check-roll (sum-of-dice) (sum-of-tiles tilelist)) (shut-tiles tilelist) (println "Roll does not equal shut tiles. Try again."))) (define (my-read-line) (let ([contents (read-line)]) (if (string=? contents "") (read-line) contents))) (define (input) (map string->number (string-split (my-read-line)))) (define (next-turn) (set! turn-number (+ 1 turn-number)) (set! took-turn #f) (dice-roll) (show-turn)) (define (show-turn) (printf "Turn: ") (println turn-number) (println tiles) (printf "Dice roll ~v ~v = ~v\n" die1 die2 (sum-of-dice) )) (define (end-of-game-test sum) (println sum) (cond [(zero? sum) #t] ( (println "continue") (define last-tile (filter (lambda (x) (<= x sum)) tiles)) (cond [(empty? last-tile) #f] [(cond [(end-of-game-test(- sum (last last-tile))) #t])] ) ) ) ) | Main Loop | (start-game) (dice-roll) (let loop() (show-turn) (define end-of-game-flag (end-of-game-test(sum-of-dice))) (println end-of-game-flag) (define tilelist (input)) (player-turn tilelist) (next-turn) (when (not end-of-game) (loop)))
Categories: LugNut Blogs

Day 26/100: Working more on slides

Craig Maloney - Mon, 06/26/2017 - 20:43

Worked more on my slides for the upcoming MUG meeting. Also did a little more reading about Scheme in the process. Fun times.

Categories: LugNut Blogs

Day 25/100: Accepting Input

Craig Maloney - Sun, 06/25/2017 - 21:12

Today I made some strides in getting this to accept input. It's starting to look like a game now:

#lang racket #| Init Block |# (define tiles '()) (define die1 0) (define die2 0) (define turn-number 1) (define took-turn #f) (define end-of-game #f) (define (start-game) (set! tiles '(1 2 3 4 5 6 7 8 9))) (define (dice) (+ 1 (random 6))) (define (dice-roll) (set! die1 (dice)) (set! die2 (dice))) (define (sum-of-dice) (+ die1 die2)) (define (sum-of-tiles tilelist) (apply + tilelist)) (define (list-check l1 l2) (andmap (lambda (x) (not (boolean? (memq x l2)))) l1)) (define (shut-tiles tilelist) (if (not took-turn) (if (list-check tilelist tiles) (for ([i tilelist]) (if (index-of tiles i) (begin (set! tiles (remove i tiles)) (set! took-turn #t)) (error "Tile already shut"))) (println "Tile not available to be shut")) (println "Already took your turn"))) (define (check-roll dice-sum tile-sum) (= dice-sum tile-sum)) (define (player-turn tilelist) (if (check-roll (sum-of-dice) (sum-of-tiles tilelist)) (shut-tiles tilelist) (println "Roll does not equal shut tiles. Try again."))) (define (my-read-line) (let ([contents (read-line)]) (if (string=? contents "") (read-line) contents))) (define (input) (map string->number (string-split (my-read-line)))) (define (next-turn) (set! turn-number (+ 1 turn-number)) (set! took-turn #f) (dice-roll) (show-turn)) (define (show-turn) (printf "Turn: ") (println turn-number) (println tiles) (printf "Dice roll ~v ~v = ~v\n" die1 die2 (sum-of-dice) )) (start-game) (dice-roll) (let loop() (show-turn) (define tilelist (input)) (player-turn tilelist) (next-turn) (when (not end-of-game) (loop)) )
Categories: LugNut Blogs

Day 24/100: Small Steps

Craig Maloney - Sat, 06/24/2017 - 23:02

Did a little bit more on my presentation, but nothing earth-shattering. Read some more of The Little Schemer and finally realized that the book is about taking small concepts to build bigger programs. Unfortunately it reads like some form of cult worksheet to brainwash someone into a new way of thinking. Perhaps that's what Scheme was all along. ;)

Categories: LugNut Blogs

Day 23/100: Working on my Scheme presentation

Craig Maloney - Sat, 06/24/2017 - 00:13

Spent most of today working on my Scheme / Racket presentation that I'll be giving at MUG in July. So no major progress to report.

Categories: LugNut Blogs

Day 22/100: Still more Shut the Box

Craig Maloney - Thu, 06/22/2017 - 22:38

Did a little more development with Scheme / Racket and Shut the Box. I fixed a few bugs in the previous implementation where you could remove tiles by flipping unflipped tiles before the flipped tiles are checked. I also put in a check so that the tiles that are flipped set a flag so additional tiles can't be flipped.

#lang racket #| Init Block |# (define tiles '()) (define die1 0) (define die2 0) (define turn-number 1) (define took-turn #f) (define (start-game) (set! tiles '(1 2 3 4 5 6 7 8 9))) (define (dice) (+ 1 (random 6))) (define (dice-roll) (set! die1 (dice)) (set! die2 (dice))) (define (sum-of-dice) (+ die1 die2)) (define (sum-of-tiles tilelist) (apply + tilelist)) (define (list-check l1 l2) (andmap (lambda (x) (not (boolean? (memq x l2)))) l1)) (define (shut-tiles tilelist) (if (not took-turn) (if (list-check tilelist tiles) (for ([i tilelist]) (if (index-of tiles i) (begin (set! tiles (remove i tiles)) (set! took-turn #t)) (error "Tile already shut"))) (error "Tile not available to be shut")) (error "Already took your turn"))) (define (check-roll dice-sum tile-sum) (= dice-sum tile-sum)) (define (player-turn tilelist) (if (check-roll (sum-of-dice) (sum-of-tiles tilelist)) (shut-tiles tilelist) (print "Roll does not equal shut tiles. Try again."))) (start-game) (dice-roll) (define (next-turn) (set! turn-number (+ 1 turn-number)) (set! took-turn #f) (dice-roll) (show-turn)) (define (show-turn) (printf "Turn: ") (println turn-number) (println tiles) (printf "Dice roll ~v ~v = ~v" die1 die2 (sum-of-dice) ))
Categories: LugNut Blogs

Day 21/100: Slow progress

Craig Maloney - Wed, 06/21/2017 - 22:53

More progress on the Shut the Box program in Racket.

Still need to figure out how to get everything together, but at least it's starting to make some sense.

#lang racket #| Init Block |# (define tiles '()) (define die1 0) (define die2 0) (define turn-number 1) (define (start-game) (set! tiles '(1 2 3 4 5 6 7 8 9))) (define (dice) (+ 1 (random 6))) (define (dice-roll) (set! die1 (dice)) (set! die2 (dice))) (define (sum-of-dice) (+ die1 die2)) (define (sum-of-tiles tilelist) (apply + tilelist)) (define (check-roll dice-sum tile-sum) (= dice-sum tile-sum)) (define (shut-tiles tilelist) (for ([i tilelist]) (if (index-of tiles i) (set! tiles (remove i tiles)) (print "Tile already shut")))) (define (player-turn tilelist) (if (check-roll (sum-of-dice) (sum-of-tiles tilelist)) (shut-tiles tilelist) (print "Roll does not equal shut tiles. Try again."))) (start-game) (dice-roll) (define (next-turn) (set! turn-number (+ 1 turn-number)) (dice-roll) (show-turn)) (define (show-turn) (printf "Turn: ") (println turn-number) (println tiles) (printf "Dice roll ~v ~v = ~v" die1 die2 (sum-of-dice) ))
Categories: LugNut Blogs

Pages