Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google foobar python: failure on two tests - lovely lucky lambs (counting of sequences)

I was invited to play Google's foobar challenge. I am currently on Level 2.2 with following question.

Lovely Lucky LAMBs

Being a henchman isn't all drudgery. Occasionally, when Commander Lambda is feeling generous, she'll hand out Lucky LAMBs (Lambda's All-purpose Money Bucks). Henchmen can use Lucky LAMBs to buy things like a second pair of socks, a pillow for their bunks, or even a third daily meal! However, actually passing out LAMBs isn't easy. Each henchman squad has a strict seniority ranking which must be respected - or else the henchmen will revolt and you'll all get demoted back to minions again!

There are 4 key rules which you must follow in order to avoid a revolt:

  1. The most junior henchman (with the least seniority) gets exactly 1 LAMB. (There will always be at least 1 henchman on a team.)
  2. A henchman will revolt if the person who ranks immediately above them gets more than double the number of LAMBs they do.
  3. A henchman will revolt if the amount of LAMBs given to their next two subordinates combined is more than the number of LAMBs they get. (Note that the two most junior henchmen won't have two subordinates, so this rule doesn't apply to them. The 2nd most junior henchman would require at least as many LAMBs as the most junior henchman.)
  4. You can always find more henchmen to pay - the Commander has plenty of employees. If there are enough LAMBs left over such that another henchman could be added as the most senior while obeying the other rules, you must always add and pay that henchman.

Note that you may not be able to hand out all the LAMBs. A single LAMB cannot be subdivided. That is, all henchmen must get a positive integer number of LAMBs.

Write a function called answer(total_lambs), where total_lambs is the integer number of LAMBs in the handout you are trying to divide. It should return an integer which represents the difference between the minimum and maximum number of henchmen who can share the LAMBs (that is, being as generous as possible to those you pay and as stingy as possible, respectively) while still obeying all of the above rules to avoid a revolt.

For instance, if you had 10 LAMBs and were as generous as possible, you could only pay 3 henchmen (1, 2, and 4 LAMBs, in order of ascending seniority), whereas if you were as stingy as possible, you could pay 4 henchmen (1, 1, 2, and 3 LAMBs). Therefore, answer(10) should return 4-3 = 1. To keep things interesting, Commander Lambda varies the sizes of the Lucky LAMB payouts: you can expect total_lambs to always be between 10 and 1 billion (10 ^ 9).

MY APPROACH AND CODE

In order to find minimum henchmen, LAMBs have to be given out generously which has a geometric progression 1,2,4,8... Since sum of geometric progression is given by

( $S = 2^n -1$ therefore number of henchmen is [ log_2 (S+1) ]

To find maximum henchmen, LAMBs have to be given out in stingy fashion in order which appears to be fibbonaci 1 , 1, 2, 3, 5 ... We can use Fibonacci index method to obtain the maximum number of henchmen:

Following the python code:

from math import sqrt
from math import log
from math import pow

def answer(total_lambs):
    phi = (1+sqrt(5))/2  # golden search ratio
    tau = (1-sqrt(5))/2  # equal to 1/phi
    eps = pow(10, -10)

    max_hunchmen = int(round(log((total_lambs + 1) * sqrt(5)+eps, phi))) - 2
    Fib_num = int(round((pow(phi, max_hunchmen+2)-pow(tau,max_hunchmen+2))/sqrt(5)))
    if total_lambs+1 < Fib_num:
      max_hunchmen -= 1

    min_hunchmen = int(log((total_lambs + 1), 2))

    return abs(max_hunchmen - min_hunchmen)

There are 10 test cases (Google doesn't tell you the details). This code passes 8 of these and failing on last two. I am not sure if there is an edge case here that I am missing. Any help/suggestion is greatly appreciate. thanks!!

like image 283
gvavvari Avatar asked Apr 15 '17 17:04

gvavvari


1 Answers

phi = (1+sqrt(5))/2  
tau = (1-sqrt(5))/2  
eps = pow(10, -10)

max_hunchmen = int(round(log((total_lambs + 1) * sqrt(5)+eps, phi))) - 2
Fib_num = int(round((pow(phi, max_hunchmen+2)-pow(tau,max_hunchmen+2))/sqrt(5)))
if total_lambs+1 < Fib_num:
  max_hunchmen -= 1
elif total_lambs + 1 == Fib_num:
    total_lambs = Fib_num
if (total_lambs + 1) % 2 == 0:
     min_hunchmen = int(round(log((total_lambs + 1), 2)))
else:
    min_hunchmen = int(log((total_lambs + 1), 2))

return abs(max_hunchmen - min_hunchmen)
like image 103
Quantum Avatar answered Nov 14 '22 23:11

Quantum