-
Notifications
You must be signed in to change notification settings - Fork 0
/
day07-sqlite.jl
102 lines (87 loc) · 2.33 KB
/
day07-sqlite.jl
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
using FunSQL
using SQLite
const funsql_as_integer = FunSQL.Fun."CAST(? AS INTEGER)"
const funsql_instr = FunSQL.Fun.instr
const funsql_length = FunSQL.Fun.length
const funsql_rtrim = FunSQL.Fun.rtrim
const funsql_substr = FunSQL.Fun.substr
@funsql begin
split_first(text, sep) =
instr($text, $sep) > 0 ? substr($text, 1, instr($text, $sep) - 1) : $text
split_rest(text, sep) =
instr($text, $sep) > 0 ? substr($text, instr($text, $sep) + $(length(sep))) : ""
current_dir(line) =
if $line == "\$ cd /"
"/"
elseif $line == "\$ cd .."
rtrim(rtrim(dir, "/"), $(join('a':'z')))
elseif substr($line, 1, 4) == "\$ cd"
concat(dir, substr($line, 6), "/")
else
dir
end
split_lines_one_step() =
begin
filter(rest != "")
define(
dir => current_dir(split_first(rest, "\n")),
size => as_integer(split_first(rest, "\n")),
rest => split_rest(rest, "\n"))
end
split_lines(text) =
begin
define(
rest => $text,
dir => missing)
split_lines_one_step()
iterate(split_lines_one_step())
end
parse_dirs() =
begin
split_lines(:input)
group(dir)
define(size => sum(size))
end
calculate_totals() =
begin
from(dirs)
join(
nested => from(dirs),
on = substr(nested.dir, 1, length(dir)) == dir)
group(dir)
define(total => sum(nested.size))
end
solve_part1() =
begin
from(totals)
filter(total <= 100000)
group()
define(part1 => sum(total))
end
solve_part2() =
begin
from(totals)
partition()
define(limit => max(total) - $(70000000 - 30000000))
filter(total >= limit)
group()
define(part2 => min(total))
end
solve_all() =
begin
solve_part1().cross_join(solve_part2())
with(totals => calculate_totals())
with(dirs => parse_dirs())
end
const q = solve_all()
end # @funsql
if isempty(ARGS)
println(FunSQL.render(q, dialect = :sqlite))
else
const db = DBInterface.connect(FunSQL.DB{SQLite.DB})
for file in ARGS
input = read(file, String)
output = first(DBInterface.execute(db, q, input = input))
println("[$file] part1: $(output.part1), part2: $(output.part2)")
end
end