aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J <thechairman@thechairman.info>2024-06-05 14:08:47 -0400
committerH.J <thechairman@thechairman.info>2024-06-05 14:08:47 -0400
commit10e7706062c64cc0da55587bfb1a85c988ae950c (patch)
treef93f1e3357e0c0aa045e1d9075ba05ce1d2b1a4e
parentde82be4d2c2b8ec3a611de18634c6380f4b6cfcb (diff)
downloadgleam_aoc-10e7706062c64cc0da55587bfb1a85c988ae950c.tar.gz
gleam_aoc-10e7706062c64cc0da55587bfb1a85c988ae950c.zip
gleam 2017 day 8
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_8.gleam131
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
+ }
+}