<commit_before>;; Game of Life

(import (use 'sturm)
  cbreak-mode)
(import (use 'ansi-term)
  home clear-screen cursor-show cursor-hide)

(to (main args)
  (let n-steps (may args.rest
                 (be '()       20)
                 (be `(,n-str) (number<-string n-str))
                 (else (error ("Usage: ~d [#steps]" .format (args 0))))))
  (let grid (grid<- 24 39))
  (paint grid 10 18 '(" **"             ;TODO: read in a pattern
                      "** "
                      " * "))
  (for cbreak-mode ()
    (display cursor-hide)
    (begin running ((grid grid) (step 0))
      (display clear-screen)
      (display home)
      grid.show
      (when (< step n-steps)
        (running grid.next step.+)))
    (display cursor-show)))

(to (smoke-test)
  (let grid (grid<- 8 8))
  (paint grid 3 3 '(" **"
                    "** "
                    " * "))
  grid.show
  (let gen1 grid.next)
  gen1.show
  gen1.next.show)

(to (paint grid top left lines)
  (let bottom (+ top lines.count -1))
  (for each! ((`(,i ,line) lines.items))
    (for each! ((`(,j ,ch) line.items))
      (grid .set! (- bottom i) (+ left j)
            (if ch.whitespace? 0 1)))))

(to (grid<- n-rows n-cols)
  ;; G is an array storing, for each Life grid cell, its value (0 or
  ;; 1). It has two extra rows and columns for the edges.
  (let R (+ n-rows 2))
  (let C (+ n-cols 2))
  (let G (array<-count (* R C) 0))
  (grid<-array n-rows n-cols G))

(to (grid<-array n-rows n-cols G)

  (let R (+ n-rows 2))
  (let C (+ n-cols 2))

  (let N (- C))
  (let S C)
  (let W (- 1))
  (let E 1)
  (let neighbor-dirs
    `(,(+ N W) ,N ,(+ N E)
      ,W          ,E
      ,(+ S W) ,S ,(+ S E)))

  ;; r in [1..n-rows], c in [1..n-cols].
  (to (at r c)
    (+ (* C r) c))

  (to (update i)
    (may (sum (for each ((dir neighbor-dirs))
                (G (+ i dir))))
      (be 2 (G i))
      (be 3 1)
      (else 0)))

  ;; Make the world toroidal by copying the edges of the array so that
  ;; row #1 effectively neighbors row #n-rows, and likewise for the
  ;; columns.
  (to (copy-edges)
    (for each! ((r (1 .to n-rows)))
      (G .set! (at r 0)       (G (at r n-cols)))
      (G .set! (at r (- C 1)) (G (at r 1))))
    (copy! (at 0 0)       (at n-rows 0) C)
    (copy! (at (- R 1) 0) (at 1 0)      C))

  (to (copy! dest lo n)
    (G .move! dest G lo (+ lo n)))

  (make life-grid
    (to (_ r c)
      (G (at r c)))
    (to (_ .set! r c value)
      (surely ('(0 1) .find? value))
      (G .set! (at r c) value))
    (to _.show
      (for each! ((r (1 .to n-rows)))
        (for each! ((c (1 .to n-cols)))
          (display (" O" (G (at r c))))
          (display " "))
        (newline)))
    (to _.next
      (copy-edges)
      (let new-G (array<-count (* R C) 0))<commit_msg>tweak<commit_after>;; Game of Life

(import (use 'sturm)
  cbreak-mode)
(import (use 'ansi-term)
  home clear-screen cursor-show cursor-hide)

(to (main args)
  (let n-steps (may args.rest
                 (be '()       20)
                 (be `(,n-str) (number<-string n-str))
                 (else (error ("Usage: ~d [#steps]" .format (args 0))))))
  (let grid (grid<- 24 39))
  (paint grid 10 18 '(" **"             ;TODO: read in a pattern
                      "** "
                      " * "))
  (for cbreak-mode ()
    (display cursor-hide)
    (begin running ((grid grid) (step 0))
      (display clear-screen)
      (display home)
      grid.show
      (when (< step n-steps)
        (running grid.next step.+)))
    (display cursor-show)))

(to (smoke-test)
  (let grid (grid<- 8 8))
  (paint grid 3 3 '(" **"
                    "** "
                    " * "))
  grid.show
  (let gen1 grid.next)
  gen1.show
  gen1.next.show)

(to (paint grid top left lines)
  (let bottom (+ top lines.count -1))
  (for each! ((`(,i ,line) lines.items))
    (for each! ((`(,j ,ch) line.items))
      (grid .set! (- bottom i) (+ left j)
            (if ch.whitespace? 0 1)))))

(to (grid<- n-rows n-cols)
  ;; G is an array storing, for each Life grid cell, its value (0 or
  ;; 1). It has two extra rows and columns for the edges.
  (let R (+ n-rows 2))
  (let C (+ n-cols 2))
  (let G (array<-count (* R C) 0))
  (grid<-array n-rows n-cols G))

(to (grid<-array n-rows n-cols G)

  (let R (+ n-rows 2))
  (let C (+ n-cols 2))

  (let N (- C))
  (let S C)
  (let W (- 1))
  (let E 1)
  (let neighbor-dirs
    `(,(+ N W) ,N ,(+ N E)
      ,W          ,E
      ,(+ S W) ,S ,(+ S E)))

  ;; r in [1..n-rows], c in [1..n-cols].
  (to (at r c)
    (+ (* C r) c))

  (to (update i)
    (may (sum (for each ((dir neighbor-dirs))
                (G (+ i dir))))
      (be 2 (G i))
      (be 3 1)
      (else 0)))

  ;; Make the world toroidal by copying the edges of the array so that
  ;; row #1 effectively neighbors row #n-rows, and likewise for the
  ;; columns.
  (to (copy-edges)
    (for each! ((r (1 .to n-rows)))
      (G .set! (at r 0)   (G (at r n-cols)))
      (G .set! (at r C.-) (G (at r 1))))
    (copy! (at 0 0)   (at n-rows 0) C)
    (copy! (at R.- 0) (at 1 0)      C))

  (to (copy! dest lo n)
    (G .move! dest G lo (+ lo n)))

  (make life-grid
    (to (_ r c)
      (G (at r c)))
    (to (_ .set! r c value)
      (surely ('(0 1) .find? value))
      (G .set! (at r c) value))
    (to _.show
      (for each! ((r (1 .to n-rows)))
        (for each! ((c (1 .to n-cols)))
          (display (" O" (G (at r c))))
          (display " "))
        (newline)))
    (to _.next
      (copy-edges)
      (let new-G (array<-count (* R C) 0))
{'fraction_non_alphanumeric': 0.19253081943437272, 'fraction_numerical': 0.019216823785351705, 'mean_word_length': 1.7298367144977733, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1276204', 'n_tokens_mistral': 2241, 'n_tokens_neox': 2094, 'n_words': 751}