diff options
Diffstat (limited to 'solutions/day9.fs')
-rw-r--r-- | solutions/day9.fs | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/solutions/day9.fs b/solutions/day9.fs index 9c1407f..b681266 100644 --- a/solutions/day9.fs +++ b/solutions/day9.fs @@ -1,39 +1,37 @@ -namespace Solutions +module Solutions.Day9 +open System.IO +open System.Text.RegularExpressions +open FSharpPlus.Operators -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 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 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)) - 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) - 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 solution ropeSize = + followPath (List.replicate ropeSize (0, 0)) Set.empty - let part1 () = instructions - |> solution 2 +let part1 () = instructions + |> solution 2 - let part2 () = instructions - |> solution 10 \ No newline at end of file +let part2 () = instructions + |> solution 10 \ No newline at end of file |