I'm trying to operate 50/50 player win/lose game based on random.sample([0,1],1).
def player_win():
global player_win_count
player_win_count += 1
return player_win_count
def player_lose():
global dealer_win_count
dealer_win_count += 1
return dealer_win_count
def game_draw():
draw_game_count += 1
return draw_game_count
def gameplay():
i = 0
while i <= 300:
test01 = random.sample([0,1],1)
i += 1
if test01 == 1:
player_win()
else:
player_lose()
print("player_win",player_win_count)
print("dealer_win",dealer_win_count)
gameplay()
The 'random.sample' code works fine, but instead of expected result, it returns
player_win 0
dealer_win 301
what's wrong with my code?
random.sample will return a list of the samples so test01 == 1 is always False.
Example:
In [181]: random.sample([0, 1], 1)
Out[181]: [1]
In [182]: random.sample([0, 1], 1)
Out[182]: [0]
In [183]: random.sample([0, 1], 1)
Out[183]: [1]
In [184]: random.sample([0, 1], 1)
Out[184]: [0]
One solution is test01[0] == 1.
Alternatively, one could use random.choices instead and generate all the flips at once:
In [188]: wins = 0
...: losses = 0
...: for flip in random.choices([0, 1], k=20):
...: if flip:
...: wins += 1
...: else:
...: losses += 1
In [189]: print(wins, losses)
7 13
As #salt-die has noted, random.sample() is designed to return a sample of the population and does so as a list.
To achieve the intended result, you could substitute random.choice() for random.sample(), which will return a single selection from the population:
def gameplay():
i = 0
while i <= 300:
test01 = random.choice([0,1]) # use random.choice()
i += 1
if test01 == 1:
player_win()
else:
player_lose()
print("player_win",player_win_count)
print("dealer_win",dealer_win_count)
If for some reason, you are required to use random.sample(), then you can use the following modification to select the first element out of the list of sample results:
while i <= 300:
test01 = random.sample([0,1], 1)[0] # use list indexing to get
# the zeroeth item from the list
Lastly, as a point of style:
It is sometimes considered Pythonic to simply test for truthiness/falsiness and thus this code could be refined a bit, if desired:
while i <= 300:
i += 1
if random.choice([0, 1]): # A `1` is considered equivalent to True
# in Python, so we can skip setting the value
# of test01 to being either 1 OR 0 and
# simply return a 1 or 0 into the if statement.
Best practice in Python is to avoid global scopes so something like this is better if you really had to use a function.
import random
def _counter(count: int):
count += 1
return count
def gameplay():
draw_game_count = 0
dealer_win_count = 0
player_win_count = 0
for i in range(300):
test01 = random.randint(0, 2)
if test01 == 0:
draw_game_count = _counter(draw_game_count)
elif test01 == 1:
player_win_count = _counter(player_win_count)
else:
dealer_win_count = _counter(dealer_win_count)
print("draw", draw_game_count)
print("player_win", player_win_count)
print("dealer_win", dealer_win_count)
if __name__ == "__main__":
gameplay()
Otherwise you could simply do this:
import random
def gameplay():
draw_game_count = 0
dealer_win_count = 0
player_win_count = 0
for i in range(300):
test01 = random.randint(0, 2)
if test01 == 0:
draw_game_count += 1
elif test01 == 1:
player_win_count += 1
else:
dealer_win_count += 1
print("draw", draw_game_count)
print("player_win", player_win_count)
print("dealer_win", dealer_win_count)
if __name__ == "__main__":
gameplay()
Related
With an = (an-2 + 1)×an-1 with a0 = 0 and a1 = 1 formula find dummy_numbers(max)
My code:
def dummy_numbers(nums):
binsize = (((nums - 2) +1) * (nums -1))
return map(lambda x: int(nums + binsize * x), range(nums))
for num in dummy_numbers(10):
print(num)
my code prints different result than I expected
Use an actual generator with yield to make this easier. The tricky part here is keeping track of an-1 and an-2 as you iterate. This can be achieve like so:
second_last, last = None, None
for current in range(10):
second_last, last = last, current
assert (second_last, last) == (8, 9)
You also need to hardcode in the constant value that get returned for 0 and 1:
def dummy_numbers(an):
if an == 0:
yield 0
elif an == 1:
yield 0
yield 1
else:
an_2, an_1 = None, None
for an_0 in dummy_numbers(an - 1):
an_2, an_1 = an_1, an_0
yield an_0
yield (an_2 + 1) * an_1
for num in dummy_numbers(10):
print(num)
Outputs:
0
1
1
2
4
12
60
780
47580
37159980
1768109008380
You could also make this non-recursive like so:
def dummy_numbers(an):
an_2, an_1 = None, None
for i in range(an):
if i == 0:
an_0 = 0
elif i == 1:
an_0 = 1
else:
an_0 = (an_2 + 1) * an_1
yield an_0
an_2, an_1 = an_1, an_0
It's supposed to be a roll of dice (random) then adjacent values (runs) are supposed to be in ( ). One challenge is using the current - 1 with the 0 index (think I got that resolved by using range(len(dieRun) -1). But another challenge is using 'current + 1' as it tends to 'out of range' errors.
One thought I have is to maybe build a function to compare the values for adjacents? Then use whatever return I get from that to reference a variable, then use that variable in a formatted Print of the dieRun? But, I don't see how that would be better as then I'd still have to figure out how to place that variable as a "(" or ")" with the print(dieRun) list.
Still a newb.
def main():
from random import randint
counter = 0
inRun = 0
dieRun = []
while counter < 20:
roll = randint(0,6)
dieRun.append(roll)
counter = counter +1
index = 0
counter = 0
value = 0
inRun == False
print(dieRun) # just to see what I'm working with
while counter < len(dieRun):
for i in range(0, len(dieRun)-1):
if dieRun[i] != dieRun[i-1]:
print(")" , end= "")
inRun = False
counter = counter + 1
if dieRun[i] == dieRun[i+1]:
inRun = True
print("(")
counter = counter + 1
print(dieRun[i])
if inRun:
print("(")
if inRun :
print(")", end="")
main()
if you want the output like: 1(3 3) 4 5 (6 6 6) 2 1 3 (2 2) 1 (4 4) 5 6 1 2
from random import randint
dieRun = []
for i in range(20):
roll = randint(0,6)
dieRun.append(roll)
inRun = False
print(dieRun)
for i, n in enumerate(dieRun):
if i < len(dieRun)-1:
if not inRun:
if n == dieRun[i+1]:
print('(', n,' ', end='')
inRun = True
else:
print(n,' ', end='')
else:
if n != dieRun[i+1]:
print(n, ')',' ', end='')
inRun = False
else:
print(n,' ', end='')
else:
if dieRun[i-1] == n:
print(n, ')')
else:
print(n)
just a thought, hope it help.
Just a quick fix, I have commented in the code.
For the inline print, you have provided the solution 'print(")" , end= "")', but I don't know why you didn't make it for every print().
if dieRun[i] != dieRun[i-1]: # will check the first number with last number
dieRun[0] != dieRun[-1]: # [-1] is the last item in the list
if dieRun[i] == dieRun[i+1]: # will index out of length
dieRun[len(..)-1] != dieRun[len(..)]: # [len(..)] wil be out of range
Since the head and tail of the list will always cause problem, I just chopped them off from the for loop, and do it manually.
There must be some cleaner solution:
from random import randint
counter = 0
inRun = 0
dieRun = []
while counter < 20:
roll = randint(0,6)
dieRun.append(roll)
counter = counter +1
index = 0
counter = 0
value = 0
inRun == False
print(dieRun)
# while counter < len(dieRun): # while loop is redundant with the for loop
print('(', dieRun[0],' ', end='') # print the first number manually
for i in range(1, len(dieRun)-1):
if dieRun[i] != dieRun[i-1]:
print(")(" , end= "") # change ")" to ")("
inRun = False
counter = counter + 1
"""
these are redundant, just like if True, don't need elif not True
# if dieRun[i] == dieRun[i+1]:
# inRun == True
# print("(", end='')
# counter = counter + 1
"""
print(dieRun[i],' ', end='')
print(dieRun[-1],')', end='') # print the last number manually
I'm currently working on making a Game of Life program (UNI related, beginner course), by using nested lists.
However I can't seem to get the update() method to work properly, I've no clue what's wrong. The generation of the first board is okay, but the update leaves only the cornercells alive, and the rest dead.
All methodcalls in this class originates from other .py files, which works well.
from random import randint
from cell import *
class Spillebrett:
def __init__(self, rows, columns):
self.genNumber = 0
self._rows = rows
self._columns = columns
self._grid = []
for i in range(self._rows):
self._grid.append([])
for j in range(self._columns):
self._grid[i].append(cell())
self.generate()
def drawBoard(self):
for i in self._grid:
print(" ".join(map(str, i)))
print()
#Method updates genNumber, checks if cells are alive or dead and updates the board accordingly
#Currently only yield board with corner-cells alive
def updateBoard(self):
self.genNumber += 1
toLive = []
toDie = []
for x, row in enumerate(self._grid):
for y, cell in enumerate(rad):
if cell.areAlive() is True:
counter = len(self.findNeighbour(x, y))
if counter < 2 or counter > 3:
toDie.append(cell)
elif counter == 2 or counter == 3:
toLive.append(cell)
elif cell.areAlive() is False:
counter = len(self.findNeighbour(x, y))
if counter == 3:
toLive.append(cell)
for i in toDie:
i.setDead()
for i in toLive:
i.setAlive()
return self.genNumber
#Code given by Uni
def generate(self):
for i in range(self._rows):
for j in range(self._columns):
rand = randint(0, 3)
if rand == 3:
self._grid[i][j].setAlive()
#Code given by Uni
def findNeighbour(self, row, column):
neighbourList = []
for i in range(-1, 2):
for j in range(-1, 2):
neighbourRow = rad + i
neighbourcolumn = column + j
if(neighbourRow == rad and neighbourcolumn == column) is not True:
if(neighbourRow < 0 or neighbourcolumn < 0 or neighbourRow >
self._rows - 1 or neighbourcolumn > self._columns - 1) is not True:
neighbourList.append(self._grid[neighbourRow][neighbourcolumn])
return neighbourList
def findAllAlive(self):
self._alive = 0
for i in range(self._rows):
for j in range(self._columns):
if self._grid[i][j].areAlive() is True:
self._alive += 1
return self._alive
old = [[0 for x in range(3)] for y in range(10)]
count =0
# check if the number has non-repeating digits
def different(number):
digit_list = [0] * 4
i = 0
while i:
digit_list[i] = number%10
number /= 10
i += 1
for x in range(0,3):
for y in range(x+1,3):
if digit_list[x] == digit_list[y]:
return False
return True
# save the tried numbers, plus and minus values
# for prediction of the next number
def save(number,plus,minus):
global count
old[count][0] = number
old[count][1] = plus
old[count][2] = minus
count += 1
return
# compare for plus values
def get_plus(number1,number2):
ret_value = 0
for x in range(0, 3):
if number1 % 10 == number2 % 10:
ret_value += 1
number1 /= 10
number2 /= 10
return ret_value
# compare for minus values
def get_minus(number1,number2):
temp = [[0]*4 for i in range(2)]
ret_value = 0
for x in range(0,3):
temp[0][x] = number1 % 10
temp[0][x] = number2 % 10
number1 /= 10
number2 /= 10
for x in range(0,3):
for y in range(0,3):
if x != y:
if temp[0][x] == temp[1][y]:
ret_value += 1
return ret_value
# compare the number to be asked with the numbers in the array
def control(number):
for x in range(0,count-1):
if get_plus(old[x][0],number) != old[x][1]:
return False
if get_minus(old[x][0],number) != old[x][2]:
return False
return True
def main():
flag = False
print('1023 ??')
plus = input('plus ?')
minus = input('minus ?')
save(1023, plus, minus)
print('4567 ??')
plus = input('plus ?')
minus = input('minus ?')
save(4567, plus, minus)
for i in range(1024, 9876):
if different(i):
if control(i):
print(i + ' ??')
plus = input('plus ?')
minus = input('minus ?')
save(i, plus, minus)
if plus == 4 and minus == 0:
print('I WON !!!')
flag = True
break
if not flag:
print('False')
return
main()
I am trying to make an AI for mindgame in python. But in this function it doesn't even start the for loop. Can anyone know why ?
The while loop in your different() function does nothing as while(0) will prevent the loop from running. Even if that would run, your different() function will always return false. At least in the last loop it will compare digit_list[3] == digit_list[3] as both loop range until 3. This is always true and the function will return false. Thus the code within your main loop will never be entered.
def different(number):
digit_list = [0] * 4
i = 0
while i:
digit_list[i] = number%10
number /= 10
i += 1
for x in range(0,3):
for y in range(x+1,3):
if digit_list[x] == digit_list[y]:
return False
return True
Try this one:
import random
def different(num):
digits = []
while num >= 1:
cur = num%10
if cur in digits:
return False
digits.append(cur)
num = (num - cur) / 10
return True
for i in range(0, 10000):
rand = random.randrange(1000, 10000)
if not different(rand):
print(rand)
I made a code that measure number of steps it takes to return to 1 in a Collatz Conjecture. Here Is my code
counter = 0
def collatz(n):
global counter
counter += 1
if n <= 0 :
return "Invalid Number"
elif n == 1 :
return counter
elif n % 2 == 1 :
n = 3*n + 1
return collatz(n)
elif n % 2 == 0 :
n = n/2
return collatz(n)
print(collatz(9921615699))
print(collatz(9921615699))
I expect the Last two print commands to print 311 and 311. Instead, they print 311 and 622. I guess that was easy enough to see in the code what is wrong. How can i fix that? how can counter reset each time a command is completed and not when the function is run.
Instead of using global variable you could make the counter a parameter with default value:
def collatz(n, counter=0):
counter += 1
if n <= 0 :
return "Invalid Number"
elif n == 1 :
return counter
elif n % 2 == 1 :
n = 3*n + 1
return collatz(n, counter)
elif n % 2 == 0 :
n = n/2
return collatz(n, counter)
You're using recursion, so just use it properly:
def collatz(n, counter=0):
counter += 1
if n <= 0 :
return "Invalid Number"
elif n == 1 :
return counter
elif n % 2 == 1 :
n = 3*n + 1
return collatz(n, counter)
elif n % 2 == 0 :
n = n/2
return collatz(n, counter)
print(collatz(9921615699))
print(collatz(9921615699))
You were using global in your original version which is usually not what you want to do. You got to see first-hand why.
You could have reset the counter, e.g.
result = counter
counter = 0
return result
But that's pretty nasty, let's not do that. When you're implementing a recursive algorithm there's probably no good reason to have a global variable.