-
-
Save remi6397/68fbf549bff1f1ab5358d527d9eb5118 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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