Part 1
The problem
Determine which games would have been possible if the bag had been loaded with only 12 red cubes, 13 green cubes, and 14 blue cubes.
First, let’s create a dataset with all draws.
all_games = DataFrame (
game_no = 0 ,
colors = "" ,
draws = 0
);
We will also need a function to find these different numbers and colors.
function find_colors_numbers (draws:: String , color:: String )
out_num_cubes = Int32 [];
idx = 1 ;
while idx < lastindex (draws)
m = match (
Regex (" (?<num_cubes> \\ d+) $ color" ),
draws,
idx
);
if isnothing (m)
break
end
push! (out_num_cubes, parse (Int32 , m["num_cubes" ]));
idx = m.offset + length (m.match);
end
return out_num_cubes
end
find_colors_numbers (generic function with 1 method)
all_colors = ["red" , "green" , "blue" ];
line = readline (input_file);
while line != ""
split_first = split (line, ":" );
game_no = split (
first (split_first), " "
) |>
x -> parse (Int32 , last (x));
draws = map (
find_colors_numbers,
[line, line, line],
all_colors
);
cur_games = DataFrame (
game_no = game_no,
colors = all_colors,
draws = draws
) |>
x -> flatten (x, : draws);
append! (all_games, cur_games);
# read the next line:
global line = readline (input_file);
end
close (input_file)
The solution
Let’s check which draws gave more than 12 red cubes, 13 green cubes, and 14 blue cubes .
all_no_draws = [12 , 13 , 14 ];
function get_games_not_possible (color, no_draws)
cur_subset = subset (
all_games,
: colors => col -> col .== color,
: draws => dr -> dr .> no_draws
);
return unique (cur_subset.game_no)
end
get_games_not_possible (generic function with 1 method)
all_games_ids_not_possible = map (
get_games_not_possible,
all_colors,
all_no_draws
) |>
x -> unique (vcat (x... ));
all_games_ids_possible = setdiff (unique (all_games.game_no), all_games_ids_not_possible);
The sum of these numbers is 2685.
Part 2
The problem
What is the minimum number of cubes that makes each game possible?
This means, that I need to find the minimum number in each game, for each color.
min_cubes_all_games = combine (
groupby (all_games, [: game_no, : colors]),
: draws => (x -> max (x... )) => : max_draw
)
301×3 DataFrame
276 rows omitted
1
0
0
2
1
red
5
3
1
green
16
4
1
blue
11
5
2
red
20
6
2
green
15
7
2
blue
13
8
3
red
10
9
3
green
7
10
3
blue
13
11
4
red
14
12
4
green
13
13
4
blue
18
⋮
⋮
⋮
⋮
290
97
red
4
291
97
green
1
292
97
blue
15
293
98
red
10
294
98
green
1
295
98
blue
11
296
99
red
8
297
99
green
16
298
99
blue
4
299
100
red
4
300
100
green
6
301
100
blue
11
The solution
Then, for each game, multiply the minimal numbers and sum up.
powers_per_game = combine (
groupby (min_cubes_all_games, : game_no),
: max_draw => (x -> reduce (* , x)) => : power
)
101×2 DataFrame
76 rows omitted
1
0
0
2
1
880
3
2
3900
4
3
910
5
4
3276
6
5
216
7
6
198
8
7
384
9
8
40
10
9
728
11
10
288
12
11
1980
13
12
70
⋮
⋮
⋮
90
89
2250
91
90
51
92
91
864
93
92
1848
94
93
18
95
94
378
96
95
840
97
96
810
98
97
60
99
98
110
100
99
512
101
100
264
The sum of these numbers is 83707.