Editorial for Google Code Jam '22 Round 2 Problem B - Pixelated Circle
Submitting an official solution before solving the problem yourself is a bannable offence.
Let and be the set of pixels colored by
draw_circle_filled
() and
draw_circle_filled_wrong
(), the number of pixels that have
different colors in these pictures would be the cardinality (size) of the
symmetric difference of and , that is:
Test Set 1
For test set 1, is small enough to build the sets of colored pixels from
draw_circle_filled
() and
draw_circle_filled_wrong
() with hash set of tuples. By
implementing the pseudocode in the problem statement, the time complexity
would be to get all colored pixels and to
compute the symmetric difference of the two sets.
Test Set 2
The key observation for optimizing the solution is that for any , every
pixel colored by draw_circle_filled_wrong
() is also colored by
draw_circle_filled
(), that is .
Therefore, we can simplify the size of symmetric difference to:
which means we can count the number of pixels colored by
draw_circle_filled
() and
draw_circle_filled_wrong
() separately, and the answer would be
the difference between these two numbers. The proof of this observation is
given at the end of this analysis.
Count pixels colored by draw_circle_filled
()
To get the number of pixels colored by draw_circle_filled
(),
we need to iterate through all possible values of and find
and for each which satisfy
for all .
A solution for them is
and . Therefore, we can get the number of
colored pixels with a for-loop for the following equation:
Time complexity:
Count pixels colored by draw_circle_filled_wrong
()
draw_circle_filled_wrong
() is composed of
draw_circle_perimeter
() calls with from to
. Notice that pixels colored by
draw_circle_perimeter
() and
draw_circle_perimeter
() never overlap if .
Based on this observation, we can count the number of pixels colored
by each draw_circle_perimeter
() separately and sum them up
to get the total number of colored pixels. The proof of this observation is
given at the
end of this analysis.
Looking into function draw_circle_perimeter
(), we can
break the colored pixels into 4 quadrants and count them separately. Since the
colored pattern is symmetric to both x-axis and y-axis, we just need to count
the pixels in Quadrant 1 (Q1), and the total count excluding the origin pixel
would be that number times 4, and plus 1 to include the origin pixel.
For , the colored pixels in Q1 are symmetric to the line , and there are exactly colored pixels between y-axis and , the closest point to line (above or on the line, ). Since is at to the x-axis, the integer would be either or . We can compute the corresponding and choose the closer one above or on the line . Afterwards, the number of colored pixels in Q1 including x-axis would be , and minus 1 if lies on the line since it is not mirrored in this case.
Time complexity: for counting pixels colored by
draw_circle_perimeter
(), and for all colored
pixels.
Proof:
For every positive , and such that and , we want to prove that the following inequality always satisfies:
which always holds since when and .
Secondly, . Therefore always holds.
The proof above shows that pixels colored by
draw_circle_filled_wrong
() with
also satisfy the coloring condition in draw_circle_filled
(),
which implies .
Proof: draw_circle_perimeter
() and draw_circle_perimeter
() never overlap
For the first coloring statement in
draw_circle_perimeter
(), we want to prove that given a
fixed , the inequality for any pair of integers and
such that and is always
true:
Based on the proof above, we can further get:
Therefore always holds for all
given a fixed such that . For the cases that , the pixels will never satisfy the coloring condition in
draw_circle_perimeter
().
We can further extend the proof above for the 2nd, 3rd, and 4th coloring
statement in draw_circle_perimeter
() and prove that pixels
colored by draw_circle_perimeter
() and
draw_circle_perimeter
() never overlap.
Comments