133 lines
3.5 KiB
Common Lisp
133 lines
3.5 KiB
Common Lisp
(* models one-dimensional cellular automaton on a circle of finite radius
|
|
arrays are faked as Strings,
|
|
X's respresent live cells, dots represent dead cells,
|
|
no error checking is done *)
|
|
class CellularAutomaton inherits IO {
|
|
population_map : String;
|
|
|
|
init(map : String) : SELF_TYPE {
|
|
{
|
|
population_map <- map;
|
|
self;
|
|
}
|
|
};
|
|
|
|
print() : SELF_TYPE {
|
|
{
|
|
out_string(population_map.concat("\n"));
|
|
self;
|
|
}
|
|
};
|
|
|
|
num_cells() : Int {
|
|
population_map.length()
|
|
};
|
|
|
|
cell(position : Int) : String {
|
|
population_map.substr(position, 1)
|
|
};
|
|
|
|
cell_left_neighbor(position : Int) : String {
|
|
if position = 0 then
|
|
cell(num_cells() - 1)
|
|
else
|
|
cell(position - 1)
|
|
fi
|
|
};
|
|
|
|
cell_right_neighbor(position : Int) : String {
|
|
if position = num_cells() - 1 then
|
|
cell(0)
|
|
else
|
|
cell(position + 1)
|
|
fi
|
|
};
|
|
|
|
(* a cell will live if exactly 1 of itself and it's immediate
|
|
neighbors are alive *)
|
|
cell_at_next_evolution(position : Int) : String {
|
|
if (if cell(position) = "X" then 1 else 0 fi
|
|
+ if cell_left_neighbor(position) = "X" then 1 else 0 fi
|
|
+ if cell_right_neighbor(position) = "X" then 1 else 0 fi
|
|
= 1)
|
|
then
|
|
"X"
|
|
else
|
|
'.'
|
|
fi
|
|
};
|
|
|
|
evolve() : SELF_TYPE {
|
|
(let position : Int in
|
|
(let num : Int <- num_cells[] in
|
|
(let temp : String in
|
|
{
|
|
while position < num loop
|
|
{
|
|
temp <- temp.concat(cell_at_next_evolution(position));
|
|
position <- position + 1;
|
|
}
|
|
pool;
|
|
population_map <- temp;
|
|
self;
|
|
}
|
|
) ) )
|
|
};
|
|
};
|
|
|
|
class Main {
|
|
cells : CellularAutomaton;
|
|
|
|
main() : SELF_TYPE {
|
|
{
|
|
cells <- (new CellularAutomaton).init(" X ");
|
|
cells.print();
|
|
(let countdown : Int <- 20 in
|
|
while countdown > 0 loop
|
|
{
|
|
cells.evolve();
|
|
cells.print();
|
|
countdown <- countdown - 1;
|
|
|
|
pool
|
|
); (* end let countdown
|
|
self;
|
|
}
|
|
};
|
|
};
|
|
*)
|
|
class AdditionalTest {
|
|
-- Int test
|
|
valid_int: Int <- 0123123;
|
|
invalid_int: Int <- 0x1234;
|
|
invalid_int2: Int <- 000_000;
|
|
-- String test
|
|
valid_str: String <- "hello world!\n";
|
|
escape_str: String <- "\"\n\\n\b\ff\t\K\*\00";
|
|
err_newline_str: String <- "This is
|
|
not ok";
|
|
err_newline_str2: String <- "This is \
|
|
also not ok";
|
|
err_newline_str3: String <- "This is \
|
|
tricky lineno
|
|
not ok";
|
|
ok_newline_string: String <- "This is \
|
|
ok";
|
|
-- Bool test
|
|
valid_bool_true: Bool <- true = tRUE = trUe;
|
|
valid_bool_false: Bool <- false = fALsE = fALSE;
|
|
invalid_bool_true: Bool <- True = TRUe;
|
|
invalid_bool_false: Bool <- False = FALSE;
|
|
-- Invalid character test
|
|
_hello: Bool <- 1 != 2 <> 3_3?;
|
|
-- Comment test
|
|
hello: Type <- 0;
|
|
-- Valid nested comment
|
|
(* (* feigling (* versagar
|
|
scheisse
|
|
scheisse*) verpfeif *)
|
|
*)
|
|
-- Invalid nested comment
|
|
(* *) (( lost left close, Unmatched * ) expected *)
|
|
(* (* lost right close, EOF in comment expected) *)
|
|
}; |