56 lines
2.2 KiB
Forth
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
|