Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Given a problem:
You have a certain amount of soldiers.
Each soldier has a given rank (some are officers, sergeants, etc). Now they are to go and kill some guys.
You have a limited amount of ammunition. Depending on the rank, each person is given a box of ammunition. The soldiers are standing in a straight line.
The person with a higher rank has to be given more ammunition if a person of lower rank is next to him.
Each person has to be given at least one box.
Example: using numbers from 1 upwards to represent rank: 4 2 3 2 2 1 3 6. the equivalent boxes of ammunition are: 2 1 2 1 2 1 2 3.
The fastest way for me to come up with the list of ammunition is to take the first three ranks and compare them to each other (i.e. from the example, I pick 4 2 3 ).Next I increment by one (i.e. 2 3 2) and make a comparison again. Obviously, this takes a lot of time.Is there a faster way?
NOTE: Soldiers with same rank standing next to each other don't care how much ammunition each has.
soldier_num = int(input())
i = 0
rating_array = []
ammo_array = []
can_can = soldier_num
while(i < soldier_num):
rating_array.append(int(input()))
ammo_array.append(1)
i += 1
i = 0
while(i < soldier_num):
if(i == 0):
if((rating_array[i] > rating_array[i+1]) and (ammo_array[i] <= ammo_array[i+1])):
ammo_array[i] += 1
i = i-1
can_can += 1
if(0<i<(soldier_num-1)):
if((rating_array[i] > rating_array[i+1]) and (ammo_array[i] <= ammo_array[i+1])):
ammo_array[i] += 1
i = i-1
can_can += 1
elif((rating_array[i] > rating_array[i-1]) and (ammo_array[i] <= ammo_array[i-1])):
ammo_array[i] += 1
i = i-1
can_can += 1
elif((rating_array[i] < rating_array[i-1]) and (ammo_array[i] >= ammo_array[i-1])):
ammo_array[i-1] += 1
i = i-1
can_can += 1
elif((rating_array[i] < rating_array[i+1]) and (ammo_array[i] >= ammo_array[i-1])):
ammo_array[i+1] += 1
i = i-1
can_can += 1
i += 1
if(i == (soldier_num-1)):
if((rating_array[i] > rating_array[i-1]) and (ammo_array[i] <= ammo_array[i-1])):
ammo_array[i] += 1
can_can += 1
print(can_can)
There are 4 possible categories for each number:
Both neighbors are higher (valley)
Both neighbors are lower (peak)
Left is higher, right is lower (downhill)
Right is higher, left is lower (uphill)
Count out-of-bounds indices as infinity when you're looking for valleys and 0 when looking for peaks. Since you say "neighbors of the same rank don't care", you can count them the same way.
First reduce all the valleys to 1. This should be straightforward.
To reduce the uphill elements, iterate through the array and reduce them to left+1.
To reduce the downhill ones, iterate backwards and reduce them to right+1.
Finally, peaks are lowered to whichever neighbor is higher, plus one.
For your example:
4 2 3 2 2 1 3 6 < original
4 1 3 1 2 1 3 6 < valleys reduced
4 1 3 1 2 1 2 3 < uphill reduced
2 1 3 1 2 1 2 3 < downhill reduced
2 1 2 1 2 1 2 3 < peaks reduced
Hint:You have to define peaks and valleys in this case. Peaks are elements that are >= their nieghbours. Valleys are elements <= their neighbours.
Assign 1 box to the valleys.
The peaks and valleys shall alternate. The number of boxes to peak = larger of distance from previous valley and next valley.
Related
Sorry for the formatting. New at posting questions
I was practicing this problem asked in the last round of Google Kick Start 2020. The problem is called Record Breaker and is as follows:
Isyana is given the number of visitors at her local theme park on N consecutive days. The number of visitors on the i-th day is Vi. A day is record breaking if it satisfies both of the following conditions: The number of visitors on the day is strictly larger than the number of visitors on each of the previous days. Either it is the last day, or the number of visitors on the day is strictly larger than the number of visitors on the following day. Note that the very first day could be a record breaking day!
Please help Isyana find out the number of record breaking days.
Input: The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the integer N. The second line contains N integers. The i-th integer is Vi.
Output: For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the number of record breaking days.
Limits Time limit: 20 seconds per test set. Memory limit: 1GB. 1 ≤ T ≤ 100. 0 ≤ Vi ≤ 2 × 105.
Test set 1
1 ≤ N ≤ 1000.
Test set 2
1 ≤ N ≤ 2 × 105 for at most 10 test cases. For the remaining cases, 1 ≤ N ≤ 1000.
Sample
Input
4
8
1 2 0 7 2 0 2 0
6
4 8 15 16 23 42
9
3 1 4 1 5 9 2 6 5
6
9 9 9 9 9 9
Output
Case #1: 2
Case #2: 1
Case #3: 3
Case #4: 0
In Sample Case #1, the bold and underlined numbers in the following represent the record breaking days: 1 2 0 7 2 0 2 0.
In Sample Case #2, only the last day is a record breaking day.
In Sample Case #3, the first, the third, and the sixth days are record breaking days.
In Sample Case #4, there is no record breaking day.
This is the solution I created. It gives a Wrong Answer in the first Test Case but I can't think of any specific case that I have missed.
def sol(testcase):
days = int(input())
record_breaking = 0
greatest = 0
visitors = [0] + list(map(int, input().split())) + [0]
for x in range(days+1):
if x == 0:
continue
if visitors[x] > greatest:
greatest = visitors[x]
if (visitors[x] > visitors[x-1]) and (visitors[x] > visitors[x+1]):
record_breaking += 1
print(f"Case #{testcase}: {record_breaking}")
testcases = int(input())
for x in range(testcases):
sol(x+1)
// Here Is Your Answer Cleared All Test Cases
T = int(input())
for i in range(T):
N = int(input())
Vs = [int(v) for v in input().split(" ")]
max_number = -1
record_breaks = 0
for j in range(N):
first_condition = Vs[j] > max_number
if j+1 < N:
second_condition = Vs[j] > Vs[j+1]
else:
second_condition = True
if first_condition and second_condition:
record_breaks +=1
if first_condition:
max_number = Vs[j]
print("Case #{}: {}".format(str(i+1), str(record_breaks)))
My solution exceeds the time limit and I can't come up with a faster solution, still very much a beginner. How can I improve it?
The problem:
A perfect ICPC team is made up of at least 1 mathematician and 1 programmer and it must have 3 members. You have the number of mathematicians, programmers and students that have no specialization. What is the maximum number of perfect teams you can make? C students are programmers, M students are mathematicians and X don't have a specialization.
Example input:
1 1 1
Example output:
1
Example input:
3 6 0
Example output:
3
Example input:
10 1 10
Example output:
1
My solution:
cmx = [int(x) for x in input().split()]
i = 0
while 0 not in cmx:
cmx[0] -= 1
cmx[1] -= 1
cmx[2] -= 1
i += 1
if cmx[0] != 0 and cmx[1] != 0 and cmx[2] == 0:
while sum(cmx) >= 3 and cmx[0] != 0 and cmx[1] != 0:
if cmx[0] >= cmx[1]:
cmx[0] -= 2
cmx[1] -= 1
i += 1
elif cmx[0] < cmx[1]:
cmx[0] -= 1
cmx[1] -= 2
i += 1
print(i)
Assume that M ≤ C. (Proof works identically if C ≤ M). How many teams can I make. It's clear that if M + C + X ≥ 3M, then I can easily make M teams. (Every team has a mathematician, a programmer, and either a second programmer or a "none".) And I can't make more than M teams. If M + C + X < 3M, then the most I can have is (M + C + X) / 3 teams, and again you make them the same way, since you have sufficient mathematicians and programmers.
The proof works identically if C ≤ M.
So min(M, C, (M + C + X) // 3). As stated above.
A simpler way of looking at it is that C, M, and (C + M + X)//3 are each, independently, an upper bound on the number of teams that you can form. You just have to show the smallest of these three upper bounds is, in fact, a reachable value.
For each index of a sorted array i = 1,...,N in this new array I want to find all indexes j such that xj is in the set (xi-5, xi+5).
x= np.array([1,2,2,3,4,6,7,9])
n=len(x)
for i in range(n):
for j in range(n):
if x[i] - 5 < x[j] and x[i] + 5 > x[j]:
print(j)
So for this array example I gave, when i=0, x=1. So it should return [1,2,3,4] because they are all in (x_1-5, x_1+5). Then when i=1, x=2, and should return [0,2,3,4,5] and so on. I should get N arrays.
But, the output gives me
0 1 2 3 4 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 6 0 1 2 3 4 5 6 1 2 3 4 5 6 7 3 4 5 6 7 5 6 7
I don't know how I can implement this and I think the problem is for j in x since it is the same as the first loop. In my eyes, it says for every i, if any xj is in (xi-5,xi+5) then return the jth element. But, I want to return N sets.
Writing your indexes that way is probably what is confusing you.
If you want to access an index that is n-2 then you have to index it that way.
What you are doing is accessing the nth index of your list and then subtracting or adding 2 from the value that you accessed.
x[i]
returns whatever value is at position i in the list.
x[i-2]
will return whatever value is at position i-2.
Also you will need to account for the fact that subtracting any number from your index variable will cause your resulting index to be out of bounds if the resulting index is greater than the length of the list - 1 or less than 0.
If you are looking for duplicates the best way is to sort first then compare neighbors.
for i in x:
if x[i] == x[i+1]:
print i;
Subsetting is done like this: x[i-2:i+2]
So to divide into n sets of 2 elements you would:
n=2
for i in x:
if i+n < len(x):
return x[i:i+n];
To divide into n sets of equal number of elements you would:
n = // Some arbitrary number.
j = int(len(x) / n);
for i in x:
if i+j < len(x):
return x[i:i+j];
for i in range(0,x):
for j in range(0,y):
if (i+j)%2 == 0:
Think of something like tossing two dices at the same time and finding if the sum on the dices is an even number but here's the catch, a dice has 6 sides but here the two can have any number of sizes, equal and not equal even!
Can anyone suggest how to merge it under one loop because I can't think of any?
based on Python combine two for loops, you can merge two for loops in a single line by importing itertools as below:
import itertools
for i, j in itertools.product(range(0,x), range(0,y)):
if (i+j)%2 == 0:
You can't get rid of the nested loop (you could hide it, like by using itertool.product, but it would still be executed somewhere, and the complexity would still be O(x * y)) but you can get rid of the condition, if you only need to generate the values of j that satisfy it, by adapting the range for j.
This way, you'll have about twice as less loops by avoiding the useless ones.
for i in range(0,x):
for j in range(i%2,y, 2):
print(i, j, i+j)
Output:
0 0 0
0 2 2
1 1 2
1 3 4
2 0 2
2 2 4
For me its much cleaner to leave it as two loops. Its much more readable and easier to understand whats happening. However you could essentially do x * y then use divmod to calculate i and j
x = 2
y = 3
for i in range(0,x):
for j in range(0,y):
print(i, j, i+j)
print("###")
for r in range(x*y):
i, j = divmod(r, y)
print(i, j, i + j)
OUTPUT
0 0 0
0 1 1
0 2 2
1 0 1
1 1 2
1 2 3
###
0 0 0
0 1 1
0 2 2
1 0 1
1 1 2
1 2 3
Please excuse my naivete as I don't have much programming experience. While googling something for an unrelated question, I stumbled upon this:
https://www.geeksforgeeks.org/find-number-of-solutions-of-a-linear-equation-of-n-variables/
I completely understand the first (extremely inefficient) bit of code. But the second:
def countSol(coeff, n, rhs):
# Create and initialize a table
# to store results of subproblems
dp = [0 for i in range(rhs + 1)]
dp[0] = 1
# Fill table in bottom up manner
for i in range(n):
for j in range(coeff[i], rhs + 1):
dp[j] += dp[j - coeff[i]]
return dp[rhs]
confuses me. My question being: why does this second program count the number of non-negative integer solutions?
I have written out several examples, including the one given in the article, and I understand that it does indeed do this. And I understand how it is populating the list. But I don't understand exactly why this works.
Please excuse what must be, to some, an ignorant question. But I would quite like to understand the logic, as I think it rather clever that such a little snip-it is able able to answer a question as general as "How many non negative integer solutions exist" (for some general equation).
This algorithms is pretty cool and demonstrates the power of looking for a solution from a different perspective.
Let's take a example: 3x + 2y + z = 6, where LHS is the left hand side and RHS is the right hand side.
dp[k] will keep track of the number of unique ways to arrive at a RHS value of k by substituting non-negative integer values for LHS variables.
The i loop iterates over the variables in the LHS. The algorithm begins with setting all the variables to zero. So, the only possible k value is zero, hence
k 0 1 2 3 4 5 6
dp[k] = 1 0 0 0 0 0 0
For i = 0, we will update dp to reflect what happens if x is 1 or 2. We don't care about x > 2 because the solutions are all non-negative and 3x would be too big. The j loop is responsible for updating dp and dp[k] gets incremented by dp[k - 3] because we can arrive at RHS value k by adding one copy of the coefficient 3 to k-3. The result is
k 0 1 2 3 4 5 6
dp[k] = 1 0 0 1 0 0 1
Now the algorithm continues with i = 1, updating dp to reflect all possible RHS values where x is 0, 1, or 2 and y is 0, 1, 2, or 3. This time the j loop increments dp[k] by dp[k-2] because we can arrive at RHS value k by adding one copy of the coefficient 2 to k-2, resulting in
k 0 1 2 3 4 5 6
dp[k] = 1 0 1 1 1 1 2
Finally, the algorithm incorporates z = 1, 2, 3, 4, 5, or 6, resulting in
k 0 1 2 3 4 5 6
dp[k] = 1 1 2 3 4 5 7
In addition to computing the answer in pseudo-polynomial time, dp encodes the answer for every RHS <= the input right hand side.