Brick Tower Building Puzzle - python

I've been given a little brainteaser to solve.
The task is to make a function with a single integer parameter. You have to figure out how many different combination of tower patterns you can make with that given amount of bricks (each proceeding tower must be less in height than one previous, kind of like). There must be 2 or more towers, one right next to the other.
For example, if you were given 3 blocks you can only produce 1 combination of towers, one with a height of 2 and its neighbor having a height of 1:
|
| |
2 1
Given 4 you can only still produce one combination since the next tower must be shorter than the previous:
|
|
| |
3 1
Given 5 you can produce 2 combinations:
|
|
|
| |
4 1
|
| |
| |
3 2
I have a function that can do all of this, however they give the example that 200 blocks should produce 487067745. Which my function simply does not do. I don't know what I am doing wrong. A push in the right direction would be very much appreciated. My function now looks like this:
def answer(num):
# divide the blocks so we have two towers, one with a height of n-1 and
# the other with a height of one
l1 = num-1
l2 = 1
combinations = 0
while True:
if l1 > l2:
# add 1 to the combinations along with how many combinations we
# can make using the blocks from tower two
combinations += 1 + answer(l2)
elif l1 == l2:
# see if we can make additional towers out of the rightmost tower
# and add that to the combinations
combinations += answer( l2 )
else:
# if the first tower is smaller than or equal to the other tower
# then we stop trying to make combinations
return combinations
l1 -= 1
l2 += 1
While this method does work for smaller numbers of bricks (returning 2 combinations for 5 blocks and 1 combination for 3 or 4 blocks), it does not work for much larger numbers that would be impossible to do on sheets of paper.

Wikipedia gives the generating function for the number of partitions of n with distinct parts as q(n) = product (1+x^k) for k=1..infinity. Given that you exclude the possibility of a single tower, the number of different valid tower arrangements is q(n)-1.
This gives this neat O(n^2) time and O(n) space program for counting tower arrangements.
def towers(n):
A = [1] + [0] * n
for k in xrange(1, n+1):
for i in xrange(n, k-1, -1):
A[i] += A[i-k]
return A[n] - 1
print towers(200)
The output is as required:
487067745
To understand the code, one can observe that A stores the first n+1 coefficients of the generating function product(1+x^k) for k=1...infinity. Each time through the k loop we add one more term to the product. We can stop at n rather than infinity, because subsequent terms of the product do not affect the first n+1 coefficients.
Another, more direct, way to think about the code is to define T(i, k) to be the number of tower combinations (including the single tower) with i blocks, and where the maximum height of any tower is k. Then:
T(0, 0) = 1
T(i, 0) = 0 if i > 0
T(i, k) = T(i, k-1) if i < k
= T(i, k-1) + T(i-k, k-1) if i >= k
Then one can observe that after j iterations of the for k loop, A contains the values of T(j, i) for i from 0 to n. The update is done somewhat carefully, updating the array from the end backwards so that results are changed only after they are used.

Imagine calling the function answer(6). Your code returns 2, the correct answer however is 3 (5, 1; 4, 2; 3, 2, 1). Why is this? your code stops when the amount of blocks above the bottom tower is greater than the length of the bottom tower, so it sees 3, 3 and stops, it therefor never considers the combination 3, 2, 1.
My advice would be to rethink the function, try to take into account the idea that you can stack a number of blocks N on top of a tower that is less than N high.

Related

Python: Find the minimum number of seconds required to make speed of vehicle equals to zero or s=0?

#Dear all, could you help me please with this task to solve and find a code solution in Python?
#An engineer is calculating performance of a brake system for a vehicle. He wants to determine in how many seconds the brake system stops the vehicle or take the speed of the vehicle to 0. (s means SPEED of vehicle, b means BRAKE INTENSITY)
#There are 2 operations which can be performed in brake system
#Each operations take 1 sec to complete. These operations can’t happen in parallel. Your program can choose to perform any of the 2 operations at each step.
Find the minimum number of seconds required to make speed of vehicle equals to zero or s=0.
Input Format
#Each test case consists of a single line containing 2 integers. First Speed and second Brake Intensity.
s=>1,
b<=10**9;
#Speed and Brake Intensity range -
s>=1,
b=<10**9;
Output Format
For each test case print a single integer i.e. minimum number of seconds required to make the speed of the vehicle to 0.
Test Case 0: s = 9 and b = 2 In above test case, one of the optimal solutions is:
#Divide s by b. After this operation
s=4,
b=2
:
#Divide s by b. After this operation
s=2,
b=2;
#Increase b. After this operation
s=,
b=3;
#Divide s by b. After this operation
s=0,
b=3;
Can be solved with recursion as follows.
Note: Simple solution but maximum recursion depth exceeded for larger values of s.
def min_count(s, b):
'''
Finds mininum number of operations to reduce s to 0
Each step we can either:
1. reduce s to s // b (i.e. integer division of s by b)
2. increment b
'''
# Base cases
if s == 0:
return 0 # 0 steps, since s already 0
if b > s:
return 1 # only one step since s // b will be zero
# Recursion step
# Answer is 1 + min of both types of operationi counts
return 1 + min(min_count(s // b, b), min_count(s, b + 1))
>>> min_count(9, 2)
4
Using Priority Queue
def solve(s, b):
'''
In each step there are two possible moves
Replace first number by the
Reduce s by s // b
increment b by 1
We use a priority queue to update the state which has made the least moves so far
'''
h = [] # Use Priority queue so we can retrieve state with least number of moves each time
heappush(h, (0, s, b)) # Initial state: 0 moves, values s & b
while h:
# Get state which has the least number of moves
moves, s, b = heappop(h) # Get current moves s & b
if s == 0:
return moves # number of moves to reach 0
# Add two new states based upon two new possible moves
heappush(h, (moves + 1, s // b, b)) # increment moves by 1
heappush(h, (moves + 1, s, b + 1)) # increment moves by 1
>>> solve(9, 2)
4
>>> solve(100000000, 2) # Recursive version can not solve this
15

How do I modify this Fibonacci Sequence Problem?

I am trying to figure out how I can modify the code below to help solve the question given. However, instead of only being able to take 1 or 2 steps at a time, I want to make it so I can also take 3 steps.
You have a ladder of N steps (rungs). You can go up the ladder by taking either 1 step or two steps at a time, in any combination. How many different routes are there (combinations of 1 steps or 2 steps) to make it up the ladder?
Here is some code that I'm trying to modify:
def countP(n):
if (n == 1 or n == 2):
return n
return countP(n-1) + countP(n-2)
I've already tried this so far and I am not getting the correct answer:
def countP(n):
if (n == 1 or n == 2 or n == 3):
return n
return countP(n-1) + countP(n-2) + countP(n-3)
Any help of guidance would be of great help! Thanks
Your base case in the recursion for n = 3 is wrong.
For n = 3, the correct answer should be 4, but you are returning 3.
I suggest you to simplify the base case by using the following observations:
Utmost base case is when n <= 1 i.e when we have only one stair or no stair, hence the only way to climb is taking a step of 1 unit or 0 unit. Hence, number of ways is countP(0) = 1 and countP(1) = 1.
What happens when n > 1 ? Well, we have three options to take for first step - we can take m units (1 unit, 2 units or 3 units step) as first step provided m <= n.
If we can take 1 unit step as first step, we can reduce the sub-problem from countP(n) to countP(n-1).
If we can take 2 units step as first step, we can reduce the sub-problem from countP(n) to countP(n-2).
If we can take 3 units step as first step, we can reduce the sub-problem from countP(n) to countP(n-3).
So, our final count will be : countP(n - m) for all m <= n
Code will be as follows:
def countP(n):
if (n == 0 or n == 1):
return 1
count = 0
for m in [1, 2, 3]:
if m <= n:
count += countP(n - m)
return count
The line return n is correct for the first problem but not the second. Keep in mind that the result is supposed to be the number of possible routes you can take.
If you can take either one or two steps at a time, then when you have one rung left, there is only one thing to do: take one step. If you have two rungs left, you have two options: either take two steps, or take one step (one rung), then another (the second rung). So, somewhat by coindicence, for this version of the problem the number of routes in the base case happens to equal the number of rungs left.
If you can take either one, two or three steps at a time, then the number of routes when you have three rungs remaining is not three; there are more than three options. You will have to count how many options there are, and return that in the case where n == 3.

How to use random numbers that executes a one dimensional random walk in python?

Start with a one dimensional space of length m, where m = 2 * n + 1. Take a step either to the left or to the right at random, with equal probability. Continue taking random steps until you go off one edge of the space, for which I'm using while 0 <= position < m.
We have to write a program that executes the random walk. We have to create a 1D space using size n = 5 and place the marker in the middle. Every step, move it either to the left or to the right using the random number generator. There should be an equal probability that it moves in either direction.
I have an idea for the plan but do not know how to write it in python:
Initialize n = 1, m = 2n + 1, and j = n + 1.
Loop until j = 0 or j = m + 1 as shown. At each step:
Move j left or right at random.
Display the current state of the walk, as shown.
Make another variable to count the total number of steps.
Initialize this variable to zero before the loop.
However j moves always increase the step count.
After the loop ends, report the total steps.
1 - Start with a list initialized with 5 items (maybe None?)
2 - place the walker at index 2
3 - randomly chose a direction (-1 or + 1)
4 - move the walker in the chosen direction
5 - maybe print the space and mark the location of the walker
6 - repeat at step 3 as many times as needed

Dynamic programming stack of plates [duplicate]

I've been given a little brainteaser to solve.
The task is to make a function with a single integer parameter. You have to figure out how many different combination of tower patterns you can make with that given amount of bricks (each proceeding tower must be less in height than one previous, kind of like). There must be 2 or more towers, one right next to the other.
For example, if you were given 3 blocks you can only produce 1 combination of towers, one with a height of 2 and its neighbor having a height of 1:
|
| |
2 1
Given 4 you can only still produce one combination since the next tower must be shorter than the previous:
|
|
| |
3 1
Given 5 you can produce 2 combinations:
|
|
|
| |
4 1
|
| |
| |
3 2
I have a function that can do all of this, however they give the example that 200 blocks should produce 487067745. Which my function simply does not do. I don't know what I am doing wrong. A push in the right direction would be very much appreciated. My function now looks like this:
def answer(num):
# divide the blocks so we have two towers, one with a height of n-1 and
# the other with a height of one
l1 = num-1
l2 = 1
combinations = 0
while True:
if l1 > l2:
# add 1 to the combinations along with how many combinations we
# can make using the blocks from tower two
combinations += 1 + answer(l2)
elif l1 == l2:
# see if we can make additional towers out of the rightmost tower
# and add that to the combinations
combinations += answer( l2 )
else:
# if the first tower is smaller than or equal to the other tower
# then we stop trying to make combinations
return combinations
l1 -= 1
l2 += 1
While this method does work for smaller numbers of bricks (returning 2 combinations for 5 blocks and 1 combination for 3 or 4 blocks), it does not work for much larger numbers that would be impossible to do on sheets of paper.
Wikipedia gives the generating function for the number of partitions of n with distinct parts as q(n) = product (1+x^k) for k=1..infinity. Given that you exclude the possibility of a single tower, the number of different valid tower arrangements is q(n)-1.
This gives this neat O(n^2) time and O(n) space program for counting tower arrangements.
def towers(n):
A = [1] + [0] * n
for k in xrange(1, n+1):
for i in xrange(n, k-1, -1):
A[i] += A[i-k]
return A[n] - 1
print towers(200)
The output is as required:
487067745
To understand the code, one can observe that A stores the first n+1 coefficients of the generating function product(1+x^k) for k=1...infinity. Each time through the k loop we add one more term to the product. We can stop at n rather than infinity, because subsequent terms of the product do not affect the first n+1 coefficients.
Another, more direct, way to think about the code is to define T(i, k) to be the number of tower combinations (including the single tower) with i blocks, and where the maximum height of any tower is k. Then:
T(0, 0) = 1
T(i, 0) = 0 if i > 0
T(i, k) = T(i, k-1) if i < k
= T(i, k-1) + T(i-k, k-1) if i >= k
Then one can observe that after j iterations of the for k loop, A contains the values of T(j, i) for i from 0 to n. The update is done somewhat carefully, updating the array from the end backwards so that results are changed only after they are used.
Imagine calling the function answer(6). Your code returns 2, the correct answer however is 3 (5, 1; 4, 2; 3, 2, 1). Why is this? your code stops when the amount of blocks above the bottom tower is greater than the length of the bottom tower, so it sees 3, 3 and stops, it therefor never considers the combination 3, 2, 1.
My advice would be to rethink the function, try to take into account the idea that you can stack a number of blocks N on top of a tower that is less than N high.

Iterating over a large list

I have a list in the range [465868129, 988379794] both inclusive. When I use the following code I get a Memory Error. What can I do?
r = [465868129, 988379794]
list = [x for x in xrange(r[0], r[1]+1)]
You could iterate over the xrange directly instead of creating a list.
for x in xrange(r[0], r[1] + 1):
...
But iterating over such a large range is a very, very slow way to find squares. The fact that you run out of memory should alert you that a different approach is needed.
A much better way would be to take the square roots of each end point and then iterate between the square roots. Each integer between the square roots, when squared, would give you one of the numbers you're searching for.
In fact, if you're clever enough, you can generate all the squares with a single list comprehension and avoid an explicit for loop entirely.
Unless you have a very good reason to store the list items in a list, iterate over the generator instead, that way Python won't need to allocate a lot of memory (causing your Memory Error) to create that list:
init, end = (465868129, 988379794)
items = xrange(init, end + 1)
for item in items:
#Do something with item
To count squares on an arbitrary range consider the following formula:
import math
number_of_squares = int(math.sqrt(end) - math.sqrt(init)) +
op(is_perfect_square(init), is_perfect_square(end))
The is_perfect_square(n) is another problem on its own, so check this post if interested.
The op is used to adjust the number of squares when the init and end of the intervals init (or/and/neither) end are perfect squares. So we need a function with the following characteristics:
Both numbers are perfect squares: Eg: 25,64 => 8 - 5 = 3 (and there are 4 squares on that range). (it should sum 1 more)
End is a perfect square: Eg: 26,64 => 8 - 5 = 3 (There are 3 squares on that range). (it is correct => it should sum 0)
Init is a perfect square: Eg: 25,65 => 8 - 5 = 3 (There are 4 squares on that range). (it should sum 1 more)
None of the numbers are primes: Eg: 26, 65 => 8 - 5 = 3 (There are 3 squares on that range) (it is correct => it should sum 0)
So we need an operator with the following characteristics, based on the past examples:
1 op 1 = 1 (Both numbers are perfect squares)
0 op 1 = 0 (End is a perfect square)
1 op 0 = 1 (Init is a perfect square)
0 op 0 = 0 (None of the numbers are perfect squares)
Note that the max function almost fulfils our needs, but it fails on the second case max(0,1) = 1 and it should be 0.
So, looks like the result only depends on the first operator: if it's one, the result is 1, on the other hand if it's 0, it returns 0.
So, it's easy to write the function with that in mind:
import math
number_of_squares = int(math.sqrt(end) - math.sqrt(init)) +
int(is_perfect_square(init))
Thanks to #kojiro, we have this approach (having a similar idea), which is easier to read:
from math import sqrt, floor, ceil
number_of_squares = 1 + floor(sqrt(end)) - ceil(sqrt(init))

Categories