aoc_1203.slt 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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_1203.md
  10. mode cockroach
  11. statement ok
  12. CREATE TABLE input (input TEXT);
  13. statement ok
  14. INSERT INTO input VALUES (
  15. '...14...954......104...98..........11...222.........38.104....708..........................217..................330.................19..
  16. .......@...................*...............................*.664........677................@....459.........187..........73.............
  17. ....41............178.....398....*...548..495..........983.........99.........282......409........*...........$.248...............165...
  18. ......261......300...............704.&.......*.......*........9.65..904.....6....*773....=.....680../511...2*.....=..99*....*..../......
  19. ..........200..............398.......22...100...........&...........10.......*.......73.....833...*...........*......300.............22.
  20. ..................@.100....*...........*...............*....19...300.....*.................@....954.......................200...........
  21. .....-....&..@............828...........@268..844....534...................563.........409........$..........244.........722.286........');
  22. query II
  23. WITH MUTUALLY RECURSIVE
  24. -- PART 0
  25. -- Parse the input as lines of text with line numbers.
  26. lines(line TEXT, row_idx INT) AS (
  27. SELECT
  28. regexp_split_to_array(input, '\n')[row_idx],
  29. row_idx
  30. FROM
  31. input,
  32. generate_series(1, (SELECT COUNT(*)::INT FROM (SELECT regexp_split_to_table(input, '\n') FROM input))) as row_idx
  33. ),
  34. chars(symbol TEXT, row_idx INT, col_idx INT) AS (
  35. SELECT
  36. substring(line, start, 1),
  37. row_idx,
  38. start
  39. FROM
  40. lines,
  41. generate_series(1, length(line)) as start
  42. WHERE
  43. substring(line, start, 1) != '.'
  44. ),
  45. numerals(number TEXT, row_idx INT, col_idx INT) AS (
  46. SELECT symbol, row_idx, col_idx
  47. FROM chars
  48. WHERE symbol IN ( VALUES ('0'), ('1'), ('2'), ('3'), ('4'), ('5'), ('6'), ('7'), ('8'), ('9') )
  49. ),
  50. symbols(symbol TEXT, row_idx INT, col_idx INT) AS (
  51. SELECT symbol, row_idx, col_idx
  52. FROM chars
  53. WHERE symbol NOT IN ( VALUES ('0'), ('1'), ('2'), ('3'), ('4'), ('5'), ('6'), ('7'), ('8'), ('9') )
  54. ),
  55. -- PART 1
  56. -- Recursively build up ranges of numerals that are "active", in the sense of being adjacent to a symbol.
  57. -- Each range has an accumulated number (as a string), a row index, a column index and length of the run.
  58. active(number TEXT, row_idx INT, col_idx INT, length INT) AS (
  59. -- Base case: numerals adjacent to a symbol
  60. SELECT numerals.*, 1
  61. FROM
  62. numerals,
  63. symbols,
  64. generate_series(-1, 1) row_off,
  65. generate_series(-1, 1) col_off
  66. WHERE numerals.row_idx = symbols.row_idx + row_off
  67. AND numerals.col_idx = symbols.col_idx + col_off
  68. UNION
  69. -- Inductive case 1: Join to the left
  70. SELECT numerals.number || active.number, numerals.row_idx, numerals.col_idx, active.length + 1
  71. FROM numerals, active
  72. WHERE numerals.row_idx = active.row_idx
  73. AND numerals.col_idx = active.col_idx - 1
  74. UNION
  75. -- Inductive case 2: Join to the right
  76. SELECT active.number || numerals.number, numerals.row_idx, active.col_idx, active.length + 1
  77. FROM numerals, active
  78. WHERE numerals.row_idx = active.row_idx
  79. AND numerals.col_idx = active.col_idx + active.length
  80. ),
  81. parts(number INT, row_idx INT, col_idx INT, length INT) AS (
  82. SELECT active.number::INT, row_idx, col_idx, length
  83. FROM active
  84. WHERE (active.row_idx, active.col_idx-1) NOT IN (SELECT row_idx, col_idx FROM numerals)
  85. AND (active.row_idx, active.col_idx+length) NOT IN (SELECT row_idx, col_idx FROM numerals)
  86. ),
  87. part1(part1 BIGINT) AS ( SELECT SUM(parts.number::INT) FROM parts ),
  88. -- PART 2
  89. -- A "gear" is a `*` adjacent to exactly two part numbers. We want the sum over gears of their product.
  90. -- A gear is identified by a location, which we will want to attempt to join with part numbers.
  91. gear_adjacent(row_idx INT, col_idx INT, number INT, part_row INT, part_col INT) AS (
  92. SELECT DISTINCT symbols.row_idx, symbols.col_idx, parts.number, parts.row_idx, parts.col_idx
  93. FROM
  94. symbols,
  95. generate_series(-1, 1) gear_r_off,
  96. generate_series(-1, 1) gear_c_off,
  97. parts,
  98. generate_series(parts.col_idx, parts.col_idx + parts.length - 1) part_col
  99. WHERE symbols.symbol = '*'
  100. AND symbols.row_idx + gear_r_off = parts.row_idx
  101. AND symbols.col_idx + gear_c_off = part_col
  102. ),
  103. gears(row_idx INT, col_idx INT) AS (
  104. SELECT row_idx, col_idx
  105. FROM gear_adjacent
  106. GROUP BY row_idx, col_idx
  107. HAVING COUNT(*) = 2
  108. ),
  109. gear_products(row_idx INT, col_idx INT, product INT) AS (
  110. SELECT DISTINCT gears.row_idx, gears.col_idx, p1.number * p2.number
  111. FROM gears, gear_adjacent p1, gear_adjacent p2
  112. WHERE gears.row_idx = p1.row_idx
  113. AND gears.col_idx = p1.col_idx
  114. AND gears.row_idx = p2.row_idx
  115. AND gears.col_idx = p2.col_idx
  116. AND (p1.part_row != p2.part_row OR p1.part_col != p2.part_col)
  117. ),
  118. part2(part2 BIGINT) AS ( SELECT SUM(product) FROM gear_products)
  119. SELECT * FROM part1, part2;
  120. ----
  121. 11374 1587570
  122. query T multiline
  123. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  124. WITH MUTUALLY RECURSIVE
  125. -- PART 0
  126. -- Parse the input as lines of text with line numbers.
  127. lines(line TEXT, row_idx INT) AS (
  128. SELECT
  129. regexp_split_to_array(input, '\n')[row_idx],
  130. row_idx
  131. FROM
  132. input,
  133. generate_series(1, (SELECT COUNT(*)::INT FROM (SELECT regexp_split_to_table(input, '\n') FROM input))) as row_idx
  134. ),
  135. chars(symbol TEXT, row_idx INT, col_idx INT) AS (
  136. SELECT
  137. substring(line, start, 1),
  138. row_idx,
  139. start
  140. FROM
  141. lines,
  142. generate_series(1, length(line)) as start
  143. WHERE
  144. substring(line, start, 1) != '.'
  145. ),
  146. numerals(number TEXT, row_idx INT, col_idx INT) AS (
  147. SELECT symbol, row_idx, col_idx
  148. FROM chars
  149. WHERE symbol IN ( VALUES ('0'), ('1'), ('2'), ('3'), ('4'), ('5'), ('6'), ('7'), ('8'), ('9') )
  150. ),
  151. symbols(symbol TEXT, row_idx INT, col_idx INT) AS (
  152. SELECT symbol, row_idx, col_idx
  153. FROM chars
  154. WHERE symbol NOT IN ( VALUES ('0'), ('1'), ('2'), ('3'), ('4'), ('5'), ('6'), ('7'), ('8'), ('9') )
  155. ),
  156. -- PART 1
  157. -- Recursively build up ranges of numerals that are "active", in the sense of being adjacent to a symbol.
  158. -- Each range has an accumulated number (as a string), a row index, a column index and length of the run.
  159. active(number TEXT, row_idx INT, col_idx INT, length INT) AS (
  160. -- Base case: numerals adjacent to a symbol
  161. SELECT numerals.*, 1
  162. FROM
  163. numerals,
  164. symbols,
  165. generate_series(-1, 1) row_off,
  166. generate_series(-1, 1) col_off
  167. WHERE numerals.row_idx = symbols.row_idx + row_off
  168. AND numerals.col_idx = symbols.col_idx + col_off
  169. UNION
  170. -- Inductive case 1: Join to the left
  171. SELECT numerals.number || active.number, numerals.row_idx, numerals.col_idx, active.length + 1
  172. FROM numerals, active
  173. WHERE numerals.row_idx = active.row_idx
  174. AND numerals.col_idx = active.col_idx - 1
  175. UNION
  176. -- Inductive case 2: Join to the right
  177. SELECT active.number || numerals.number, numerals.row_idx, active.col_idx, active.length + 1
  178. FROM numerals, active
  179. WHERE numerals.row_idx = active.row_idx
  180. AND numerals.col_idx = active.col_idx + active.length
  181. ),
  182. parts(number INT, row_idx INT, col_idx INT, length INT) AS (
  183. SELECT active.number::INT, row_idx, col_idx, length
  184. FROM active
  185. WHERE (active.row_idx, active.col_idx-1) NOT IN (SELECT row_idx, col_idx FROM numerals)
  186. AND (active.row_idx, active.col_idx+length) NOT IN (SELECT row_idx, col_idx FROM numerals)
  187. ),
  188. part1(part1 BIGINT) AS ( SELECT SUM(parts.number::INT) FROM parts ),
  189. -- PART 2
  190. -- A "gear" is a `*` adjacent to exactly two part numbers. We want the sum over gears of their product.
  191. -- A gear is identified by a location, which we will want to attempt to join with part numbers.
  192. gear_adjacent(row_idx INT, col_idx INT, number INT, part_row INT, part_col INT) AS (
  193. SELECT DISTINCT symbols.row_idx, symbols.col_idx, parts.number, parts.row_idx, parts.col_idx
  194. FROM
  195. symbols,
  196. generate_series(-1, 1) gear_r_off,
  197. generate_series(-1, 1) gear_c_off,
  198. parts,
  199. generate_series(parts.col_idx, parts.col_idx + parts.length - 1) part_col
  200. WHERE symbols.symbol = '*'
  201. AND symbols.row_idx + gear_r_off = parts.row_idx
  202. AND symbols.col_idx + gear_c_off = part_col
  203. ),
  204. gears(row_idx INT, col_idx INT) AS (
  205. SELECT row_idx, col_idx
  206. FROM gear_adjacent
  207. GROUP BY row_idx, col_idx
  208. HAVING COUNT(*) = 2
  209. ),
  210. gear_products(row_idx INT, col_idx INT, product INT) AS (
  211. SELECT DISTINCT gears.row_idx, gears.col_idx, p1.number * p2.number
  212. FROM gears, gear_adjacent p1, gear_adjacent p2
  213. WHERE gears.row_idx = p1.row_idx
  214. AND gears.col_idx = p1.col_idx
  215. AND gears.row_idx = p2.row_idx
  216. AND gears.col_idx = p2.col_idx
  217. AND (p1.part_row != p2.part_row OR p1.part_col != p2.part_col)
  218. ),
  219. part2(part2 BIGINT) AS ( SELECT SUM(product) FROM gear_products)
  220. SELECT * FROM part1, part2;
  221. ----
  222. Explained Query:
  223. With
  224. cte l0 =
  225. Reduce aggregates=[count(*)] // { arity: 1 }
  226. Project () // { arity: 0 }
  227. FlatMap unnest_array(regexp_split_to_array["\n", case_insensitive=false](#0{input})) // { arity: 2 }
  228. ReadStorage materialize.public.input // { arity: 1 }
  229. cte l1 =
  230. Project (#0, #2, #3) // { arity: 3 }
  231. Filter (#3 != ".") // { arity: 4 }
  232. Map (substr(#1{line}, #2{start}, 1)) // { arity: 4 }
  233. FlatMap generate_series(1, char_length(#1{line}), 1) // { arity: 3 }
  234. Project (#1, #2) // { arity: 2 }
  235. Map (array_index(regexp_split_to_array["\n", case_insensitive=false](#0{input}), integer_to_bigint(#1{row_idx}))) // { arity: 3 }
  236. CrossJoin type=differential // { arity: 2 }
  237. implementation
  238. %0:input[×] » %1[×]
  239. ArrangeBy keys=[[]] // { arity: 1 }
  240. ReadStorage materialize.public.input // { arity: 1 }
  241. ArrangeBy keys=[[]] // { arity: 1 }
  242. Project (#1) // { arity: 1 }
  243. FlatMap generate_series(1, #0, 1) // { arity: 2 }
  244. Project (#1) // { arity: 1 }
  245. Map (bigint_to_integer(#0{count})) // { arity: 2 }
  246. Union // { arity: 1 }
  247. Get l0 // { arity: 1 }
  248. Map (0) // { arity: 1 }
  249. Union // { arity: 0 }
  250. Negate // { arity: 0 }
  251. Project () // { arity: 0 }
  252. Get l0 // { arity: 1 }
  253. Constant // { arity: 0 }
  254. - ()
  255. cte l2 =
  256. Distinct project=[#0] // { arity: 1 }
  257. Project (#2) // { arity: 1 }
  258. Get l1 // { arity: 3 }
  259. cte l3 =
  260. Distinct project=[#0] // { arity: 1 }
  261. Project (#0) // { arity: 1 }
  262. Filter (#0{symbol} = #1{right_col0_0}) // { arity: 2 }
  263. FlatMap wrap1("0", "1", "2", "3", "4", "5", "6", "7", "8", "9") // { arity: 2 }
  264. Get l2 // { arity: 1 }
  265. cte l4 =
  266. ArrangeBy keys=[[#2]] // { arity: 3 }
  267. Get l1 // { arity: 3 }
  268. cte l5 =
  269. Project (#0..=#2) // { arity: 3 }
  270. Join on=(#2 = #3) type=differential // { arity: 4 }
  271. implementation
  272. %1:l3[#0]UKA » %0:l4[#2]K
  273. Get l4 // { arity: 3 }
  274. ArrangeBy keys=[[#0]] // { arity: 1 }
  275. Get l3 // { arity: 1 }
  276. cte l6 =
  277. Project (#0..=#2) // { arity: 3 }
  278. Join on=(#2 = #3) type=differential // { arity: 4 }
  279. implementation
  280. %0:l4[#2]K » %1[#0]K
  281. Get l4 // { arity: 3 }
  282. ArrangeBy keys=[[#0]] // { arity: 1 }
  283. Union // { arity: 1 }
  284. Negate // { arity: 1 }
  285. Get l3 // { arity: 1 }
  286. Get l2 // { arity: 1 }
  287. cte l7 =
  288. ArrangeBy keys=[[]] // { arity: 1 }
  289. Constant // { arity: 1 }
  290. - (0)
  291. - (-1)
  292. - (1)
  293. cte l8 =
  294. ArrangeBy keys=[[#0{row_idx}, #1{col_idx}]] // { arity: 3 }
  295. Get l5 // { arity: 3 }
  296. Return // { arity: 2 }
  297. With Mutually Recursive
  298. cte l9 =
  299. Distinct project=[#0..=#3] // { arity: 4 }
  300. Union // { arity: 4 }
  301. Distinct project=[#0..=#3] // { arity: 4 }
  302. Union // { arity: 4 }
  303. Project (#2, #0, #1, #7) // { arity: 4 }
  304. Map (1) // { arity: 8 }
  305. Join on=(#0{row_idx} = (#3{row_idx} + #5{row_off}) AND #1{col_idx} = (#4{col_idx} + #6{col_off})) type=delta // { arity: 7 }
  306. implementation
  307. %0:l5 » %1:l6[×] » %2:l7[×] » %3:l7[×]
  308. %1:l6 » %0:l5[×] » %2:l7[×] » %3:l7[×]
  309. %2:l7 » %0:l5[×] » %1:l6[×] » %3:l7[×]
  310. %3:l7 » %0:l5[×] » %1:l6[×] » %2:l7[×]
  311. ArrangeBy keys=[[]] // { arity: 3 }
  312. Get l5 // { arity: 3 }
  313. ArrangeBy keys=[[]] // { arity: 2 }
  314. Project (#0, #1) // { arity: 2 }
  315. Get l6 // { arity: 3 }
  316. Get l7 // { arity: 1 }
  317. Get l7 // { arity: 1 }
  318. Project (#7, #0, #1, #8) // { arity: 4 }
  319. Map ((#2{number} || #3{number}), (#6{length} + 1)) // { arity: 9 }
  320. Join on=(#0{row_idx} = #4{row_idx} AND #1{col_idx} = (#5{col_idx} - 1)) type=differential // { arity: 7 }
  321. implementation
  322. %0:l8[#0{row_idx}, #1{col_idx}]KK » %1:l9[#1{row_idx}, (#2{col_idx} - 1)]KK
  323. Get l8 // { arity: 3 }
  324. ArrangeBy keys=[[#1{row_idx}, (#2{col_idx} - 1)]] // { arity: 4 }
  325. Get l9 // { arity: 4 }
  326. Project (#7, #0, #5, #8) // { arity: 4 }
  327. Map ((#3{number} || #2{number}), (#6{length} + 1)) // { arity: 9 }
  328. Join on=(#0{row_idx} = #4{row_idx} AND #1{col_idx} = (#5{col_idx} + #6{length})) type=differential // { arity: 7 }
  329. implementation
  330. %0:l8[#0{row_idx}, #1{col_idx}]KK » %1:l9[#1{row_idx}, (#2{col_idx} + #3{length})]KK
  331. Get l8 // { arity: 3 }
  332. ArrangeBy keys=[[#1{row_idx}, (#2{col_idx} + #3{length})]] // { arity: 4 }
  333. Get l9 // { arity: 4 }
  334. Return // { arity: 2 }
  335. With
  336. cte l10 =
  337. Distinct project=[#0, #1] // { arity: 2 }
  338. Project (#1, #2) // { arity: 2 }
  339. Get l9 // { arity: 4 }
  340. cte l11 =
  341. ArrangeBy keys=[[#0{right_col0_4}, #1{right_col1_5}]] // { arity: 2 }
  342. Project (#0, #1) // { arity: 2 }
  343. Get l5 // { arity: 3 }
  344. cte l12 =
  345. Project (#0..=#3) // { arity: 4 }
  346. Join on=(#1 = #4 AND #2 = #5) type=differential // { arity: 6 }
  347. implementation
  348. %0:l9[#1, #2]KK » %1[#0, #1]KK
  349. ArrangeBy keys=[[#1, #2]] // { arity: 4 }
  350. Get l9 // { arity: 4 }
  351. ArrangeBy keys=[[#0, #1]] // { arity: 2 }
  352. Union // { arity: 2 }
  353. Negate // { arity: 2 }
  354. Distinct project=[#0, #1] // { arity: 2 }
  355. Project (#0, #1) // { arity: 2 }
  356. Join on=(#0{row_idx} = #2{right_col0_4} AND #3{right_col1_5} = (#1{col_idx} - 1)) type=differential // { arity: 4 }
  357. implementation
  358. %0:l10[#0{row_idx}, (#1{col_idx} - 1)]KK » %1:l11[#0{right_col0_4}, #1{right_col1_5}]KK
  359. ArrangeBy keys=[[#0{row_idx}, (#1{col_idx} - 1)]] // { arity: 2 }
  360. Get l10 // { arity: 2 }
  361. Get l11 // { arity: 2 }
  362. Get l10 // { arity: 2 }
  363. cte l13 =
  364. Distinct project=[#0..=#2] // { arity: 3 }
  365. Project (#1..=#3) // { arity: 3 }
  366. Get l12 // { arity: 4 }
  367. cte l14 =
  368. Project (#1..=#3, #7) // { arity: 4 }
  369. Map (text_to_integer(#0{number})) // { arity: 8 }
  370. Join on=(#1 = #4 AND #2 = #5 AND #3 = #6) type=differential // { arity: 7 }
  371. implementation
  372. %0:l12[#1..=#3]KKK » %1[#0..=#2]KKK
  373. ArrangeBy keys=[[#1..=#3]] // { arity: 4 }
  374. Get l12 // { arity: 4 }
  375. ArrangeBy keys=[[#0..=#2]] // { arity: 3 }
  376. Union // { arity: 3 }
  377. Negate // { arity: 3 }
  378. Distinct project=[#0..=#2] // { arity: 3 }
  379. Project (#0..=#2) // { arity: 3 }
  380. Join on=(#0{row_idx} = #3{right_col0_7} AND #4{right_col1_8} = (#1{col_idx} + #2{length})) type=differential // { arity: 5 }
  381. implementation
  382. %0:l13[#0{row_idx}, (#1{col_idx} + #2{length})]KK » %1:l11[#0{right_col0_7}, #1{right_col1_8}]KK
  383. ArrangeBy keys=[[#0{row_idx}, (#1{col_idx} + #2{length})]] // { arity: 3 }
  384. Get l13 // { arity: 3 }
  385. Get l11 // { arity: 2 }
  386. Get l13 // { arity: 3 }
  387. cte l15 =
  388. Reduce aggregates=[sum(#0{number})] // { arity: 1 }
  389. Project (#3) // { arity: 1 }
  390. Get l14 // { arity: 4 }
  391. cte l16 =
  392. ArrangeBy keys=[[]] // { arity: 1 }
  393. Constant // { arity: 1 }
  394. - (0)
  395. - (-1)
  396. - (1)
  397. cte l17 =
  398. Distinct project=[#0, #1, #4, #2, #3] // { arity: 5 }
  399. Project (#0, #1, #3, #4, #6) // { arity: 5 }
  400. Filter (#7{part_col} = (#1{col_idx} + #2{gear_c_off})) // { arity: 8 }
  401. FlatMap generate_series(#4{col_idx}, ((#4{col_idx} + #5{length}) - 1), 1) // { arity: 8 }
  402. Project (#0, #1, #3..=#7) // { arity: 7 }
  403. Join on=(#4{row_idx} = (#0{row_idx} + #2{gear_r_off})) type=delta // { arity: 8 }
  404. implementation
  405. %0:l6 » %1:l16[×] » %3:l14[#0{row_idx}]K » %2:l16[×]
  406. %1:l16 » %0:l6[×]ef » %3:l14[#0{row_idx}]K » %2:l16[×]
  407. %2:l16 » %0:l6[×]ef » %1:l16[×] » %3:l14[#0{row_idx}]K
  408. %3:l14 » %0:l6[×]ef » %1:l16[×] » %2:l16[×]
  409. ArrangeBy keys=[[]] // { arity: 2 }
  410. Project (#0, #1) // { arity: 2 }
  411. Filter (#2{symbol} = "*") // { arity: 3 }
  412. Get l6 // { arity: 3 }
  413. Get l16 // { arity: 1 }
  414. Get l16 // { arity: 1 }
  415. ArrangeBy keys=[[#0{row_idx}]] // { arity: 4 }
  416. Get l14 // { arity: 4 }
  417. cte l18 =
  418. ArrangeBy keys=[[#0{row_idx}, #1{col_idx}]] // { arity: 5 }
  419. Get l17 // { arity: 5 }
  420. cte l19 =
  421. Reduce aggregates=[sum(#0{product})] // { arity: 1 }
  422. Project (#2) // { arity: 1 }
  423. Distinct project=[#0, #1, (#2{number} * #3{number})] // { arity: 3 }
  424. Project (#0, #1, #5, #10) // { arity: 4 }
  425. Filter (#2{count} = 2) AND ((#6{part_row} != #11{part_row}) OR (#7{part_col} != #12{part_col})) // { arity: 13 }
  426. Join on=(#0{row_idx} = #3{row_idx} = #8{row_idx} AND #1{col_idx} = #4{col_idx} = #9{col_idx}) type=delta // { arity: 13 }
  427. implementation
  428. %0 » %1:l18[#0{row_idx}, #1{col_idx}]KK » %2:l18[#0{row_idx}, #1{col_idx}]KK
  429. %1:l18 » %0[#0, #1]UKKAef » %2:l18[#0{row_idx}, #1{col_idx}]KK
  430. %2:l18 » %0[#0, #1]UKKAef » %1:l18[#0{row_idx}, #1{col_idx}]KK
  431. ArrangeBy keys=[[#0, #1]] // { arity: 3 }
  432. Reduce group_by=[#0, #1] aggregates=[count(*)] // { arity: 3 }
  433. Project (#0, #1) // { arity: 2 }
  434. Get l17 // { arity: 5 }
  435. Get l18 // { arity: 5 }
  436. Get l18 // { arity: 5 }
  437. Return // { arity: 2 }
  438. CrossJoin type=differential // { arity: 2 }
  439. implementation
  440. %0[×]U » %1[×]U
  441. ArrangeBy keys=[[]] // { arity: 1 }
  442. Union // { arity: 1 }
  443. Get l15 // { arity: 1 }
  444. Map (null) // { arity: 1 }
  445. Union // { arity: 0 }
  446. Negate // { arity: 0 }
  447. Project () // { arity: 0 }
  448. Get l15 // { arity: 1 }
  449. Constant // { arity: 0 }
  450. - ()
  451. ArrangeBy keys=[[]] // { arity: 1 }
  452. Union // { arity: 1 }
  453. Get l19 // { arity: 1 }
  454. Map (null) // { arity: 1 }
  455. Union // { arity: 0 }
  456. Negate // { arity: 0 }
  457. Project () // { arity: 0 }
  458. Get l19 // { arity: 1 }
  459. Constant // { arity: 0 }
  460. - ()
  461. Source materialize.public.input
  462. Target cluster: quickstart
  463. EOF