A 9/lex.mll => 9/lex.mll +11 -0
@@ 0,0 1,11 @@
+{
+type token =
+ | Line of char * int
+ | Eof
+
+let i = int_of_string
+}
+
+rule token = parse
+ | (['A'-'Z'] as c) ' ' (['0'-'9']+ as s) '\n' { Line (c, i s) }
+ | eof { Eof }
A 9/t1.ml => 9/t1.ml +49 -0
@@ 0,0 1,49 @@
+let rec f lexbuf =
+ match Lex.token lexbuf with
+ | Eof -> []
+ | Line (c, i) ->
+ let dir =
+ match c with
+ | 'L' -> (-1, 0)
+ | 'R' -> (1, 0)
+ | 'U' -> (0, 1)
+ | 'D' -> (0, -1)
+ | _ -> failwith "wut"
+ in
+ (dir, i) :: f lexbuf
+
+module PairSet = Set.Make(
+ struct
+ type t = int * int
+ let compare = compare
+ end
+)
+
+let move' (x, y) (dx, dy) = x + dx, y + dy
+
+let move_follow ((x, y) as tail) (x', y') =
+ let d =
+ match x'- x, y' - y with
+ | dx, dy when abs dx = 2 -> dx / 2, dy
+ | dx, dy when abs dy = 2 -> dx, dy / 2
+ | _ -> 0, 0
+ in
+ move' tail d
+
+let move_tail set tail head =
+ let newtail = move_follow tail head in
+ (PairSet.add newtail set, newtail, head)
+
+let rec move ((set, tail, head) as state) (d, n) =
+ match n with
+ | 0 -> state
+ | n -> move (move_tail set tail (move' head d)) (d, n - 1)
+
+let () =
+ stdin
+ |> Lexing.from_channel
+ |> f
+ |> List.fold_left move (PairSet.singleton (0, 0), (0, 0), (0, 0))
+ |> fun (x, _, _) -> x
+ |> PairSet.cardinal
+ |> Printf.printf "%d\n"
A 9/t2.ml => 9/t2.ml +51 -0
@@ 0,0 1,51 @@
+let rec f lexbuf =
+ match Lex.token lexbuf with
+ | Eof -> []
+ | Line (c, i) ->
+ let dir =
+ match c with
+ | 'L' -> (-1, 0)
+ | 'R' -> (1, 0)
+ | 'U' -> (0, 1)
+ | 'D' -> (0, -1)
+ | _ -> failwith "wut"
+ in
+ (dir, i) :: f lexbuf
+
+module PairSet = Set.Make(
+ struct
+ type t = int * int
+ let compare = compare
+ end
+)
+
+let move' (x, y) (dx, dy) = x + dx, y + dy
+
+let move_follow (x', y') ((x, y) as tail) =
+ let d =
+ match x' - x, y' - y with
+ | dx, dy when abs dx = 2 -> dx / 2, dy
+ | dx, dy when abs dy = 2 -> dx, dy / 2
+ | _ -> 0, 0
+ in
+ let tail = move' tail d in
+ tail, tail
+
+let move_tail set tail head =
+ let last, tail = List.fold_left_map move_follow head tail in
+ (PairSet.add last set, tail, head)
+
+let rec move ((set, tail, head) as state) (d, n) =
+ match n with
+ | 0 -> state
+ | n -> move (move_tail set tail (move' head d)) (d, n - 1)
+
+let () =
+ let init = List.init 8 (fun _ -> (0, 0)) in
+ stdin
+ |> Lexing.from_channel
+ |> f
+ |> List.fold_left move (PairSet.singleton (0, 0), init, (0, 0))
+ |> fun (x, _, _) -> x
+ |> PairSet.cardinal
+ |> Printf.printf "%d\n"