my solutions to advent of code
aoc advent-of-code

ugly day 14 2015

aylac.top 43ccf73a 1bc0a569

verified
Changed files
+237
2015
+20
2015/14/gleam/gleam.toml
···
···
+
name = "main"
+
version = "1.0.0"
+
+
# Fill out these fields if you intend to generate HTML documentation or publish
+
# your project to the Hex package manager.
+
#
+
# description = ""
+
# licences = ["Apache-2.0"]
+
# repository = { type = "github", user = "", repo = "" }
+
# links = [{ title = "Website", href = "" }]
+
#
+
# For a full reference of all the available options, you can have a look at
+
# https://gleam.run/writing-gleam/gleam-toml/.
+
+
[dependencies]
+
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
+
simplifile = ">= 2.3.0 and < 3.0.0"
+
+
[dev-dependencies]
+
gleeunit = ">= 1.0.0 and < 2.0.0"
+14
2015/14/gleam/manifest.toml
···
···
+
# This file was generated by Gleam
+
# You typically do not need to edit this file
+
+
packages = [
+
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
+
{ name = "gleeunit", version = "1.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "CD701726CBCE5588B375D157B4391CFD0F2F134CD12D9B6998A395484DE05C58" },
+
{ name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" },
+
]
+
+
[requirements]
+
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
+
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+
simplifile = { version = ">= 2.3.0 and < 3.0.0" }
+203
2015/14/gleam/src/main.gleam
···
···
+
import gleam/dict.{type Dict}
+
import gleam/int
+
import gleam/io
+
import gleam/list
+
import gleam/order.{Eq, Gt, Lt}
+
import gleam/result
+
import gleam/set.{type Set}
+
import gleam/string
+
import simplifile as file
+
+
pub type Reindeer {
+
Reindeer(name: String, speed: Int, run: Int, rest: Int)
+
}
+
+
pub type Action {
+
Run
+
Rest
+
}
+
+
pub type ReindeerState {
+
ReindeerState(km: Int, action: Action, time_until_change: Int)
+
}
+
+
pub type RunState =
+
dict.Dict(String, ReindeerState)
+
+
pub type ReindeerStatePoints {
+
ReindeerStatePoints(
+
points: Int,
+
km: Int,
+
action: Action,
+
time_until_change: Int,
+
)
+
}
+
+
pub type LeadKm {
+
LeadKm(km: Int, leads: Set(String))
+
}
+
+
pub type RunStatePoints {
+
RunStatePoints(lead_km: LeadKm, state: Dict(String, ReindeerStatePoints))
+
}
+
+
pub fn to_int(number_string) {
+
let assert Ok(number) = number_string |> int.base_parse(10)
+
as { number_string <> " is not a number" }
+
number
+
}
+
+
pub fn do_calculate_run_state(state: RunState, reindeers: List(Reindeer), sec) {
+
case sec > 0 {
+
False -> state
+
True -> {
+
reindeers
+
|> list.fold(state, fn(state, reindeer) {
+
let Reindeer(name, speed, run, rest) = reindeer
+
let ReindeerState(km, action, time_until_change) =
+
state
+
|> dict.get(reindeer.name)
+
|> result.unwrap(ReindeerState(0, Run, run))
+
+
let km = case action {
+
Run -> km + speed
+
Rest -> km
+
}
+
case time_until_change, action {
+
1, Run -> ReindeerState(km, Rest, rest)
+
1, Rest -> ReindeerState(km, Run, run)
+
_, _ -> ReindeerState(km, action, time_until_change - 1)
+
}
+
|> dict.insert(state, name, _)
+
})
+
|> do_calculate_run_state(reindeers, sec - 1)
+
}
+
}
+
}
+
+
pub fn calculate_run_state(reindeers: List(Reindeer), sec: Int) {
+
do_calculate_run_state(dict.new(), reindeers, sec)
+
}
+
+
pub fn get_winner_km(state: RunState) {
+
state
+
|> dict.fold(0, fn(winner, _, state) {
+
case state.km > winner {
+
True -> state.km
+
False -> winner
+
}
+
})
+
}
+
+
pub fn do_calculate_run_state_pt2(
+
state: RunStatePoints,
+
reindeers: List(Reindeer),
+
sec,
+
) {
+
case sec > 0 {
+
False -> state
+
True -> {
+
let RunStatePoints(LeadKm(_, leads), state) =
+
reindeers
+
|> list.fold(state, fn(s, reindeer) {
+
let RunStatePoints(lead_km, state) = s
+
let Reindeer(name, speed, run, rest) = reindeer
+
let ReindeerStatePoints(points, km, action, time_until_change) =
+
state
+
|> dict.get(reindeer.name)
+
|> result.unwrap(ReindeerStatePoints(0, 0, Run, run))
+
+
let km = case action {
+
Run -> km + speed
+
Rest -> km
+
}
+
let state =
+
case time_until_change, action {
+
1, Run -> ReindeerStatePoints(points, km, Rest, rest)
+
1, Rest -> ReindeerStatePoints(points, km, Run, run)
+
_, _ ->
+
ReindeerStatePoints(points, km, action, time_until_change - 1)
+
}
+
|> dict.insert(state, name, _)
+
+
let lead_km = case int.compare(km, lead_km.km) {
+
Eq -> LeadKm(km, lead_km.leads |> set.insert(name))
+
Gt -> LeadKm(km, set.new() |> set.insert(name))
+
Lt -> lead_km
+
}
+
+
RunStatePoints(lead_km, state)
+
})
+
+
let state =
+
leads
+
|> set.fold(state, fn(state, reindeer_name) {
+
let assert Ok(ReindeerStatePoints(
+
points,
+
km,
+
action,
+
time_until_change,
+
)) =
+
state
+
|> dict.get(reindeer_name)
+
state
+
|> dict.insert(
+
reindeer_name,
+
ReindeerStatePoints(points + 1, km, action, time_until_change),
+
)
+
})
+
+
RunStatePoints(LeadKm(0, set.new()), state)
+
|> do_calculate_run_state_pt2(reindeers, sec - 1)
+
}
+
}
+
}
+
+
pub fn calculate_run_state_pt2(reindeers: List(Reindeer), sec: Int) {
+
do_calculate_run_state_pt2(
+
RunStatePoints(LeadKm(0, set.new()), dict.new()),
+
reindeers,
+
sec,
+
)
+
}
+
+
pub fn get_winner_points(state: RunStatePoints) {
+
state.state
+
|> dict.fold(0, fn(winner, _, state) {
+
case state.points > winner {
+
True -> state.points
+
False -> winner
+
}
+
})
+
}
+
+
pub fn main() {
+
let assert Ok(reindeer) = file.read(from: "../input.txt")
+
as "Input file not found"
+
let reindeer =
+
reindeer
+
|> string.trim
+
|> string.split("\n")
+
|> list.map(fn(v) {
+
case v |> string.split(" ") {
+
// (name) can fly (speed) km/s for (run) seconds, but then must rest for (rest) seconds.
+
[name, _, _, speed, _, _, run, _, _, _, _, _, _, rest, _] ->
+
Reindeer(name, speed |> to_int, run |> to_int, rest |> to_int)
+
_ -> panic as { v <> " is not a valid line" }
+
}
+
})
+
+
"Part 1" |> io.println
+
reindeer
+
|> calculate_run_state(2503)
+
|> get_winner_km
+
|> int.to_string
+
|> io.println
+
+
"Part 2" |> io.println
+
reindeer
+
|> calculate_run_state_pt2(2503)
+
|> get_winner_points
+
|> int.to_string
+
|> io.println
+
}