about summary refs log tree commit diff stats
path: root/shen/life.shen
blob: 65030421af36ac1fd7fe3e5b1e5efd4949f1fb32 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
(datatype subtype
  (subtype B A); X : B;
  _____________________
  X : A;)
 
(datatype integer
  if (integer? X)
  ___________
  X: integer;
 
  ________________________
  (subtype integer number);)
 
(datatype bit
  if (< X 2)
  _______
  X: bit;
 
  _____________________
  (subtype bit integer);)
 
(datatype row
 
  _________
  [] : row;
 
  C : bit; Row : row;
  ===================
  [C | Row] : row;)
 
(datatype universe
 
  ______________
  [] : universe;
 
  R : row; Uni : universe;
  ========================
  [R | Uni] : universe;)
 
(define conway-nth
  \\ returns value of x from row if it exists, else 0
  { number --> row --> bit }
  _ [] -> 0
  N _ -> 0 where (< N 0)
  0 [A|B] -> A
  N [A|B] -> (conway-nth (- N 1) B))

(define row-retrieve
  { number --> universe --> row }
  _ [] -> []
  0 [] -> []
  0 [A|B] -> A
  N [A|B] -> (row-retrieve (- N 1) B))
 
(define cell-retrieve
  { number --> number --> universe --> bit }
  X Y Universe -> (conway-nth X (row-retrieve Y Universe)))
 
(define neighbors
  \\ takes an X and Y, retrieves the number of neighbors
  { number --> number --> universe --> number }
  X Y Universe -> (let Inc (+ 1)
                       Dec (/. X (- X 1))
                    (+ (cell-retrieve (Inc X) Y Universe)
                       (cell-retrieve (Inc X) (Inc Y) Universe)
                       (cell-retrieve (Inc X) (Dec Y) Universe)
                       (cell-retrieve (Dec X) Y Universe)
                       (cell-retrieve (Dec X) (Inc Y) Universe)
                       (cell-retrieve (Dec X) (Dec Y) Universe)
                       (cell-retrieve X (Inc Y) Universe)
                       (cell-retrieve X (Dec Y) Universe))))

(define handle-alive
  { number --> number --> universe --> bit }
  X Y Universe -> (if (or (= (neighbors X Y Universe) 2)
                          (= (neighbors X Y Universe) 3))
                      1 0))
 
(define handle-dead
  { number --> number --> universe --> bit }
  X Y Universe -> (if (= (neighbors X Y Universe) 3)
                      1 0))
 
(define next-row
  \\ first argument must be a previous row, second must be 0 when
  \\ first called, third must be a Y value and the final must be the
  \\ current universe
  { row --> number --> number --> universe --> row }
  [] _ _ _ -> []
  [1|B] X Y Universe -> (cons (handle-alive X Y Universe)
                              (next-row B (+ X 1) Y Universe))
  [_|B] X Y Universe -> (cons (handle-dead X Y Universe)
                              (next-row B (+ X 1) Y Universe)))
 
(define next-universe
  \\ both the first and second arguments must be the same universe,
  \\ the third must be 0 upon first call
  { universe --> number --> universe --> universe }
  [] _ _ -> []
  [Row|Rest] Y Universe -> (cons (next-row Row 0 Y Universe)
                                 (next-universe Rest (+ Y 1) Universe)))
 
(define display-row
  { row --> number }
  [] -> (nl)
  [1|Rest] -> (do (output "* ")
                  (display-row Rest))
  [_|Rest] -> (do (output "  ")
                  (display-row Rest)))
 
(define display-universe
  { universe --> number }
  [] -> (nl 2)
  [Row|Rest] -> (do (display-row Row)
                    (display-universe Rest)))
 
(define iterate-universe
  { number --> universe --> number }
  0 _ -> (nl)
  N Universe -> (do (display-universe Universe)
                    (iterate-universe (- N 1)
                                      (next-universe Universe 0 Universe))))
 
(iterate-universe
 10
 [[0 0 0 0 0 0]
  [0 0 0 0 0 0]
  [0 0 1 1 1 0]
  [0 1 1 1 0 0]
  [0 0 0 0 0 0]
  [0 0 0 0 0 0]])