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
|
import adglent.{First, Second}
import gleam/io
import gleam/int
import gleam/list
import gleam/option.{Some}
import gleam/regex.{type Match, Match}
import gleam/string
type Coord {
Coord(x: Int, y: Int)
}
type Direction {
Up
Right
Down
Left
}
type Dig {
Dig(dir: Direction, dist: Int)
}
fn to_direction(c: String) {
case c {
"R" | "0" -> Right
"D" | "1" -> Down
"L" | "2" -> Left
"U" | "3" -> Up
_ -> panic
}
}
fn parse_front(line: String) {
let assert Ok(re) = regex.from_string("(.) (.*) \\(.*\\)")
let assert [Match(submatches: [Some(dir), Some(dist)], ..)] =
regex.scan(with: re, content: line)
let assert Ok(n) = int.parse(dist)
Dig(to_direction(dir), n)
}
fn parse_hex(line: String) {
let assert Ok(re) = regex.from_string("\\(#(.....)(.)\\)")
let assert [Match(submatches: [Some(dist), Some(dir)], ..)] =
regex.scan(with: re, content: line)
let assert Ok(n) = int.base_parse(dist, 16)
Dig(to_direction(dir), n)
}
fn go(current: Coord, dig: Dig) {
case dig {
Dig(Up, n) -> Coord(current.x, current.y + n)
Dig(Right, n) -> Coord(current.x + n, current.y)
Dig(Down, n) -> Coord(current.x, current.y - n)
Dig(Left, n) -> Coord(current.x - n, current.y)
}
}
fn double_triangle(c1: Coord, c2: Coord) {
{ c1.x * c2.y } - { c2.x * c1.y }
}
fn start_dig(digs: List(Dig)) {
do_next_dig(digs, Coord(0, 0), 0, 0)
}
fn do_next_dig(
digs: List(Dig),
current: Coord,
area: Int,
perimeter: Int,
) -> Int {
case digs {
[] -> int.absolute_value(area) / 2 + { perimeter / 2 } + 1
[dig, ..rest] -> {
let next = go(current, dig)
let area = area + double_triangle(current, next)
let perimeter = perimeter + dig.dist
do_next_dig(rest, next, area, perimeter)
}
}
}
fn solve_with(input, f) {
input
|> string.split("\n")
|> list.map(f)
|> start_dig
|> string.inspect
}
pub fn part1(input: String) {
solve_with(input, parse_front)
}
pub fn part2(input: String) {
solve_with(input, parse_hex)
}
pub fn main() {
let assert Ok(part) = adglent.get_part()
let assert Ok(input) = adglent.get_input("18")
case part {
First ->
part1(input)
|> adglent.inspect
|> io.println
Second ->
part2(input)
|> adglent.inspect
|> io.println
}
}
|