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
|
module Day22
open System.IO
open System.Text.RegularExpressions
open FSharpPlus
open FSharpPlus.Math.Generic
open Common
let passwordRegex = Regex("L|R|\d+", RegexOptions.Compiled)
let facing =
function
| Vec2 (1, 0) -> 0
| Vec2 (0, 1) -> 1
| Vec2 (-1, 0) -> 2
| Vec2 (0, -1) -> 3
| v -> failwithf "Invalid direction: %A" v
let solution wrapper input =
let map, password = Util.splitStringToTuple "\n\n" input
let map =
map
|> String.split [ "\n" ]
|> Seq.map (String.padRight 150)
|> array2D
let (pos, dir) =
passwordRegex.Matches(password)
|> Seq.fold
(fun (pos, dir) c ->
match c.Value with
| "R" -> pos, Vec2.rotateLeft dir
| "L" -> pos, Vec2.rotateRight dir
| dist ->
Util.composition
(int dist)
(fun state ->
let state' = state |> mapItem1 ((+) <| snd state) |> wrapper
match Util.mAt map (fst state') with
| '.' -> state'
| _ -> state)
(pos, dir))
(Vec2(Seq.findIndex ((=) '.') map[0, *], 0), Vec2.right)
let (Vec2 (x, y)) = pos + Vec2.ones
y * 1000 + x * 4 + facing dir
let wrap1 (Vec2 (x, y), d) =
let x, y =
match (divE x 50, divE y 50, d) with
| (1, 3, Vec2 (0, 1))
| (2, 1, Vec2 (0, 1)) -> x, 0
| (2, -1, Vec2 (0, -1)) -> x, 49
| (0, 4, Vec2 (0, 1)) -> x, 100
| (1, -1, Vec2 (0, -1)) -> x, 149
| (0, 1, Vec2 (0, -1)) -> x, 199
| (1, 3, Vec2 (1, 0))
| (2, 2, Vec2 (1, 0)) -> 0, y
| (-1, 3, Vec2 (-1, 0)) -> 49, y
| (2, 1, Vec2 (1, 0))
| (3, 0, Vec2 (1, 0)) -> 50, y
| (-1, 2, Vec2 (-1, 0))
| (0, 1, Vec2 (-1, 0)) -> 99, y
| (0, 0, Vec2 (-1, 0)) -> 149, y
| _ -> x, y
Vec2(x, y), d
let wrap2 (Vec2 (x, y), d) =
let x, y, t =
match (divE x 50, divE y 50, d) with
| (-1, 2, Vec2 (-1, 0)) -> 50, 149 - y, Vec2.flip
| (-1, 3, Vec2 (-1, 0)) -> y - 100, 0, Vec2.rotateRight
| (0, 0, Vec2 (-1, 0)) -> 0, 149 - y, Vec2.flip
| (0, 1, Vec2 (-1, 0)) -> y - 50, 100, Vec2.rotateRight
| (0, 1, Vec2 (0, -1)) -> 50, x + 50, Vec2.rotateLeft
| (0, 4, Vec2 (0, 1)) -> x + 100, 0, id
| (1, -1, Vec2 (0, -1)) -> 0, x + 100, Vec2.rotateLeft
| (1, 3, Vec2 (1, 0)) -> y - 100, 149, Vec2.rotateRight
| (1, 3, Vec2 (0, 1)) -> 49, x + 100, Vec2.rotateLeft
| (2, -1, Vec2 (0, -1)) -> x - 100, 199, id
| (2, 1, Vec2 (1, 0)) -> y + 50, 49, Vec2.rotateRight
| (2, 1, Vec2 (0, 1)) -> 99, x - 50, Vec2.rotateLeft
| (2, 2, Vec2 (1, 0)) -> 149, 149 - y, Vec2.flip
| (3, 0, Vec2 (1, 0)) -> 99, 149 - y, Vec2.flip
| _ -> x, y, id
Vec2(x, y), t d
let input = File.ReadAllText("input.txt")
printfn "%d" <| solution wrap1 input
printfn "%d" <| solution wrap2 input
|