From 81a7024da64efd12b31d451e28f85219a38bf366 Mon Sep 17 00:00:00 2001 From: Ville Penttinen Date: Wed, 6 Dec 2023 13:33:10 +0200 Subject: [PATCH] implement aoc2023 day6 --- visp/examples/aoc2023/day6.visp | 105 ++++++++++++++++++ visp/examples/aoc2023/inputs/day6.txt | 2 + visp/examples/aoc2023/inputs/day6_example.txt | 2 + 3 files changed, 109 insertions(+) create mode 100644 visp/examples/aoc2023/day6.visp create mode 100644 visp/examples/aoc2023/inputs/day6.txt create mode 100644 visp/examples/aoc2023/inputs/day6_example.txt diff --git a/visp/examples/aoc2023/day6.visp b/visp/examples/aoc2023/day6.visp new file mode 100644 index 0000000..b65879d --- /dev/null +++ b/visp/examples/aoc2023/day6.visp @@ -0,0 +1,105 @@ +;; Copyright 2023 Ville Penttinen +;; Distributed under the MIT License. +;; https://github.com/vipentti/visp-fs/blob/main/LICENSE.md +;; +;; for basic syntax highlighting +;; vim: set syntax=clojure: +(require SpanUtils "0.4.0") + +(open System) +(open System.Collections.Generic) +(open System.Text.RegularExpressions) +(open SpanUtils.Extensions) + +(fn WriteResult (part value ex) + (printfn "%s: %A %A" part value (= value ex))) + +(let example (not (Array.contains "full" ARGV))) +(let day "day6") +(let filepath (+ "./inputs/" day (if example "_example" "") ".txt")) + +(let splitOptions + (bor StringSplitOptions.TrimEntries StringSplitOptions.RemoveEmptyEntries)) + +(printfn "filepath: %s" filepath) + +(let contents (System.IO.File.ReadAllText filepath)) + +(fn SplitLines ([text: string]) + (text.EnumerateSplitSubstrings ((!array #\lf #\cr), splitOptions))) + +(fn ParseRaces ([lines: string]) + (mut enu (SplitLines lines)) + (let _ (enu.MoveNext)) + (let times enu.Current) + (let _ (enu.MoveNext)) + (let distances enu.Current) + + (let timesColon (times.IndexOf #\:)) + (let distancesColon (distances.IndexOf #\:)) + + (let times (times.Slice (inc timesColon))) + (let distances (distances.Slice (inc distancesColon))) + + (mut timesEnu (times.EnumerateSplitSubstrings (#\space, splitOptions))) + (mut distancesEnu (distances.EnumerateSplitSubstrings (#\space, splitOptions))) + + (let timesResult (!vector)) + (let distancesResult (!vector)) + + (while (timesEnu.MoveNext) + (timesResult.Add (span->int32 timesEnu.Current))) + + (while (distancesEnu.MoveNext) + (distancesResult.Add (span->int32 distancesEnu.Current))) + + (->> (Seq.zip timesResult distancesResult) + (List.ofSeq)) +) + +(type race int32*int32) + +(let races (ParseRaces contents)) + +(fn inline distance ([time: 'a] [speed: 'a]) (* time speed)) + +(fn inline estimate ([time: 'a] [held: 'a]) + (let speed held) + (let remaining (- time held)) + (distance remaining speed)) + +(fn ConcatNumbers (nums) + (->> nums + (Seq.map #(.ToString %1)) + (String.concat ""))) + +(fn inline CountWinsGen [rc] + (match rc + [(time . maxdist) + (mut result LanguagePrimitives.GenericZero) + (let start LanguagePrimitives.GenericOne) + (let end (dec time)) + + (for/in [held (!range start .. end)] + (let est (estimate time held)) + (if (> est maxdist) + (set! result (inc result)) + )) + + result + ] + ) +) + +(let part1 (->> races (List.map CountWinsGen) (List.reduce mul))) + +(WriteResult "part1" part1 (if example 288 2612736)) + +(let newTimes (->> races (Seq.map fst) ConcatNumbers int64)) +(let newDistances (->> races (Seq.map snd) ConcatNumbers int64)) + +(let part2 (CountWinsGen (newTimes . newDistances))) + +(WriteResult "part2" part2 (if example 71503 29891250)) + +() diff --git a/visp/examples/aoc2023/inputs/day6.txt b/visp/examples/aoc2023/inputs/day6.txt new file mode 100644 index 0000000..698b723 --- /dev/null +++ b/visp/examples/aoc2023/inputs/day6.txt @@ -0,0 +1,2 @@ +Time: 45 97 72 95 +Distance: 305 1062 1110 1695 diff --git a/visp/examples/aoc2023/inputs/day6_example.txt b/visp/examples/aoc2023/inputs/day6_example.txt new file mode 100644 index 0000000..28f5ae9 --- /dev/null +++ b/visp/examples/aoc2023/inputs/day6_example.txt @@ -0,0 +1,2 @@ +Time: 7 15 30 +Distance: 9 40 200