-
Notifications
You must be signed in to change notification settings - Fork 0
/
day12-postgresql.jl
93 lines (77 loc) · 2.37 KB
/
day12-postgresql.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
using FunSQL
using LibPQ
using DBInterface
# Make LibPQ compatible with DBInterface.
DBInterface.connect(::Type{LibPQ.Connection}, args...; kws...) =
LibPQ.Connection(args...; kws...)
DBInterface.prepare(conn::LibPQ.Connection, args...; kws...) =
LibPQ.prepare(conn, args...; kws...)
DBInterface.execute(conn::Union{LibPQ.Connection, LibPQ.Statement}, args...; kws...) =
LibPQ.execute(conn, args...; kws...)
const funsql_ascii = FunSQL.Fun.ascii
const funsql_least = FunSQL.Fun.least
const funsql_string_to_table = FunSQL.Fun.string_to_table
const funsql_with_ordinality = FunSQL.Fun."? WITH ORDINALITY"
@funsql begin
parse_heights() =
begin
from(
with_ordinality(string_to_table(:input, "\n")),
columns = [line, row])
cross_join(
from(
with_ordinality(string_to_table(line, missing)),
columns = [char, col]))
define(
height =>
ascii(char == "S" ? "a" : char == "E" ? "z" : char) - ascii("a"),
start => char == "S",
finish => char == "E")
end
dist_lag() =
case(height <= lag(height) + 1, lag(dist) + 1)
dist_lead() =
case(height <= lead(height) + 1, lead(dist) + 1)
step() =
begin
partition()
filter(is_null(min(dist, filter = finish)))
partition(row, order_by = [col])
define(
left => dist_lag(),
right => dist_lead())
partition(col, order_by = [row])
define(
up => dist_lag(),
down => dist_lead())
define(dist => least(dist, left, right, up, down))
end
solve(name, init) =
begin
from(heights)
define(dist => case($init, 0))
iterate(step())
group()
define($name => max(dist))
end
solve_part1() =
solve(part1, start)
solve_part2() =
solve(part2, height == 0)
solve_all() =
begin
solve_part1().cross_join(solve_part2())
with(heights => parse_heights())
end
const q = solve_all()
end # @funsql
if isempty(ARGS)
println(FunSQL.render(q, dialect = :postgresql))
else
const db = DBInterface.connect(FunSQL.DB{LibPQ.Connection}, "")
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