aoc_1202.slt 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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_1202.md
  10. mode cockroach
  11. statement ok
  12. CREATE TABLE input (input TEXT);
  13. statement ok
  14. INSERT INTO input VALUES ('Game 1: 1 red, 4 green, 4 blue; 3 red, 4 blue; 2 red, 1 green; 1 green, 1 red');
  15. statement ok
  16. INSERT INTO input VALUES ('Game 2: 20 green, 1 red; 1 blue, 4 red; 1 green, 1 red, 1 blue; 1 green, 1 red, 1 blue');
  17. statement ok
  18. INSERT INTO input VALUES ('Game 3: 8 red, 1 blue, 5 green; 9 red, 3 blue, 3 green; 3 green, 4 red');
  19. statement ok
  20. INSERT INTO input VALUES ('Game 4: 0 blue, 8 red, 4 green; 7 green, 8 blue, 9 red; 2 green, 5 red, 1 blue');
  21. statement ok
  22. INSERT INTO input VALUES ('Game 5: 20 red, 10 blue, 9 green; 2 blue, 3 red, 7 green; 1 green, 3 blue');
  23. statement ok
  24. CREATE TABLE aoc_1202 (game_id TEXT, set_id TEXT, green_cnt INT, red_cnt INT, blue_cnt INT);
  25. statement ok
  26. INSERT INTO aoc_1202 VALUES ('Game 1', 'set_0', 4, 1, 4), ('Game 1', 'set_1', 0, 3, 4), ('Game 1', 'set_2', 1, 2, 0), ('Game 1', 'set_3', 1, 1, 0);
  27. statement ok
  28. INSERT INTO aoc_1202 VALUES ('Game 2', 'set_0', 20, 1, 0), ('Game 2', 'set_1', 0, 4, 1), ('Game 2', 'set_2', 1, 1, 1), ('Game 2', 'set_3', 1, 1, 1);
  29. statement ok
  30. INSERT INTO aoc_1202 VALUES ('Game 3', 'set_0', 5, 8, 1), ('Game 3', 'set_1', 3, 9, 3), ('Game 3', 'set_2', 3, 4, 0);
  31. statement ok
  32. INSERT INTO aoc_1202 VALUES ('Game 4', 'set_0', 4, 8, 0), ('Game 4', 'set_1', 7, 9, 8), ('Game 4', 'set_2', 2, 5, 1);
  33. statement ok
  34. INSERT INTO aoc_1202 VALUES ('Game 5', 'set_0', 9, 20, 10), ('Game 5', 'set_1', 7, 3, 2), ('Game 5', 'set_2', 1, 0, 3);
  35. query I
  36. WITH game_cnt AS (
  37. SELECT split_part(game_id,' ', 2)::int AS game_id,
  38. COUNT(set_id) AS total_set_cnt,
  39. COUNT(set_id) FILTER (WHERE (green_cnt <= 13) AND (red_cnt <= 12) AND (blue_cnt <= 14)) AS possible_set_cnt
  40. FROM aoc_1202
  41. GROUP BY game_id
  42. )
  43. SELECT SUM(game_id) FROM game_cnt WHERE total_set_cnt = possible_set_cnt;
  44. ----
  45. 8
  46. query T multiline
  47. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  48. WITH game_cnt AS (
  49. SELECT split_part(game_id,' ', 2)::int AS game_id,
  50. COUNT(set_id) AS total_set_cnt,
  51. COUNT(set_id) FILTER (WHERE (green_cnt <= 13) AND (red_cnt <= 12) AND (blue_cnt <= 14)) AS possible_set_cnt
  52. FROM aoc_1202
  53. GROUP BY game_id
  54. )
  55. SELECT SUM(game_id) FROM game_cnt WHERE total_set_cnt = possible_set_cnt;
  56. ----
  57. Explained Query:
  58. With
  59. cte l0 =
  60. Reduce aggregates=[sum(text_to_integer(split_string(#0{game_id}, " ", 2)))] // { arity: 1 }
  61. Project (#0{game_id}) // { arity: 1 }
  62. Filter (#1{count_set_id} = #2{count}) // { arity: 3 }
  63. Reduce group_by=[#0{game_id}] aggregates=[count(#1{set_id}), count(case when ((#2{green_cnt} <= 13) AND (#3{red_cnt} <= 12) AND (#4{blue_cnt} <= 14)) then #1{set_id} else null end)] // { arity: 3 }
  64. ReadStorage materialize.public.aoc_1202 // { arity: 5 }
  65. Return // { arity: 1 }
  66. Union // { arity: 1 }
  67. Get l0 // { arity: 1 }
  68. Map (null) // { arity: 1 }
  69. Union // { arity: 0 }
  70. Negate // { arity: 0 }
  71. Project () // { arity: 0 }
  72. Get l0 // { arity: 1 }
  73. Constant // { arity: 0 }
  74. - ()
  75. Source materialize.public.aoc_1202
  76. Target cluster: quickstart
  77. EOF
  78. query I
  79. WITH game_min AS (
  80. SELECT split_part(game_id,' ', 2)::int AS game_id,
  81. MAX(green_cnt) AS green_min,
  82. MAX(red_cnt) AS red_min,
  83. MAX(blue_cnt) AS blue_min
  84. FROM aoc_1202
  85. GROUP BY split_part(game_id,' ', 2)::int
  86. )
  87. SELECT SUM(green_min*red_min*blue_min) FROM game_min;
  88. ----
  89. 2567
  90. query T multiline
  91. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  92. WITH game_min AS (
  93. SELECT split_part(game_id,' ', 2)::int AS game_id,
  94. MAX(green_cnt) AS green_min,
  95. MAX(red_cnt) AS red_min,
  96. MAX(blue_cnt) AS blue_min
  97. FROM aoc_1202
  98. GROUP BY split_part(game_id,' ', 2)::int
  99. )
  100. SELECT SUM(green_min*red_min*blue_min) FROM game_min;
  101. ----
  102. Explained Query:
  103. With
  104. cte l0 =
  105. Reduce aggregates=[sum(((#0{max_green_cnt} * #1{max_red_cnt}) * #2{max_blue_cnt}))] // { arity: 1 }
  106. Project (#1{max_green_cnt}..=#3{max_blue_cnt}) // { arity: 3 }
  107. Reduce group_by=[text_to_integer(split_string(#0{game_id}, " ", 2))] aggregates=[max(#1{green_cnt}), max(#2{red_cnt}), max(#3{blue_cnt})] // { arity: 4 }
  108. Project (#0{game_id}, #2{green_cnt}..=#4{blue_cnt}) // { arity: 4 }
  109. ReadStorage materialize.public.aoc_1202 // { arity: 5 }
  110. Return // { arity: 1 }
  111. Union // { arity: 1 }
  112. Get l0 // { arity: 1 }
  113. Map (null) // { arity: 1 }
  114. Union // { arity: 0 }
  115. Negate // { arity: 0 }
  116. Project () // { arity: 0 }
  117. Get l0 // { arity: 1 }
  118. Constant // { arity: 0 }
  119. - ()
  120. Source materialize.public.aoc_1202
  121. Target cluster: quickstart
  122. EOF
  123. query II
  124. with mutually recursive
  125. -- Parse the input up
  126. lines(line TEXT) as (select regexp_split_to_table(input, '\n') as line from input),
  127. games(game TEXT, report TEXT) as (select regexp_split_to_array(line, ':')[1], regexp_split_to_array(line, ':')[2] from lines),
  128. round(game TEXT, visible TEXT) as (select game, regexp_split_to_table(report, ';') from games),
  129. bacon(game TEXT, color TEXT) as (select game, regexp_split_to_table(visible, ',') from round),
  130. parsed(game INT, color TEXT, number INT) as (
  131. select
  132. substring(game, 5)::INT as game,
  133. regexp_split_to_array(color, ' ')[3] as color,
  134. regexp_split_to_array(color, ' ')[2]::INT as number
  135. from bacon
  136. ),
  137. -- PART 1
  138. limits(color TEXT, number INT) as (SELECT * FROM (VALUES ('red', 12), ('green', 13), ('blue', 14))),
  139. bad_news(game INT) as (
  140. select game
  141. from parsed, limits
  142. where parsed.color = limits.color
  143. AND parsed.number > limits.number
  144. ),
  145. plausible(game INT) as (select distinct parsed.game from parsed left join bad_news on(parsed.game = bad_news.game) where bad_news.game IS NULL),
  146. part1(part1 BIGINT) as (select SUM(game) from plausible),
  147. -- PART 2
  148. maximum(game INT, color TEXT, number INT) as (select game, color, max(number) from parsed GROUP BY game, color),
  149. red(game INT) as (select game from maximum, generate_series(1, number) where color = 'red'),
  150. blue(game INT) as (select game from maximum, generate_series(1, number) where color = 'blue'),
  151. green(game INT) as (select game from maximum, generate_series(1, number) where color = 'green'),
  152. power(game INT, product BIGINT) as (SELECT red.game, count(*) from red, blue, green where red.game = blue.game and blue.game = green.game GROUP BY red.game),
  153. part2(part2 BIGINT) as (select sum(product)::BIGINT from power)
  154. select * from part1, part2;
  155. ----
  156. 8 2567
  157. query T multiline
  158. EXPLAIN OPTIMIZED PLAN WITH(humanized expressions, arity, join implementations) AS VERBOSE TEXT FOR
  159. with mutually recursive
  160. -- Parse the input up
  161. lines(line TEXT) as (select regexp_split_to_table(input, '\n') as line from input),
  162. games(game TEXT, report TEXT) as (select regexp_split_to_array(line, ':')[1], regexp_split_to_array(line, ':')[2] from lines),
  163. round(game TEXT, visible TEXT) as (select game, regexp_split_to_table(report, ';') from games),
  164. bacon(game TEXT, color TEXT) as (select game, regexp_split_to_table(visible, ',') from round),
  165. parsed(game INT, color TEXT, number INT) as (
  166. select
  167. substring(game, 5)::INT as game,
  168. regexp_split_to_array(color, ' ')[3] as color,
  169. regexp_split_to_array(color, ' ')[2]::INT as number
  170. from bacon
  171. ),
  172. -- PART 1
  173. limits(color TEXT, number INT) as (SELECT * FROM (VALUES ('red', 12), ('green', 13), ('blue', 14))),
  174. bad_news(game INT) as (
  175. select game
  176. from parsed, limits
  177. where parsed.color = limits.color
  178. AND parsed.number > limits.number
  179. ),
  180. plausible(game INT) as (select distinct parsed.game from parsed left join bad_news on(parsed.game = bad_news.game) where bad_news.game IS NULL),
  181. part1(part1 BIGINT) as (select SUM(game) from plausible),
  182. -- PART 2
  183. maximum(game INT, color TEXT, number INT) as (select game, color, max(number) from parsed GROUP BY game, color),
  184. red(game INT) as (select game from maximum, generate_series(1, number) where color = 'red'),
  185. blue(game INT) as (select game from maximum, generate_series(1, number) where color = 'blue'),
  186. green(game INT) as (select game from maximum, generate_series(1, number) where color = 'green'),
  187. power(game INT, product BIGINT) as (SELECT red.game, count(*) from red, blue, green where red.game = blue.game and blue.game = green.game GROUP BY red.game),
  188. part2(part2 BIGINT) as (select sum(product)::BIGINT from power)
  189. select * from part1, part2;
  190. ----
  191. Explained Query:
  192. With
  193. cte l0 =
  194. Project (#3, #5, #6) // { arity: 3 }
  195. Map (text_to_integer(substr(#0{game}, 5)), regexp_split_to_array[" ", case_insensitive=false](#2{color}), array_index(#4, 3), text_to_integer(array_index(#4, 2))) // { arity: 7 }
  196. FlatMap unnest_array(regexp_split_to_array[",", case_insensitive=false](#1{visible})) // { arity: 3 }
  197. Project (#0, #2) // { arity: 2 }
  198. FlatMap unnest_array(regexp_split_to_array[";", case_insensitive=false](#1{report})) // { arity: 3 }
  199. Project (#3, #4) // { arity: 2 }
  200. Map (regexp_split_to_array[":", case_insensitive=false](#1{line}), array_index(#2, 1), array_index(#2, 2)) // { arity: 5 }
  201. FlatMap unnest_array(regexp_split_to_array["\n", case_insensitive=false](#0{input})) // { arity: 2 }
  202. ReadStorage materialize.public.input // { arity: 1 }
  203. cte l1 =
  204. Filter (#0{game}) IS NOT NULL // { arity: 3 }
  205. Get l0 // { arity: 3 }
  206. cte l2 =
  207. ArrangeBy keys=[[#0{game}]] // { arity: 1 }
  208. Project (#0) // { arity: 1 }
  209. Get l1 // { arity: 3 }
  210. cte l3 =
  211. Reduce aggregates=[sum(#0{game})] // { arity: 1 }
  212. Distinct project=[#0] // { arity: 1 }
  213. Union // { arity: 1 }
  214. Negate // { arity: 1 }
  215. Project (#0) // { arity: 1 }
  216. Join on=(#0{game} = #1) type=differential // { arity: 2 }
  217. implementation
  218. %1[#0]UKA » %0:l2[#0{game}]K
  219. Get l2 // { arity: 1 }
  220. ArrangeBy keys=[[#0]] // { arity: 1 }
  221. Distinct project=[#0] // { arity: 1 }
  222. Project (#0) // { arity: 1 }
  223. Filter (#3{number} > #5{number}) // { arity: 6 }
  224. Join on=(#0{game} = #1{game} AND #2{color} = #4{color}) type=delta // { arity: 6 }
  225. implementation
  226. %0:l2 » %1:l0[#0{game}]K » %2[#0{color}]UK
  227. %1:l0 » %2[#0{color}]UK » %0:l2[#0{game}]K
  228. %2 » %1:l0[#1{color}]K » %0:l2[#0{game}]K
  229. Get l2 // { arity: 1 }
  230. ArrangeBy keys=[[#0{game}], [#1{color}]] // { arity: 3 }
  231. Filter (#0{game}) IS NOT NULL AND (#1{color}) IS NOT NULL // { arity: 3 }
  232. Get l0 // { arity: 3 }
  233. ArrangeBy keys=[[#0{color}]] // { arity: 2 }
  234. Constant // { arity: 2 }
  235. - ("red", 12)
  236. - ("blue", 14)
  237. - ("green", 13)
  238. Project (#0) // { arity: 1 }
  239. Get l0 // { arity: 3 }
  240. cte l4 =
  241. Reduce group_by=[#0, #1] aggregates=[max(#2{number})] // { arity: 3 }
  242. Get l1 // { arity: 3 }
  243. cte l5 =
  244. Reduce aggregates=[sum(#0{count})] // { arity: 1 }
  245. Project (#1{count}) // { arity: 1 }
  246. Reduce group_by=[#0] aggregates=[count(*)] // { arity: 2 }
  247. Project (#0) // { arity: 1 }
  248. Join on=(#0{game} = #1{game} = #2{game}) type=delta // { arity: 3 }
  249. implementation
  250. %0 » %1[#0{game}]K » %2[#0{game}]K
  251. %1 » %0[#0{game}]K » %2[#0{game}]K
  252. %2 » %0[#0{game}]K » %1[#0{game}]K
  253. ArrangeBy keys=[[#0{game}]] // { arity: 1 }
  254. Project (#0) // { arity: 1 }
  255. FlatMap generate_series(1, #1{max}, 1) // { arity: 3 }
  256. Project (#0, #2{max}) // { arity: 2 }
  257. Filter (#1{color} = "red") // { arity: 3 }
  258. Get l4 // { arity: 3 }
  259. ArrangeBy keys=[[#0{game}]] // { arity: 1 }
  260. Project (#0) // { arity: 1 }
  261. FlatMap generate_series(1, #1{max}, 1) // { arity: 3 }
  262. Project (#0, #2{max}) // { arity: 2 }
  263. Filter (#1{color} = "blue") // { arity: 3 }
  264. Get l4 // { arity: 3 }
  265. ArrangeBy keys=[[#0{game}]] // { arity: 1 }
  266. Project (#0) // { arity: 1 }
  267. FlatMap generate_series(1, #1{max}, 1) // { arity: 3 }
  268. Project (#0, #2{max}) // { arity: 2 }
  269. Filter (#1{color} = "green") // { arity: 3 }
  270. Get l4 // { arity: 3 }
  271. Return // { arity: 2 }
  272. CrossJoin type=differential // { arity: 2 }
  273. implementation
  274. %0[×]U » %1[×]U
  275. ArrangeBy keys=[[]] // { arity: 1 }
  276. Union // { arity: 1 }
  277. Get l3 // { arity: 1 }
  278. Map (null) // { arity: 1 }
  279. Union // { arity: 0 }
  280. Negate // { arity: 0 }
  281. Project () // { arity: 0 }
  282. Get l3 // { arity: 1 }
  283. Constant // { arity: 0 }
  284. - ()
  285. ArrangeBy keys=[[]] // { arity: 1 }
  286. Project (#1) // { arity: 1 }
  287. Map (numeric_to_bigint(#0{sum_count})) // { arity: 2 }
  288. Union // { arity: 1 }
  289. Get l5 // { arity: 1 }
  290. Map (null) // { arity: 1 }
  291. Union // { arity: 0 }
  292. Negate // { arity: 0 }
  293. Project () // { arity: 0 }
  294. Get l5 // { arity: 1 }
  295. Constant // { arity: 0 }
  296. - ()
  297. Source materialize.public.input
  298. Target cluster: quickstart
  299. EOF