aboutsummaryrefslogtreecommitdiff
path: root/aoc-2020-gleam/src/days/day13.gleam
diff options
context:
space:
mode:
authorTomasz Chojnacki <tomaszchojnacki2001@gmail.com>2023-04-06 22:00:05 +0200
committerTomasz Chojnacki <tomaszchojnacki2001@gmail.com>2023-04-06 22:00:05 +0200
commit76e1d24c9cb3f2461f4dca08271fa25f97e820b7 (patch)
tree232859b85c356d71fdb89e8c627df17455bd812b /aoc-2020-gleam/src/days/day13.gleam
parent20852d6e60bee896e84c9bae77f45211773dbf60 (diff)
downloadgleam_aoc2020-76e1d24c9cb3f2461f4dca08271fa25f97e820b7.tar.gz
gleam_aoc2020-76e1d24c9cb3f2461f4dca08271fa25f97e820b7.zip
Finish day 13
Diffstat (limited to 'aoc-2020-gleam/src/days/day13.gleam')
-rw-r--r--aoc-2020-gleam/src/days/day13.gleam113
1 files changed, 113 insertions, 0 deletions
diff --git a/aoc-2020-gleam/src/days/day13.gleam b/aoc-2020-gleam/src/days/day13.gleam
new file mode 100644
index 0000000..c95cd42
--- /dev/null
+++ b/aoc-2020-gleam/src/days/day13.gleam
@@ -0,0 +1,113 @@
+import gleam/io
+import gleam/int
+import gleam/list
+import gleam/pair
+import gleam/string as str
+import gleam/iterator as iter
+import ext/intx
+import ext/resultx as resx
+import ext/iteratorx as iterx
+import util/input_util
+
+type Bus {
+ Any
+ Line(Int)
+}
+
+type Problem {
+ Problem(timestamp: Int, buses: List(Bus))
+}
+
+fn parse_problem(input: String) -> Problem {
+ let assert Ok(#(timestamp, buses)) =
+ input
+ |> str.trim
+ |> str.split_once(on: "\n")
+ let assert Ok(timestamp) = int.parse(timestamp)
+ let buses =
+ buses
+ |> str.split(on: ",")
+ |> list.map(with: fn(b) {
+ case b == "x" {
+ True -> Any
+ False ->
+ b
+ |> int.parse
+ |> resx.assert_unwrap
+ |> Line
+ }
+ })
+ Problem(timestamp, buses)
+}
+
+fn part1(input: String) -> Int {
+ let problem = parse_problem(input)
+
+ problem.buses
+ |> list.filter_map(with: fn(b) {
+ case b {
+ Line(line) -> Ok(line)
+ Any -> Error(Nil)
+ }
+ })
+ |> list.map(with: fn(b) {
+ #(b, b * intx.ceil_divide(problem.timestamp, by: b) - problem.timestamp)
+ })
+ |> list.reduce(with: fn(acc, cur) {
+ case cur.1 < acc.1 {
+ True -> cur
+ False -> acc
+ }
+ })
+ |> resx.assert_unwrap
+ |> fn(res: #(Int, Int)) { res.0 * res.1 }
+}
+
+fn part2(input: String) -> Int {
+ let problem = parse_problem(input)
+
+ let buses =
+ problem.buses
+ |> iter.from_list
+ |> iter.index
+ |> iter.flat_map(fn(entry) {
+ let #(i, b) = entry
+ case b {
+ Line(line) -> iter.single(#(line, i))
+ Any -> iter.empty()
+ }
+ })
+ |> iter.to_list
+
+ let assert [#(timestamp, _), ..] = buses
+
+ buses
+ |> list.fold(
+ from: #(timestamp, timestamp),
+ with: fn(prev, entry) {
+ let #(timestamp, period) = prev
+ let #(id, i) = entry
+
+ let assert Ok(timestamp) =
+ timestamp
+ |> iterx.unfold_infinitely(with: int.add(_, period))
+ |> iter.find(one_that: fn(t) { { t + i } % id == 0 })
+ let period = intx.lcm(period, id)
+
+ #(timestamp, period)
+ },
+ )
+ |> pair.first
+}
+
+pub fn main() -> Nil {
+ let test = input_util.read_text("test13")
+ let assert 295 = part1(test)
+ let assert 1_068_781 = part2(test)
+
+ let input = input_util.read_text("day13")
+ io.debug(part1(input))
+ io.debug(part2(input))
+
+ Nil
+}