aoc_1213.slt 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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_1213.md
  10. mode cockroach
  11. statement ok
  12. CREATE TABLE input (input TEXT);
  13. statement ok
  14. INSERT INTO input VALUES (
  15. '#.###..##
  16. ..###..#.
  17. .##.....#
  18. ..###....
  19. ..##..#..
  20. .##.#..#.
  21. ##...##..
  22. ..#.#.#.#
  23. #####.###
  24. ....#.##.
  25. .#.######
  26. ....##...
  27. #..##...#
  28. <EMPTY_LINE>
  29. ###.#..###.#....#
  30. ...#....#..#..#.#
  31. ...#...##.#.#.#..
  32. ##.#...##.#.....#
  33. .#..#....##...##.
  34. .##....#...#.#...
  35. ..#.##.##.#..##.#
  36. ........#.##.#..#
  37. <EMPTY_LINE>
  38. #...#..#.......
  39. .#.###.##.#.###
  40. .#.##..........
  41. ##.##.##.###.##
  42. ..###.#.....#..
  43. ..###.#.....#..
  44. ##.##.##.###.##
  45. #....#.##...###
  46. #.#.....##..#..
  47. ...###.....#...
  48. ..#.....#..#...
  49. ##.###.##......
  50. ...#.##.#.#.#.#
  51. ..........####.
  52. <EMPTY_LINE>
  53. ...#.....
  54. ...#.....
  55. ...#.....
  56. #...##...
  57. ..#.....#
  58. ...#.####
  59. .##....##
  60. ......#..
  61. #.....#..
  62. ....#.#.#
  63. ##...####
  64. <EMPTY_LINE>
  65. ...##.##.#.##
  66. #....#..#..##
  67. ##.##....###.
  68. #..###....#.#
  69. ###...##..#..
  70. #.#...#.#.##.
  71. ###..#.......
  72. ..##.#.#...##
  73. ##..#..#..#.#
  74. ......#...###
  75. ..#..#.##....
  76. ##.#...#.#...
  77. #..#.....####
  78. ....##.##..#.
  79. ####......###
  80. <EMPTY_LINE>
  81. #.##..#..##
  82. .#.#####..#
  83. .##.##...##
  84. .#.#..#...#
  85. ...####.#..
  86. #..######..
  87. ..#....#...
  88. .#####.##.#
  89. ..........#
  90. ##.#..#.#.#
  91. .......#...
  92. <EMPTY_LINE>
  93. .#.#..#....###...
  94. ######..#.###.#..
  95. ##..##.#..#..#...
  96. ...##...##...#.#.
  97. #...#..####..#.#.
  98. ..####.#..#...#.#
  99. ####.#......#.#..
  100. ##..##...#.#...#.
  101. <EMPTY_LINE>
  102. #..#.##..........
  103. .#....##....#.#.#
  104. .##.....##....###
  105. #####...##...##..
  106. ###.....#...###.#
  107. #....#.#......#.#
  108. #..#...###...#..#
  109. #.#......#.###.#.
  110. #..#.##..........
  111. <EMPTY_LINE>
  112. .##.#.#.##..#.#..
  113. ...####...##..#..
  114. ....##...#...##.#
  115. ..###..#..#..####
  116. .#...##...#.###..
  117. ...###.....#...##
  118. <EMPTY_LINE>
  119. .#...#.####.#
  120. ##..#.#....#.
  121. .#..#...#..#.
  122. ..#....#.#.#.
  123. .#...##....#.
  124. #.###.##..###
  125. #..#.#....###
  126. .##..#.#.#...
  127. .##.#.##..#..
  128. #...###..##..');
  129. statement ok
  130. UPDATE input SET input = replace(input, '<EMPTY_LINE>', '');
  131. query II
  132. WITH MUTUALLY RECURSIVE
  133. blocks(b INT, block TEXT) AS (
  134. SELECT b, regexp_split_to_array(input, '\n\n')[b] as block
  135. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n\n'), 1)) b
  136. ),
  137. lines(b INT, r INT, line TEXT) AS (
  138. SELECT b, r, regexp_split_to_array(block, '\n')[r] as block
  139. FROM blocks, generate_series(1, array_length(regexp_split_to_array(block, '\n'), 1)) r
  140. ),
  141. cells(b INT, r INT, c INT, symbol TEXT) AS (
  142. SELECT b, r, c, substring(line, c, 1)
  143. FROM lines, generate_series(1, length(line)) c
  144. ),
  145. columns(b INT, c INT, column TEXT) AS (
  146. SELECT b, c, string_agg(symbol, '' ORDER BY r) FROM cells GROUP BY b, c
  147. ),
  148. row_mirror(b INT, r INT) AS (
  149. SELECT *
  150. FROM (SELECT DISTINCT b, r FROM cells) o
  151. WHERE NOT EXISTS (
  152. -- We would be upset to find rows at mirrored positions that do not match
  153. -- Rows that match, or have no mirrored position, are fine.
  154. SELECT FROM lines
  155. WHERE o.b = lines.b
  156. GROUP BY abs(2 * lines.r - (2 * o.r - 1))
  157. HAVING COUNT(DISTINCT lines.line) > 1
  158. )
  159. ),
  160. col_mirror(b INT, c INT) AS (
  161. SELECT *
  162. FROM (SELECT DISTINCT b, c FROM cells) o
  163. WHERE NOT EXISTS (
  164. -- We would be upset to find rows at mirrored positions that do not match
  165. -- Rows that match, or have no mirrored position, are fine.
  166. SELECT FROM columns
  167. WHERE o.b = columns.b
  168. GROUP BY abs(2 * columns.c - (2 * o.c - 1))
  169. HAVING COUNT(DISTINCT columns.column) > 1
  170. )
  171. ),
  172. part1(part1 BIGINT) AS (
  173. SELECT COALESCE((SELECT SUM(r-1) FROM row_mirror), 0) * 100
  174. + COALESCE((SELECT SUM(c-1) FROM col_mirror), 0)
  175. ),
  176. row_mirror2(b INT, r INT) AS (
  177. SELECT *
  178. FROM (SELECT DISTINCT b, r FROM cells) o
  179. WHERE 1 = (
  180. SELECT COUNT(*)
  181. FROM cells c1, cells c2
  182. WHERE abs(2 * c1.r - (2 * o.r - 1)) = abs(2 * c2.r - (2 * o.r - 1))
  183. AND c1.r < c2.r
  184. AND c1.c = c2.c
  185. AND c1.b = c2.b
  186. AND c1.b = o.b
  187. AND c1.symbol != c2.symbol
  188. )
  189. ),
  190. col_mirror2(b INT, c INT) AS (
  191. SELECT *
  192. FROM (SELECT DISTINCT b, c FROM cells) o
  193. WHERE 1 = (
  194. SELECT COUNT(*)
  195. FROM cells c1, cells c2
  196. WHERE abs(2 * c1.c - (2 * o.c - 1)) = abs(2 * c2.c - (2 * o.c - 1))
  197. AND c1.c < c2.c
  198. AND c1.r = c2.r
  199. AND c1.b = c2.b
  200. AND c1.b = o.b
  201. AND c1.symbol != c2.symbol
  202. )
  203. ),
  204. part2(part2 BIGINT) AS (
  205. SELECT COALESCE((SELECT SUM(r-1) FROM row_mirror2), 0) * 100
  206. + COALESCE((SELECT SUM(c-1) FROM col_mirror2), 0)
  207. ),
  208. potato (x INT) AS ( SELECT 1 )
  209. SELECT * FROM part1, part2;
  210. ----
  211. 100 16
  212. query T multiline
  213. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  214. WITH MUTUALLY RECURSIVE
  215. blocks(b INT, block TEXT) AS (
  216. SELECT b, regexp_split_to_array(input, '\n\n')[b] as block
  217. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n\n'), 1)) b
  218. ),
  219. lines(b INT, r INT, line TEXT) AS (
  220. SELECT b, r, regexp_split_to_array(block, '\n')[r] as block
  221. FROM blocks, generate_series(1, array_length(regexp_split_to_array(block, '\n'), 1)) r
  222. ),
  223. cells(b INT, r INT, c INT, symbol TEXT) AS (
  224. SELECT b, r, c, substring(line, c, 1)
  225. FROM lines, generate_series(1, length(line)) c
  226. ),
  227. columns(b INT, c INT, column TEXT) AS (
  228. SELECT b, c, string_agg(symbol, '' ORDER BY r) FROM cells GROUP BY b, c
  229. ),
  230. row_mirror(b INT, r INT) AS (
  231. SELECT *
  232. FROM (SELECT DISTINCT b, r FROM cells) o
  233. WHERE NOT EXISTS (
  234. -- We would be upset to find rows at mirrored positions that do not match
  235. -- Rows that match, or have no mirrored position, are fine.
  236. SELECT FROM lines
  237. WHERE o.b = lines.b
  238. GROUP BY abs(2 * lines.r - (2 * o.r - 1))
  239. HAVING COUNT(DISTINCT lines.line) > 1
  240. )
  241. ),
  242. col_mirror(b INT, c INT) AS (
  243. SELECT *
  244. FROM (SELECT DISTINCT b, c FROM cells) o
  245. WHERE NOT EXISTS (
  246. -- We would be upset to find rows at mirrored positions that do not match
  247. -- Rows that match, or have no mirrored position, are fine.
  248. SELECT FROM columns
  249. WHERE o.b = columns.b
  250. GROUP BY abs(2 * columns.c - (2 * o.c - 1))
  251. HAVING COUNT(DISTINCT columns.column) > 1
  252. )
  253. ),
  254. part1(part1 BIGINT) AS (
  255. SELECT COALESCE((SELECT SUM(r-1) FROM row_mirror), 0) * 100
  256. + COALESCE((SELECT SUM(c-1) FROM col_mirror), 0)
  257. ),
  258. row_mirror2(b INT, r INT) AS (
  259. SELECT *
  260. FROM (SELECT DISTINCT b, r FROM cells) o
  261. WHERE 1 = (
  262. SELECT COUNT(*)
  263. FROM cells c1, cells c2
  264. WHERE abs(2 * c1.r - (2 * o.r - 1)) = abs(2 * c2.r - (2 * o.r - 1))
  265. AND c1.r < c2.r
  266. AND c1.c = c2.c
  267. AND c1.b = c2.b
  268. AND c1.b = o.b
  269. AND c1.symbol != c2.symbol
  270. )
  271. ),
  272. col_mirror2(b INT, c INT) AS (
  273. SELECT *
  274. FROM (SELECT DISTINCT b, c FROM cells) o
  275. WHERE 1 = (
  276. SELECT COUNT(*)
  277. FROM cells c1, cells c2
  278. WHERE abs(2 * c1.c - (2 * o.c - 1)) = abs(2 * c2.c - (2 * o.c - 1))
  279. AND c1.c < c2.c
  280. AND c1.r = c2.r
  281. AND c1.b = c2.b
  282. AND c1.b = o.b
  283. AND c1.symbol != c2.symbol
  284. )
  285. ),
  286. part2(part2 BIGINT) AS (
  287. SELECT COALESCE((SELECT SUM(r-1) FROM row_mirror2), 0) * 100
  288. + COALESCE((SELECT SUM(c-1) FROM col_mirror2), 0)
  289. ),
  290. potato (x INT) AS ( SELECT 1 )
  291. SELECT * FROM part1, part2;
  292. ----
  293. Explained Query:
  294. With
  295. cte l0 =
  296. Project (#0, #2, #3) // { arity: 3 }
  297. Map (array_index(regexp_split_to_array["\n", case_insensitive=false](#1{block}), integer_to_bigint(#2{r}))) // { arity: 4 }
  298. FlatMap generate_series(1, (regexp_split_to_array["\n", case_insensitive=false](#1{block}) array_length 1), 1) // { arity: 3 }
  299. Project (#1, #2) // { arity: 2 }
  300. Map (array_index(regexp_split_to_array["\n\n", case_insensitive=false](#0{input}), integer_to_bigint(#1{b}))) // { arity: 3 }
  301. FlatMap generate_series(1, (regexp_split_to_array["\n\n", case_insensitive=false](#0{input}) array_length 1), 1) // { arity: 2 }
  302. ReadStorage materialize.public.input // { arity: 1 }
  303. cte l1 =
  304. Project (#0, #1, #3, #4) // { arity: 4 }
  305. Map (substr(#2{line}, #3{c}, 1)) // { arity: 5 }
  306. FlatMap generate_series(1, char_length(#2{line}), 1) // { arity: 4 }
  307. Get l0 // { arity: 3 }
  308. cte l2 =
  309. Distinct project=[#0, #1] // { arity: 2 }
  310. Project (#0, #1) // { arity: 2 }
  311. Get l1 // { arity: 4 }
  312. cte l3 =
  313. Distinct project=[#0, #1] // { arity: 2 }
  314. Project (#0, #2) // { arity: 2 }
  315. Get l1 // { arity: 4 }
  316. cte l4 =
  317. ArrangeBy keys=[[#0{b}]] // { arity: 2 }
  318. Get l2 // { arity: 2 }
  319. cte l5 =
  320. Reduce aggregates=[sum((#0{r} - 1))] // { arity: 1 }
  321. Union // { arity: 1 }
  322. Negate // { arity: 1 }
  323. Project (#1) // { arity: 1 }
  324. Distinct project=[#0, #1] // { arity: 2 }
  325. Project (#0, #1) // { arity: 2 }
  326. Filter (#3{count} > 1) // { arity: 4 }
  327. Reduce group_by=[#0, #1, abs(((2 * #2{r}) - ((2 * #1{r}) - 1)))] aggregates=[count(distinct #3{line})] // { arity: 4 }
  328. Project (#0, #1, #3, #4) // { arity: 4 }
  329. Join on=(#0{b} = #2{b}) type=differential // { arity: 5 }
  330. implementation
  331. %0:l4[#0{b}]K » %1:l0[#0{b}]K
  332. Get l4 // { arity: 2 }
  333. ArrangeBy keys=[[#0{b}]] // { arity: 3 }
  334. Get l0 // { arity: 3 }
  335. Project (#1) // { arity: 1 }
  336. Get l2 // { arity: 2 }
  337. cte l6 =
  338. Union // { arity: 1 }
  339. Get l5 // { arity: 1 }
  340. Map (null) // { arity: 1 }
  341. Union // { arity: 0 }
  342. Negate // { arity: 0 }
  343. Project () // { arity: 0 }
  344. Get l5 // { arity: 1 }
  345. Constant // { arity: 0 }
  346. - ()
  347. cte l7 =
  348. ArrangeBy keys=[[#0{b}]] // { arity: 2 }
  349. Get l3 // { arity: 2 }
  350. cte l8 =
  351. Reduce aggregates=[sum((#0{c} - 1))] // { arity: 1 }
  352. Union // { arity: 1 }
  353. Negate // { arity: 1 }
  354. Project (#1) // { arity: 1 }
  355. Distinct project=[#0, #1] // { arity: 2 }
  356. Project (#0, #1) // { arity: 2 }
  357. Filter (#3{count_string_agg} > 1) // { arity: 4 }
  358. Reduce group_by=[#0, #1, abs(((2 * #2{c}) - ((2 * #1{c}) - 1)))] aggregates=[count(distinct #3{string_agg})] // { arity: 4 }
  359. Project (#0, #1, #3, #4{string_agg}) // { arity: 4 }
  360. Join on=(#0{b} = #2{b}) type=differential // { arity: 5 }
  361. implementation
  362. %0:l7[#0{b}]K » %1[#0{b}]K
  363. Get l7 // { arity: 2 }
  364. ArrangeBy keys=[[#0{b}]] // { arity: 3 }
  365. Reduce group_by=[#0, #2] aggregates=[string_agg[order_by=[#0 asc nulls_last]](row(row(#3{symbol}, ""), #1{r}))] // { arity: 3 }
  366. Get l1 // { arity: 4 }
  367. Project (#1) // { arity: 1 }
  368. Get l3 // { arity: 2 }
  369. cte l9 =
  370. Union // { arity: 1 }
  371. Get l8 // { arity: 1 }
  372. Map (null) // { arity: 1 }
  373. Union // { arity: 0 }
  374. Negate // { arity: 0 }
  375. Project () // { arity: 0 }
  376. Get l8 // { arity: 1 }
  377. Constant // { arity: 0 }
  378. - ()
  379. cte l10 =
  380. Reduce aggregates=[sum((#0{r} - 1))] // { arity: 1 }
  381. Project (#1) // { arity: 1 }
  382. Filter (#2{count} = 1) // { arity: 3 }
  383. Reduce group_by=[#0, #1] aggregates=[count(*)] // { arity: 3 }
  384. Project (#0, #1) // { arity: 2 }
  385. Filter (#5{symbol} != #9{symbol}) AND (#3{r} < #7{r}) // { arity: 10 }
  386. Join on=(#0{b} = #2{b} = #6{b} AND #4{c} = #8{c} AND abs(((2 * #3{r}) - ((2 * #1{r}) - 1))) = abs(((2 * #7{r}) - ((2 * #1{r}) - 1)))) type=delta // { arity: 10 }
  387. implementation
  388. %0:l4 » %1:l1[#0{b}]K » %2:l1[#0{b}, #2{c}]KK
  389. %1:l1 » %2:l1[#0{b}, #2{c}]KK » %0:l4[#0{b}]K
  390. %2:l1 » %1:l1[#0{b}, #2{c}]KK » %0:l4[#0{b}]K
  391. Get l4 // { arity: 2 }
  392. ArrangeBy keys=[[#0{b}], [#0{b}, #2{c}]] // { arity: 4 }
  393. Get l1 // { arity: 4 }
  394. ArrangeBy keys=[[#0{b}, #2{c}]] // { arity: 4 }
  395. Get l1 // { arity: 4 }
  396. cte l11 =
  397. Union // { arity: 1 }
  398. Get l10 // { arity: 1 }
  399. Map (null) // { arity: 1 }
  400. Union // { arity: 0 }
  401. Negate // { arity: 0 }
  402. Project () // { arity: 0 }
  403. Get l10 // { arity: 1 }
  404. Constant // { arity: 0 }
  405. - ()
  406. cte l12 =
  407. Reduce aggregates=[sum((#0{c} - 1))] // { arity: 1 }
  408. Project (#1) // { arity: 1 }
  409. Filter (#2{count} = 1) // { arity: 3 }
  410. Reduce group_by=[#0, #1] aggregates=[count(*)] // { arity: 3 }
  411. Project (#0, #1) // { arity: 2 }
  412. Filter (#5{symbol} != #9{symbol}) AND (#4{c} < #8{c}) // { arity: 10 }
  413. Join on=(#0{b} = #2{b} = #6{b} AND #3{r} = #7{r} AND abs(((2 * #4{c}) - ((2 * #1{c}) - 1))) = abs(((2 * #8{c}) - ((2 * #1{c}) - 1)))) type=delta // { arity: 10 }
  414. implementation
  415. %0:l7 » %1:l1[#0{b}]K » %2:l1[#0{b}, #1{r}]KK
  416. %1:l1 » %2:l1[#0{b}, #1{r}]KK » %0:l7[#0{b}]K
  417. %2:l1 » %1:l1[#0{b}, #1{r}]KK » %0:l7[#0{b}]K
  418. Get l7 // { arity: 2 }
  419. ArrangeBy keys=[[#0{b}], [#0{b}, #1{r}]] // { arity: 4 }
  420. Get l1 // { arity: 4 }
  421. ArrangeBy keys=[[#0{b}, #1{r}]] // { arity: 4 }
  422. Get l1 // { arity: 4 }
  423. cte l13 =
  424. Union // { arity: 1 }
  425. Get l12 // { arity: 1 }
  426. Map (null) // { arity: 1 }
  427. Union // { arity: 0 }
  428. Negate // { arity: 0 }
  429. Project () // { arity: 0 }
  430. Get l12 // { arity: 1 }
  431. Constant // { arity: 0 }
  432. - ()
  433. Return // { arity: 2 }
  434. Project (#4, #5) // { arity: 2 }
  435. Map (((coalesce(#0{sum}, 0) * 100) + coalesce(#1{sum}, 0)), ((coalesce(#2{sum}, 0) * 100) + coalesce(#3{sum}, 0))) // { arity: 6 }
  436. CrossJoin type=delta // { arity: 4 }
  437. implementation
  438. %0 » %1[×]U » %2[×]U » %3[×]U
  439. %1 » %0[×]U » %2[×]U » %3[×]U
  440. %2 » %0[×]U » %1[×]U » %3[×]U
  441. %3 » %0[×]U » %1[×]U » %2[×]U
  442. ArrangeBy keys=[[]] // { arity: 1 }
  443. Union // { arity: 1 }
  444. Get l6 // { arity: 1 }
  445. Map (null) // { arity: 1 }
  446. Union // { arity: 0 }
  447. Negate // { arity: 0 }
  448. Project () // { arity: 0 }
  449. Get l6 // { arity: 1 }
  450. Constant // { arity: 0 }
  451. - ()
  452. ArrangeBy keys=[[]] // { arity: 1 }
  453. Union // { arity: 1 }
  454. Get l9 // { arity: 1 }
  455. Map (null) // { arity: 1 }
  456. Union // { arity: 0 }
  457. Negate // { arity: 0 }
  458. Project () // { arity: 0 }
  459. Get l9 // { arity: 1 }
  460. Constant // { arity: 0 }
  461. - ()
  462. ArrangeBy keys=[[]] // { arity: 1 }
  463. Union // { arity: 1 }
  464. Get l11 // { arity: 1 }
  465. Map (null) // { arity: 1 }
  466. Union // { arity: 0 }
  467. Negate // { arity: 0 }
  468. Project () // { arity: 0 }
  469. Get l11 // { arity: 1 }
  470. Constant // { arity: 0 }
  471. - ()
  472. ArrangeBy keys=[[]] // { arity: 1 }
  473. Union // { arity: 1 }
  474. Get l13 // { arity: 1 }
  475. Map (null) // { arity: 1 }
  476. Union // { arity: 0 }
  477. Negate // { arity: 0 }
  478. Project () // { arity: 0 }
  479. Get l13 // { arity: 1 }
  480. Constant // { arity: 0 }
  481. - ()
  482. Source materialize.public.input
  483. Target cluster: quickstart
  484. EOF