+35
-101
2015/11/gleam/src/main.gleam
+35
-101
2015/11/gleam/src/main.gleam
···
1
-
import gleam/dict
2
1
import gleam/io.{println}
3
2
import gleam/list
4
3
import gleam/result
5
4
import gleam/string.{trim}
6
5
import simplifile.{read}
7
6
8
-
const letter_value_list = [
9
-
#("a", 0),
10
-
#("b", 1),
11
-
#("c", 2),
12
-
#("d", 3),
13
-
#("e", 4),
14
-
#("f", 5),
15
-
#("g", 6),
16
-
#("h", 7),
17
-
#("i", 8),
18
-
#("j", 9),
19
-
#("k", 10),
20
-
#("l", 11),
21
-
#("m", 12),
22
-
#("n", 13),
23
-
#("o", 14),
24
-
#("p", 15),
25
-
#("q", 16),
26
-
#("r", 17),
27
-
#("s", 18),
28
-
#("t", 19),
29
-
#("u", 20),
30
-
#("v", 21),
31
-
#("w", 22),
32
-
#("x", 23),
33
-
#("y", 24),
34
-
#("z", 25),
35
-
]
36
-
37
-
const value_letter_list = [
38
-
#(0, "a"),
39
-
#(1, "b"),
40
-
#(2, "c"),
41
-
#(3, "d"),
42
-
#(4, "e"),
43
-
#(5, "f"),
44
-
#(6, "g"),
45
-
#(7, "h"),
46
-
#(8, "i"),
47
-
#(9, "j"),
48
-
#(10, "k"),
49
-
#(11, "l"),
50
-
#(12, "m"),
51
-
#(13, "n"),
52
-
#(14, "o"),
53
-
#(15, "p"),
54
-
#(16, "q"),
55
-
#(17, "r"),
56
-
#(18, "s"),
57
-
#(19, "t"),
58
-
#(20, "u"),
59
-
#(21, "v"),
60
-
#(22, "w"),
61
-
#(23, "x"),
62
-
#(24, "y"),
63
-
#(25, "z"),
64
-
]
65
-
66
-
type LVDicts {
67
-
LVDicts(value: dict.Dict(String, Int), letter: dict.Dict(Int, String))
68
-
}
69
-
70
7
fn has_three_letter_sequence(
71
-
letter_value_map lvm,
72
8
input input,
73
9
iterator i,
74
10
prev_letter_value prev_letter_value,
75
11
line_length line_length,
76
12
) {
77
13
let letter = string.slice(input, i, 1)
78
-
let letter_value_wrap = dict.get(lvm, letter)
79
-
case letter_value_wrap {
80
-
Error(_) -> False
81
-
Ok(v) -> {
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)
82
19
let in_sequence = prev_letter_value == v - 1
83
20
case in_sequence && line_length == 1 {
84
21
False -> {
···
86
23
True -> line_length + 1
87
24
False -> 0
88
25
}
89
-
has_three_letter_sequence(lvm, input, i + 1, v, line_length)
26
+
has_three_letter_sequence(input, i + 1, v, line_length)
90
27
}
91
28
True -> True
92
29
}
···
114
51
}
115
52
}
116
53
117
-
fn valid_password(letter_value_dict, input) {
118
-
letter_value_dict |> has_three_letter_sequence(input, 1, 50, 0)
54
+
fn valid_password(input) {
55
+
has_three_letter_sequence(input, 1, 50, 0)
119
56
&& ["i", "o", "l"]
120
57
|> list.fold_until(True, fn(_, letter) {
121
58
case !string.contains(input, letter) {
···
126
63
&& has_two_pairs(input, 0, "", 0)
127
64
}
128
65
129
-
fn increment_password(lvdicts: LVDicts, input) {
130
-
input
131
-
|> string.split("")
132
-
|> list.fold_right(#("", 0), fn(acc, letter) {
133
-
let #(acc_str, pass) = acc
134
-
let add = case acc_str == "" {
135
-
True -> 1
136
-
False -> pass
137
-
}
138
-
let value = { lvdicts.value |> dict.get(letter) |> result.unwrap(50) } + add
139
-
case value == 26 {
140
-
True -> #(string.append("a", acc_str), 1)
141
-
False -> #(
142
-
string.append(
143
-
lvdicts.letter |> dict.get(value) |> result.unwrap("a"),
144
-
acc_str,
145
-
),
146
-
0,
147
-
)
148
-
}
149
-
})
66
+
fn 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
150
88
}
151
89
152
-
fn get_valid_password(lvdicts: LVDicts, input) {
153
-
case valid_password(lvdicts.value, input) {
154
-
False -> get_valid_password(lvdicts, increment_password(lvdicts, input).0)
90
+
fn get_valid_password(input) {
91
+
case valid_password(input) {
92
+
False -> get_valid_password(increment_password(input))
155
93
True -> input
156
94
}
157
95
}
···
159
97
pub fn main() {
160
98
let input = read(from: "../input.txt") |> result.unwrap("") |> trim()
161
99
162
-
let letter_value_dict = dict.from_list(letter_value_list)
163
-
let value_letter_dict = dict.from_list(value_letter_list)
164
-
let lvdicts = LVDicts(letter_value_dict, value_letter_dict)
165
-
166
-
let part1 = get_valid_password(lvdicts, input)
100
+
let part1 = get_valid_password(input)
167
101
println(part1)
168
-
let part2 = get_valid_password(lvdicts, increment_password(lvdicts, part1).0)
102
+
let part2 = get_valid_password(increment_password(part1))
169
103
println(part2)
170
104
}