diff options
-rw-r--r-- | AoC2022.fsproj | 4 | ||||
-rw-r--r-- | Program.fs | 2 | ||||
-rw-r--r-- | solutions/day9.fs | 39 |
3 files changed, 45 insertions, 0 deletions
diff --git a/AoC2022.fsproj b/AoC2022.fsproj index acbbdb1..13269ee 100644 --- a/AoC2022.fsproj +++ b/AoC2022.fsproj @@ -7,4 +7,8 @@ <Compile Include="solutions/**" /> <Compile Include="Program.fs" /> </ItemGroup> + <ItemGroup> + <PackageReference Include="FSharpPlus" Version="1.3.2" /> + <PackageReference Update="FSharp.Core" Version="6.0.6" /> + </ItemGroup> </Project> \ No newline at end of file diff --git a/Program.fs b/Program.fs index ff91000..4d78505 100644 --- a/Program.fs +++ b/Program.fs @@ -24,5 +24,7 @@ match (day, part) with | (7, 2) -> printf $"{Day7.part2 ()}\n" | (8, 1) -> printf $"{Day8.part1 ()}\n" | (8, 2) -> printf $"{Day8.part2 ()}\n" +| (9, 1) -> printf $"{Day9.part1 ()}\n" +| (9, 2) -> printf $"{Day9.part2 ()}\n" | (x, y) when (1 <= x && x <= 25) && (y = 1 || y = 2) -> raise (NotImplemented("not implemented yet")) | _ -> raise (NotImplemented("invalid values")) \ No newline at end of file diff --git a/solutions/day9.fs b/solutions/day9.fs new file mode 100644 index 0000000..9c1407f --- /dev/null +++ b/solutions/day9.fs @@ -0,0 +1,39 @@ +namespace Solutions + +module Day9 = + open System.IO + open System.Text.RegularExpressions + open FSharpPlus.Operators + + let parseInstruction line = + let groups = Regex.Match(line, "([LRUD]) (\d+)").Groups + |> Seq.map (fun x -> x.Value) + |> Array.ofSeq + match groups[1], groups[2] with + | "L", count -> List.replicate (int count) (-1, 0) + | "R", count -> List.replicate (int count) (1, 0) + | "U", count -> List.replicate (int count) (0, 1) + | "D", count -> List.replicate (int count) (0, -1) + | _ -> failwith "invalid input" + + let headPositions steps = List.scan (fun (x1, y1) (x2, y2) -> (x1 + x2, y1 + y2)) (0, 0) steps + let instructions = File.ReadLines("inputs/day9.txt") |> Seq.map parseInstruction |> Seq.concat |> List.ofSeq |> headPositions + + let rec followPath (rope: list<int * int>) (tailSet: Set<int*int>) (heads: list<int*int>) = + let touches pointA pointB = abs (fst pointA - fst pointB) <= 1 && abs (snd pointA - snd pointB) <= 1 + let moveTowards head tail = (fst tail + signum (fst head - fst tail), snd tail + signum (snd head - snd tail)) + + if List.length heads = 0 then Set.count tailSet + else + let newHead = List.head heads + let newRope = List.scan (fun head tail -> if touches head tail then tail else moveTowards head tail) newHead (List.tail rope) + followPath newRope (Set.add (List.last newRope) tailSet) (List.tail heads) + + let solution ropeSize = + followPath (List.replicate ropeSize (0, 0)) Set.empty + + let part1 () = instructions + |> solution 2 + + let part2 () = instructions + |> solution 10 \ No newline at end of file |