Tuesday, 3 November 2015

Programming Number Squares

I want to produce number squares (10 x 10 grids of numbers up to 100) and highlight different sequences of numbers to help in my maths teaching. For example: what sequence is highlighted in the number square below?



I could make these in a spreadsheet, but why not program it so that I can quickly produce a range of number squares?

I've been playing with the Racket programming language (http://racket-lang.org/) and given that it has graphics primitives built in to the basic language it seems like a good choice.

Here's an example of what it can do with graphics, try each line in turn...
(require 2htdp/image) 
(text "21" 50 "black") 
(rectangle 70 70 "solid" "yellow") 
(overlay (text "21" 50 "black")  (rectangle 70 70 "solid" "yellow")) 
OK, so we have a yellow square with 21 in it. So from these basics we can build some number squares:
(require 2htdp/image)  
(require math/number-theory)
(define NUMBERS-PER-LINE 10)  
(define NUMBER-SIZE 30)
(define BOX-SIZE 60)
(define (number-in-box n pred)
  (overlay (text (number->string n) NUMBER-SIZE "black")
           (if (pred n)
               (rectangle BOX-SIZE BOX-SIZE "solid" "pink")
               (rectangle BOX-SIZE BOX-SIZE "outline" "black"))))
(define (number-block n pred)
  (define numbers (rest (build-list (+ n 1)
                                    (λ (x) (number-in-box x pred)))))
  (define (number-lines l)
    (cond [(= (length l) NUMBERS-PER-LINE)
           (apply beside (take l NUMBERS-PER-LINE))]
          [else
           (above
            (apply beside (take l NUMBERS-PER-LINE))
            (number-lines (drop l NUMBERS-PER-LINE)))]))
  (number-lines numbers))
The first procedure number-in-box draws one number and colours it (or not) depending on the predicate pred, which is a test for the number. Try these:

(number-in-box 5 odd?)
(number-in-box 5 even?)

The second procedure number-block draws the block of numbers, again with the predicate (which it simply passes on to number-in-box. Try these:
(number-block 100 odd?)  
(number-block 100 prime?) 
(number-block 100 square-number?)

Making times tables with curry

To make tables for times tables you need to add a predicate to test for multiples of a number, e.g.:
(define (multiple-of-3? n)
  (zero? (remainder n 3))) 
Now you can run:
(number-block 100 multiple-of-3?)
However, it's a bit of work to have to define a new procedure each time we want a new times table. What about a predicate like this?

(define (multiple-of? m n)
  (zero? (remainder n m)))

This takes two parameters like this: (multiple-of? 3 9)
in this example, is 9 a multiple of 3?

However, our predicate that we want to pass to number-block expects a single argument: the number in the number square. How can we adapt this procedure to accept a single argument? The answer: with currying.

(curry multiple-of? 3) is a new version of our procedure with the three already passed, so this version is ready to accept the number from the number square. Try these examples:

(number-block 100 (curry multiple-of? 4))
(number-block 100 (curry multiple-of? 5))
(number-block 100 (curry multiple-of? 6))


No comments:

Post a Comment