Hackerrank - Minimum Time Required Solution

Hackerrank - Minimum Time Required Solution

You are planning production for an order. You have a number of machines that each have a fixed number of days to produce an item. Given that all the machines operate simultaneously, determine the minimum number of days to produce the required order.

For example, you have to produce  items. You have three machines that take  days to produce an item. The following is a schedule of items produced:

Day Production  Count
2   2               2
3   1               3
4   2               5
6   3               8
8   2              10

It takes  days to produce  items using these machines.

Function Description

Complete the minimumTime function in the editor below. It should return an integer representing the minimum number of days required to complete the order.

minimumTime has the following parameter(s):

  • machines: an array of integers representing days to produce one item per machine
  • goal: an integer, the number of items required to complete the order

Input Format

The first line consists of two integers  and , the size of  and the target production.
The next line contains  space-separated integers, .

Constraints

Output Format

Return the minimum time required to produce  items considering all machines work simultaneously.

Sample Input 0

2 5
2 3

Sample Output 0

6

Explanation 0

In  days  can produce  items and  can produce  items. This totals up to .

Sample Input 1

3 10
1 3 4

Sample Output 1

7

Explanation 1

In  minutes,  can produce  items,  can produce  items and  can produce  item, which totals up to .

Sample Input 2

3 12
4 5 6

Sample Output 2

20

Explanation 2

In  days  can produce  items,  can produce , and  can produce .

Solution in Python

from math import ceil
from collections import Counter

def minTime(machines, goal):
    c = Counter(machines)
    fastest = min(c)
    min_days = 1
    max_days = ceil((fastest*goal)/c[fastest])
    while max_days-min_days>1:
        mid = (min_days+max_days)//2
        output = sum((mid//x)*y for x,y in c.items())
        if output<goal:
            min_days = mid
        else:
            max_days = mid
    return max_days

n,goal = map(int,input().split())
machines = list(map(int,input().split()))
print(minTime(machines, goal))

Algorithm explanation

We know that since the goal is atleast 1, then we need a minimum of 1 day to complete the task and a maximum of 1018 days (when goal is 1 and the number of machine is 1 and it's rate is 1).

So, we can iterate over all the days starting from 1 and check for each number of days if our goal can be accomplished by traversing the array and getting the total count of number of items produced in that many number of days. The complexity is this approach will be O(days*n), which will not pass as number of days can be as larges as 1018. We can do better.

This problem can be solved using binary search over the answer. Since we have the  and  pointers, we can apply binary search. Now, at every iteration we check if we can complete our task in  days by traversing the array and summing up the total items produced by each machine. If yes, then we move towards left else we move towards right (Since, we need to minimize the answer).

Python code explanation

Lets machines = [2,3,2] and goal = 20

First, we group machines that take the same number of days using Counter

>>> c = Counter(machines)
>>> c
Counter({2: 2, 3: 1})

We already know that minimum days it will take to reach our goal is 1 therefore, min_days = 1

Now we have to find the maximum days it will take.

Maximum days will be given by goal*days taken by fastest machine/total count of the fastest machine

Our fastest machine produces 1 unit in 2 days therefore it will take at least 2*goal = 2*20 = 40 days if we use only 1 of our fastest machine.

>>> fastest = min(c)
>>> fastest
2

But since we have 2 counts of our fastest machine we will divide this number by 2

Therefore max_days = 20

>>> max_days = ceil((fastest*goal)/c[fastest])
>>> max_days
20

Now we know that our total number of days will be anywhere between 1 to 20 days

The number of output produced by a machine on a particular day can be obtained by days//number of days to produce 1 unit

Example day = 5, machine speed = 2, i.e 1 unit every 2 days

Total output in day 5 = 5//2 = 2

If we have more than 1 of the same machine, (5//2)*number of machines

For example, on day 5 our fastest machine will product 5//2*2 = 4 units instead of 2 since we have more than one of the same machines.

Therefore we can use the following code to find the total output on a particular day for all machines combined.

>>> sum((day//x)*y for x,y in c.items())

where x is number of days taken by that machine to produce 1 unit and y is the total count of that machine

Now the looping part

while max_days-min_days>1:
    mid = (min_days+max_days)//2
    output = sum((mid//x)*y for x,y in c.items())
    if output<goal:
        min_days = mid
    else:
        max_days = mid

Since we know that it will take anywhere between 1 to 20 days. We will check how many outputs we get in the midpoint that is 20+1//2 = 10th day.

mid = (min_days+max_days)//2 = 10

>>> sum((mid//x)*y for x,y in c.items())
13

Now we know that on the 10th day our total output will be only 13 which means our required answers come after day 10.

Since now we know that it will take atleast 10 day to reach our goal. Therefore we set min_days = min i.e.(min_days = 10)

>>> sum((mid//x)*y for x,y in c.items())
19

Now min_days= 10 and max_days= 20, mid = (10+20)//2 = 15

19 still less than 20 but very close.  Again min_days = min i.e.(min_days = 15)

Now min_days= 15 and max_days= 20, mid = (15+20)//2 = 17

>>> sum((mid//x)*y for x,y in c.items())
21

Since 21 exceeds our goal=20, We now set max_days = mid i.e(max_days = 17)

Now min_days= 15 and max_days= 17, mid = (15+17)//2 = 16

>>> sum((mid//x)*y for x,y in c.items())
21

Since 21 exceeds our goal=20, We now set max_days = mid i.e(max_days = 16)

Now min_days= 15 and max_days= 16, mid = (15+17)//2 = 16

>>> sum((mid//x)*y for x,y in c.items())
21

We stop when max_days-min_days = 1. Our required answer will be max_days i.e. 16.

Since, we have already calculated earlier than we don't reach our goal when days = min_days.

That's it. If you have any confusion leave a comment below.

Subscribe to The Poor Coder | Algorithm Solutions

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
[email protected]
Subscribe