aboutsummaryrefslogtreecommitdiff
path: root/aoc2023-gleam/src/day19/solve.gleam
diff options
context:
space:
mode:
Diffstat (limited to 'aoc2023-gleam/src/day19/solve.gleam')
-rw-r--r--aoc2023-gleam/src/day19/solve.gleam255
1 files changed, 0 insertions, 255 deletions
diff --git a/aoc2023-gleam/src/day19/solve.gleam b/aoc2023-gleam/src/day19/solve.gleam
deleted file mode 100644
index 186e783..0000000
--- a/aoc2023-gleam/src/day19/solve.gleam
+++ /dev/null
@@ -1,255 +0,0 @@
-import adglent.{First, Second}
-import gleam/io
-import gleam/string
-import gleam/dict.{type Dict}
-import gleam/order.{type Order, Gt, Lt}
-import gleam/regex.{type Match, Match}
-import gleam/list
-import gleam/option.{Some}
-import gleam/int
-
-type Rating {
- XtremelyCool
- Musical
- Aerodynamic
- Shiny
-}
-
-type Part {
- Part(x: Int, m: Int, a: Int, s: Int)
-}
-
-type Action {
- Accept
- Reject
- SendTo(String)
-}
-
-type Rule {
- If(rating: Rating, comparison: Order, threshold: Int, do: Action)
- Just(do: Action)
-}
-
-type Workflow =
- Dict(String, List(Rule))
-
-type Interval {
- Interval(min: Int, max: Int)
-}
-
-type PartRange {
- PartRange(x: Interval, m: Interval, a: Interval, s: Interval)
-}
-
-fn parse_workflow(input: String) -> Workflow {
- let assert Ok(re) = regex.from_string("(.*){(.*)}")
-
- use acc, line <- list.fold(string.split(input, "\n"), dict.new())
- let assert [Match(submatches: [Some(name), Some(all_rules)], ..)] =
- regex.scan(re, line)
- let rules =
- string.split(all_rules, ",")
- |> parse_rules
- dict.insert(acc, name, rules)
-}
-
-fn parse_rules(rules: List(String)) -> List(Rule) {
- let assert Ok(re_rule) = regex.from_string("(.*)(>|<)(.*):(.*)")
- use rule <- list.map(rules)
- case regex.scan(re_rule, rule) {
- [Match(submatches: [Some(r), Some(c), Some(t), Some(i)], ..)] ->
- If(to_rating(r), to_comp(c), to_val(t), to_instruction(i))
- _nomatch -> Just(to_instruction(rule))
- }
-}
-
-fn to_instruction(rule: String) {
- case rule {
- "A" -> Accept
- "R" -> Reject
- name -> SendTo(name)
- }
-}
-
-fn to_rating(rating: String) {
- case rating {
- "x" -> XtremelyCool
- "m" -> Musical
- "a" -> Aerodynamic
- _s -> Shiny
- }
-}
-
-fn get_rating(part: Part, rating: Rating) -> Int {
- case rating {
- XtremelyCool -> part.x
- Musical -> part.m
- Aerodynamic -> part.a
- Shiny -> part.s
- }
-}
-
-fn to_comp(comp: String) {
- case comp {
- "<" -> Lt
- _gt -> Gt
- }
-}
-
-fn to_val(val: String) {
- let assert Ok(n) = int.parse(val)
- n
-}
-
-fn parse_parts(input: String) -> List(Part) {
- let assert Ok(re) = regex.from_string("{x=(.*),m=(.*),a=(.*),s=(.*)}")
-
- use part <- list.map(string.split(input, "\n"))
- let assert [Match(submatches: [Some(x), Some(m), Some(a), Some(s)], ..)] =
- regex.scan(re, part)
- Part(to_val(x), to_val(m), to_val(a), to_val(s))
-}
-
-fn start_evaluating_workflow(part: Part, workflow: Workflow) -> Int {
- evaluate_workflow(part, "in", workflow)
-}
-
-fn evaluate_workflow(part: Part, name: String, workflow: Workflow) -> Int {
- let assert Ok(rules) = dict.get(workflow, name)
- case evaluate_rules(part, rules) {
- Accept -> part.x + part.m + part.a + part.s
- Reject -> 0
- SendTo(name) -> evaluate_workflow(part, name, workflow)
- }
-}
-
-fn evaluate_rules(part: Part, rules: List(Rule)) -> Action {
- case rules {
- [] -> panic
- [Just(do), ..] -> do
- [If(rating, comparison, threshold, do), ..rest] ->
- case int.compare(get_rating(part, rating), threshold) == comparison {
- True -> do
- False -> evaluate_rules(part, rest)
- }
- }
-}
-
-pub fn part1(input: String) {
- let assert Ok(#(workflows_str, parts_str)) = string.split_once(input, "\n\n")
-
- let workflows = parse_workflow(workflows_str)
- let parts = parse_parts(parts_str)
-
- list.map(parts, start_evaluating_workflow(_, workflows))
- |> int.sum
- |> string.inspect
-}
-
-fn size(interval: Interval) {
- interval.max - interval.min + 1
-}
-
-fn all_in_range(pr: PartRange) {
- size(pr.x) * size(pr.m) * size(pr.a) * size(pr.s)
-}
-
-fn get_partrange(pr: PartRange, rating: Rating) -> Interval {
- case rating {
- XtremelyCool -> pr.x
- Musical -> pr.m
- Aerodynamic -> pr.a
- Shiny -> pr.s
- }
-}
-
-fn update_partrange(pr: PartRange, rating: Rating, i: Interval) -> PartRange {
- case rating {
- XtremelyCool -> PartRange(..pr, x: i)
- Musical -> PartRange(..pr, m: i)
- Aerodynamic -> PartRange(..pr, a: i)
- Shiny -> PartRange(..pr, s: i)
- }
-}
-
-pub fn part2(input: String) {
- let assert Ok(#(workflows_str, _)) = string.split_once(input, "\n\n")
-
- let workflow = parse_workflow(workflows_str)
- let start = Interval(1, 4000)
-
- PartRange(start, start, start, start)
- |> evaluate_workflow_on_range("in", workflow)
- |> string.inspect
-}
-
-fn evaluate_workflow_on_range(
- pr: PartRange,
- name: String,
- workflow: Workflow,
-) -> Int {
- let assert Ok(rules) = dict.get(workflow, name)
- evaluate_rules_on_range(pr, rules, workflow)
-}
-
-fn evaluate_rules_on_range(
- pr: PartRange,
- rules: List(Rule),
- workflow: Workflow,
-) -> Int {
- case rules {
- [Just(Accept), ..] -> all_in_range(pr)
- [Just(Reject), ..] -> 0
- [Just(SendTo(name)), ..] -> evaluate_workflow_on_range(pr, name, workflow)
- [If(rating, comparison, t, action), ..rest] -> {
- let mod_i = get_partrange(pr, rating)
- case comparison {
- Lt ->
- split_range(
- keep: update_partrange(pr, rating, Interval(mod_i.min, t - 1)),
- and_do: action,
- pass: update_partrange(pr, rating, Interval(t, mod_i.max)),
- and_eval: rest,
- with: workflow,
- )
- _gt ->
- split_range(
- keep: update_partrange(pr, rating, Interval(t + 1, mod_i.max)),
- and_do: action,
- pass: update_partrange(pr, rating, Interval(mod_i.min, t)),
- and_eval: rest,
- with: workflow,
- )
- }
- }
- [] -> panic
- }
-}
-
-fn split_range(
- keep keep: PartRange,
- and_do action: Action,
- pass pass: PartRange,
- and_eval rest: List(Rule),
- with workflow: Workflow,
-) -> Int {
- int.add(
- evaluate_rules_on_range(keep, [Just(action)], workflow),
- evaluate_rules_on_range(pass, rest, workflow),
- )
-}
-
-pub fn main() {
- let assert Ok(part) = adglent.get_part()
- let assert Ok(input) = adglent.get_input("19")
- case part {
- First ->
- part1(input)
- |> adglent.inspect
- |> io.println
- Second ->
- part2(input)
- |> adglent.inspect
- |> io.println
- }
-}