I'm losing my mind with this codewars/project euler problem: https://www.codewars.com/kata/551f23362ff852e2ab000037/train/python
I need to find the max sum in all of the possible pyramid slide downs, and as of right know I'm trying to calculate the possible slide downs that exist in the pyramid. It works fine but for integers bigger than 25 the function begins to be really slow.
My code is this:
def find_seq(x):
'''
input: x, positive integer greater than 1
Returns an array with the slides from the top to the bottom of
an x floors high pyramid
'''
list_slides = []
if x == 2:
return [[0,0],[0,1]]
else:
prev_slides = find_seq(x-1)
for el in prev_slides:
list_slides.append([0]+el)
for el in prev_slides:
list_slides.append([0]+list(i+1 for i in el))
return list_slides
I can see that for each new floor the calculating time grows exponentially but I can't think of any other way to adress the problem.
tl;dr: Go from the bottom up for linear complexity.
Well, you are right it grows exponentially.
The problem is not your code, but your direction.
Let's look at the pyramid from bottom up - you can see right away that if you are at the second to last layer and you want to slide down, you will choose the path that is directly under you and has the larger value, i.e you can slide only left or right and the bigger will be better.
Now, going up to the third to last, you only need to find the route down to the floor below which is the best (summing up the value of the bottom floor of course).
keep going like that to the top of the pyramid and by the end, you get the value of the best route, or longest slide.
code:
def longest_slide_down(pyramid):
if len(pyramid) == 1:
return pyramid[0][0]
last_layer = pyramid[-1]
add_layer = []
for i in range(1, len(last_layer)):
add_layer.append(max(last_layer[i], last_layer[i-1]))
pyramid[-2] = [a+b for a, b in zip(pyramid[-2], add_layer)]
return longest_slide_down(pyramid[:-1])
And for the efficiency seekers out there, a numpyed version of the same code:
import numpy as np
def longest_slide_down(pyramid):
if len(pyramid) == 1:
return pyramid[0][0]
pyramid = np.array(pyramid)
pyramid[-2] += np.maximum(pyramid[-1][:-1], pyramid[-1][1:])
return longest_slide_down(pyramid[:-1])
Related
I have a problem regarding a competition question I'm attempting to do. Here is the question (its a bit long)
""""
Welcome aboard, Captain! Today you are in charge of the first ever doughnut-shaped spaceship, The
Circular. There are N cabins arranged in a circle on the spaceship. They are numbered from 1 to N in
a clockwise direction around the ship. The ith and the (i + 1)th cabins are connected. So too are cabin
1 and cabin N.
Currently the ith cabin has Ai crewmates, however the spaceship cannot depart unless there are exactly
Bi crewmates in this cabin.
To achieve this, you have the power to pay crewmates to change cabins. You can pay a crewmate $1 to
move to an adjacent cabin. A crewmate can be asked to move multiple times, provided that you pay
them $1 each time.
What is the fewest dollars you must pay before you can depart? It is always be possible to depart.
""""
https://orac2.info/problem/aio22spaceship/ (the link to the intereactive Qs)
I searched the web and i found no solutions to the Q. My code seems to be infinite looping i guess but im not sure as i cant see what cases the sit uses to determine if my code is right.
Heres my code
#!/usr/bin/env python
import sys
sys.setrecursionlimit(1000000000)
#
# Solution Template for Spaceship Shuffle
#
# Australian Informatics Olympiad 2022
#
# This file is provided to assist with reading and writing of the input
# files for the problem. You may modify this file however you wish, or
# you may choose not to use this file at all.
#
# N is the number of cabins.
N = None
# A contains the initial number of crewmates in each cabin. Note that here the
# cabins are numbered starting from 0.
A = []
# B contains the desired number of crewmates in each cabin. Note that here the
# cabins are numbered starting from 0.
B = []
answer = 0
# Open the input and output files.
input_file = open("spacein.txt", "r")
output_file = open("spaceout.txt", "w")
# Read the value of N.
N = int(input_file.readline().strip())
# Read the values of A and B.
input_line = input_file.readline().strip()
A = list(map(int, input_line.split()))
input_line = input_file.readline().strip()
B = list(map(int, input_line.split()))
AM = A
#AM is my modifying set
# TODO: This is where you should compute your solution. Store the fewest
# dollars you must pay before you can depart into the variable
while AM != B:
#Check if the set is correct
#notfound is a testing variable to see if my code was looping due to input error
notfound = True
for i in range(N):
#Check which places needs people to be moved
while AM[i]>B[i]:
notfound = False
#RV and LV check the "neediness" for each half's people requirements. I check how many people
#are needed on one side compared to the other and subtract the "overflow of people"
RV = 0
LV = 0
for j in range(int(N/2-0.5)):
#The range thing makes sure that if N is odd, im splitting the middle but if N is even, i leave out the end pod
RV += B[(i+j+1)%N]-AM[(i+j+1)%N]
LV += B[(i-j-1)%N]-AM[(i-j-1)%N]
answer +=1
if RV>LV:
AM[i]+=-1
AM[(i+1)%N]+=1
else:
AM[i]+=-1
AM[(i-1)%N]+=1
print(AM,B)
if notfound:
break
print(answer)
# Write the answer to the output file.
output_file.write("%d\n" % (answer))
# Finally, close the input/output files.
input_file.close()
output_file.close()
please help i really neeed to know the answer, driving me mad ngl
Welp, there aren't any resources online and I've tried everything. I think the problem might be that because of my solving method, passengers may be flicked between two pods indefinitely. Not sure since i could make a case that demoed this.
also my post probably is messy since this is my first time posting
My Idea is as follows and i want to really get to learn more about programming and how to structure a program:
I want to let count waves on a stock chart.
Within the Elliott Wave Rules are some specifications, like (most basic):
Wave 2 never retraces more than 100% of wave 1.
Wave 3 cannot be the shortest of the three impulse waves, namely waves 1, 3 and 5.
Wave 4 does not overlap with the price territory of wave 1, except in the
rare case of a diagonal triangle formation.
(from Wikipedia https://en.wikipedia.org/wiki/Elliott_wave_principle#Wave_rules_and_guidelines)
There are more sophisticated rules of course, but in my imagination, they could be addressed by the same iterative logic like in which I want to apply my rules.
Please guys, and girls, give me feedback on my thoughts if they make any sense in structure and layout to set up a program or not, because i lack experience here:
I want to find the minima and maxima, and give them a wavecount depending on the minima and maxima before.
Therefore i would check every candle (every closing price, day, hour, etc) if the value is below or above the previous value and also values. For example:
If there are two candles going up, then one down, then three up, then two down, then two up, this could be a complete Impulsewave, according to the above-listed rules. In total, i would have 10 candles and the following rules must apply:
The third candle (or the first that goes down, after the two going up) must not close below the starting price of the initial candle. AND also it must be met, that the following candles (how much that would become) must all go up in a row, unless they overcome the price of the previous maxima (the second candle).
When the price starts to drop again, it could be counted as wave 4 then (second minima in a sequence) and when it goes up again, this would indicate wave 5.
Then it also must be met, that, if the price starts to go down again, it does not close below the first maxima (in this case the second candle).
And so on and so on.
My question now is: Is this kind of looping through certain data points is even a appropriate way to approach that kind of project? Or am I totally wrong here?
I just thought: because of the fractal character of Elliott waves, I would only need very basic rules, that would depend on, what the same iterative process spits out the previous times it is scanning data points.
What do you think?
Is there a better, a smarter way to realise what i am planing to do?
And also, how I could do this in a good way?
Maybe there is also a way to just feed some patterns into a predefined execution structure and then let this run over data points just as price charts.
What would your approach look like?
Thanks a lot and best wishes, Benjamin
Here is my idea/code for finding highs and lows. It's doenst work standalone. If you have any idea, how it can help to find waves, let me know.
import pandas as pd
import config.Text
class AnalyzerHighLow(object):
def __init__(self, df):
self.high_low = None
self.df = df.close.values
self.highs = pd.DataFrame(columns=[config.Text.date, config.Text.extrema, config.Text.type])
self.lows = pd.DataFrame(columns=[config.Text.date, config.Text.extrema, config.Text.type])
def highlow(self):
idx_start = 0
self.find_high(self.df, idx_start)
self.find_low(self.df, idx_start)
self.high_low = pd.concat([self.highs, self.lows], ignore_index=True, sort=True, axis=0)
self.high_low = self.high_low.sort_values(by=[config.Text.date])
self.high_low = self.high_low.reset_index(drop=True)
return self.high_low
def find_high(self, high_low, idx_start):
pvt_high = high_low[idx_start]
reached = False
for i in range(idx_start + 1, len(high_low)):
act_high = high_low[i]
if act_high > pvt_high:
reached = True
pvt_high = act_high
elif act_high < pvt_high and reached is True:
self.highs.loc[i - 1] = [i - 1, pvt_high, config.Text.maxima]
return self.find_high(high_low, i)
elif act_high < pvt_high:
pvt_high = high_low[i]
if (reached is True) and (i == (len(high_low))):
self.highs.loc[i - 1] = [i - 1, pvt_high, config.Text.maxima]
def find_low(self, high_low, idx_start):
pvt_low = high_low[idx_start]
reached = False
for i in range(idx_start + 1, len(high_low)):
act_low = high_low[i]
if act_low < pvt_low:
reached = True
pvt_low = act_low
elif act_low > pvt_low and reached is True:
self.lows.loc[i - 1] = [i - 1, pvt_low, config.Text.minima]
return self.find_low(high_low, i)
elif act_low > pvt_low:
pvt_low = high_low[i]
if (reached is True) and (i == (len(high_low) - 1)):
self.lows.loc[i - 1] = [i - 1, pvt_low, config.Text.minima]
I have the following code that generates a x_d and x_y. I then want to add or subtract these values from the last calculated x and y (returned from config.get_last_point()), and store it in the latest point.
def generate_asv_configuration(
asv_count, generate_left_concavity, corner_angle=None):
# Create a configuration
config = Configuration(generate_left_concavity)
for i in range(2, asv_count):
# Calculate the angle to be used in the calculations
turning_angle = turning_angle - delta_angle
# Calculate the delta-x, and -y.
x_d = MAX_BOOM_LENGTH * math.cos(turning_angle)
y_d = MAX_BOOM_LENGTH * math.sin(turning_angle)
# print generate_left_concavity
if (i % 2) == 0:
print '1: Left, i: {0}'.format(i)
x = config.get_last_point()[0] - x_d
y = config.get_last_point()[1] - y_d
else:
print '2: Right, i: {0}'.format(i)
x = config.get_last_point()[0] + x_d
y = config.get_last_point()[1] + y_d
config.add_point((x, y))
The problem I'm having is that code generates an image similar to . That looks good, the different points have varying angles (you can see that some are almost closed, others are very open). However, when I change the first if condition to (i % 2) == 0 and generate_left_concavity, and I call it with generate_left_concavity to True, I guess something similar to . The problem is, there is really open polygons.
Unfortunately, I've tried a few different if conditions, and whenever I have generate_left_concavity in the condition, it always generates differently. I have even tried nested if conditions.
I believe I've even tried having the above two conditions, then in a later condition, I check if generate_left_concavity, if so, I add 2 * x_d to compensate. It still generates the images similar to .
I don't see how much of my code could directly affect the generation of x and y calculations based on an if condition, but I could be wrong. I can guarantee, however, that they are always entering the same condition branch, but generate differently.
Not really an answer but: If I think something weird is going on in a conditional, I try to make the conditional suites as simple as possible to eliminate or separate possible problem code. Yours could be refactored:
if (i % 2) == 0:
print '1: Left, i: {0}'.format(i)
x_d, y_d = -x_d, -y_d
else:
print '2: Right, i: {0}'.format(i)
x = config.get_last_point()[0] + x_d
y = config.get_last_point()[1] + y_d
I've looked into a bit more, and it turns out that when I'm trying to generate a left-concavity open polygon, the range of angles that are possible are different to the possible angles for a right-concavity open polygon. Once I found out that if I find the min/max allowed angles for the concavity that I am generating, it was correctly selecting an angle within the bounds, therefore, generating the way I want :) Thanks everyone for you help and guidance!
As a beginner programmer, I don't know how to conceptually think about brute-forcing. My mind can't really fathom how to write code that will try every possibility. My answer is recursion, but as you will see below, I have failed.
If you need the full source
I have a problem that I want to solve. Here is a code snippet (there are other functions, but no reason to include them here, they just do background work):
def initiate(seen):
step_segment = []
STATS = [250,0,0,0,13,0]
if len(seen) >= 256: # when to escape the recursion
return seen
while (len(step_segment)) < 128:
step_segment, STATS = take_step(step_segment, STATS)
if STATS[5] == "B": # if there is a battle
if STATS[0] in seen: # if battle has been done before
status = seen.index(STATS[0]) # get battle status:
status += 1 # which is next to step_id (= G or B)
if seen[status] == "B": # for seen battles, try Glitch ("G")
step_segment = do_glitch(step_segment, STATS)
else:
step_segment, STATS = do_fight(step_segment, STATS) # fight
seen = seen + [STATS[0],STATS[5]]
time = get_frames(step_segment)
print "\nTime:", time
print seen
return initiate(seen)
The goal: I want to produce a list of every possible decision through a segment, along with how long it takes.
Description:
I will take a step (There's only one direction: forward). Every time I take a step, my stats are updated. This takes a step and updates the stats: step_segment, STATS = take_step(step_segment, STATS)
A list of steps taken, along with the stats, are kept in
step_segment. This is so I can 'undo' an arbitrary amount of
steps, if I want. To undo a step call the function:
step_segment, STATS = undo_step(step_segment, STATS)
I can see how long my current route has taken by doing: time = frames(step_segment).
At some point, I will get into a Battle. I get into a battle when
STATS[5] == "B"
When there is a battle I have to make a decision, I simply have two choices: i. Fight the
battle (B), or, ii. Run away glitch (G).
If I want to Fight, I do: step_segment = do_fight(step_segment, STATS). This also records that I chose to fight, along with the stats, in step_segment. (So I can undo it, if i want).
If I want to Run Away Glitch, I do: step_segment = do_glitch(step_segment,STATS).
I want to see every possible combination of Glitch & Fight (the only two choices, when I reach a battle).
At the moment, my code is very bad and does not try all of the possibilities. I don't really know how to code for all possibilities.
So, that's why I'm here. How can I implement a way of trying all possibilities when facing a decision?
I understand the problem has exponential amount of possibilities, but thankfully the maximum number is pretty small (<1024).
I have read about tree traversal, but I have no idea how my problem can be put into that format. Eg, I don't know what a 'node' would be in my problem. I actually don't know what anything would be... That's why I'm asking.
I'm starting out in python.. The details I have written in the below.. It goes to an infinite loop and give me an error when I try to call the function inside itself.. Is this kind of recursion not allowed ?
Posting code below.. Thanks for all your help :)
The program assumes that we have 100 passengers boarding a plane. Assuming if the first one has lost his boarding pass, he finds a random seat and sits there. Then the other incoming passengers sit in their places if unoccupied or some other random seat if occupied.
The final aim is to find the probability with which the last passenger will not sit in his/her own seat. I haven't added the loop part yet which
would make it a proper simulation. The question above is actually a puzzle in probability. I am trying to verify the answer as I don't really follow the reasoning.
import random
from numpy import zeros
rand = zeros((100,3))
# The rows are : Passenger number , The seat he is occupying and if his designated seat is occupied. I am assuming that the passengers have seats which are same as the order in which they enter. so the 1st passenger enter has a designated seat number 1, 2nd to enter has no. 2 etc.
def cio(r): # Says if the seat is occupied ( 1 if occupied, 0 if not)
if rand[r][2]==1:
return 1
if rand[r][2]==0:
return 0
def assign(ini,mov): # The first is passenger no. and the second is the final seat he gets. So I keep on chaning the mov variable if the seat that he randomly picked was occupied too.
if cio(rand[mov][2])== 0 :
rand[mov][2] = 1
rand[mov][1] = ini
elif cio(rand[mov][2])== 1 :
mov2 = random.randint(0,99)
# print(mov2) Was used to debug.. didn't really help
assign(ini,mov2) # I get the error pointing to this line :(
# Defining the first passenger's stats.
rand[0][0] = 1
rand[0][1] = random.randint(1,100)
m = rand[0][1]
rand[m][2]= 1
for x in range(99):
rand[x+1][0] = x + 2
for x in range(99):
assign(x+1,x+1)
if rand[99][0]==rand[99][1] :
print(1);
else :
print(0);
Please tell me if y'all get the same error.. ALso tell me if I am breaking any rules coz thisi sthe first question I'm posting.. Sorry if it seems too long.
This is how it should've been...
The code does work fine in this case with the following mods :
def assign(ini,mov):
if cio(mov)== 0 : """Changed here"""
rand[mov][2] = 1
rand[mov][1] = ini
elif cio(mov)== 1 : """And here"""
mov2 = random.randint(0,99)
assign(ini,mov2)
I am using Python 2.6.6 on Windows 7, using a software from Enthought Academic Version of Python.
http://www.enthought.com/products/getepd.php
Also the answer to this puzzle is 0.5 which is actually what I am getting(almost) by running it 10000 times.
I didn't see it here but it had to be available online..
http://www.brightbubble.net/2010/07/10/100-passengers-and-plane-seats/
Recursion, while allowed, isn't your best first choice for this.
Python enforces an upper bound on recursive functions. It appears that your loop exceeds the upper bound.
You really want some kind of while loop in assign.
def assign(ini,mov):
"""The first is passenger no. and the second is the final seat he gets. So I keep on chaning the mov variable if the seat that he randomly picked was occupied too.
"""
while cio(rand[mov][2])== 1:
mov = random.randint(0,99)
assert cio(rand[mov][2])== 0
rand[mov][2] = 1
rand[mov][1] = ini
This may be more what you're trying to do.
Note the change to your comments. Triple-quoted string just after the def.
you may be able to find the exact solution using dynamic programming
http://en.wikipedia.org/wiki/Dynamic_programming
For this you will need to add memoization to your recursive function:
What is memoization and how can I use it in Python?
If you just want to estimate the probability using simulation with random numbers then I suggest you break out of your recursive function after a certain depth when the probability is getting really small because this will only change some of the smaller decimal places (most likely.. you may want to plot the change in result as you change the depth).
to measure the depth you could add an integer to your parameters:
f(depth):
if depth>10:
return something
else: f(depth+1)
the maximum recursion depth allowed by default is 1000 although you can change this you will just run out of memory before you get your answer