Simulating n games of craps in python - python-3.x

I'm pretty new to python and I have been trying to make this simulator that creates a simulator for "games" of craps. My professor wanted it to be made in the most basic form possible which is the reason for having a function for rolling one dice then another. For some reason I can't get my simOneGame function to cooperate and I can't even get it to print a value when I assign a variable to it although it should print a 1 or 0. Here is my code:
def main():
x = eval(input("how many games will be played?: "))
y = simNGames(x)
print(y)
def simOneGame():
win = 0
lose = 0
x = rollDice()
if x == 2 or x == 3 or x == 12:
lose += 1
elif x == 7 or x == 11:
win += 1
y = rollDice()
while y != 7 or y != x :
y = rollDice()
if y == x:
win += 1
elif y == 7 :
lose += 1
if win > lose:
return(1)
else:
return(0)
def simNGames(n):
wins = 0
loses = 0
x = simOneGame()
for i in range(n):
if x > 0:
wins += 1
else:
pass
frac = wins / n
return float(frac)
def rollDice():
return rollDie() + rollDie()
def rollDie():
return randrange(1,7)
I don't get an answer unless input a number greater than 100 and it's always a 1.0

There are several issues I see with your code.
First off, your simNGames only actually simulates one game, but then it adds up that game's results n times. You need to move your x = simOneGame() line inside the loop so that it gets called repeatedly.
There's a separate issue with your simOneGame function's logic. A single craps game is either won or lost, there's no scoring. That means you don't need to be adding up win and loss values. You should change all the places where you do win += 1 to do return 1 instead, and all the places that do lose += 1 should be return 0 (this means you can get rid of the rest of the code dealing with the win and lose variables too).
You also might consider returning True and False rather than 1 and 0, but this might have been decided by your teacher, and it's more a design style point than an error.
Finally, I think the while loop in simOneGame needs an and rather than an or to make the logic work correctly.

Related

CODEFORCES 1744B, how could I fix runtime error?

I'm trying to solve the next problem: https://codeforces.com/contest/1744/problem/B
When I run the code in my terminal, it works with the example given in the exercise; but it doesn't when I submit it in CodeForces, it cause a runtime error which I cannot figure out.
def increment(arr, length, option, add):
for i in range(length):
if(option == '0') and (arr[i]%2 == 0):
arr[i] += add
elif(option == '1') and (arr[i]%2 != 0):
arr[i] += add
else:
pass
return arr
def main():
quantityOperation = int(input())
while quantityOperation > 0:
length, times = input().split()
length = int(length)
times = int(times)
arr = [int(x) for x in input().split()]
while times > 0:
opt, add = input().split()
add = int(add)
res = sum(increment(arr, length, opt, add))
print(res)
times -= 1
quantityOperation -= 1
main()
The loop inside your main function doesn't end. You should put quantityOperation -= 1 inside the while loop.
However, your code will still become time limit exceeded after fixing this. The correct idea is to precalculate odd and even sum and modify them according to the queries instead of looping all elements inside increment function every time. You can check the editorial for this problem.

Why is my python function not working properly when I call it recursively?

I'm doing a question from a previous Waterloo ccc competition (https://cemc.uwaterloo.ca/contests/computing/2020/ccc/juniorEF.pdf problem J5)
and my code isn't working the way I expected
Here's the sample input I'm using:
3
4
3 10 8 14
1 11 12 12
6 2 3 9
Here's my code so far
y_size = int(input())
x_size = int(input())
mat = []
"ok".split()
for i in range(y_size):
row = input().split()
mat.append(row)
pos_list = [[0, 0]]
current_num = int(mat[0][0])
a = 0
def canEscape():
global a
global mat
global pos_list
global current_num
end = y_size * x_size
if y_size -1 * x_size -1 == current_num:
return True
for i in range(y_size):
print("______")
for j in range(x_size):
v = (i + 1) * (j + 1)
print(v)
print(current_num)
if v == current_num:
print("ok")
if v == end:
print("ok")
a += 1
current_num = mat[i][j]
pos_list.append([i, j])
canEscape()
pos_list.pop(-1)
a -= 1
current_num = mat[pos_list[a][0]][pos_list[a][1]]
canEscape()
The problem I'm having is that I expect if v == current_num: to be true when I call it again. Both current_num and v are equal to 8 but the code seems to carry on with the for-in loop and break, without entering the if statement. I've made the output print v followed by current_num for every iteration of the for loop to try and figure out the problem but it seems that both variables == 8 so I really don't know what I did wrong. Did I make a silly mistake or did I structure my whole program wrong?
I'm having trouble following what your program is doing at all. This problem involves integer factoring, and I do not see where you're factoring integers. You definitely are not understanding that aspect of the problem.
When you calculate what cells you can go to you look at the value of your current cell. Lets say it is 6. 6 has the factors 1, 2, 3, and 6 because all of those numbers can be multiplied by another number to equal 6. So, you can go to the cells (1, 6), (6, 1), (2, 3), and (3, 2), because those are the pairs of numbers that can be multiplied together to equal 6.
Also, you never convert the lines of input into integers. When you append to the matrix, you are appending a list of strings that happen to be numbers. You must convert those into integers.
Anyways, this program will solve the problem. I copy and pasted the factoring algorithm from other threads:
n_rows = int(input())
n_cols = int(input())
mat = []
for i in range(n_rows):
mat.append(list(map(lambda x: int(x), input().split()))) # Convert input strings to integers.
def reduce(f, l):
# This is just needed for the factoring function
# It's not relevant to the problem
r = None
for e in l:
if r is None:
r = e
else:
r = f(r, e)
return r
def factors(n):
# An efficient function for calculating factors.
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
def get_pairs(items):
for i in range(len(items) // 2):
yield (items[i],items[len(items) - 1 - i]) # use yield to save memory
if(len(items) % 2 != 0): # This is for square numbers.
n = items[len(items) // 2]
yield (n,n)
checked_numbers = set()
def isPath(r=1, c=1):
# check if the testing row or column is to large.
if r > n_rows or c > n_cols:
return False
y = r - 1
x = c - 1
n = mat[y][x]
# If we've already checked a number with a certain value we dont need to check it again.
if n in checked_numbers:
return False
checked_numbers.add(n)
# Check if we've reached the exit.
if(r == n_rows and c == n_cols):
return True
# Calculate the factors of the number, and then find all valid pairs with those factors.
pairs = get_pairs(sorted(list(factors(n))))
# Remember to check each pair with both combinations of every pair of factors.
# If any of the pairs lead to the exit then we return true.
return any([isPath(pair[0], pair[1]) or isPath(pair[1], pair[0]) for pair in pairs])
if isPath():
print("yes");
else:
print("no");
This works and it is fast. However, it if you are limited on memory and/or have a large data input size your program could easily run out of memory. I think it is likely that this will happen with some of the testing inputs but I'm not sure.. It is surely possible to write this program in a way that would use a fraction of the memory, perhaps by converting the factors function to a function that uses iterators, as well as converting the get_pairs function to somehow iterate as well.
I would imagine that this solution solves most of the testing inputs they have but will not solve the ones towards the end, because they will be very large and it will run out of memory.

Create a function that computes the approximation of pi, based on the number of iterations specified

hint:pi can be computed by 4*(1-1/3+1/5-1/7+1/9- ...).
I have idea to solve this question by using while loop, but I'm confused that, in while loop, how can I save my variable every time when i use if conditional.
Here is my code.
def piA(num):
i = 1
pi = 4
while i <= num:
s = 0
float(s)
if i % 2 == 1:
s = s + (1/(2*i-1))
print(s)
elif i % 2 == 0:
s = s - (1/(2*i-1))
print(s)
i += 1
print(s)
return pi*s
print(piA(2))
The result shows:
1.0
1.0
-0.3333333333333333
-0.3333333333333333
-1.3333333333333333
You don't have to save the previous variable, just use builtin method sum():
def pi(num):
return 4*sum((1 if i % 2 else -1)*(1 / (2*i - 1)) for i in range(1, num+1))
print(pi(10000))
Prints:
3.1414926535900345

Python generator only returning first instance of yield

This code should produce all prime numbers in order when 'next' is called, but it only produces 2, the first prime number of the list. The list works properly to produce prime numbers.
def genPrime():
x = 1
primeList = [2]
while True:
x += 1
tempList = []
for i in range(len(primeList)):
tempList.append(x % primeList[i])
if min(tempList) > 0:
next = primeList[-1]
yield next
primeList.append(x)
prime = genPrime()
print(prime.__next__())
That's exactly what a generator is supposed to do. .__next__() only returns the next item, just as the name says.
Try:
print(prime.__next__())
print(prime.__next__())
print(prime.__next__())
You will see that you get them one by one.
Further, it is important that .__next__() is not meant to be called directly. The correct way is:
print(next(prime))
print(next(prime))
print(next(prime))
If you want them all, do:
for p in prime:
print(p)
Further, while not part of the answer, I give you a couple of programming tips:
for i in range(len(primeList)):
tempList.append(x % primeList[i])
has an unnecessary indirection. Just do
for prime in primeList:
tempList.append(x % prime)
Also, the entire tempList is unnecessary.
Just use a for-else construct:
def genPrime():
x = 1
primeList = []
while True:
x += 1
for prime in primeList:
if x % prime == 0:
break
else:
yield x
primeList.append(x)

Loop only adds the last result to a list

I am trying to run a small casino roulette betting outcome simulator. As a result I want to understand how big of a bank the casino should have in order not to go bankrupt in relation to the players betting size.
Please see code below:
from random import choices
bankroll = 500
bet = 50
lose = -50
population = [bet, lose]
weights = [0.4865, 0.5135]
game_count = 1
winning_game_count = []
bankrupt_game_count = []
for i in range(10000):
while bankroll != 0 and game_count < 5000:
result = int(choices(population, weights)[0])
bankroll -= result
game_count += 1
if game_count > 4999:
winning_game_count.append('won')
elif bankroll == 0:
bankrupt_game_count.append('lost')
print(winning_game_count)
print(bankrupt_game_count)
I am getting the result of the last iteration only, whereas I want to get the total sum of all games (5000 games) and the number of games where bankroll resulted in 0. I am lost.
You only get the result of the last iteration because you only run 1 iteration.
You need to reset the variables that control your loop condition between each iteration:
for i in range(10000):
bankroll=500
game_count = 1
while bankroll != 0 and game_count < 5000:

Resources