aoc_1214.slt 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  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_1214.md
  10. mode cockroach
  11. statement ok
  12. CREATE TABLE input (input TEXT);
  13. statement ok
  14. INSERT INTO input VALUES (
  15. '.O.#....#.#.#.....O..O..O...
  16. .O.#....O....#..#....#####..
  17. .O..##..O..#O...##..#...O...
  18. O.##.OO#O.#...#.#.#.O..##.O.
  19. O..#..OO#...#..#.#O.#.#.OO.#
  20. #.#.#.O.O##...O...#0##..O...
  21. .O#...#..#.O..O.#.##..#..O..');
  22. query I
  23. WITH MUTUALLY RECURSIVE
  24. lines(r INT, line TEXT) AS (
  25. SELECT r, regexp_split_to_array(input, '\n')[r] as block
  26. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n'), 1)) r
  27. ),
  28. cells(r INT, c INT, symbol TEXT) AS (
  29. SELECT r, c, substring(line, c, 1)
  30. FROM lines, generate_series(1, length(line)) c
  31. ),
  32. northward(r INT, c INT, symbol TEXT) AS (
  33. SELECT * FROM northward
  34. -- Anyone on the move does so
  35. UNION ALL SELECT r - 1, c, 'O' FROM north_move
  36. EXCEPT ALL SELECT r - 1, c, '.' FROM north_move
  37. UNION ALL SELECT r, c, '.' FROM north_move
  38. EXCEPT ALL SELECT r, c, 'O' FROM north_move
  39. -- Initial state is cells, but not refreshed each round.
  40. UNION ALL SELECT * FROM cells
  41. EXCEPT ALL SELECT * FROM cells_delay
  42. ),
  43. -- Each 'O' with a '.' to the north will move.
  44. north_move(r INT, c INT) AS (
  45. SELECT n1.r, n1.c
  46. FROM northward n1, northward n2
  47. WHERE n1.symbol = 'O'
  48. AND n1.r = n2.r + 1
  49. AND n1.c = n2.c
  50. AND n2.symbol = '.'
  51. ),
  52. part1(part1 BIGINT) AS (
  53. SELECT SUM(1 + (SELECT MAX(r) FROM lines) - r)
  54. FROM northward
  55. WHERE symbol = 'O'
  56. ),
  57. output (r INT, line TEXT) AS (
  58. SELECT r, string_agg(symbol, ' ' ORDER BY c)
  59. FROM northward
  60. GROUP BY r
  61. ),
  62. cells_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM cells )
  63. SELECT * FROM part1;
  64. ----
  65. 146
  66. query T multiline
  67. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  68. WITH MUTUALLY RECURSIVE
  69. lines(r INT, line TEXT) AS (
  70. SELECT r, regexp_split_to_array(input, '\n')[r] as block
  71. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n'), 1)) r
  72. ),
  73. cells(r INT, c INT, symbol TEXT) AS (
  74. SELECT r, c, substring(line, c, 1)
  75. FROM lines, generate_series(1, length(line)) c
  76. ),
  77. northward(r INT, c INT, symbol TEXT) AS (
  78. SELECT * FROM northward
  79. -- Anyone on the move does so
  80. UNION ALL SELECT r - 1, c, 'O' FROM north_move
  81. EXCEPT ALL SELECT r - 1, c, '.' FROM north_move
  82. UNION ALL SELECT r, c, '.' FROM north_move
  83. EXCEPT ALL SELECT r, c, 'O' FROM north_move
  84. -- Initial state is cells, but not refreshed each round.
  85. UNION ALL SELECT * FROM cells
  86. EXCEPT ALL SELECT * FROM cells_delay
  87. ),
  88. -- Each 'O' with a '.' to the north will move.
  89. north_move(r INT, c INT) AS (
  90. SELECT n1.r, n1.c
  91. FROM northward n1, northward n2
  92. WHERE n1.symbol = 'O'
  93. AND n1.r = n2.r + 1
  94. AND n1.c = n2.c
  95. AND n2.symbol = '.'
  96. ),
  97. part1(part1 BIGINT) AS (
  98. SELECT SUM(1 + (SELECT MAX(r) FROM lines) - r)
  99. FROM northward
  100. WHERE symbol = 'O'
  101. ),
  102. output (r INT, line TEXT) AS (
  103. SELECT r, string_agg(symbol, ' ' ORDER BY c)
  104. FROM northward
  105. GROUP BY r
  106. ),
  107. cells_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM cells )
  108. SELECT * FROM part1;
  109. ----
  110. Explained Query:
  111. With
  112. cte l0 =
  113. Project (#1, #2) // { arity: 2 }
  114. Map (array_index(regexp_split_to_array["\n", case_insensitive=false](#0{input}), integer_to_bigint(#1{r}))) // { arity: 3 }
  115. FlatMap generate_series(1, (regexp_split_to_array["\n", case_insensitive=false](#0{input}) array_length 1), 1) // { arity: 2 }
  116. ReadStorage materialize.public.input // { arity: 1 }
  117. cte l1 =
  118. Reduce aggregates=[max(#0{r})] // { arity: 1 }
  119. Project (#0) // { arity: 1 }
  120. Get l0 // { arity: 2 }
  121. cte l2 =
  122. Union // { arity: 1 }
  123. Get l1 // { arity: 1 }
  124. Map (null) // { arity: 1 }
  125. Union // { arity: 0 }
  126. Negate // { arity: 0 }
  127. Project () // { arity: 0 }
  128. Get l1 // { arity: 1 }
  129. Constant // { arity: 0 }
  130. - ()
  131. cte l3 =
  132. Project (#0, #2, #3) // { arity: 3 }
  133. Map (substr(#1{line}, #2{c}, 1)) // { arity: 4 }
  134. FlatMap generate_series(1, char_length(#1{line}), 1) // { arity: 3 }
  135. Get l0 // { arity: 2 }
  136. Return // { arity: 1 }
  137. With Mutually Recursive
  138. cte l4 =
  139. Threshold // { arity: 3 }
  140. Union // { arity: 3 }
  141. Threshold // { arity: 3 }
  142. Union // { arity: 3 }
  143. Threshold // { arity: 3 }
  144. Union // { arity: 3 }
  145. Get l4 // { arity: 3 }
  146. Project (#2, #1, #3) // { arity: 3 }
  147. Map ((#0{r} - 1), "O") // { arity: 4 }
  148. Get l6 // { arity: 2 }
  149. Negate // { arity: 3 }
  150. Project (#2, #1, #3) // { arity: 3 }
  151. Map ((#0{r} - 1), ".") // { arity: 4 }
  152. Get l6 // { arity: 2 }
  153. Map (".") // { arity: 3 }
  154. Get l6 // { arity: 2 }
  155. Negate // { arity: 3 }
  156. Map ("O") // { arity: 3 }
  157. Get l6 // { arity: 2 }
  158. Get l3 // { arity: 3 }
  159. Negate // { arity: 3 }
  160. Get l8 // { arity: 3 }
  161. cte l5 =
  162. Project (#0, #1) // { arity: 2 }
  163. Filter (#2{symbol} = "O") // { arity: 3 }
  164. Get l4 // { arity: 3 }
  165. cte l6 =
  166. Project (#0, #1) // { arity: 2 }
  167. Join on=(#0{r} = (#2{r} + 1) AND #1{c} = #3{c}) type=differential // { arity: 4 }
  168. implementation
  169. %0:l5[#1{c}, #0{r}]KKef » %1:l4[#1{c}, (#0{r} + 1)]KKef
  170. ArrangeBy keys=[[#1{c}, #0{r}]] // { arity: 2 }
  171. Get l5 // { arity: 2 }
  172. ArrangeBy keys=[[#1{c}, (#0{r} + 1)]] // { arity: 2 }
  173. Project (#0, #1) // { arity: 2 }
  174. Filter (#2{symbol} = ".") // { arity: 3 }
  175. Get l4 // { arity: 3 }
  176. cte l7 =
  177. Reduce aggregates=[sum(((1 + #1{max}) - #0{r}))] // { arity: 1 }
  178. CrossJoin type=differential // { arity: 2 }
  179. implementation
  180. %1[×]U » %0:l5[×]ef
  181. ArrangeBy keys=[[]] // { arity: 1 }
  182. Project (#0) // { arity: 1 }
  183. Get l5 // { arity: 2 }
  184. ArrangeBy keys=[[]] // { arity: 1 }
  185. Union // { arity: 1 }
  186. Get l2 // { arity: 1 }
  187. Map (null) // { arity: 1 }
  188. Union // { arity: 0 }
  189. Negate // { arity: 0 }
  190. Project () // { arity: 0 }
  191. Get l2 // { arity: 1 }
  192. Constant // { arity: 0 }
  193. - ()
  194. cte l8 =
  195. Get l3 // { arity: 3 }
  196. Return // { arity: 1 }
  197. Union // { arity: 1 }
  198. Get l7 // { arity: 1 }
  199. Map (null) // { arity: 1 }
  200. Union // { arity: 0 }
  201. Negate // { arity: 0 }
  202. Project () // { arity: 0 }
  203. Get l7 // { arity: 1 }
  204. Constant // { arity: 0 }
  205. - ()
  206. Source materialize.public.input
  207. Target cluster: quickstart
  208. EOF
  209. query I
  210. WITH MUTUALLY RECURSIVE (RETURN AT RECURSION LIMIT 142)
  211. lines(r INT, line TEXT) AS (
  212. SELECT r, regexp_split_to_array(input, '\n')[r] as block
  213. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n'), 1)) r
  214. ),
  215. cells(r INT, c INT, symbol TEXT) AS (
  216. SELECT r, c, substring(line, c, 1)
  217. FROM lines, generate_series(1, length(line)) c
  218. ),
  219. -- Where should we start each iteration from?
  220. -- From `east`, once it exits, but initially `cells`.
  221. round(r INT, c INT, symbol TEXT) AS (
  222. SELECT * FROM east
  223. UNION ALL SELECT * FROM cells
  224. EXCEPT ALL SELECT * FROM cells_delay
  225. ),
  226. north(r INT, c INT, symbol TEXT) AS (
  227. WITH MUTUALLY RECURSIVE
  228. start(r INT, c INT, symbol TEXT) AS (
  229. SELECT * FROM round
  230. ),
  231. northward(r INT, c INT, symbol TEXT) AS (
  232. SELECT * FROM northward
  233. -- Anyone on the move does so
  234. UNION ALL SELECT r - 1, c, 'O' FROM north_move
  235. EXCEPT ALL SELECT r - 1, c, '.' FROM north_move
  236. UNION ALL SELECT r, c, '.' FROM north_move
  237. EXCEPT ALL SELECT r, c, 'O' FROM north_move
  238. -- Second time around, the above cancels and `east` is non-empty.
  239. UNION ALL SELECT * FROM start
  240. EXCEPT ALL SELECT * FROM start_delay
  241. ),
  242. -- Each 'O' with a '.' in front of them will move.
  243. north_move(r INT, c INT) AS (
  244. SELECT n1.r, n1.c
  245. FROM northward n1, northward n2
  246. WHERE n1.symbol = 'O'
  247. AND n1.r = n2.r + 1
  248. AND n1.c = n2.c
  249. AND n2.symbol = '.'
  250. ),
  251. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  252. SELECT * FROM northward
  253. ),
  254. west(r INT, c INT, symbol TEXT) AS (
  255. WITH MUTUALLY RECURSIVE
  256. start(r INT, c INT, symbol TEXT) AS (
  257. SELECT * FROM north
  258. ),
  259. westward(r INT, c INT, symbol TEXT) AS (
  260. SELECT * FROM westward
  261. -- Anyone on the move does so
  262. UNION ALL SELECT r, c - 1, 'O' FROM west_move
  263. EXCEPT ALL SELECT r, c - 1, '.' FROM west_move
  264. UNION ALL SELECT r, c, '.' FROM west_move
  265. EXCEPT ALL SELECT r, c, 'O' FROM west_move
  266. -- Initial state is cells, but not refreshed each round.
  267. UNION ALL SELECT * FROM start
  268. EXCEPT ALL SELECT * FROM start_delay
  269. ),
  270. -- Each 'O' with a '.' in front of them will move.
  271. west_move(r INT, c INT) AS (
  272. SELECT w1.r, w1.c
  273. FROM westward w1, westward w2
  274. WHERE w1.symbol = 'O'
  275. AND w1.r = w2.r
  276. AND w1.c = w2.c + 1
  277. AND w2.symbol = '.'
  278. ),
  279. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  280. SELECT * FROM westward
  281. ),
  282. south(r INT, c INT, symbol TEXT) AS (
  283. WITH MUTUALLY RECURSIVE
  284. start(r INT, c INT, symbol TEXT) AS (
  285. SELECT * FROM west
  286. ),
  287. southward(r INT, c INT, symbol TEXT) AS (
  288. SELECT * FROM southward
  289. -- Anyone on the move does so
  290. UNION ALL SELECT r + 1, c, 'O' FROM south_move
  291. EXCEPT ALL SELECT r + 1, c, '.' FROM south_move
  292. UNION ALL SELECT r, c, '.' FROM south_move
  293. EXCEPT ALL SELECT r, c, 'O' FROM south_move
  294. -- Initial state is cells, but not refreshed each round.
  295. UNION ALL SELECT * FROM start
  296. EXCEPT ALL SELECT * FROM start_delay
  297. ),
  298. -- Each 'O' with a '.' in front of them will move.
  299. south_move(r INT, c INT) AS (
  300. SELECT s1.r, s1.c
  301. FROM southward s1, southward s2
  302. WHERE s1.symbol = 'O'
  303. AND s1.r = s2.r - 1
  304. AND s1.c = s2.c
  305. AND s2.symbol = '.'
  306. ),
  307. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  308. SELECT * FROM southward
  309. ),
  310. east(r INT, c INT, symbol TEXT) AS (
  311. WITH MUTUALLY RECURSIVE
  312. start(r INT, c INT, symbol TEXT) AS (
  313. SELECT * FROM south
  314. ),
  315. eastward(r INT, c INT, symbol TEXT) AS (
  316. SELECT * FROM eastward
  317. -- Anyone on the move does so
  318. UNION ALL SELECT r, c + 1, 'O' FROM east_move
  319. EXCEPT ALL SELECT r, c + 1, '.' FROM east_move
  320. UNION ALL SELECT r, c, '.' FROM east_move
  321. EXCEPT ALL SELECT r, c, 'O' FROM east_move
  322. -- Initial state is cells, but not refreshed each round.
  323. UNION ALL SELECT * FROM start
  324. EXCEPT ALL SELECT * FROM start_delay
  325. ),
  326. -- Each 'O' with a '.' in front of them will move.
  327. east_move(r INT, c INT) AS (
  328. SELECT e1.r, e1.c
  329. FROM eastward e1, eastward e2
  330. WHERE e1.symbol = 'O'
  331. AND e1.r = e2.r
  332. AND e1.c = e2.c - 1
  333. AND e2.symbol = '.'
  334. ),
  335. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  336. SELECT * FROM eastward
  337. ),
  338. output (r INT, line TEXT) AS (
  339. SELECT r, string_agg(symbol, ' ' ORDER BY c)
  340. FROM round
  341. GROUP BY r
  342. ),
  343. transitions(source TEXT, target TEXT) AS (
  344. SELECT
  345. (SELECT string_agg(symbol, '' ORDER BY r, c) FROM round),
  346. (SELECT string_agg(symbol, '' ORDER BY r, c) FROM east)
  347. UNION ALL
  348. SELECT * FROM transitions
  349. ),
  350. part2(part2 BIGINT) AS (
  351. SELECT SUM(1 + (SELECT MAX(r) FROM lines) - r)
  352. FROM east
  353. WHERE symbol = 'O'
  354. ),
  355. cells_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM cells )
  356. -- SELECT count, COUNT(*)
  357. -- FROM (
  358. -- SELECT source, target, COUNT(*) count
  359. -- FROM transitions
  360. -- GROUP BY source, target)
  361. -- GROUP BY count;
  362. -- SELECT * FROM output ORDER BY r;
  363. SELECT * FROM part2;
  364. ----
  365. 105
  366. query T multiline
  367. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  368. WITH MUTUALLY RECURSIVE (RETURN AT RECURSION LIMIT 142)
  369. lines(r INT, line TEXT) AS (
  370. SELECT r, regexp_split_to_array(input, '\n')[r] as block
  371. FROM input, generate_series(1, array_length(regexp_split_to_array(input, '\n'), 1)) r
  372. ),
  373. cells(r INT, c INT, symbol TEXT) AS (
  374. SELECT r, c, substring(line, c, 1)
  375. FROM lines, generate_series(1, length(line)) c
  376. ),
  377. -- Where should we start each iteration from?
  378. -- From `east`, once it exits, but initially `cells`.
  379. round(r INT, c INT, symbol TEXT) AS (
  380. SELECT * FROM east
  381. UNION ALL SELECT * FROM cells
  382. EXCEPT ALL SELECT * FROM cells_delay
  383. ),
  384. north(r INT, c INT, symbol TEXT) AS (
  385. WITH MUTUALLY RECURSIVE
  386. start(r INT, c INT, symbol TEXT) AS (
  387. SELECT * FROM round
  388. ),
  389. northward(r INT, c INT, symbol TEXT) AS (
  390. SELECT * FROM northward
  391. -- Anyone on the move does so
  392. UNION ALL SELECT r - 1, c, 'O' FROM north_move
  393. EXCEPT ALL SELECT r - 1, c, '.' FROM north_move
  394. UNION ALL SELECT r, c, '.' FROM north_move
  395. EXCEPT ALL SELECT r, c, 'O' FROM north_move
  396. -- Second time around, the above cancels and `east` is non-empty.
  397. UNION ALL SELECT * FROM start
  398. EXCEPT ALL SELECT * FROM start_delay
  399. ),
  400. -- Each 'O' with a '.' in front of them will move.
  401. north_move(r INT, c INT) AS (
  402. SELECT n1.r, n1.c
  403. FROM northward n1, northward n2
  404. WHERE n1.symbol = 'O'
  405. AND n1.r = n2.r + 1
  406. AND n1.c = n2.c
  407. AND n2.symbol = '.'
  408. ),
  409. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  410. SELECT * FROM northward
  411. ),
  412. west(r INT, c INT, symbol TEXT) AS (
  413. WITH MUTUALLY RECURSIVE
  414. start(r INT, c INT, symbol TEXT) AS (
  415. SELECT * FROM north
  416. ),
  417. westward(r INT, c INT, symbol TEXT) AS (
  418. SELECT * FROM westward
  419. -- Anyone on the move does so
  420. UNION ALL SELECT r, c - 1, 'O' FROM west_move
  421. EXCEPT ALL SELECT r, c - 1, '.' FROM west_move
  422. UNION ALL SELECT r, c, '.' FROM west_move
  423. EXCEPT ALL SELECT r, c, 'O' FROM west_move
  424. -- Initial state is cells, but not refreshed each round.
  425. UNION ALL SELECT * FROM start
  426. EXCEPT ALL SELECT * FROM start_delay
  427. ),
  428. -- Each 'O' with a '.' in front of them will move.
  429. west_move(r INT, c INT) AS (
  430. SELECT w1.r, w1.c
  431. FROM westward w1, westward w2
  432. WHERE w1.symbol = 'O'
  433. AND w1.r = w2.r
  434. AND w1.c = w2.c + 1
  435. AND w2.symbol = '.'
  436. ),
  437. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  438. SELECT * FROM westward
  439. ),
  440. south(r INT, c INT, symbol TEXT) AS (
  441. WITH MUTUALLY RECURSIVE
  442. start(r INT, c INT, symbol TEXT) AS (
  443. SELECT * FROM west
  444. ),
  445. southward(r INT, c INT, symbol TEXT) AS (
  446. SELECT * FROM southward
  447. -- Anyone on the move does so
  448. UNION ALL SELECT r + 1, c, 'O' FROM south_move
  449. EXCEPT ALL SELECT r + 1, c, '.' FROM south_move
  450. UNION ALL SELECT r, c, '.' FROM south_move
  451. EXCEPT ALL SELECT r, c, 'O' FROM south_move
  452. -- Initial state is cells, but not refreshed each round.
  453. UNION ALL SELECT * FROM start
  454. EXCEPT ALL SELECT * FROM start_delay
  455. ),
  456. -- Each 'O' with a '.' in front of them will move.
  457. south_move(r INT, c INT) AS (
  458. SELECT s1.r, s1.c
  459. FROM southward s1, southward s2
  460. WHERE s1.symbol = 'O'
  461. AND s1.r = s2.r - 1
  462. AND s1.c = s2.c
  463. AND s2.symbol = '.'
  464. ),
  465. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  466. SELECT * FROM southward
  467. ),
  468. east(r INT, c INT, symbol TEXT) AS (
  469. WITH MUTUALLY RECURSIVE
  470. start(r INT, c INT, symbol TEXT) AS (
  471. SELECT * FROM south
  472. ),
  473. eastward(r INT, c INT, symbol TEXT) AS (
  474. SELECT * FROM eastward
  475. -- Anyone on the move does so
  476. UNION ALL SELECT r, c + 1, 'O' FROM east_move
  477. EXCEPT ALL SELECT r, c + 1, '.' FROM east_move
  478. UNION ALL SELECT r, c, '.' FROM east_move
  479. EXCEPT ALL SELECT r, c, 'O' FROM east_move
  480. -- Initial state is cells, but not refreshed each round.
  481. UNION ALL SELECT * FROM start
  482. EXCEPT ALL SELECT * FROM start_delay
  483. ),
  484. -- Each 'O' with a '.' in front of them will move.
  485. east_move(r INT, c INT) AS (
  486. SELECT e1.r, e1.c
  487. FROM eastward e1, eastward e2
  488. WHERE e1.symbol = 'O'
  489. AND e1.r = e2.r
  490. AND e1.c = e2.c - 1
  491. AND e2.symbol = '.'
  492. ),
  493. start_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM start )
  494. SELECT * FROM eastward
  495. ),
  496. output (r INT, line TEXT) AS (
  497. SELECT r, string_agg(symbol, ' ' ORDER BY c)
  498. FROM round
  499. GROUP BY r
  500. ),
  501. transitions(source TEXT, target TEXT) AS (
  502. SELECT
  503. (SELECT string_agg(symbol, '' ORDER BY r, c) FROM round),
  504. (SELECT string_agg(symbol, '' ORDER BY r, c) FROM east)
  505. UNION ALL
  506. SELECT * FROM transitions
  507. ),
  508. part2(part2 BIGINT) AS (
  509. SELECT SUM(1 + (SELECT MAX(r) FROM lines) - r)
  510. FROM east
  511. WHERE symbol = 'O'
  512. ),
  513. cells_delay(r INT, c INT, symbol TEXT) AS ( SELECT * FROM cells )
  514. -- SELECT count, COUNT(*)
  515. -- FROM (
  516. -- SELECT source, target, COUNT(*) count
  517. -- FROM transitions
  518. -- GROUP BY source, target)
  519. -- GROUP BY count;
  520. -- SELECT * FROM output ORDER BY r;
  521. SELECT * FROM part2;
  522. ----
  523. Explained Query:
  524. With
  525. cte l0 =
  526. Project (#1, #2) // { arity: 2 }
  527. Map (array_index(regexp_split_to_array["\n", case_insensitive=false](#0{input}), integer_to_bigint(#1{r}))) // { arity: 3 }
  528. FlatMap generate_series(1, (regexp_split_to_array["\n", case_insensitive=false](#0{input}) array_length 1), 1) // { arity: 2 }
  529. ReadStorage materialize.public.input // { arity: 1 }
  530. cte l1 =
  531. Reduce aggregates=[max(#0{r})] // { arity: 1 }
  532. Project (#0) // { arity: 1 }
  533. Get l0 // { arity: 2 }
  534. cte l2 =
  535. Union // { arity: 1 }
  536. Get l1 // { arity: 1 }
  537. Map (null) // { arity: 1 }
  538. Union // { arity: 0 }
  539. Negate // { arity: 0 }
  540. Project () // { arity: 0 }
  541. Get l1 // { arity: 1 }
  542. Constant // { arity: 0 }
  543. - ()
  544. cte l3 =
  545. Project (#0, #2, #3) // { arity: 3 }
  546. Map (substr(#1{line}, #2{c}, 1)) // { arity: 4 }
  547. FlatMap generate_series(1, char_length(#1{line}), 1) // { arity: 3 }
  548. Get l0 // { arity: 2 }
  549. Return // { arity: 1 }
  550. With Mutually Recursive
  551. cte [recursion_limit=142, return_at_limit] l4 =
  552. Threshold // { arity: 3 }
  553. Union // { arity: 3 }
  554. Get l20 // { arity: 3 }
  555. Get l3 // { arity: 3 }
  556. Negate // { arity: 3 }
  557. Get l22 // { arity: 3 }
  558. cte l8 =
  559. With Mutually Recursive
  560. cte l5 =
  561. Threshold // { arity: 3 }
  562. Union // { arity: 3 }
  563. Threshold // { arity: 3 }
  564. Union // { arity: 3 }
  565. Threshold // { arity: 3 }
  566. Union // { arity: 3 }
  567. Get l5 // { arity: 3 }
  568. Project (#2, #1, #3) // { arity: 3 }
  569. Map ((#0{r} - 1), "O") // { arity: 4 }
  570. Get l6 // { arity: 2 }
  571. Negate // { arity: 3 }
  572. Project (#2, #1, #3) // { arity: 3 }
  573. Map ((#0{r} - 1), ".") // { arity: 4 }
  574. Get l6 // { arity: 2 }
  575. Map (".") // { arity: 3 }
  576. Get l6 // { arity: 2 }
  577. Negate // { arity: 3 }
  578. Map ("O") // { arity: 3 }
  579. Get l6 // { arity: 2 }
  580. Get l4 // { arity: 3 }
  581. Negate // { arity: 3 }
  582. Get l7 // { arity: 3 }
  583. cte l6 =
  584. Project (#0, #1) // { arity: 2 }
  585. Join on=(#0{r} = (#2{r} + 1) AND #1{c} = #3{c}) type=differential // { arity: 4 }
  586. implementation
  587. %0:l5[#1{c}, #0{r}]KKef » %1:l5[#1{c}, (#0{r} + 1)]KKef
  588. ArrangeBy keys=[[#1{c}, #0{r}]] // { arity: 2 }
  589. Project (#0, #1) // { arity: 2 }
  590. Filter (#2{symbol} = "O") // { arity: 3 }
  591. Get l5 // { arity: 3 }
  592. ArrangeBy keys=[[#1{c}, (#0{r} + 1)]] // { arity: 2 }
  593. Project (#0, #1) // { arity: 2 }
  594. Filter (#2{symbol} = ".") // { arity: 3 }
  595. Get l5 // { arity: 3 }
  596. cte l7 =
  597. Get l4 // { arity: 3 }
  598. Return // { arity: 3 }
  599. Get l5 // { arity: 3 }
  600. cte l12 =
  601. With Mutually Recursive
  602. cte l9 =
  603. Threshold // { arity: 3 }
  604. Union // { arity: 3 }
  605. Threshold // { arity: 3 }
  606. Union // { arity: 3 }
  607. Threshold // { arity: 3 }
  608. Union // { arity: 3 }
  609. Get l9 // { arity: 3 }
  610. Project (#0, #2, #3) // { arity: 3 }
  611. Map ((#1{c} - 1), "O") // { arity: 4 }
  612. Get l10 // { arity: 2 }
  613. Negate // { arity: 3 }
  614. Project (#0, #2, #3) // { arity: 3 }
  615. Map ((#1{c} - 1), ".") // { arity: 4 }
  616. Get l10 // { arity: 2 }
  617. Map (".") // { arity: 3 }
  618. Get l10 // { arity: 2 }
  619. Negate // { arity: 3 }
  620. Map ("O") // { arity: 3 }
  621. Get l10 // { arity: 2 }
  622. Get l8 // { arity: 3 }
  623. Negate // { arity: 3 }
  624. Get l11 // { arity: 3 }
  625. cte l10 =
  626. Project (#0, #1) // { arity: 2 }
  627. Join on=(#0{r} = #2{r} AND #1{c} = (#3{c} + 1)) type=differential // { arity: 4 }
  628. implementation
  629. %0:l9[#0{r}, #1{c}]KKef » %1:l9[#0{r}, (#1{c} + 1)]KKef
  630. ArrangeBy keys=[[#0{r}, #1{c}]] // { arity: 2 }
  631. Project (#0, #1) // { arity: 2 }
  632. Filter (#2{symbol} = "O") // { arity: 3 }
  633. Get l9 // { arity: 3 }
  634. ArrangeBy keys=[[#0{r}, (#1{c} + 1)]] // { arity: 2 }
  635. Project (#0, #1) // { arity: 2 }
  636. Filter (#2{symbol} = ".") // { arity: 3 }
  637. Get l9 // { arity: 3 }
  638. cte l11 =
  639. Get l8 // { arity: 3 }
  640. Return // { arity: 3 }
  641. Get l9 // { arity: 3 }
  642. cte l16 =
  643. With Mutually Recursive
  644. cte l13 =
  645. Threshold // { arity: 3 }
  646. Union // { arity: 3 }
  647. Threshold // { arity: 3 }
  648. Union // { arity: 3 }
  649. Threshold // { arity: 3 }
  650. Union // { arity: 3 }
  651. Get l13 // { arity: 3 }
  652. Project (#2, #1, #3) // { arity: 3 }
  653. Map ((#0{r} + 1), "O") // { arity: 4 }
  654. Get l14 // { arity: 2 }
  655. Negate // { arity: 3 }
  656. Project (#2, #1, #3) // { arity: 3 }
  657. Map ((#0{r} + 1), ".") // { arity: 4 }
  658. Get l14 // { arity: 2 }
  659. Map (".") // { arity: 3 }
  660. Get l14 // { arity: 2 }
  661. Negate // { arity: 3 }
  662. Map ("O") // { arity: 3 }
  663. Get l14 // { arity: 2 }
  664. Get l12 // { arity: 3 }
  665. Negate // { arity: 3 }
  666. Get l15 // { arity: 3 }
  667. cte l14 =
  668. Project (#0, #1) // { arity: 2 }
  669. Join on=(#0{r} = (#2{r} - 1) AND #1{c} = #3{c}) type=differential // { arity: 4 }
  670. implementation
  671. %0:l13[#1{c}, #0{r}]KKef » %1:l13[#1{c}, (#0{r} - 1)]KKef
  672. ArrangeBy keys=[[#1{c}, #0{r}]] // { arity: 2 }
  673. Project (#0, #1) // { arity: 2 }
  674. Filter (#2{symbol} = "O") // { arity: 3 }
  675. Get l13 // { arity: 3 }
  676. ArrangeBy keys=[[#1{c}, (#0{r} - 1)]] // { arity: 2 }
  677. Project (#0, #1) // { arity: 2 }
  678. Filter (#2{symbol} = ".") // { arity: 3 }
  679. Get l13 // { arity: 3 }
  680. cte l15 =
  681. Get l12 // { arity: 3 }
  682. Return // { arity: 3 }
  683. Get l13 // { arity: 3 }
  684. cte [recursion_limit=142, return_at_limit] l20 =
  685. With Mutually Recursive
  686. cte l17 =
  687. Threshold // { arity: 3 }
  688. Union // { arity: 3 }
  689. Threshold // { arity: 3 }
  690. Union // { arity: 3 }
  691. Threshold // { arity: 3 }
  692. Union // { arity: 3 }
  693. Get l17 // { arity: 3 }
  694. Project (#0, #2, #3) // { arity: 3 }
  695. Map ((#1{c} + 1), "O") // { arity: 4 }
  696. Get l18 // { arity: 2 }
  697. Negate // { arity: 3 }
  698. Project (#0, #2, #3) // { arity: 3 }
  699. Map ((#1{c} + 1), ".") // { arity: 4 }
  700. Get l18 // { arity: 2 }
  701. Map (".") // { arity: 3 }
  702. Get l18 // { arity: 2 }
  703. Negate // { arity: 3 }
  704. Map ("O") // { arity: 3 }
  705. Get l18 // { arity: 2 }
  706. Get l16 // { arity: 3 }
  707. Negate // { arity: 3 }
  708. Get l19 // { arity: 3 }
  709. cte l18 =
  710. Project (#0, #1) // { arity: 2 }
  711. Join on=(#0{r} = #2{r} AND #1{c} = (#3{c} - 1)) type=differential // { arity: 4 }
  712. implementation
  713. %0:l17[#0{r}, #1{c}]KKef » %1:l17[#0{r}, (#1{c} - 1)]KKef
  714. ArrangeBy keys=[[#0{r}, #1{c}]] // { arity: 2 }
  715. Project (#0, #1) // { arity: 2 }
  716. Filter (#2{symbol} = "O") // { arity: 3 }
  717. Get l17 // { arity: 3 }
  718. ArrangeBy keys=[[#0{r}, (#1{c} - 1)]] // { arity: 2 }
  719. Project (#0, #1) // { arity: 2 }
  720. Filter (#2{symbol} = ".") // { arity: 3 }
  721. Get l17 // { arity: 3 }
  722. cte l19 =
  723. Get l16 // { arity: 3 }
  724. Return // { arity: 3 }
  725. Get l17 // { arity: 3 }
  726. cte l21 =
  727. Reduce aggregates=[sum(((1 + #1{max}) - #0{r}))] // { arity: 1 }
  728. CrossJoin type=differential // { arity: 2 }
  729. implementation
  730. %1[×]U » %0:l20[×]ef
  731. ArrangeBy keys=[[]] // { arity: 1 }
  732. Project (#0) // { arity: 1 }
  733. Filter (#2{symbol} = "O") // { arity: 3 }
  734. Get l20 // { arity: 3 }
  735. ArrangeBy keys=[[]] // { arity: 1 }
  736. Union // { arity: 1 }
  737. Get l2 // { arity: 1 }
  738. Map (null) // { arity: 1 }
  739. Union // { arity: 0 }
  740. Negate // { arity: 0 }
  741. Project () // { arity: 0 }
  742. Get l2 // { arity: 1 }
  743. Constant // { arity: 0 }
  744. - ()
  745. cte [recursion_limit=142, return_at_limit] l22 =
  746. Get l3 // { arity: 3 }
  747. Return // { arity: 1 }
  748. Union // { arity: 1 }
  749. Get l21 // { arity: 1 }
  750. Map (null) // { arity: 1 }
  751. Union // { arity: 0 }
  752. Negate // { arity: 0 }
  753. Project () // { arity: 0 }
  754. Get l21 // { arity: 1 }
  755. Constant // { arity: 0 }
  756. - ()
  757. Source materialize.public.input
  758. Target cluster: quickstart
  759. EOF