Skip to content

Instantly share code, notes, and snippets.

@remi6397
Last active February 24, 2018 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remi6397/68fbf549bff1f1ab5358d527d9eb5118 to your computer and use it in GitHub Desktop.
Save remi6397/68fbf549bff1f1ab5358d527d9eb5118 to your computer and use it in GitHub Desktop.
open Containers
type state =
| Empty
| Head
| Tail
| Conductor
type cell = {
mutable state : state;
mutable neighbors : cell list
}
let tick (board : cell array array) : unit =
for y = 0 to Array.length board do
for x = 0 to Array.length board.(0) do
let cell_cur = board.(y).(x) in
cell_cur.state <-
match cell_cur.state with
| Head -> Tail
| Tail -> Conductor
| Conductor ->
let num_heads = List.length (List.filter (fun c -> Equal.physical c.state Head) cell_cur.neighbors) in
if num_heads = 2 || num_heads = 1 then Head else Conductor
| Empty -> Empty
done
done
let decode_board str =
let decode_variant = function
| 'O' -> Head
| 'o' -> Tail
| '#' -> Conductor
| _ -> Empty in
let justify xs =
let longest = Array.fold_left (fun acc x -> Int.max acc (Array.length x)) 0 xs in
Array.map (fun x ->
if Array.length x < longest then
Array.concat [ x; Array.init (longest - Array.length x) (fun _ -> ' ') ]
else x) xs in
let board =
str
|> String.split ~by:"\n"
|> Array.of_list
|> Array.map String.to_array
|> justify
|> Array.mapi (fun posx x->
Array.mapi (fun posy y ->
{
state = decode_variant y;
neighbors = []
}
) x) in
let ymax = Array.length board - 1 in
let xmax = Array.length board.(0) - 1 in
for y = 0 to ymax do
for x = 0 to xmax do
board.(y).(x).neighbors <- List.filter_map (fun a -> (* This essentially checks whether a potential neighbor is within bounds of the board *)
let (x', y', el) = a in
let yrel = match y with
| 0 -> -1
| _ -> if y = ymax then 1 else 0 in
let xrel = match x with
| 0 -> -1
| _ -> if x = xmax then 1 else 0 in
match (y', x', y' - yrel, x' - xrel) with
| (_, _, 0, 0) -> Some el
| (0, _, _, 0) -> Some el
| (_, 0, 0, _) -> Some el
| _ -> None
) [
(-1, 0, board.(y-1).(x));
( 1, 0, board.(y+1).(x));
(-1, -1, board.(y-1).(x-1));
( 1, -1, board.(y+1).(x-1));
( 1, 1, board.(y+1).(x+1));
(-1, 1, board.(y-1).(x+1));
( 0, -1, board.(y).(x-1));
( 0, 1, board.(y).(x+1));
]
done
done;
board
let () =
let is = if Array.length Sys.argv >= 3 then open_in Sys.argv.(2) else stdin in
let board = decode_board @@ IO.read_all is in
for gen = 0 to int_of_string (Sys.argv.(1)) do
tick board
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment