diff --git a/advent-of-code/Program.fs b/advent-of-code/Program.fs index 75fad6e..37c95f2 100644 --- a/advent-of-code/Program.fs +++ b/advent-of-code/Program.fs @@ -20,4 +20,8 @@ let main _ = printfn $"{day4Star1}" let day4Star2 = day_4.Star2.main printfn $"{day4Star2}" + let day5Star1 = day_5.Star1.main + printfn $"%A{day5Star1}" + let day5Star2 = day_5.Star2.main + printfn $"%A{day5Star2}" 0 diff --git a/advent-of-code/tasks/day-5/Star1.fs b/advent-of-code/tasks/day-5/Star1.fs new file mode 100644 index 0000000..a1afb23 --- /dev/null +++ b/advent-of-code/tasks/day-5/Star1.fs @@ -0,0 +1,31 @@ +module advent_of_code.tasks.day_5.Star1 + +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 rec checkFresh (freshList: (int64 * int64) list) = + if stream.EndOfStream then + 0 + else + let fruit = stream.ReadLine() |> int64 + let freshness = List.sum (freshList |> List.map (isFresh fruit)) + (if freshness = 0 then 0 else 1) + checkFresh freshList + +let main = + let freshSet = List.sort (buildFresh()) + checkFresh freshSet diff --git a/advent-of-code/tasks/day-5/Star2.fs b/advent-of-code/tasks/day-5/Star2.fs new file mode 100644 index 0000000..5522315 --- /dev/null +++ b/advent-of-code/tasks/day-5/Star2.fs @@ -0,0 +1,55 @@ +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