diff options
author | H.J <thechairman@thechairman.info> | 2024-06-05 14:08:47 -0400 |
---|---|---|
committer | H.J <thechairman@thechairman.info> | 2024-06-05 14:08:47 -0400 |
commit | 10e7706062c64cc0da55587bfb1a85c988ae950c (patch) | |
tree | f93f1e3357e0c0aa045e1d9075ba05ce1d2b1a4e | |
parent | de82be4d2c2b8ec3a611de18634c6380f4b6cfcb (diff) | |
download | gleam_aoc-10e7706062c64cc0da55587bfb1a85c988ae950c.tar.gz gleam_aoc-10e7706062c64cc0da55587bfb1a85c988ae950c.zip |
gleam 2017 day 8
-rw-r--r-- | aoc2017-gleam/src/aoc_2017/day_8.gleam | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/aoc2017-gleam/src/aoc_2017/day_8.gleam b/aoc2017-gleam/src/aoc_2017/day_8.gleam new file mode 100644 index 0000000..2f9d0dc --- /dev/null +++ b/aoc2017-gleam/src/aoc_2017/day_8.gleam @@ -0,0 +1,131 @@ +import gleam/dict +import gleam/int +import gleam/list +import gleam/option.{None, Some} +import gleam/string + +const max_register = "__MAX" + +pub type Instruction { + Instruction(register: String, op: Operation, condition: Condition) +} + +pub type Operation { + Inc(by: Int) + Dec(by: Int) +} + +pub type Condition { + Equal(register: String, value: Int) + NotEqual(register: String, value: Int) + LessThan(register: String, value: Int) + GreaterThan(register: String, value: Int) + LessThanOrEq(register: String, value: Int) + GreaterThanOrEq(register: String, value: Int) +} + +type Registers = + dict.Dict(String, Int) + +pub fn parse(input: String) { + input + |> string.split("\n") + |> list.map(parse_instruction) +} + +fn parse_instruction(str: String) -> Instruction { + case string.split(str, " ") { + [name, op, by, "if", cond_name, cond_type, cond_by] -> + Instruction(name, to_op(op, by), to_cond(cond_name, cond_type, cond_by)) + _ -> panic as { "couldn't parse: " <> str } + } +} + +pub fn pt_1(input: List(Instruction)) { + let registers = dict.new() |> dict.insert(max_register, 0) + + input + |> list.fold(registers, next_instruction) + |> dict.delete(max_register) + |> dict.values() + |> list.reduce(int.max) +} + +fn next_instruction(regs: Registers, inst: Instruction) { + case to_compare_fn(inst.condition)(fetch(inst.condition.register, regs)) { + True -> { + let updated_regs = dict.update(regs, inst.register, to_update_fn(inst.op)) + let assert Ok(max) = updated_regs |> dict.values |> list.reduce(int.max) + dict.insert(updated_regs, max_register, max) + } + False -> regs + } +} + +pub fn pt_2(input: List(Instruction)) { + let registers = dict.new() |> dict.insert(max_register, 0) + + input + |> list.fold(registers, next_instruction) + |> dict.get(max_register) +} + +fn int(str: String) -> Int { + let assert Ok(n) = int.parse(str) + n +} + +fn to_op(raw_op: String, raw_by: String) -> Operation { + case raw_op { + "inc" -> Inc(int(raw_by)) + "dec" -> Dec(int(raw_by)) + _ -> panic as { "bad op: " <> raw_op } + } +} + +fn to_cond(name: String, raw_type: String, raw_by: String) -> Condition { + case raw_type { + "==" -> Equal(name, int(raw_by)) + "!=" -> NotEqual(name, int(raw_by)) + ">" -> GreaterThan(name, int(raw_by)) + "<" -> LessThan(name, int(raw_by)) + ">=" -> GreaterThanOrEq(name, int(raw_by)) + "<=" -> LessThanOrEq(name, int(raw_by)) + _ -> panic as { "bad condition: " <> raw_type } + } +} + +fn to_compare_fn(condition: Condition) -> fn(Int) -> Bool { + case condition { + Equal(value: v, ..) -> fn(a) { a == v } + NotEqual(value: v, ..) -> fn(a) { a != v } + GreaterThan(value: v, ..) -> fn(a) { a > v } + LessThan(value: v, ..) -> fn(a) { a < v } + GreaterThanOrEq(value: v, ..) -> fn(a) { a >= v } + LessThanOrEq(value: v, ..) -> fn(a) { a <= v } + } +} + +fn to_update_fn(op: Operation) { + case op { + Inc(n) -> fn(x) { + case x { + Some(i) -> i + n + None -> n + } + } + Dec(n) -> fn(x) { + case x { + Some(i) -> i - n + None -> -n + } + } + } +} + +fn fetch(name: String, registers: Registers) -> Int { + case dict.get(registers, name) { + Ok(n) -> n + Error(_) -> 0 + } +} |