-
Notifications
You must be signed in to change notification settings - Fork 0
/
01-felix.roc
138 lines (121 loc) · 4.65 KB
/
01-felix.roc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
app "01-felix"
packages {
pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br",
}
imports [pf.Stdout, pf.Task, pf.File, pf.Path]
provides [main] to pf
main =
path = "01-felix.txt"
task =
text <- File.readUtf8 (Path.fromStr path) |> Task.await
output1 =
when part1 text is
Ok answer -> "Answer: \(Num.toStr answer)"
Err NoNumber -> "Error: Not all lines contain a number!"
output2v1 =
when part2V1 text is
Ok answer -> "Answer: \(Num.toStr answer)"
Err NoNumber -> "Error: Not all lines contain a number!"
output2v2 =
when part2V2 text is
Ok answer -> "Answer: \(Num.toStr answer)"
Err NoNumber -> "Error: Not all lines contain a number!"
Stdout.line
"""
Part 1) \(output1)
Part 2v1) \(output2v1)
Part 2v2) \(output2v2)
"""
Task.onErr task \_ -> Stdout.line "error: failed to read file \(path)"
part1 : Str -> Result Nat [NoNumber]
part1 = \text ->
text
|> Str.trim
|> Str.split "\n"
|> List.mapTry \line ->
numbers =
line
|> Str.graphemes
|> List.keepOks Str.toNat
when (List.first numbers, List.last numbers) is
(Ok first, Ok last) -> Ok (10 * first + last)
_ -> Err NoNumber
|> Result.map List.sum
part2V1 : Str -> Result Nat [NoNumber]
part2V1 = \text ->
words = [
("one", "o1e"),
("two", "t2o"),
("three", "t3e"),
("four", "f4r"),
("five", "f5e"),
("six", "s6x"),
("seven", "s7n"),
("eight", "e8t"),
("nine", "n9e"),
]
words
|> List.walk text \acc, (a, b) -> acc |> Str.replaceEach a b
|> part1
part2V2 : Str -> Result Nat [NoNumber]
part2V2 = \text ->
words = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
text
|> Str.trim
|> Str.split "\n"
|> List.mapTry \line ->
numbers =
line
|> Str.graphemes
|> List.walk
{ current: "", values: [] }
\{ current, values }, char ->
next = current |> Str.concat char
maybeDigit = char |> Str.toNat
nCandidates = Str.countGraphemes next
candidates =
List.range { start: At 0, end: Length nCandidates }
|> List.map \start ->
next
|> Str.graphemes
|> List.sublist { start, len: nCandidates - start }
|> Str.joinWith ""
maybeHit =
candidates
|> List.keepOks \candidate ->
words |> List.findFirstIndex \word -> word == candidate
|> List.first
maybeCandidate =
candidates
|> List.findFirst \candidate ->
words |> List.any \word -> Str.startsWith word candidate
when maybeDigit is
Ok number ->
{
current: "",
values: values |> List.append number,
}
Err InvalidNumStr ->
when maybeHit is
Ok number ->
{
current: next,
values: values |> List.append (number + 1),
}
Err ListWasEmpty ->
when maybeCandidate is
Ok candidate ->
{
current: candidate,
values: values,
}
Err _ ->
{
current: "",
values: values,
}
|> .values
when (List.first numbers, List.last numbers) is
(Ok first, Ok last) -> Ok (10 * first + last)
_ -> Err NoNumber
|> Result.map List.sum