For simplicity we will assume that everyone in the pyramid weighs exactly 200 pounds. Person
A at the top of the pyramid has no weight on her back. People B and C are each carrying half of
person A's weight. That means that each of them is shouldering 100 pounds.
Now, let's look at the people in the third row. Let’s begin by focusing on person E. How much
weight is she supporting? Well, she’s directly supporting half the weight of person B (100
pounds) and half the weight of person E (100 pounds), so she’s supporting at least 200 pounds.
On top of this, she’s feeling some of the weight that people B and C are carrying. Half of the
weight that person B is shouldering (50 pounds) gets transmitted down onto person E and half
the weight that person C is shouldering (50 pounds) similarly gets sent down to person E, so
person E ends up feeling an extra 100 pounds. That means she’s supporting a net total of 300
pounds.
Write a recursive function (using no loops), weightOn(r,c), which returns the weight
on the back of the person in row r and and column c. Rows and columns are 0-based,
so the top position is (0,0), for example, and person H is in position (3,1). The following
also hold:
weightOn(0,0) == 0.00
weightOn(3,1) == 425.00
Weights should be floating-point numbers.
I have already tried a lot. I will include my most recent code below.
t = 0.0
x = 0.0
def weightOn(r, c):
global t
if r < 0:
print('Not valid')
elif r == 0 and c == 0:
return t
elif r > 0 and c == 0:
t += 200 / (2 ** r)
return weightOn(r - 1, 0)
elif r > 0 and c == r:
t += 200 / (2 ** r)
return weightOn(r - 1, 0)
elif r > c > 0:
mid(r, c)
return t
def mid(r, c):
global x
x = weightOn(r - 1, c - 1) + weightOn(r - 1, c)
'''I have also tried: x = (((weightOn(r - 1, c - 1) + 200) / 2) + ((weightOn(r - 1, c) + 200) / 2))'''
return x
r = int(input('r: '))
c = int(input('c: '))
weightOn(r, c)
if r > c > 0:
print(x)
else:
print(t)
It always brings up the wrong output. I can correctly pull up all of the edges (when c == 0 or c == r). But other than that it won't work.
Ex. Input (3, 1) outputs 500
(3, 2) outputs 550
Using global variables suggests that you haven't considered this recursively.
Each person shoulders half the weight of the persons on each shoulder. The effective weight of each person is what they shoulder, plus 200 pounds. If a person is on the edge, then the "person" on the other shoulder has 0 weight.
So ...
def weight(r, c):
# Code base cases
if r < 0: # Past the pyramid top; no such person
return 0
if c < 0 or c > r: # Off the edge; no such person
return 0
return 200 + (weight(r - 1, c - 1) + weight(r - 1, c)) / 2
Then weightOn is simply the above routine without the 200 +.
That's your outline; can you take it from there?
def weight_on (r,c):
second_person = 200 #finds out if there is a second person on top or not
if c - 1 < 0 or c > r - 1 :
second_person = 0
if c < 0 or c > r:
return 0
elif r <= 0:
return 0
else:
return (second_person + 200 + weight_on (r - 1,c - 1) + weight_on (r - 1,c))/2
Related
PROBLEM STATEMENT:
You are about to go shopping for some candy in a local store. They sell candy for either $1 or $2 pieces. You would like to know in how many unique ways you can purchase candy based on the amount of money you have.
def buying_candy(amount_of_money):
if amount_of_money < 2:
return 1
dp = {0: 1, 1: 1}
x = 1
while x < amount_of_money:
if x not in dp:
dp[x] = 1
dp[x] = dp[x] + dp[x - 1]
x += 1
return dp[amount_of_money - 1]
print(buying_candy(4))
OUTPUT: 5
EXPLANATION:
1 + 1 + 1 + 1
2 + 2
2 + 1 + 1
1 + 2 + 1
1 + 1 + 2
UPDATE:
SOLUTION of Problem
def buying_candy(amount_of_money):
if amount_of_money < 2:
return 1
dp = {
0: 1,
1: 1
}
x = 2
while x < amount_of_money + 1:
if x not in dp:
dp[x] = 1
dp[x] = dp[x - 1] + dp[x - 2]
x += 1
return dp[amount_of_money]
This problem does not require dynamic programming. Denote the amount of money by n. There are between 0 and ⌊n/2⌋ twos. If the number of twos is k, then the number of ones is n−2k, and the total number of ones and twos is n-2k+k = n-k. Each solution with k twos corresponds to choosing k out of the n-k positions for the twos. So the total number of solutions with k twos is (n-k choose k), and the total number of solutions is the sum of this expression over k from 0 and ⌊n/2⌋.
In Python:
import math
n = 4 # amount of money
total = sum(math.comb(n-k,k) for k in range(n//2+1)) # total number of solutions
print(total)
If the rules of the game require using dynamic programming, here is a correct version:
def buying_candies(n):
if n < 2:
return 1
dp = [1, 1] # use list instead of dictionary, as keys are 0,1,2,...
for i in range(2, n+1):
dp.append(dp[i-1] + dp[i-2])
return dp[n]
print(buying_candies(4))
It is all just Fibonacci sequence, in fact :)
So there is in fact a closed formula.
Given an arbitrary range of 1 to F and a starting point S with an ending point G such that the only directions we could go is L Left steps and R Right Steps (also arbitrary), create a general solution that will return the number of steps it would take to go from S to R if it is possible otherwise return not possible.
You are bound to the range [1, F] which means that you cannot move L or R steps if the next move will be more than F or less than 1
Example:
F = 100
S = 2
G = 1
L = 0
R = 1
Output: not possible
F = 10
S = 1
G = 10
L = 1
R = 2
Output: 6
Explanation: [1 -> 3(R) -> 5(R) -> 7(R) -> 9(R) -> 8(L) -> 10(R)]
I've been given this problem in our class and our current topic is binary search and divide and conquer. Here's my approach but this does not solve one hidden case.
F = int(input())
S = int(input())
G = int(input())
L = int(input())
R = int(input())
count = 0
while S != G:
dist = abs(S - G) # Takes the current distance from S to G
if S > G:
if S-L > 0:
S -= L
count += 1
else:
S += R
count += 1
else:
if S+R <= F:
S += R
count += 1
else:
S -= L
count += 1
if dist == abs(S - G): # If distance doesn't change after trying
print("not possible") # a move, conclude that it is not possible.
break
if S == G: print(count)
Mathematically this problem means that we are looking for
integer solutions (for x and y) of the following equation:
x * R - y * L = G - S
we can start by creating a function to check if there is a solution quickly:
def path(S, G, F, L, R):
x=0
while True:
y = (x * R - G + S) / L
if y>=0 and int(y)==y:
return(x,y)
else:
x+=1
This will work if there are solutions, but not if they are not.
It can be proved mathematically that there is no solution when L devides R but not G-S. Here is the proof:
If
R mod L =0 (L devides R)
(G - S)/L != 0 (L doesn't devide G-S)
then by deviding the whole equation (x * R - y * L = G - S) by L we take:
x * R/L - y = (G - S)/L <=>
y= (x * R/L) - (G - S)/L
Now, we want y mod 1 = 0 (means that y is integer) for x mod 1 =0 (x integers). Using common modulo operations we take:
y mod 1 = [(x * R/L) - (G - S)/L] mod 1 =
[(x * R/L) mod 1 - ((G - S)/L) mod 1] mod 1 =
[(x mod 1 * (R/L) mod 1) mod 1 - ((G - S)/L) mod 1] mod 1 =
[(x mod 1 * 0) mod 1 - ((G - S)/L) mod 1] mod 1 =
[((G - S)/L) mod 1] mod 1
This cannot be 0 if L doesn't devide G-S which eventally means that there are no pair of integers x,y that can satisfy the original condition.
Programatically this means for our code, the following additions:
def path(S, G, F, L, R):
if R%L==0 and (G-S)%L != 0 :
return 'No solutions'
x=0
while True:
y = (x * R - G + S) / L
if y>=0 and int(y)==y:
return(x,y)
else:
x+=1
I don;t know if mathematically we can prove that the above if is the only exception, it can probably be proved with some more modulo operations. Programatically we can add some clock in our code so that if there are no solutions, which means that it will go to infitive loop, we can return False after some time. Here is how we can do this:
How would I stop a while loop after n amount of time?
If the distance didn't change that doesn't mean it's impossible, you could have just jumped over the point and made it to the other side with the same distance, imagine L=2, R=1, S=3, G=2, you start distance 1 from goal, jump left (still distance 1) then jump right and win. What you need to check is whether you have gone in a loop and ended up at a location you have already tried before. You can either keep track of these locations (say in a set) or do some math ahead of time and figure out how many Ls and Rs it takes before you have definitely looped (probably not intended to figure this out).
F=int(input())
S=int(input())
G=int(input())
L=int(input())
R=int(input())
L*=-1
Fl=1-L
Fr=F-R
h0=set()
n=0
while True:
if S<G:
S+= R if S<=Fr else L
elif G<S:
S+= L if Fl<=S else R
else:
print(n)
break
if S in h0:
print('not possible')
break
h0.add(S)
n+=1
I am writing a code for a class in which I have to create a code that approximates the root of a cubic function between an interval using bisection. I have written a code in which should preform that, however; after inputting values for the variables, it preforms the print command then breaks and stops just before the while command. The text cursor enters into a new line like I am supposed to input more info when it's supposed to be executing the while loop().
import sys
print('The function should be in the format: Ax^3 + Bx^2 + Cx + D. ')
A = float(input(' What is the value of A? '))
B = float(input(' What is the value of B? '))
C = float(input(' What is the value of C? '))
D = float(input(' What is the value of D? '))
a = float(input(' What is the value of the smallest x-value of your interval? '))
b = float(input(' What is the value of the largest x-value of your interval? '))
g = a > b
interval = (b - a) / 2
tolerance = 10 ** -6
print(interval)
if g:
print('b must be larger than a'), sys.exit()
while interval > tolerance:
iteration = 0
p = (a + b) / 2
f0p = A * (p ** 3) + B * (p ** 2) + C * p + D
if f0p == 0:
print('The root of the function is', p)
else:
if p < 0 and a > 0:
b = p
if p < 0 and b > 0:
a = p
if p > 0 and a < 0:
b = p
if p > 0 and b < 0:
a = p
iteration += 1
print('The root is x=', p, ',calculated in', iteration, 'iterations.')
I have tried changing indentation, and I've looked everywhere as to why the while loop would refuse to execute and the text cursor would drop down to a new line as if it wanted more input.
It isn't waiting for additional input. You never modify the interval value, so the while loop condition is always true, and the loop just continues.
Your while loop gets executed, it just never finishes
A group of k boys, should be paid marbles as follows: they sit in a circle, and each boy will take 1 marble more than the boy to his right just did, and pass the bag with the remainder of the marbles to the boy on his left.
The leader starts by taking out 1 marble for himself. He passes the bag to the boy on his left, who then removes 2 marbles for himself, and passes the bag to his left. That boy then takes 3 coins and passes the bag on to his left, and so on. This process continues until the bag is empty (the last boy to take from the bag may not get as many marbles as he should).
I want to get the total number of marbles that the LEADER receives at the end of the process.
This is what I have, it works but it is too slow:
def countMarbles(n, k):
c = 0
leader = 0
while n>0:
for i in range(k):
c+=1
if i == 0:
if c<=n:
leader += c
else:
leader += n
n -= c
return leader
The marbles you are speding are 1, then 2, then 3...
There is a formula for this kind of sum, the sum of 1 to x is (x)(x + 1) / 2.
Now you are given n, and want to know how many passes of the bag you can make. This means getting highest x such that (x)(x + 1) / 2 is lower or equal to n.
We can get this by solving 0 = x^2 + x - 2n. We might get a decimal result there, so we should take the floor value of the positive answer to the equation.
Once we found the correct x, we just know that every k passes of the bag, 1 goes to the leader. He first gets 1 marble, then he gets k + 1 marbles, then 2k + 1...
If there were x passes, ceil of x / k went to the leader. Taking out the first pass which is always 1, we get l = ceil(x / k) - 1 passes that have a k coefficient greater than 0: ((k + 1) + (2k + 1) + ... + (lk + 1)) = (1 + 2 + 3 + ... + l) * k + l = (l * (l + 1) / 2) * k + l.
Considering leader started with 1, the solution is (l * (l + 1) / 2) * k + l + 1
The only problem is what happens with the remainding marbles that were left in the bag. In the case that those should have gone to leader, we also need to take them into account. For that to happen, x must be a multiple of k, meaning that we finished the round so the next should have been leader, but there were not enough marbles to make another pass.
Here is a python implementation:
import math
def solve (n, k):
x = math.floor((-1 + math.sqrt(1 + 8*n)) / 2)
l = math.ceil(x / k) - 1
sol = (l * (l + 1) / 2) * k + l + 1
if x % k == 0 :
sol += n - (x * (x + 1) / 2)
return int(sol)
So, I'm generating an array of spaces, which have the property that they can be either red or black. However, I want to prevent red from being enclosed by black. I have some examples to show exactly what I mean:
0 0 0 0 0 0 0 1
0 1 0 0 0 0 1 0
1 0 1 0 0 0 0 1
0 1 0 0 1 1 1 0
0 0 0 0 1 0 1 0
1 1 1 0 1 1 1 0
0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 0
If red is 0 and black is 1, then this example contains four enclosures, all of which I want to avoid when I generate the array. The inputs I have are the size of the array and the number of 1s I can generate.
How would I go about doing this?
Does this code fits well for you?
Basically I fill a matrix from left to right, from top to bottom.
When I have to assign 0 or 1 to a cell, I check (north and west) if adding a 1 could enclose a 0; in this case I put a 0, else a random 0 or 1.
import sys, random
n = int(sys.argv[1])
m = int(sys.argv[2])
# fill matrix with zeroes
matrix = [[0 for _ in xrange(m)] for _ in xrange(n)]
# functions to get north, south, west and east
# cell wrt this cell.
# If we are going out of bounds, we suppose the matrix
# is sorrounded by 1s.
def get_n(r, c):
if r <= 0: return 1
return matrix[r - 1][c]
def get_s(r, c):
if r >= n - 1: return 1
return matrix[r + 1][c]
def get_w(r, c):
if c <= 0: return 1
return matrix[r][c - 1]
def get_e(r, c):
if c >= m - 1: return 1
return matrix[r][c + 1]
# Checks if the cell is already enclosed by 3 1s.
def enclosed(r, c):
enclosing = get_n(r, c) + get_s(r, c) + get_w(r, c) + get_e(r, c)
if (enclosing > 3): raise Exception('Got a 0 enclosed by 1s')
return enclosing == 3
for r in xrange(n):
for c in xrange(m):
# check west and north
if enclosed(r, c - 1) or enclosed(r - 1, c):
matrix[r][c] = 0
else:
matrix[r][c] = random.randint(0, 1)
print str(matrix[r][c]) + ' ',
print ''
Sample run: python spaces.py 10 10
So you can do the following:
Fill array with zeroes
Randomly select a point
If the condition holds, flip color
Repeat from step 2 or exit
The condition holds for all-zeros array. It is hold on any iteration. So, by induction, it is also true for the final array.
In the step 4 you can decide whether to stop or continue by doing, say N=a*b*1000 iterations or whether the ratio red/black is close to 1. In both cases, the result would be slightly biased since you start from all zeros.
Now, what is the condition. You have to ensure that all black points connected and all red points connected as well. In other words, there's maximum 2 connected clusters. Flipping a color could create more connected clusters, so you flip only when the its number is one or two. You can do the check quite efficiently using Union-Find algorithm, described here.
Edit: if however you want to permit black points to be surrounded by red ones but not vice-versa, you may change the condition to have any number of black clusters but only 0 or 1 of red clusters.
This would be a possible way to check the condition:
def: findStart(myArr):
for i in range(len(myArr)):
for j in range(len(myArr[0])):
if(myArr[i][j] == 0):
return (i,j)
def: checkCon(myArr, number_Ones):
width = len(myArr[0])
height = len(myArr)
pen = [] #A list of all points that are waiting to get a visit
vis = [] #A list of all points that are already visited
x = findStart(myArr)
while(len(pen) != 0): #Visit points as long as there are points left
p = pen.pop() #Pick a point to visit
if p in vis:
#do nothing since this point already was visited
else:
vis.append(p)
x,y = p
#A vertical check
if(x == 0 and myArr[x+1][y] == 0):
pen.append((x+1,y))
elif(x == (height-1) and myArr[x-1][y] == 0):
pen.append((x-1,y))
else:
if(myArr[x-1][y] == 0 and x-1 >= 0):
pen.append((x-1,y))
if(myArr[x+1][y] == 0):
pen.append((x+1,y))
#A horizontal check
if(y == 0 and myArr[x][y+1] == 0):
pen.append((x,y+1))
elif(y == (width-1) and myArr[x][y-1] == 0):
pen.append((x,y-1))
else:
if(myArr[x][y+1] == 0):
pen.append((x,y+1))
if(myArr[x][y-1] == 0 and y-1 >= 0):
pen.append((x,y-1))
print((height*width-number_Ones) == len(vis)) #if true, alle Zeros are connected and not enclosed
To clarify this is just a concept to check the condition. The idea is to visit all connected zeros and see if there are any left (that are not connected). If that is the case, there are some enclosed.
This method also doesn't work when the 1's form a frame around the matrix like this:
1 1 1 1
1 0 0 1
1 0 0 1
1 1 1 1
Again, just a concept :)
The problem has two parts actually. Generating the board state, and then checking if it is correct. I realised that checking the correctness was actually worse than just being sure correct states were always generated. This is what I did:
Note that I have defined self.WallSpaces to be an array equal in length to the height of my array, comprised of integers with the number of bits equal to the width of my array. self.Width and self.Height provide the end indices for the array. Basically, Intersects works by checking all the spaces surrounding a point for 1s, except the direction the space was "built from" (see below) and returning True if any of these are the edge of the array or a 1.
def Intersects(self, point, direction):
if (point[0] > 0):
if (direction != [1, 0] and self.WallSpaces[point[0] - 1] & (1 << point[1]) != 0):
return True
if (point[1] == 0 or self.WallSpaces[point[0] - 1] & (1 << (point[1] - 1)) != 0):
return True
if (point[1] == self.Width or self.WallSpaces[point[0] - 1] & (1 << (point[1] + 1)) != 0):
return True
else:
return True
if (point[0] < self.Height):
if (direction != [-1, 0] and self.WallSpaces[point[0] + 1] & (1 << point[1]) != 0):
return True
if (point[1] == 0 or self.WallSpaces[point[0] + 1] & (1 << (point[1] - 1)) != 0):
return True
if (point[1] == self.Width or self.WallSpaces[point[0] + 1] & (1 << (point[1] + 1)) != 0):
return True
else:
return True
if (point[1] == 0 or (direction != [0, 1] and self.WallSpaces[ point[0] ] & (1 << (point[1] - 1)) != 0)):
return True
if (point[1] == self.Width or (direction != [0, -1] and self.WallSpaces[ point[0] ] & (1 << (point[1] + 1)) != 0)):
return True
return False
The directions GPacW.Left, GPacW.Right, GPackW.Up, and GPacW.Down represent the cardinal directions for movement. This function works by constructing "walls" in the array from random points, which can turn in random directions, ending when they have intersected twice.
def BuildWalls(self):
numWalls = 0
directions = [ [GPacW.Left, GPacW.Right], [GPacW.Up, GPacW.Down] ]
start = [ random.randint(0, self.Height), random.randint(0, self.Width) ]
length = 0
horizontalOrVertical = random.randint(0, 1)
direction = random.randint(0, 1)
d = directions[horizontalOrVertical][direction]
intersected = False
while (numWalls < self.Walls):
while (start == [0, 0] or start == [self.Height, self.Width] or self.Intersects(start, d)):
start = [ random.randint(0, self.Height), random.randint(0, self.Width) ]
if (length == 0):
horizontalOrVertical = not horizontalOrVertical
direction = random.randint(0, 1)
length = random.randint(3, min(self.Height, self.Width))
d = directions[horizontalOrVertical][direction]
if (self.WallSpaces[ start[0] ] & (1 << start[1] ) == 0):
self.WallSpaces[ start[0] ] |= 1 << start[1]
numWalls += 1
length -= 1
if (0 <= (start[0] + d[0]) <= self.Height and 0 <= (start[1] + d[1]) <= self.Width):
start[0] += d[0]
start[1] += d[1]
else:
start = [0,0]
if (self.Intersects(start, d)):
if (intersected):
intersected = False
start = [0,0]
length = 0
else:
intersected = True
return