aoc_1217.slt 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. # Copyright Materialize, Inc. and contributors. All rights reserved.
  2. #
  3. # Use of this software is governed by the Business Source License
  4. # included in the LICENSE file at the root of this repository.
  5. #
  6. # As of the Change Date specified in that file, in accordance with
  7. # the Business Source License, use of this software will be governed
  8. # by the Apache License, Version 2.0.
  9. # https://github.com/MaterializeInc/advent-of-code-2023/blob/main/week1/aoc_1216.md
  10. mode cockroach
  11. statement ok
  12. CREATE TABLE input (input TEXT);
  13. statement ok
  14. INSERT INTO input VALUES (
  15. '62838899848717171482491386857
  16. 97364142198727715957423491912
  17. 86369399573486615223592185179
  18. 65896629415741215317915596532
  19. 87429913559342885454881133182
  20. 87599176619626884624793447611
  21. 69826949796636945138977813282
  22. 97787786569751297721492648197
  23. 56111693893781611276884581493
  24. 11326495731998819531787964758
  25. 45631262918273787936318151868');
  26. query II
  27. WITH MUTUALLY RECURSIVE
  28. lines(r INT, line TEXT) AS (
  29. SELECT r, regexp_split_to_array(input, '\n')[r] as block
  30. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n'), 1)) r
  31. ),
  32. cells(r INT, c INT, cost INT) AS (
  33. SELECT r, c, substring(line, c, 1)::INT
  34. FROM lines, generate_series(1, length(line)) c
  35. ),
  36. -- For each cell, we can be headed n, e, w, s and have gone 1, 2, 3 steps already.
  37. -- There is a mimimum cost path to reach this configuration, and .. we might need
  38. -- to remember how we got there but let's do that in part 2.
  39. min_cost(r INT, c INT, dr INT, dc INT, steps INT, cost INT) AS (
  40. SELECT r, c, dr, dc, steps, MIN(cost)
  41. FROM (
  42. SELECT 1 as r, 1 as c, 1 as dr, 0 as dc, 0 as steps, 0 as cost
  43. UNION ALL
  44. SELECT 1, 1, 0, 1, 0, 0
  45. -- We could have just stepped to r, c in a few ways, incurring its cost.
  46. UNION ALL
  47. SELECT cells.r, cells.c, dr, dc, steps + 1, min_cost.cost + cells.cost
  48. FROM min_cost, cells
  49. WHERE steps < 3
  50. AND cells.r = min_cost.r + dr
  51. AND cells.c = min_cost.c + dc
  52. -- We could take a ??? turn
  53. UNION ALL
  54. SELECT cells.r, cells.c, dc, dr, 1, min_cost.cost + cells.cost
  55. FROM min_cost, cells
  56. WHERE cells.r = min_cost.r + dc
  57. AND cells.c = min_cost.c + dr
  58. -- We could take a ??? turn
  59. UNION ALL
  60. SELECT cells.r, cells.c, -dc, -dr, 1, min_cost.cost + cells.cost
  61. FROM min_cost, cells
  62. WHERE cells.r = min_cost.r - dc
  63. AND cells.c = min_cost.c - dr
  64. )
  65. GROUP BY r, c, dr, dc, steps
  66. ),
  67. part1(part1 INT) AS (
  68. SELECT MIN(cost)
  69. FROM min_cost
  70. WHERE r = (SELECT MAX(r) FROM cells)
  71. AND c = (SELECT MAX(c) FROM cells)
  72. ),
  73. potato(x INT) AS (SELECT 1),
  74. -- For each cell, we can be headed n, e, w, s and have gone 1, 2, 3 steps already.
  75. -- There is a mimimum cost path to reach this configuration, and .. we might need
  76. -- to remember how we got there but let's do that in part 2.
  77. min_cost2(r INT, c INT, dr INT, dc INT, steps INT, cost INT) AS (
  78. SELECT r, c, dr, dc, steps, MIN(cost)
  79. FROM (
  80. SELECT 1 as r, 1 as c, 1 as dr, 0 as dc, 0 as steps, 0 as cost
  81. UNION ALL
  82. SELECT 1, 1, 0, 1, 0, 0
  83. -- We could have just stepped to r, c in a few ways, incurring its cost.
  84. UNION ALL
  85. SELECT cells.r, cells.c, dr, dc, steps + 1, min_cost2.cost + cells.cost
  86. FROM min_cost2, cells
  87. WHERE steps < 10
  88. AND cells.r = min_cost2.r + dr
  89. AND cells.c = min_cost2.c + dc
  90. -- We could take a XYZ turn
  91. UNION ALL
  92. SELECT cells.r, cells.c, dc, dr, 1, min_cost2.cost + cells.cost
  93. FROM min_cost2, cells
  94. WHERE steps >= 4
  95. AND cells.r = min_cost2.r + dc
  96. AND cells.c = min_cost2.c + dr
  97. -- We could take a ZYX turn
  98. UNION ALL
  99. SELECT cells.r, cells.c, -dc, -dr, 1, min_cost2.cost + cells.cost
  100. FROM min_cost2, cells
  101. WHERE steps >= 4
  102. AND cells.r = min_cost2.r - dc
  103. AND cells.c = min_cost2.c - dr
  104. )
  105. GROUP BY r, c, dr, dc, steps
  106. ),
  107. part2(part2 INT) AS (
  108. SELECT MIN(cost)
  109. FROM min_cost2
  110. WHERE r = (SELECT MAX(r) FROM cells)
  111. AND c = (SELECT MAX(c) FROM cells)
  112. AND steps >= 4
  113. )
  114. SELECT * FROM part1, part2;
  115. ----
  116. 156 190
  117. query T multiline
  118. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  119. WITH MUTUALLY RECURSIVE
  120. lines(r INT, line TEXT) AS (
  121. SELECT r, regexp_split_to_array(input, '\n')[r] as block
  122. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n'), 1)) r
  123. ),
  124. cells(r INT, c INT, cost INT) AS (
  125. SELECT r, c, substring(line, c, 1)::INT
  126. FROM lines, generate_series(1, length(line)) c
  127. ),
  128. -- For each cell, we can be headed n, e, w, s and have gone 1, 2, 3 steps already.
  129. -- There is a mimimum cost path to reach this configuration, and .. we might need
  130. -- to remember how we got there but let's do that in part 2.
  131. min_cost(r INT, c INT, dr INT, dc INT, steps INT, cost INT) AS (
  132. SELECT r, c, dr, dc, steps, MIN(cost)
  133. FROM (
  134. SELECT 1 as r, 1 as c, 1 as dr, 0 as dc, 0 as steps, 0 as cost
  135. UNION ALL
  136. SELECT 1, 1, 0, 1, 0, 0
  137. -- We could have just stepped to r, c in a few ways, incurring its cost.
  138. UNION ALL
  139. SELECT cells.r, cells.c, dr, dc, steps + 1, min_cost.cost + cells.cost
  140. FROM min_cost, cells
  141. WHERE steps < 3
  142. AND cells.r = min_cost.r + dr
  143. AND cells.c = min_cost.c + dc
  144. -- We could take a ??? turn
  145. UNION ALL
  146. SELECT cells.r, cells.c, dc, dr, 1, min_cost.cost + cells.cost
  147. FROM min_cost, cells
  148. WHERE cells.r = min_cost.r + dc
  149. AND cells.c = min_cost.c + dr
  150. -- We could take a ??? turn
  151. UNION ALL
  152. SELECT cells.r, cells.c, -dc, -dr, 1, min_cost.cost + cells.cost
  153. FROM min_cost, cells
  154. WHERE cells.r = min_cost.r - dc
  155. AND cells.c = min_cost.c - dr
  156. )
  157. GROUP BY r, c, dr, dc, steps
  158. ),
  159. part1(part1 INT) AS (
  160. SELECT MIN(cost)
  161. FROM min_cost
  162. WHERE r = (SELECT MAX(r) FROM cells)
  163. AND c = (SELECT MAX(c) FROM cells)
  164. ),
  165. potato(x INT) AS (SELECT 1),
  166. -- For each cell, we can be headed n, e, w, s and have gone 1, 2, 3 steps already.
  167. -- There is a mimimum cost path to reach this configuration, and .. we might need
  168. -- to remember how we got there but let's do that in part 2.
  169. min_cost2(r INT, c INT, dr INT, dc INT, steps INT, cost INT) AS (
  170. SELECT r, c, dr, dc, steps, MIN(cost)
  171. FROM (
  172. SELECT 1 as r, 1 as c, 1 as dr, 0 as dc, 0 as steps, 0 as cost
  173. UNION ALL
  174. SELECT 1, 1, 0, 1, 0, 0
  175. -- We could have just stepped to r, c in a few ways, incurring its cost.
  176. UNION ALL
  177. SELECT cells.r, cells.c, dr, dc, steps + 1, min_cost2.cost + cells.cost
  178. FROM min_cost2, cells
  179. WHERE steps < 10
  180. AND cells.r = min_cost2.r + dr
  181. AND cells.c = min_cost2.c + dc
  182. -- We could take a XYZ turn
  183. UNION ALL
  184. SELECT cells.r, cells.c, dc, dr, 1, min_cost2.cost + cells.cost
  185. FROM min_cost2, cells
  186. WHERE steps >= 4
  187. AND cells.r = min_cost2.r + dc
  188. AND cells.c = min_cost2.c + dr
  189. -- We could take a ZYX turn
  190. UNION ALL
  191. SELECT cells.r, cells.c, -dc, -dr, 1, min_cost2.cost + cells.cost
  192. FROM min_cost2, cells
  193. WHERE steps >= 4
  194. AND cells.r = min_cost2.r - dc
  195. AND cells.c = min_cost2.c - dr
  196. )
  197. GROUP BY r, c, dr, dc, steps
  198. ),
  199. part2(part2 INT) AS (
  200. SELECT MIN(cost)
  201. FROM min_cost2
  202. WHERE r = (SELECT MAX(r) FROM cells)
  203. AND c = (SELECT MAX(c) FROM cells)
  204. AND steps >= 4
  205. )
  206. SELECT * FROM part1, part2;
  207. ----
  208. Explained Query:
  209. With
  210. cte l0 =
  211. Project (#0, #2, #3) // { arity: 3 }
  212. Map (text_to_integer(substr(#1{line}, #2{c}, 1))) // { arity: 4 }
  213. FlatMap generate_series(1, char_length(#1{line}), 1) // { arity: 3 }
  214. Project (#1, #2) // { arity: 2 }
  215. Map (array_index(regexp_split_to_array["\n", case_insensitive=false](#0{input}), integer_to_bigint(#1{r}))) // { arity: 3 }
  216. FlatMap generate_series(1, (regexp_split_to_array["\n", case_insensitive=false](#0{input}) array_length 1), 1) // { arity: 2 }
  217. ReadStorage materialize.public.input // { arity: 1 }
  218. cte l1 =
  219. ArrangeBy keys=[[#0{r}, #1{c}]] // { arity: 3 }
  220. Get l0 // { arity: 3 }
  221. Return // { arity: 2 }
  222. With Mutually Recursive
  223. cte l2 =
  224. Project (#0..=#3, #5{min}) // { arity: 5 }
  225. Get l3 // { arity: 6 }
  226. cte l3 =
  227. Reduce group_by=[#0..=#4] aggregates=[min(#5{cost})] // { arity: 6 }
  228. Union // { arity: 6 }
  229. Project (#6, #7, #2, #3, #9, #10) // { arity: 6 }
  230. Map ((#4{steps} + 1), (#5{cost} + #8{cost})) // { arity: 11 }
  231. Join on=(#6{r} = (#0{r} + #2{dr}) AND #7{c} = (#1{c} + #3{dc})) type=differential // { arity: 9 }
  232. implementation
  233. %0:l3[(#0{r} + #2{dr}), (#1{c} + #3{dc})]KKif » %1:l1[#0{r}, #1{c}]KKif
  234. ArrangeBy keys=[[(#0{r} + #2{dr}), (#1{c} + #3{dc})]] // { arity: 6 }
  235. Filter (#4{steps} < 3) // { arity: 6 }
  236. Get l3 // { arity: 6 }
  237. Get l1 // { arity: 3 }
  238. Project (#5, #6, #3, #2, #9, #8) // { arity: 6 }
  239. Map ((#4{cost} + #7{cost}), 1) // { arity: 10 }
  240. Join on=(#5{r} = (#0{r} + #3{dc}) AND #6{c} = (#1{c} + #2{dr})) type=differential // { arity: 8 }
  241. implementation
  242. %0:l2[(#0{r} + #3{dc}), (#1{c} + #2{dr})]KK » %1:l1[#0{r}, #1{c}]KK
  243. ArrangeBy keys=[[(#0{r} + #3{dc}), (#1{c} + #2{dr})]] // { arity: 5 }
  244. Get l2 // { arity: 5 }
  245. Get l1 // { arity: 3 }
  246. Project (#5, #6, #8, #9, #11, #10) // { arity: 6 }
  247. Map (-(#3{dc}), -(#2{dr}), (#4{cost} + #7{cost}), 1) // { arity: 12 }
  248. Join on=(#5{r} = (#0{r} - #3{dc}) AND #6{c} = (#1{c} - #2{dr})) type=differential // { arity: 8 }
  249. implementation
  250. %0:l2[(#0{r} - #3{dc}), (#1{c} - #2{dr})]KK » %1:l1[#0{r}, #1{c}]KK
  251. ArrangeBy keys=[[(#0{r} - #3{dc}), (#1{c} - #2{dr})]] // { arity: 5 }
  252. Get l2 // { arity: 5 }
  253. Get l1 // { arity: 3 }
  254. Constant // { arity: 6 }
  255. - (1, 1, 0, 1, 0, 0)
  256. - (1, 1, 1, 0, 0, 0)
  257. cte l4 =
  258. Reduce aggregates=[min(#0{min})] // { arity: 1 }
  259. Project (#2{min}) // { arity: 1 }
  260. Join on=(#0{r} = #3{max} AND #1{c} = #4{max}) type=differential // { arity: 5 }
  261. implementation
  262. %1[×]UA » %2[×]UA » %0:l3[#0{r}, #1{c}]KK
  263. ArrangeBy keys=[[#0{r}, #1{c}]] // { arity: 3 }
  264. Project (#0, #1, #5{min}) // { arity: 3 }
  265. Get l3 // { arity: 6 }
  266. ArrangeBy keys=[[]] // { arity: 1 }
  267. Reduce aggregates=[max(#0{r})] // { arity: 1 }
  268. Project (#0) // { arity: 1 }
  269. Get l0 // { arity: 3 }
  270. ArrangeBy keys=[[]] // { arity: 1 }
  271. Reduce aggregates=[max(#0{c})] // { arity: 1 }
  272. Project (#1) // { arity: 1 }
  273. Get l0 // { arity: 3 }
  274. cte l5 =
  275. Project (#0..=#3, #5{min}) // { arity: 5 }
  276. Filter (#4{steps} >= 4) // { arity: 6 }
  277. Get l6 // { arity: 6 }
  278. cte l6 =
  279. Reduce group_by=[#0..=#4] aggregates=[min(#5{cost})] // { arity: 6 }
  280. Union // { arity: 6 }
  281. Project (#6, #7, #2, #3, #9, #10) // { arity: 6 }
  282. Map ((#4{steps} + 1), (#5{cost} + #8{cost})) // { arity: 11 }
  283. Join on=(#6{r} = (#0{r} + #2{dr}) AND #7{c} = (#1{c} + #3{dc})) type=differential // { arity: 9 }
  284. implementation
  285. %0:l6[(#0{r} + #2{dr}), (#1{c} + #3{dc})]KKif » %1:l1[#0{r}, #1{c}]KKif
  286. ArrangeBy keys=[[(#0{r} + #2{dr}), (#1{c} + #3{dc})]] // { arity: 6 }
  287. Filter (#4{steps} < 10) // { arity: 6 }
  288. Get l6 // { arity: 6 }
  289. Get l1 // { arity: 3 }
  290. Project (#5, #6, #3, #2, #9, #8) // { arity: 6 }
  291. Map ((#4{cost} + #7{cost}), 1) // { arity: 10 }
  292. Join on=(#5{r} = (#0{r} + #3{dc}) AND #6{c} = (#1{c} + #2{dr})) type=differential // { arity: 8 }
  293. implementation
  294. %0:l5[(#0{r} + #3{dc}), (#1{c} + #2{dr})]KKif » %1:l1[#0{r}, #1{c}]KKif
  295. ArrangeBy keys=[[(#0{r} + #3{dc}), (#1{c} + #2{dr})]] // { arity: 5 }
  296. Get l5 // { arity: 5 }
  297. Get l1 // { arity: 3 }
  298. Project (#5, #6, #8, #9, #11, #10) // { arity: 6 }
  299. Map (-(#3{dc}), -(#2{dr}), (#4{cost} + #7{cost}), 1) // { arity: 12 }
  300. Join on=(#5{r} = (#0{r} - #3{dc}) AND #6{c} = (#1{c} - #2{dr})) type=differential // { arity: 8 }
  301. implementation
  302. %0:l5[(#0{r} - #3{dc}), (#1{c} - #2{dr})]KKif » %1:l1[#0{r}, #1{c}]KKif
  303. ArrangeBy keys=[[(#0{r} - #3{dc}), (#1{c} - #2{dr})]] // { arity: 5 }
  304. Get l5 // { arity: 5 }
  305. Get l1 // { arity: 3 }
  306. Constant // { arity: 6 }
  307. - (1, 1, 0, 1, 0, 0)
  308. - (1, 1, 1, 0, 0, 0)
  309. Return // { arity: 2 }
  310. With
  311. cte l7 =
  312. Reduce aggregates=[min(#0{min})] // { arity: 1 }
  313. Project (#2{min}) // { arity: 1 }
  314. Join on=(#0{r} = #3{max} AND #1{c} = #4{max}) type=differential // { arity: 5 }
  315. implementation
  316. %1[×]UA » %2[×]UA » %0:l6[#0{r}, #1{c}]KKif
  317. ArrangeBy keys=[[#0{r}, #1{c}]] // { arity: 3 }
  318. Project (#0, #1, #5{min}) // { arity: 3 }
  319. Filter (#4{steps} >= 4) // { arity: 6 }
  320. Get l6 // { arity: 6 }
  321. ArrangeBy keys=[[]] // { arity: 1 }
  322. Reduce aggregates=[max(#0{r})] // { arity: 1 }
  323. Project (#0) // { arity: 1 }
  324. Get l0 // { arity: 3 }
  325. ArrangeBy keys=[[]] // { arity: 1 }
  326. Reduce aggregates=[max(#0{c})] // { arity: 1 }
  327. Project (#1) // { arity: 1 }
  328. Get l0 // { arity: 3 }
  329. Return // { arity: 2 }
  330. CrossJoin type=differential // { arity: 2 }
  331. implementation
  332. %0[×]U » %1[×]U
  333. ArrangeBy keys=[[]] // { arity: 1 }
  334. Union // { arity: 1 }
  335. Get l4 // { arity: 1 }
  336. Map (null) // { arity: 1 }
  337. Union // { arity: 0 }
  338. Negate // { arity: 0 }
  339. Project () // { arity: 0 }
  340. Get l4 // { arity: 1 }
  341. Constant // { arity: 0 }
  342. - ()
  343. ArrangeBy keys=[[]] // { arity: 1 }
  344. Union // { arity: 1 }
  345. Get l7 // { arity: 1 }
  346. Map (null) // { arity: 1 }
  347. Union // { arity: 0 }
  348. Negate // { arity: 0 }
  349. Project () // { arity: 0 }
  350. Get l7 // { arity: 1 }
  351. Constant // { arity: 0 }
  352. - ()
  353. Source materialize.public.input
  354. Target cluster: quickstart
  355. EOF