2025-12-05 19:28:58 +00:00

56 lines
2.2 KiB
Forth

module advent_of_code.tasks.day_5.Star2
open System
open System.IO
let stream = new StreamReader("tasks/day-5/input.txt")
let rec buildFresh() =
let line = stream.ReadLine()
if line.Length = 0 then
List.empty
else
let splitLine = line.Split("-")
let low, high = splitLine[0] |> int64, splitLine[1] |> int64
List.append [ (low, high) ] (buildFresh())
let isFresh (fruit: int64) (range: int64 * int64) =
let low, high = range.Deconstruct()
if (fruit >= low && fruit <= high) then 1 else 0
let matchRange (a: int64 * int64) (b: int64 * int64) =
let aMin, aMax = a.Deconstruct()
let bMin, bMax = b.Deconstruct()
(aMin <= bMin && bMin <= aMax) || (bMin <= aMin && aMin <= bMax) ||
(aMin <= bMin && aMax >= bMax) || (bMin <= aMin && bMax >= aMax)
let combineRange (a: int64 * int64) (b: int64 * int64) =
let aMin, aMax = a.Deconstruct()
let bMin, bMax = b.Deconstruct()
(min aMin bMin, max aMax bMax)
let rec trimFresh (trimmedFreshList: (int64 * int64) list) (fullFreshList: (int64 * int64) list) =
let currentRange, tail = fullFreshList.Head, fullFreshList.Tail
let overlaps = trimmedFreshList |> List.map (matchRange currentRange)
let firstOverlap = List.tryFindIndex ((=) true) overlaps
let newTrimmedList =
match firstOverlap with
| None -> List.append trimmedFreshList [currentRange]
| Some 0 -> List.append [combineRange currentRange trimmedFreshList[0]] trimmedFreshList[1 ..]
| Some index -> List.append (List.append trimmedFreshList[.. index - 1] [combineRange currentRange trimmedFreshList[index]]) trimmedFreshList[index + 1 ..]
if tail.IsEmpty then newTrimmedList else trimFresh newTrimmedList tail
let rec trimLoop (fullFreshList: (int64 * int64) list) =
let trimmedList = trimFresh List.empty fullFreshList
if trimmedList.Length = fullFreshList.Length then trimmedList else trimLoop trimmedList
let rec addRanges (ranges: (int64 * int64) list) =
let range, tail = ranges.Head, ranges.Tail
let low, high = range.Deconstruct()
((high - low) + (1 |> int64)) + (if tail.IsEmpty then 0 |> int64 else (addRanges tail))
let main =
let freshSet = List.sort (buildFresh())
let trimmed = trimLoop freshSet
addRanges trimmed