diff options
Diffstat (limited to 'solutions')
-rw-r--r-- | solutions/day15.fs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/solutions/day15.fs b/solutions/day15.fs new file mode 100644 index 0000000..46f03c6 --- /dev/null +++ b/solutions/day15.fs @@ -0,0 +1,81 @@ +module Solutions.Day15 +open System.IO +open System.Text.RegularExpressions +open FSharpPlus.Operators + +let cave = set {0 .. 4_000_000} + +type Sensor(location: int*int, beacon: int*int) = + let manhattan (x1, y1) (x2, y2) = abs (x1 - x2) + abs (y1 - y2) + + member _.Location = location + + member _.Beacon = beacon + + member _.Distance = manhattan location beacon + + member s.Range (y: int) = + let scanWidth = s.Distance - abs (snd s.Location - y) + fst s.Location - scanWidth, fst s.Location + scanWidth + + override s.ToString() = + $"{s.Location} {s.Beacon}" + +let getCoords (line: string) = + let matches = Regex.Matches(line, "x=(-?\d+), y=(-?\d+)") + matches + |> Seq.map ((fun x -> x.Groups) >> Seq.tail >> (Seq.map (fun x -> int x.Value)) >> Array.ofSeq >> (fun x -> x[0], x[1])) + |> (Array.ofSeq >> (fun x -> Sensor(x[0], x[1]))) + +let sensors = File.ReadAllLines("inputs/day15.txt") + |> Seq.map getCoords + |> List.ofSeq + +let rangeSort (ax, ay) (bx, by) = + match ax - bx with + | 0 -> ay - by + | d -> d + +let reduceRanges ranges = + let foldMerge (acc: (int * int) list) (newStart, newEnd) = + match acc with + | [] -> [newStart, newEnd] + | (currStart, currEnd)::tail when newStart <= (currEnd + 1) && currEnd < newEnd -> (currStart, newEnd)::tail + | (_, currEnd)::_ when newStart <= currEnd + 1 -> acc + | _ -> (newStart, newEnd)::acc + ranges + |> List.sortWith rangeSort + |> List.fold foldMerge List.empty + +let sumRanges acc (rStart, rEnd) = acc + abs (rEnd + 1 - rStart) + +let getRanges y = + sensors + |> List.map (fun x -> x.Range y) + |> List.filter (fun x -> fst x < snd x) + |> reduceRanges + +let part1 () = + let beaconCount = + sensors + |> List.map (fun x -> x.Beacon) + |> List.filter (fun x -> snd x = 2_000_000) + |> List.distinct + |> List.length + + getRanges 2_000_000 + |> List.fold sumRanges 0 + |> fun x -> x - beaconCount + + +let part2 () = + let getGap ranges = + List.sortWith rangeSort ranges + |> List.head + |> snd + |> (+) 1 + + seq {0 .. 4_000_000} + |> Seq.map (fun i -> i, getRanges i) + |> Seq.find (snd >> List.length >> (=) 2) + |> fun (i, ranges) -> int64 (getGap ranges) * 4_000_000L + int64 i \ No newline at end of file |