my solutions to advent of code
aoc
advent-of-code
1import gleam/io.{println}
2import gleam/list
3import gleam/result
4import gleam/string.{trim}
5import simplifile.{read}
6
7fn has_three_letter_sequence(
8 input input,
9 iterator i,
10 prev_letter_value prev_letter_value,
11 line_length line_length,
12) {
13 let letter = string.slice(input, i, 1)
14 case letter != "" {
15 False -> False
16 True -> {
17 let assert [codepoint] = string.to_utf_codepoints(letter)
18 let v = string.utf_codepoint_to_int(codepoint)
19 let in_sequence = prev_letter_value == v - 1
20 case in_sequence && line_length == 1 {
21 False -> {
22 let line_length = case in_sequence {
23 True -> line_length + 1
24 False -> 0
25 }
26 has_three_letter_sequence(input, i + 1, v, line_length)
27 }
28 True -> True
29 }
30 }
31 }
32}
33
34fn has_two_pairs(input input, iterator i, prev_letter prev_letter, pairs pairs) {
35 let letter = string.slice(input, i, 1)
36 case letter != "" {
37 False -> False
38 True -> {
39 let pair = prev_letter == letter
40 case pair {
41 False -> has_two_pairs(input, i + 1, letter, pairs)
42 True -> {
43 let pairs = pairs + 1
44 case pairs {
45 2 -> True
46 _ -> has_two_pairs(input, i + 1, "", pairs)
47 }
48 }
49 }
50 }
51 }
52}
53
54fn valid_password(input) {
55 has_three_letter_sequence(input, 1, 50, 0)
56 && ["i", "o", "l"]
57 |> list.fold_until(True, fn(_, letter) {
58 case !string.contains(input, letter) {
59 False -> list.Stop(False)
60 True -> list.Continue(True)
61 }
62 })
63 && has_two_pairs(input, 0, "", 0)
64}
65
66fn increment_password(input) {
67 {
68 input
69 |> string.to_utf_codepoints
70 |> list.fold_right(#([], 0), fn(acc, letter) {
71 let #(acc_str, pass) = acc
72 let add = case acc_str == [] {
73 True -> 1
74 False -> pass
75 }
76 let new_letter = string.utf_codepoint_to_int(letter) + add
77 let assert Ok(letter_codepoint) = string.utf_codepoint(new_letter)
78 case new_letter > 122 {
79 True -> {
80 let assert Ok(a) = string.utf_codepoint(97)
81 #(list.prepend(acc_str, a), 1)
82 }
83 False -> #(list.prepend(acc_str, letter_codepoint), 0)
84 }
85 })
86 }.0
87 |> string.from_utf_codepoints
88}
89
90fn get_valid_password(input) {
91 case valid_password(input) {
92 False -> get_valid_password(increment_password(input))
93 True -> input
94 }
95}
96
97pub fn main() {
98 let input = read(from: "../input.txt") |> result.unwrap("") |> trim()
99
100 let part1 = get_valid_password(input)
101 println(part1)
102 let part2 = get_valid_password(increment_password(part1))
103 println(part2)
104}