{"id":775,"date":"2015-04-12T07:28:09","date_gmt":"2015-04-12T07:28:09","guid":{"rendered":"http:\/\/www.themissingdocs.net\/wordpress\/?p=775"},"modified":"2015-04-12T07:28:09","modified_gmt":"2015-04-12T07:28:09","slug":"gcj15-qr","status":"publish","type":"post","link":"https:\/\/www.themissingdocs.net\/?p=775","title":{"rendered":"GCJ15 QR"},"content":{"rendered":"<p>20 points to advance meant that a full solution to the simplest problem wasn&#8217;t sufficient.\u00a0 Even so 12438 people advance to round 1.\u00a0 23296 people got a positive score.\u00a0 Makes the 1371 people who turned up to topcoder open pretty tiny, although maybe the simultaneous scheduling of code jam qualifying round and topcoder open was part of why topcoder open&#8217;s numbers were so much lower than usual.<\/p>\n<p>348 perfect scores, despite the problem worth the most points having significant scenarios in the large input that were not even close to covered in the small input.<\/p>\n<p><strong>Q1) Given a count of the number of people who will stand up for each threshold of people already standing up, determine the minimum number of extra people (of any mixture of thresholds) required to make everyone stand up.<\/strong><\/p>\n<p>A1) This is a basic greedy problem, consider each threshold with non-zero population in order, if there aren&#8217;t enough people assume there are by adding the difference between how many are standing up and need to be standing up to the already standing up set.\u00a0 Accumulate these differences and return.\u00a0 This works because larger thresholds won&#8217;t stand up before earlier thresholds, and so you have to add enough to trigger the earlier threshold.\u00a0 Large input is only 1000, and the solution is linear anyway, so no problems with running time.<\/p>\n<p><strong>Q2) Given stacks that go down by one every minute, except if you pause everything and move a subset of one stack to anywhere else, including making a new stack, what is the minimum time for all stacks to become empty?<\/strong><\/p>\n<p>A2) So my first instincts here were wrong, a single stack of size 9 can be done in 5 minutes, but my first instinct was to only ever divide stacks into two, which gives 6 minutes as best effort here.\u00a0 The correct approach is to take 6 (or 3) off , then 3 off the remaining stack of 6, then allow 3 minutes to run its course of the 3 stacks of size 3.\u00a0 Interestingly the small input includes stacks of size 9, so at least this mistake wouldn&#8217;t slip past to the large input.\u00a0 The high percentage failure rate on the small input here suggest I may not have been alone in missing this key point at first.<\/p>\n<p>To get the large input done in time it is sufficient to solve the problem in O(NK) time, so one option is to consider best time where you split tall stacks down to a maximum height of m before allowing time to run.\u00a0 Height ranges to consider are from 1 to tallest stack, and number of turns to split a stack down to at most height m is given by simple division, so the total of all stacks can be done in O(N) time.\u00a0 Giving a total of O(NK) N being number of stacks and K being the height of the largest stack.<\/p>\n<p>Assumptions at play here are that it is always better to split first before letting time run.\u00a0 This is pretty obvious as if a split is worth doing, doing it sooner means more pancakes per second are removed later.<\/p>\n<p>I think there is an approach with better runtime characteristics, which involves considering only a subset of all heights, something like O(N*Sqrt(K)*Log(N*Sqrt(K))).\u00a0 For each stack generate the the set of heights for splits down to sqrt of its height, sort all of these in decreasing order and consider the ones greater or equal to sqrt of the largest height.\u00a0 Each step through this list of heights corresponds to one extra minute doing a split, and defines a sequence of heights of highest remaining after n splits.\u00a0 Then just linear search for best.\u00a0 This approach presumes it is never any better to divide a pile beyond its square root, which seems straight forwardly true, dividing things further takes more than one extra split per height reduced.<\/p>\n<p><strong>Q3) Given a potentially repeating sequence if i&#8217;s j&#8217;s and k&#8217;s, determine if it is possible to subdivide them into sections which evaluate to i, j and k respectively assuming that the i, j and k&#8217;s represent standard quaternion&#8217;s and are being multiplied using standard quaternion multiplication.<\/strong><\/p>\n<p>A3) The problem helpfully explains that quaternion&#8217;s satisfy A*(B*C) = (A*B)*C.<\/p>\n<p>One approach (which is a bit slow, but just sufficient for the large input) is to determine all prefixes which can create i, all the postfixes which can create k, and determine if the gaps in between create j.\u00a0 The fact that the sequence can be repeating (and the repeat count can be huge) appears to be a problem at first, but a close inspection of quaternion powers reveals this is not going to be a problem.\u00a0 A fairly quick inspection finds that any quaternion to the power 4 is 1.\u00a0 Hence repeat counts mod 4 are the only cases needing to be considered.\u00a0 So, calculate the value of the entire repeating sequence, and consider each of its 4 powers as a pre multiple of any prefix of the repeating sequence.\u00a0 If the answer is i, store the pairing of the mod 4 power and the prefix length.\u00a0 Similar for k, but post multiply and postfix of the sequence.\u00a0 Both of these sets can be generated on O(N) the size of the repeating sequence which is at most 10k.\u00a0 Each set is also O(N) in size, so we have to be able to determine whether there exists a j in between in O(1) time, as anything over O(N^2) is clearly too slow.<\/p>\n<p>Given a candidate i and k prefix\/postfix &#8211; there are 2 possibilities, the prefix postfix meet at the same central location and the j is the middle section of that repeated segment, or they have a larger gap in between, and j is a postfix (optional repeats) prefix sequence.\u00a0 The later is easiest, the postfix length is defined by the prefix length of the candidate i, the prefix length defined by the postfix length of the k candidate and the number of repeats, mod 4 is defined by the mod 4 of each of the i and k candidates and the total number of repeats.\u00a0 Care must be taken if the number of repeats is small that the only mod 4 value which satisfies the criterion, might be negative.\u00a0 If you have a cache of prefix\/postfix values and powers of the repeated section, this becomes 3 quaternion multiplies.<\/p>\n<p>The first case where the 2 touch is more difficult.\u00a0 Need to check the mod sum vs the total repeats works out, since the j section doesn&#8217;t have any repeats this time.\u00a0 But unless you pre-cache the product of every subsection of the repeated section, it can&#8217;t be done in O(1) time.\u00a0 That pre-caching is another O(N^2) cost, and a lot of memory, so nice if we can avoid it.\u00a0 The solution is quaternion division (pre\/post) is well defined.\u00a0 Each quaternion multiplication is a permutation, so for a result and one of the input multipliers, there is only one possible value.\u00a0 We know the value for the product of an entire section, and the value of the prefix and postfix, so we can do prefix division and then postfix division to determine the value of the middle part.\u00a0\u00a0 This is O(1) time, as we need.<\/p>\n<p>However, there is a better way! &#8211; if the sequence can be broken in to i, j and k subsections, its total product must be the same as the product of i j and k, which is -1.\u00a0 So if the total product if the entire sequence (including repeats) is not -1, we can exit out early.\u00a0 If it is, there is no need to verify the value of j, instead all that is required is to verify that there exist i and k prefix\/postfix, and those do not overlap.\u00a0 So generate the i and k prefix\/postfixes as before, but select the shortest of each.\u00a0 Now there is no longer an O(N^2) inner loop, just a check of the 2 shortest prefix\/postfixes do not overlap.\u00a0 If they don&#8217;t, then the inner section is known to be j &#8211; given by the fact that quaternion division is well defined and knowing the total product.<\/p>\n<p><strong>Q4) In a game where an opponent gets to choose one n-omino, and you have to place it in an RxC sized container and then fill the remaining space with n-ominos of the same size (but not any specific shapes), determine whether for a given RxC and n the game is always winnable by the opponent (as in they can always choose an n-omino that you cannot place and fill the surrounds).<\/strong><\/p>\n<p>A4) The small input is interesting here because the number of test cases is 64 exactly.\u00a0 This corresponds to the number of possible small inputs! &#8211; R, C and n are all limited to the range 1-4.\u00a0 The large they are limited to 20, meaning there are only 8000 possible inputs.\u00a0 You could theoretically write a less efficient program, brute force them all and hard code the result.<\/p>\n<p>There is one main early out.\u00a0 If R*C % n is non-zero, it doesn&#8217;t matter what the opponent does, they always win by default.<\/p>\n<p>Another easy scope reduction is if R is larger than C, switch so R is the small one and C is the larger.\u00a0 Then if n is larger than 2R it can be made into an L shape that cannot possibly fit, so the opponent wins.\u00a0 This is actually almost sufficient for the small input, the one remaining case is the t piece can be selected in 2&#215;4 for n=4, which splits the the space into a 1 and 3 areas which can&#8217;t be filled.<\/p>\n<p>The large input covers a lot more scenarios.\u00a0 But they can be brute forced by hand, if you are careful.\u00a0 The 17% pass rate suggests cases are easy to miss&#8230; First there is a hint in the problem itself, it shows some of the 7-ominos, one of them has a hole.\u00a0 Obviously the opponent can always choose this piece and make tiling impossible.\u00a0 This is trivially extended to all larger n-omino&#8217;s.<\/p>\n<p>Before I cover the remaining scenarios it is worth mentioning that if the opponent can&#8217;t win for AxB, anything larger than AxB that satisfies the mod n condition also can&#8217;t be won by the opponent.\u00a0 So we just have to start small and work our way out, as soon as we get a case where we win, everything larger is a given.\u00a0 It is fairly trivial to see that some simple zig-zag filling can be used to fill any L shape or rectangle shape that you might add to an AxB to make it a larger case, so long as these L\/rectangle shapes themselves are a multiple of n in area.<\/p>\n<p>So lets cover things in order<\/p>\n<ul>\n<li>n = 1 &#8211; trivially no opponent win.<\/li>\n<li>n = 2 &#8211; trivially no opponent win if mod satisfied<\/li>\n<li>n = 3 &#8211; no opponent win if R &gt; 1 and mod satisfied, otherwise opponent win &#8211; again pretty trivial.<\/li>\n<li>n = 4 &#8211; opponent win for R = 1 by L shape.\u00a0 As mentioned before the t shape is opponent win for R = 2 and C = 4, but this extends to R = 2 in general, as it leaves both sides of wherever you place it with a 1 mod 2 value, which can&#8217;t be tiled using pieces of size 4.\u00a0 R = 3 and higher always works because 3&#215;4 can easily be tiled regardless of opponent choice. (There aren&#8217;t many choices for tetromino&#8217;s so they are easily worked through.)<\/li>\n<li>n = 5 &#8211; here is where it gets tricky&#8230; base is opponent win for R &lt;= 2 using the L shape. R &gt;= 4 is no opponent win, not trivial to work out, but you can consider all 12 by hand for 4&#215;5, and then larger falls out.<br \/>\nR = 3 is the gotcha case.\u00a0 The tricky piece is the diagonal step shape &#8211; also known as &#8216;W&#8217; under standard pentomino naming.\u00a0 Regardless of rotation in an R=3 space this divides the space into two parts.\u00a0 For C = 5, the size of these parts is 3 and 7, or 6 and 4 depending on placement.\u00a0 Neither of these can be tilled.\u00a0 But for C = 10 or higher, it can be placed so the spaces are 15 and 10 (in the C = 10 case, similar in larger), which can be tiled easily.<\/li>\n<li>n = 6 &#8211; again L shape gives opponent win for R = 2.\u00a0 R = 3 is an opponent win by the dagger shape a 4&#215;3 cross which divides the shape into 2 mod 3 and 1 mod 3 spaces, which can&#8217;t be tiled by size 6 shapes.\u00a0 It also can&#8217;t be tiled due to the 3&#215;3 &#8216;space invader&#8217;, despite being able to place it in any rotation, which I think is cool&#8230;<br \/>\nR = 4 &#8211; this time there are 35 different 6-omino&#8217;s to brute force, but none of them cause trouble in 4&#215;6, and hence all larger is no opponent win if mod condition is satisfied.<\/li>\n<li>n &gt;= 7 &#8211; the piece with a hole gives guaranteed win to opponent.<\/li>\n<\/ul>\n<p>I missed the W shape in n = 5 when I tried to work these things out by hand, I wonder what the most common mistake was for the large input.<\/p>\n<p>I also wonder how many people tried to actually solve the puzzle programmatically rather than hard coding rules from by hand brute force.\u00a0 This is not trivial as it involves determining whether you can tile a connected space or not and it is possible to create a &#8216;t&#8217; junction which means even if the space to fill is a multiple of the n under question, it depends on how many pieces are on each side of the &#8216;t&#8217; junction as to whether it can be connected.\u00a0 Its also tedious generating all the n-ominos (if you don&#8217;t hard code them) and writing reflection\/rotation generation and sliding them all around.\u00a0 And for the largest sizes you might risk time-out, unless you take advantage of the expansion proof where smaller cases answer larger cases I mentioned, and pre-calculate the answer for all possible inputs (from small to large) before running the 100 test cases.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>20 points to advance meant that a full solution to the simplest problem wasn&#8217;t sufficient.\u00a0 Even so 12438 people advance to round 1.\u00a0 23296 people got a positive score.\u00a0 Makes the 1371 people who turned up to topcoder open pretty tiny, although maybe the simultaneous scheduling of code jam qualifying round and topcoder open was &hellip; <a href=\"https:\/\/www.themissingdocs.net\/?p=775\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">GCJ15 QR<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-775","post","type-post","status-publish","format-standard","hentry","category-code-competitions"],"_links":{"self":[{"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=\/wp\/v2\/posts\/775","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=775"}],"version-history":[{"count":0,"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=\/wp\/v2\/posts\/775\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=775"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.themissingdocs.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}