Python Set Birthday - python

So I am trying to make a program that creates the probability of a bunch of people in a room to have the same birthday... I can't figure out how to create the function. Here is what I have so far
def birthday():
mySet = set()
x = 1
for item in mySet:
if item in mySet:
return x
else:
mySet().append() # don't know what to do here.
Edit:
Alright so what I am trying to accomplish is to make a function using a set that stores birthdays using numbers 1 through 365...For example, if you randomly pick a room with 30 people in it, they may not have the same birthday. Although, if you have twins in the same room, you only need 2 people
in the room to have the same birthday. So eventually I want a parameter that tests this function several times and averages it all up. Unfortunately I can't figure out how to make this. I want x to be a counter of how many people are in the room and when there is a match the loop stops and it stops. I also don't know what to append to.

Is there a reason why you're trying to simulate this rather than using the closed form solution to this problem? There's a pretty decent approximation that's fast and easy to code:
import math
def closed_form_approx_birthday_collision_probability(num_people):
return 1 - math.exp(-num_people * (num_people - 1) / (2 * 365.0))
You could also implement an very good "exact" solution (in quotes because some fidelity is lost when converting to float):
import operator
import functools
import fractions
def slow_fac(n):
return functools.reduce(operator.mul, range(2, n+1), 1)
def closed_form_exact_birthday_collision_probability(num_people):
p_no_collision = fractions.Fraction(slow_fac(365), 365 ** num_people * slow_fac(365 - num_people))
return float(1 - p_no_collision)
To do a simulation, you'd do something like this. I'm using a list rather than a set because the number of possibilities is small and this avoids some extra work that using a set would do:
import random
def birthday_collision_simulate_once(num_people):
s = [False] * 365
for _ in range(num_people):
birthday = random.randint(0, 364)
if s[birthday]:
return True
else:
s[birthday] = True
return False
def birthday_collision_simulation(num_people, runs):
collisions = 0
for _ in range(runs):
if birthday_collision_simulate_once(num_people):
collisions += 1
return collisions / float(runs)
The numbers I get from the simulation and the closed form solution look similar to the table at http://en.wikipedia.org/wiki/Birthday_problem
>>> closed_form_approx_birthday_collision_probability(20)
0.40580512747932584
>>> closed_form_exact_birthday_collision_probability(20)
0.41143838358058
>>> birthday_collision_simulation(20, 100000)
0.41108
Of course the simulation with that many runs is closer to the actual 41.1%, it's much slower to calculate. I'd choose one of the closed form solutions, depending on how accurate it needs to be.

Related

How to set up this programm idea? : Elliott Wave Counter on Stock Charts by finding Minima and Maxima and how they relate to each other

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]

How to convert bar count to time, in midi? (music)

Given a midi file, how can one convert the bar count to time?
Generally, how can one easily map the bar count, in entire numbers, to the time in seconds in the song
Using pretty midi, my solution
import pretty_midi as pm
def get_bar_to_time_dict(self,song,id):
def get_numerator_for_sig_change(signature_change,id):
# since sometime pretty midi count are wierd
if int(signature_change.numerator)==6 and int(signature_change.denominator)==8:
# 6/8 goes to 2 for sure
return 2
return signature_change.numerator
# we have to take into account time-signature-changes
changes = song.time_signature_changes
beats = song.get_beats()
bar_to_time_dict = dict()
# first bar is on first position
current_beat_index = 0
current_bar = 1
bar_to_time_dict[current_bar] = beats[current_beat_index]
for index_time_sig, _ in enumerate(changes):
numerator = get_numerator_for_sig_change(changes[index_time_sig],id)
# keep adding to dictionary until the time signature changes, or we are in the last change, in that case iterate till end of beats
while index_time_sig == len(changes) - 1 or beats[current_beat_index] < changes[index_time_sig + 1].time:
# we have to increase in numerator steps, minus 1 for counting logic of natural counting
current_beat_index += numerator
if current_beat_index > len(beats) - 1:
# we labeled all beats so end function
return bar_to_time_dict
current_bar += 1
bar_to_time_dict[current_bar] = beats[current_beat_index]
return bar_to_time_dict
song = pm.PrettyMIDI('some_midi_file.midi')
get_bar_to_time_dict(song)
If anyone knows a function in pretty midi or music21 that solves the same issue please let me know, couldn't find one.
EDIT: There was also an issue with 6/8 beats, I think this covers all edge cases(not 100% sure)

Algorithm to return all possible paths in this program to a nested list

So I have a game with a function findViableMoves(base). If i call this function at the start with the parameter base, I get an output [move1, move2 ... moven] which denotes all of the n viable moves that the user can perform give the state base. (there are in fact 2 root moves)
Upon performing a move, say move2 - base gets changed depending on the move, the function gets called again and now we have an output for findViableMoves(base) of [move21,move22 .... move2n].
Depth-first-tree
If you look at this diagram, it's a very similar situation - there's no looping back, it's just a normal tree. I need a program that performs a depth-first search (i think?) on all the possible moves given a starting state of base, and then returns then in a list as such:
[[move1,move11,move111],[move1,move11,move112],....[moven,moven1,moven11],...]
There will be more elements in these lists (14 at most), but I was just wondering if someone could provide any hints over how I can build an algorithm to do this? Efficiency doesn't really matter to me as there isn't too many paths, I just want it done for now.
I'm not 100% clear on what you're after, but if you have a list or similar iterable that is changing while the loop is happening you could try something like the below.
This example allows the list and the loop condition to both remain dynamic during the loop execution.
import random
import sys
import time
changing_list = ['A', 27, 0.12]
def perform_operation(changing_list, counter):
sometimes_add_another_element_threshold = 0.6
if random.random() > sometimes_add_another_element_threshold:
changing_list.append(random.random())
print(changing_list[counter])
def main(z=0):
safety_limit = 100
counter = 0
condition = True
while condition and counter < safety_limit:
perform_operation(changing_list, counter)
counter += 1
condition = counter<len(changing_list)
print("loop finished")
if __name__ == '__main__':
start_time = time.time()
main(int(sys.argv[1])) if len(sys.argv)>1 else main()
print(time.time() - start_time)
which provides output of varying length that looks something like:
A
27
0.12
0.21045788812161237
0.20230442292518247
loop finished
0.0058634281158447266

python - generating a non repeating random pairs of numbers

I'm trying to generate random pairs of numbers to place objects at random locations in a grid. I've tried looking for answers but I haven't found one that works for what I need. I don't want the pair to repeat but the objects can still be placed in the same row or column. Also the size of the grid and the number of objects is inputted by the user
def create_bombs(self):
bombs_flaged = 0
#creates the bombs
for i in range(self.bomb_num):
bomb_row = randint(0,self.board_size - 1)
bomb_col = randint(1,self.board_size)
self.bomb_list.append(Bomb(bomb_row, bomb_col, self, bombs_flaged))
One way to think about this is: there are X*Y possible positions (specifically board_size * board_size, in your case), and you want to pick N (self.bomb_num) random samples from those positions, without repetition.
The sample function in the random module does this perfectly:
possible_coordinates = [(x, y) for x in range(X) for y in range(1, Y+1)]
bomb_coordinates = random.sample(possible_coordinates, N)
Creating that list is a little wasteful—but given that board_size is probably something small, like 30, a temporary list of 900 elements is not worth worrying about.
Python's sets are meant to do just what you need: membership testing is very fast, with them (constant time):
def create_bombs(self):
bombs_flagged = 0
existing_bomb_coords = set() # All bomb coordinates so far
# Creates the bombs
while len(existing_bomb_coords) < self.bomb_num: # Looping as much as needed
bomb_row = randint(0, self.board_size-1)
bomb_col = randint(1, self.board_size)
bomb_coords = (bomb_row, bomb_col)
if bomb_coords not in existing_bomb_coords: # Very fast test
self.bomb_list.append(Bomb(bomb_row, bomb_col, self, bombs_flagged))
existing_bomb_coords.add(bomb_coords) # New bomb registration
Now, I like #abarnert's answer too: it is a bit wasteful, as he indicates, but it is very legible.

how do I use modular expression/ working with large intergers

I want to make a program that calculate the the populations after x years.
where the pop in 2002 is 6.2 billion people and increases 1.3 % each year.
The formula I will use is
population = ((1.013)**x) * 6.2B
How do I make 6.2B easier to work with?
Here is your code. Read and learn well. This is probably a problem that you could have solved with Google.
import math
def calculate_population(years_since_2002): #the original calculation
population_2002 = 6.2*10**9
final_population = int(((1.013)**years_since_2002)*population_2002)
return final_population
def pretty_print(num,trunc=0):
multiplier = int(math.log10(num)) #finds the power of 10
remainder = float(num)/(10**multiplier) #finds the float after
str_remainder = str(remainder)
if trunc != 0:
str_remainder = remainder[:trunc+1] #truncates to trunc digits total
return str_remainder+'e'+str(multiplier) #can also be print

Categories

Resources