aboutsummaryrefslogtreecommitdiff
path: root/aoc2017-gleam/src
diff options
context:
space:
mode:
Diffstat (limited to 'aoc2017-gleam/src')
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_4.gleam31
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_5.gleam48
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_6.gleam65
-rw-r--r--aoc2017-gleam/src/aoc_2017/day_7.gleam42
4 files changed, 186 insertions, 0 deletions
diff --git a/aoc2017-gleam/src/aoc_2017/day_4.gleam b/aoc2017-gleam/src/aoc_2017/day_4.gleam
new file mode 100644
index 0000000..9bc4f9a
--- /dev/null
+++ b/aoc2017-gleam/src/aoc_2017/day_4.gleam
@@ -0,0 +1,31 @@
+import gleam/list
+import gleam/string
+
+pub fn parse(input: String) -> List(List(String)) {
+ use row <- list.map(string.split(input, "\n"))
+ string.split(row, " ")
+}
+
+pub fn pt_1(input: List(List(String))) {
+ use acc, passwords <- list.fold(input, 0)
+ case passwords == list.unique(passwords) {
+ True -> acc + 1
+ False -> acc
+ }
+}
+
+pub fn pt_2(input: List(List(String))) {
+ use acc, passwords <- list.fold(input, 0)
+ let sorted_passwords = list.map(passwords, sort_graphemes)
+ case sorted_passwords == list.unique(sorted_passwords) {
+ True -> acc + 1
+ False -> acc
+ }
+}
+
+fn sort_graphemes(word: String) -> String {
+ word
+ |> string.to_graphemes
+ |> list.sort(string.compare)
+ |> string.concat
+}
diff --git a/aoc2017-gleam/src/aoc_2017/day_5.gleam b/aoc2017-gleam/src/aoc_2017/day_5.gleam
new file mode 100644
index 0000000..a0b9b80
--- /dev/null
+++ b/aoc2017-gleam/src/aoc_2017/day_5.gleam
@@ -0,0 +1,48 @@
+import gary.{type ErlangArray}
+import gary/array
+import gleam/int
+import gleam/list
+import gleam/result
+import gleam/string
+
+pub fn parse(input: String) -> ErlangArray(Int) {
+ input
+ |> string.split("\n")
+ |> list.map(int.parse)
+ |> result.values()
+ |> array.from_list(default: 0)
+ |> array.make_fixed()
+}
+
+pub fn pt_1(input: ErlangArray(Int)) {
+ next_step(input, 0, 0, part: 1)
+}
+
+pub fn pt_2(input: ErlangArray(Int)) {
+ next_step(input, 0, 0, part: 2)
+}
+
+fn next_step(
+ instructions: ErlangArray(Int),
+ pointer: Int,
+ step: Int,
+ part part: Int,
+) {
+ case array.get(from: instructions, at: pointer) {
+ Ok(distance) -> {
+ let delta = delta(distance, part)
+ let assert Ok(updated_instructions) =
+ array.set(instructions, at: pointer, put: distance + delta)
+ next_step(updated_instructions, pointer + distance, step + 1, part)
+ }
+ Error(_) -> step
+ }
+}
+
+fn delta(d: Int, part: Int) {
+ case part, d {
+ 1, _ -> 1
+ _, n if n < 3 -> 1
+ _, _ -> -1
+ }
+}
diff --git a/aoc2017-gleam/src/aoc_2017/day_6.gleam b/aoc2017-gleam/src/aoc_2017/day_6.gleam
new file mode 100644
index 0000000..84222e1
--- /dev/null
+++ b/aoc2017-gleam/src/aoc_2017/day_6.gleam
@@ -0,0 +1,65 @@
+import gary.{type ErlangArray}
+import gary/array
+import gleam/bool
+import gleam/int
+import gleam/list
+import gleam/result
+import gleam/set.{type Set}
+import gleam/string
+
+pub fn parse(input) -> ErlangArray(Int) {
+ input
+ |> string.split("\t")
+ |> list.map(int.parse)
+ |> result.values()
+ |> array.from_list(default: -1)
+ |> array.make_fixed()
+}
+
+pub fn pt_1(input: ErlangArray(Int)) {
+ check_cycle(input, set.from_list([input]), 1).1
+}
+
+pub fn pt_2(input: ErlangArray(Int)) {
+ let #(target, cycle) = check_cycle(input, set.from_list([input]), 1)
+ cycle - check_cycle(input, set.from_list([input, target]), 1).1
+}
+
+fn get_max(array: ErlangArray(Int)) -> #(Int, Int) {
+ use index, value, max <- array.fold(over: array, from: #(-1, -1))
+ case value > max.1 {
+ True -> #(index, value)
+ False -> max
+ }
+}
+
+fn redistribute(
+ array: ErlangArray(Int),
+ pointer: Int,
+ remaining: Int,
+) -> ErlangArray(Int) {
+ use <- bool.guard(remaining == 0, array)
+ case array.get(from: array, at: pointer) {
+ Error(_) -> redistribute(array, 0, remaining)
+ Ok(n) -> {
+ let assert Ok(updated_array) =
+ array.set(into: array, at: pointer, put: n + 1)
+ redistribute(updated_array, pointer + 1, remaining - 1)
+ }
+ }
+}
+
+fn check_cycle(
+ current: ErlangArray(Int),
+ cache: Set(ErlangArray(Int)),
+ cycle: Int,
+) -> #(ErlangArray(Int), Int) {
+ let #(index, to_redistribute) = current |> get_max
+ let assert Ok(zeroed) = array.set(into: current, at: index, put: 0)
+ let next = redistribute(zeroed, index + 1, to_redistribute)
+
+ case set.contains(cache, next) {
+ True -> #(next, cycle)
+ False -> check_cycle(next, set.insert(cache, next), cycle + 1)
+ }
+}
diff --git a/aoc2017-gleam/src/aoc_2017/day_7.gleam b/aoc2017-gleam/src/aoc_2017/day_7.gleam
new file mode 100644
index 0000000..593282b
--- /dev/null
+++ b/aoc2017-gleam/src/aoc_2017/day_7.gleam
@@ -0,0 +1,42 @@
+import gleam/int
+import gleam/io
+import gleam/list
+import gleam/option.{None, Some}
+import gleam/regex.{type Match, Match}
+import gleam/set
+import gleam/string
+
+pub type Program {
+ Program(name: String, weight: Int, supporting: List(String))
+}
+
+pub fn parse(input: String) {
+ let assert Ok(re) = regex.from_string("([a-z]+) \\(([0-9]+)\\)(?> -> (.*))?")
+
+ use match <- list.map(string.split(input, "\n"))
+ case regex.scan(re, match) {
+ [Match(submatches: [Some(name), Some(weight)], ..)] ->
+ Program(name, to_int(weight), [])
+ [Match(submatches: [Some(name), Some(weight), Some(supporting)], ..)] ->
+ Program(name, to_int(weight), string.split(supporting, ", "))
+ _ -> panic as { "couldn't parse" <> match }
+ }
+}
+
+fn to_int(str: String) -> Int {
+ let assert Ok(n) = int.parse(str)
+ n
+}
+
+pub fn pt_1(input: List(Program)) {
+ let supporters = input |> list.map(fn(p) { p.name }) |> set.from_list()
+ let supporting =
+ input |> list.flat_map(fn(p) { p.supporting }) |> set.from_list()
+
+ let assert [base] = set.difference(supporters, supporting) |> set.to_list
+ base
+}
+
+pub fn pt_2(input: List(Program)) {
+ todo as "part 2 not implemented"
+}