JuanMata's blog

By JuanMata, 11 years ago, In English

Tomorrow will take place the Qualification Round of Google Code Jam 2014.
Contest will start 14 hours from now. Note that the contest duration has been extended by 2 hours, so now it will be 27 hours long! :)
Registration for the round has already started, and will be open until end of contest.

Wish all participants good luck in advancing to Round 1. You must score atleast 25 points to advance.

We can discuss the problems here after contest!

  • Vote: I like it
  • +53
  • Vote: I do not like it

| Write comment?
»
11 years ago, # |
Rev. 3   Vote: I like it -13 Vote: I do not like it

so, this time there were no hard problems.

problem B: ternary search over the number of cookie farms

problem C: boring greedy implementation

problem D:

Sort two arrays.

Game of war: iterate Ken's array from left to right. For each block, try to find the block with lower weight in Naomi's array. Remove two blocks.

Deceitful war: iterate Naomi's array from left to right. For each block, try to find the block with lower weight in Ken's array. Remove two blocks.

  • »
    »
    11 years ago, # ^ |
      Vote: I like it +58 Vote: I do not like it

    There was no need even for ternary search in B; my solution was plain linear, adding farms one-by-one if the next farm would speed up getting to the goal number of cookies.

    • »
      »
      »
      11 years ago, # ^ |
      Rev. 3   Vote: I like it 0 Vote: I do not like it

      i just used a simple recursion to solve B:

      def solve(r, ub):
      	if x/r > ub:
      		return ub
      	return c/r + solve(r+f, x/r-c/r)
      
      print solve(2, x/2)
      

      here, r is the current rate of generation of cookies and ub is the upper bound of what the function can return (returning anything above that is useless because answer can be reduced by not buying more farms).

      • »
        »
        »
        »
        11 years ago, # ^ |
        Rev. 2   Vote: I like it 0 Vote: I do not like it

        How can this code give correct solution for 30.0 1.0 2.0

        x/2.0 = 1.0
        ub = 1.0
        

        I can't understand the logic for recurrsion. Can you help?

        • »
          »
          »
          »
          »
          11 years ago, # ^ |
          Rev. 3   Vote: I like it 0 Vote: I do not like it

          think of it as kind of a binary tree, with each node having left subtree as a single node, and right subtree as similar to current tree.

          so, solve(r) will have two options:

          • left child assumes that he buys no more farms, so answer is just x/r.
          • right child assumes that he buys one farm. so he has to spend some more time getting back c cookies, but now he has faster r. therefore answer in this case is c/r + solve(r+f).

          now, it only makes sense to use the right child if it yields x cookies faster than left child. for this we require x/r <= c/r + solve(r+f). so we add an extra parameter ub (upper bound on function's return value) and assign ub for the right child as x/r - c/r.
          therefore we get the formula that i posted above.

          hope u understood. if not, tell me which part i need to explain more.

          • »
            »
            »
            »
            »
            »
            11 years ago, # ^ |
              Vote: I like it 0 Vote: I do not like it

            Thanks. I'm not getting what ub is exactly doing. Sorry.

            • »
              »
              »
              »
              »
              »
              »
              11 years ago, # ^ |
                Vote: I like it 0 Vote: I do not like it

              it just makes sure that infinite recursion is prevented.
              because using ub allows us to stop recursing when buying more farms wont be useful.

              • »
                »
                »
                »
                »
                »
                »
                »
                11 years ago, # ^ |
                  Vote: I like it 0 Vote: I do not like it

                How do you decide the upper bound.?

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  11 years ago, # ^ |
                  Rev. 3   Vote: I like it 0 Vote: I do not like it

                  if i choose not to buy any more farms, then i will need x/r time to get x cookies. so now i need to make sure time after buying extra farm doesnt exceed this.
                  since c/r time has been used to generate cookies to buy the farm, remaining time is x/r - c/r, which is the upper bound after recursing.

                  EDIT: initially ub will be x/2, as this time can be achieved by not buying even a single farm.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  11 years ago, # ^ |
                  Rev. 2   Vote: I like it 0 Vote: I do not like it

                  Thank u.! Chelsea fan and BITS, guess we have something in common.:) Which year btw ? I am in 1st.

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      I solved it using the same idea , no need for ternary search

  • »
    »
    11 years ago, # ^ |
      Vote: I like it +4 Vote: I do not like it

    Can you explain the approach for minesweeper? Couldn't get that done. Thanks!

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      my approach was to find the solution in the form of at most 3 connected rectangles X × Y, X1 × 1, 1 × Y1 such that X·Y + X1 + Y1 = R·C - M ,

      where X1 ≤ X, Y1 ≤ Y and (X, X1, Y, Y1) ≠ 1.

      Example:

      4 4 3
      
      X = 3; Y = 3; X1 = 2; Y1 = 2
      
      BB**
      AAA*
      AAAC
      AAAC
      
    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it +7 Vote: I do not like it

      If R = 1 or C = 1, it's clear that we can just make the last M cells contain mines.

      Next, there's a special case of M = RC - 1; if M < RC - 1, the field we click on mustn't neighbor mines.

      You can always get +1 free space (without mines) by cutting off concave corners (a mine neighboring 3 free spaces). By doing so, you get a rectangle a × b from f connected free cells, eventually — that means you can get any number of free cells from f to ab.

      The smallest f (that you could get a given a × b rectangle from) is clearly achieved by making a path 2 cells thick along 2 sides of the field and next to a corner, and it's f = 2a + 2b - 4, so it suffices to find some a, b such that 2(a + b - 2) ≤ RC - M ≤ ab, cut off that space next to a corner (a - 1 and b - 1 cells not neighboring any others, along a vertical and a horizontal side) and then remove mines from as many cells from that a × b rectangle as necessary. Example:

      R C M
      4 5 9
      

      for example x = 3, y = 4

      ....*
      ....*
      ..***
      *****
      

      and remove 1 more mine

      ....*
      ....*
      ...**
      *****
      
      • »
        »
        »
        »
        11 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        can you explain with less math jargon plz? I want to know the logic in few sentences if that is possible. forgive my noobness in pure mathematics.

        • »
          »
          »
          »
          »
          11 years ago, # ^ |
            Vote: I like it +3 Vote: I do not like it

          I could make the explanation very long, or too short to explain anything. This is about the best I could do (also, I haven't slept this night). Try to compare your own ideas with mine, look at the examples, etc. Something that helps you understand...

    • »
      »
      »
      11 years ago, # ^ |
      Rev. 2   Vote: I like it +8 Vote: I do not like it

      My solution:

      1) R = 1 or C = 1 or M = R·C - 1 as Xellos described.

      2) Try to fill the rectangle (r - 2) × (c - 2) ([0..r - 3] × [0..c - 3]) line by line (fill the the row 0 and all cells [0..c - 3] then the row 1 and etc.).

      3) If you have no remained mines, then you are done.

      4) If the number of remained mines is odd then we try to steal the mine at (r - 3, c - 3) and now the number of remained mines is even.

      5) Now we consider all the rows and columns which have 2 free cells. And fill them by putting 2 mines into those rows and columns.

      If at the end we have remained mines or we couldn't steal mine at step 4 when we need it, then it's Impossible.

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it +5 Vote: I do not like it

      My solution:

      1. R = 1 or C = 1 or M = R C — 1 as Xellos described.
      2. M = 0
      3. (R = 2 or C = 2) and M % 2 == 1 and M != R C — 1 -> Impossible
      4. Let's count free cells, not mines. So, we need RC — M cells. Let's click in a corner. Now we have 4 revealed cells. Then recursively try open new cells while count of revealed is less than needed. Less words, more code:
      void dfs(i, j, current_field, revealed)
           if revealed == M - RC
                 answer <- current_field
           temp <- count of closed adjacent cells
           if temp == 0 or revealed + temp > M - RC
                 return
           current_field <- current_field with revealed adjacent cells
           for dx : -1..1
                 for dy : -1..1
                        dfs(i + dx, j + dy, current_field, revealed + temp)
      

      When I was coding it, I thought that it's bruteforce and works very slow. But execution time of 134 large tests was about 1 second.

      But I can't prove the fact that if solution exists, we can find it, clicking in a corner

    • »
      »
      »
      11 years ago, # ^ |
      Rev. 2   Vote: I like it 0 Vote: I do not like it

      My approach. Place bombs to the cells at the shorter side of the remaining rectangle. The only corner case is if number of remaining bombs equal to the (shorter_side_size — 1). In this case we have to place (shorter_side_size — 2) bombs for this side and leave 1 bomb to next iteration.

      Example:
      5 rows 7 columns 28 bombs
      Step 1. Place 5 bomb to 1 column. (remaining rectangle after this step 5x6)
      Step 2. Place 5 bomb to 2 column. (remaining rectangle after this step 5x5)
      Step 3. Place 5 bomb to 3 column. (remaining rectangle after this step 4x5)
      Step 4. Place 5 bomb to 1 row. (remaining rectangle after this step 4x4)
      Step 5. Place 4 bomb to 4 column. (remaining rectangle after this step 3x4)
      Step 6. Place 4 bomb to 2 row. (remaining rectangle after this step 3x3)
      Done.
      
  • »
    »
    11 years ago, # ^ |
    Rev. 12   Vote: I like it 0 Vote: I do not like it

    I understand the strategy of Ken in normal War game, but get confused in Deceitful War. If I was right, then in normal War game, for each value of Naomi, Ken will always find the smallest value that still bigger than Naomi's value. For example, if Naomi give 4 and Ken have 2, 3, 7, 10 then he give 7 and win 1 point. However, in Deceitful War, I don't see this strategy can gives him only 1 point in the last testcase i.e. gives Naomi 8 points. Could you explain which part I was wrong ?

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      If Naomy gives 4 but says that he gives any block with mass > 10, Ken will think that he must play the smallest possible block because he loses anyway. Then he will give 2 and Naomi will win since 4 > 2 .

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it +3 Vote: I do not like it

      Basically, Naomi can make Ken play the blocks in the order that's the most advantageous for her.

      She could pick her lightest i blocks, make each of them just a little bit lighter than each of Ken's heaviest i blocks, and thus make him play these blocks (scoring i points). Then, she could pick her N - i heaviest blocks, play them from lightest to heaviest, which will make Ken play his N - i lightest blocks also from lightest to heaviest, making Naomi score N - i points. (Of course, this strategy doesn't have to be possible for some i, but it can be shown that if it isn't, then the answer isn't N - i.)

    • »
      »
      »
      11 years ago, # ^ |
      Rev. 2   Vote: I like it +3 Vote: I do not like it

      Sorted blocks:

      ['0.186', '0.300', '0.389', '0.557', '0.832', '0.899', '0.907', '0.959', '0.992']

      ['0.215', '0.271', '0.341', '0.458', '0.520', '0.521', '0.700', '0.728', '0.916']

      Firstly, take Naomi's blocks which are less than Ken's ones. In our case — 0.186. Naomi know that she won't win this point, but she does not say the real value, because she wants to destroy the heaviest possible Ken's block — 0.916. For example, she can say 0.915, but the value does not matter in this problem. Ken get 1 point, but lose the biggest block.

      Secondly, take the next Naomi's block — 0.300. Note there is Ken's block that are less that Naomi's one — 0.215. Naomi says the value which is heavier that all of Ken's values — 0.729 (again, exact value does not matter). Ken see that he won't win this point, so he wants to lose the smallest block — 0.215. 0.215 < 0.300 — this point goes to Naomi. The next pair will be 0.389 > 0.271 and so on. The last pair will be 0.992 > 0.728. 8 pairs — 8 points.

  • »
    »
    11 years ago, # ^ |
      Vote: I like it +18 Vote: I do not like it

    It's easy to prove in B that optimal answer is N = [X/C — 2/F]. Because X <= 100000, C >= 1, we can only consider all n <= 100000 by line and it wiil be correct solution.

  • »
    »
    11 years ago, # ^ |
    Rev. 2   Vote: I like it +11 Vote: I do not like it

    My accepted solution for deceitful war was :-

    Case #x: y z

    Here, in order to find y and z,

    int y = deceitful(naomi, ken);

    int z = N - deceitful(ken, naomi);

    Here, in order to find the score if naomi played game of war optimally, I considered that Ken played deceitful war.

    If you read the rules, Ken also knew the weight of Naomi's block before his chance. Using this, we can say that Ken too played deceitful war game

  • »
    »
    11 years ago, # ^ |
      Vote: I like it +8 Vote: I do not like it

    Wtf, why is there so many negative votes?

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      because ternary search in B was superfluous

»
11 years ago, # |
Rev. 2   Vote: I like it +9 Vote: I do not like it

Problem D is awesome. Let's order all 2N blocks by weight and mark them with +1 if the block belongs to Naomi and with -1 if the block belongs to Ken. Then: 1. The result of War game doesn't depend on Naomi's strategy and is equal to the maximum sum of the suffixes of the array. 2. The result of Deceitful War is equal to N minus the maximum sum of the prefixes of the array.

»
11 years ago, # |
Rev. 8   Vote: I like it +3 Vote: I do not like it

My C-Small Solution was pretty funny.

I figure out there is 225 different input at all, And how about precomputing them?

I used a Brute-Force for precomputing with O(2^RC), RC<=25 for each input, it takes about 1 minute to compute all of them. Then i put the result of this as a part of my final code.

And in final solution i just do a O(RC) to print the answers.

UPD : The picture below show a part of my code to avoid misunderstanding, i don't check states, i found them all before

  • »
    »
    11 years ago, # ^ |
      Vote: I like it +5 Vote: I do not like it

    Why any precomputing, when brute force works fast enough at all test cases? :)

    • »
      »
      »
      11 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      I thought i could hack that code with T=230 and for each R=5 C=5 M=22 ( Should Check 2^25 permutation for each 230 testcases ).

      Also we could do Memorization, But with precomputing i could trust my code will output less than 1 second.

      And also precomputing helps me finding bugs in my two wrong submissions ;)

      • »
        »
        »
        »
        11 years ago, # ^ |
          Vote: I like it +3 Vote: I do not like it

        That's not how GCJ tests work. If you want to check whether your code's correct with just 1 test file, that file should contain many different test cases. Also, a lot of them would probably be rather small.

        You know, your code can take minutes to produce the output...

        • »
          »
          »
          »
          »
          11 years ago, # ^ |
          Rev. 2   Vote: I like it +3 Vote: I do not like it

          Yes Surely, I just calculate the worst worst case of Brute-Force.

          My precomputings has been run in my oun computer, in something like this


          for(r=1;r<=5;r++) for(c=1;c<=5;c++) for(m=1;m<=r*c;m++) for(k=0;k<(1<<(r*c));k++){ if(check(k,r,c,m)){ cout<<"Per["<<r<<"]["<<c<<"]["<<m<<"]="<<k<<";"<<endl; break; } }

          and i only put output of this as a part of my final code ;-)

          My final solution was O(RC) without any permutation checking.