Using a variable from one function in another function (parameter 'dice' unfilled) - python

Hi im trying to create a game where the computer generates 5 random numbers between 1 and 6. but my issue is i have created a list which will gain '1' in its respective section depending on what number comes up. e.g. if the computer generates 31534 the list needs to show [1,0,2,1,1,0] (because there was two 3's it fills 2 in the 3 slot) it only displays the 5 random numbers and nothing else
from random import randint
def rollDice():
dice = [str(randint(1, 6)) for _ in range(5)]
print(dice)
return dice
#-----------------------------------------------------------------
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
if x == 1:
totals = totals[1] + 1
elif x == 2:
totals = totals[2] + 1
elif x == 3:
totals = totals[3] + 1
elif x == 4:
totals = totals[4] + 1
elif x == 5:
totals = totals[5] + 1
print(totals)
return totals
#------------------------------------------------------------------
rollDice()
countVals()

I believe your error lies when you increment the count of each number,
totals = totals[1] + 1
should be,
totals[1] = totals[1] + 1
Also depending on your application you may be able to simplify your code
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
totals[x - 1] += 1
print (totals)
return totals

I think the problem is that the result returned by your rollDice function is a list of strings. The if - else statement in countVals then falls through cause for example '5' == 5 -> False. You could modify rollDice to return a list of int's instead (don't convert your ints to strings):
def rollDice():
dice = [randint(1, 6) for _ in range(5)]
print(dice)
return dice
If you absolutely want rollDice to return a list of strings you could convert the strings to ints using the int method in your countVals method. Example: int('5') -> 5, or just compare strings and not ints. x == '5'
Also make sure that you are saving your totals back to the right index in you totals list (in rollDice). You could do this a little more succinctly as follows: totals[1] += 1, for example:
def countVals(dice):
totals = [0, 0, 0, 0, 0, 0] #alternatively could be 'totals = [0]*6' :)
for value in dice:
totals[value - 1] += 1
print(totals)
return totals
(assuming rollDice has been modified to return a list of integers)
You should be able to call the methods as follows totals = countVals(rollDice()) to get your list of totals.

You could try the following:
dice = rollDice()
countVals(dice)
Also you want to fix the indentation of the print and return statements in countVals(). Currently, they only trigger if x==5. And as Salvador Dali mentions, either remove str from rollDice() or change the comparisons in countVals() to x == '1', etc.
Edit:
Here is how you may want to write your script:
def rollDice():
dice = [randint(1, 6) for _ in range(5)]
print(dice)
return dice
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
# x can be, 1-5. Index of totals can be 0-4.
totals[x-1] += 1
print(totals)
return totals
dice = rollDice()
countVals(dice)

Related

Finding a more concise way to add values to empty list Python

I am new to Python and while my task is deemed correct, I know there is a more efficient way to write the code and am looking for advice.
My goal is to count the number of scores (between 1-6) of a dice roll and assign each number to a list. In this case I know the value of the dice roll 'N' - 1 will be the index at which it is added to the list but I am unsure as to how to go about writing it.
import random
dice = [0]*6
for roll in range(1001):
N = random.randint(1,6)
if N == 1:
dice[0] = dice[0] + 1
if N == 2:
dice[1] = dice[1] + 1
if N == 3:
dice[2] = dice[2] + 1
if N == 4:
dice[3] = dice[3] + 1
if N == 5:
dice[4] = dice[4] + 1
if N == 6:
dice[5] = dice[5] + 1
print(f' the number of times the dice rolled 1-6 is as follows {dice}')
You can use N-1 for the index of the list.
dice[N-1] += 1
When dealing with lists of random values, I recommend numpy:
import numpy as np
_, counts = np.unique(np.random.randint(1,7, 1000), return_counts=True)
Here you go:
dice = [0]*6
for roll in range(1001):
dice[random.randint(0, 5)] += 1
print(f' the number of times the dice rolled 1-6 is as follows {dice}')
The list is being indexed with N-1.
import random
a = random.sample(range(1, 1001), 6)
print(a)
This could brief a lot more what you are looking for
https://pynative.com/python-random-sample/

How can I eliminate one of the arguments in this function?

I want to eliminate the third argument in my code below which is just an empty array that I think I should be able to create as a local variable within the function itself.
As a bonus, I would also like to build this into a single function although I don't think this can be achieved with the current recursive structure of the code.
I tried creating an empty array as a local variable (See the commented out integers list)
I also tried to create a count variable to increment with each combination found (See the commented out count variable)
def count_combinations(number, integers_available, integers):
coin_set = []
# integers = []
# count = 0
if sum(integers) == number:
coin_set.append(integers)
# count += 1
elif sum(integers) > number:
pass
elif integers_available == []:
pass
else:
for c in count_combinations(number, integers_available[:], integers + [integers_available[0]]):
coin_set.append(c)
# count += 1
for c in count_combinations(number, integers_available[1:], integers):
coin_set.append(c)
# count += 1
# return count += 1
return coin_set
def count_total(number, integers_available, integers):
return len(count_combinations(number, integers_available, integers))
# Testing the code
number = 15
integers_available = [1, 5, 10]
print(count_total(number, integers_available, []))
I expect to get the same results but with fewer arguments in the function since one of the arguments will have been switched to a local variable instead.
As discussed in the comments, a dynamic programming approach may be more Pythonic here.
from collections import Counter
def ways(total, coins=(1,2,5,10,20,50,100)):
counts = [[Counter()]] + [[] for _ in range(total)]
for coin in coins:
for i in range(coin, total + 1):
counts[i] += [c + Counter({coin: 1}) for c in counts[i-coin]]
return counts[total]
Demo:
>>> ways(15, coins=(1,5,10))
[Counter({1: 15}),
Counter({1: 10, 5: 1}),
Counter({1: 5, 5: 2}),
Counter({5: 3}),
Counter({1: 5, 10: 1}),
Counter({5: 1, 10: 1})]
>>> len(ways(15, coins=(1,5,10)))
6
Without regard to the algorithm or the goal of the code, here's how you can tidy it up a little by making it into a single function and giving integers parameter a default value:
def count_total(number, integers_available):
def count_combinations(number, integers_available, integers=[]):
coin_set = []
# integers = []
# count = 0
if sum(integers) == number:
coin_set.append(integers)
# count += 1
elif sum(integers) > number:
pass
elif integers_available == []:
pass
else:
for c in count_combinations(number, integers_available[:], integers + [integers_available[0]]):
coin_set.append(c)
# count += 1
for c in count_combinations(number, integers_available[1:], integers):
coin_set.append(c)
# count += 1
# return count += 1
return coin_set
return len(count_combinations(number, integers_available))
# Testing the code
number = 15
integers_available = [1, 5, 10]
print(count_total(number, integers_available))

how to output my functions numeric values as a list in python

here is my function:
def seq_sum(n):
""" input: n, generate a sequence of n random coin flips
output: return the number of heads
Hint: For simplicity, use 1,0 to represent head,tails
"""
flip = 0
heads = 0
while flip <= n:
coin = random.randint(0,2)
flip += 1
if coin == 1:
heads += 1
print(heads)
the output looks like this:
55
1
0
2
1
and so on. but what I want is the number of heads, plus a LIST of the output:
55
[1, 0, 2, 1, .....]
when I tried print(list(heads))I get the following error message:
TypeError: 'int' object is not iterable
In your function, you are merely keeping track of the total number of heads and not their history. You need to create an iterable collection to hold the interim values, such as a list or Numpy Array.
import numpy as np
def seq_sum(n):
flips = np.random.randint(low=0, high=2, size=n)
return sum(flips), flips.tolist()
# Example usage.
total_heads, flips = seq_sum(n=10)
Note that the start and end points are inclusive and exclusive, respectively, for numpy's randint function.
Hope this code will do what you want
def seq_sum(n):
flips = [random.randint(0, 1) for _ in range(n)]
return sum(flips), flips
Usage
s, l = seq_sum(10)
From the comment in your code I can tell that the function should return only the number of heads so
def seq_sum(n):
return sum(random.randint(0, 1) for _ in range(n))
import random
# edit in place
def seq_sum(n):
""" input: n, generate a sequence of n random coin flips
output: return the number of heads
Hint: For simplicity, use 1,0 to represent head,tails
"""
flip = 0
heads = 0
seq = list()
while flip <= n:
coin = random.randint(0,2)
seq.append(coin)
flip += 1
if coin == 1:
heads += 1
print(heads,seq)
#solution 2
def seq_sum(n):
flip = 0
seq = list() #create a list to store every random value
while flip < n: # if want to generate n values, the while loop only need compare 0,1,2,...n-1 times, so you need <, not <=.
coin = random.randint(0,1) # coin has only two sides
seq.append(coin)
flip += 1
return seq
# print(heads) # it is not good idea to print data in function.
random_list = seq_sum(55)
head_num = sum(random_list)
I don't know if I understood correctly, but here's my quite simple solution.
import random
def seq_sum(n):
""" input: n, generate a sequence of n random coin flips
output: return the number of heads
Hint: For simplicity, use 1,0 to represent head,tails
"""
flip = 0
heads = 0
outcomes=[]
while flip < n:
coin = random.randint(0,2)
outcomes.append(coin)
flip += 1
if coin == 1:
heads += 1
print(heads)
print(outcomes)
--------
output in console:
>>>seq_sum(3)
>>>2
>>>[1, 2, 1]
when I tried print(list(heads))I get the following error message:
TypeError: 'int' object is not iterable
Let's start with here. heads is always an integer from beginning till the end. Thus, when you put list( ) around heads, Python is complaining that you are feeding list an integer, which is not iterable.
Takeaway 1: some objects can only take certain kinds of arguments.
Second stop: I want to have a list to store the heads and tails. What should I do? One way is to create a list to store it.
my_list = [] # or list()
To add to the list, you can use append method. append method adds one element to the end of the list.
my_list.append(1)
# now my_list is [1]
my_list.append(0)
# now my_list looks like [1, 0]
Third goal: I want to randomly generate 0s and 1s to represent tails and heads. Are you really doing what you want to do? Be careful about the functions you call, especially those you are not familiar with. Read about what do the functions do.
random.randint(a, b)
Return a random integer N such that a <= N <= b. -- documentation for randint
randint(0, 2) will generate 0, 1, 2 randomly, which can represent head, tail, and... ohhh we don't have 3 things to represent.
Goal 4: Do you want to return/save the values for later use? or just print it out? Think about it and make the decision. Do you know you can turn 2 things/more at a time?
def bar():
return 1, 2
c = bar() # c is a tuple that holds two values, 0 and 1 now!
# c[0] == 1 # access the first element with index 0
# c[1] == 2
Hope with these, you can code your own answer.

Same values in two lists (pairs)

I need to have a list going where I have one list with a load of values between 1 and 8 randomly generated and another list with a load of values between 1 and 8 randomly also. I have managed to do this on my code below:
from random import *
listA = []
listB = []
inp = int(input('Number of values generated'))
for x in range(0,inp):
num = randint(0,8)
listA.append(num)
if num == 0:
numB = randint(1,8)
else:
numB = randint(0,8)
listB.append(numB)
print(listA)
print(listB)
The value in the first list can't be 0 and the value in the second list can't be zero too on the same trial. I have this already in my code. However this is the problem I have.
[4, 5, 2, 5, 1]
[1, 2, 3, 2, 4]
In listA, the 5 is produced twice and the 2 below it on the second list is produced twice also. I can't figure out a solution to get these out from my lists, when they create a pair like this.
You can use a helper function as below to generate a unique number that is not in the list and append that to the list.
This should work for you:
def generateUnique(list, start, end): # Helper Function to generate and return unique number not in list
num = randint(start, end)
while num in list: # loop will keep generating a value, until it is unique in the given list
num = randint(start, end)
return num
from random import *
listA = []
listB = []
inp = int(input('Number of values generated'))
for x in range(0,inp):
num = generateUnique(listA, 0, 8)
listA.append(num)
if num == 0:
numB = generateUnique(listB, 1, 8)
else:
numB = generateUnique(listB, 0, 8)
listB.append(numB)
print(listA)
print(listB)
Hope this helps!

Generate triangular numbers

This function is supposed to take an integer, generate the list of triangular numbers within range of that integer, check that list for the longest list of numbers whose sum == number and return them in a list, otherwise if there is no such list within that range of triangular numbers, return an empty list. I thought I had it somewhat, and it runs on python tutor.com, but when I run it in IDLE, nothing happens.
def checkio(number):
x = 4
lst = [1, 3, 6]
new = []
if number == 0:
return []
elif number == 1:
return [1]
elif number == 3:
return []
elif number == 6:
return []
elif number == 4:
return [1, 3]
elif number == 7:
return [1, 6]
elif number == 10:
return [1, 3, 6]
elif number > 10:
while number > lst[-1]: # Generates a list of all the triangular numbers up to number
for item in range(lst[-1]):
lst.append(x + lst[-1])
x += 1
go = []
start = 0
end = 0
count = 0
while count < len(lst) * 2:
if sum(lst[start:end+1]) < number:
end += 1
count += 1
elif sum(lst[start:end+1]) > number:
start += 1
count += 1
elif sum(lst[start:end+1]) == number:
go.append(lst[start:end+1])
break
return go
if count >= len(lst) * 2:
return []
In the code you post you are just declaring a function. In order to run it, you have to make a call to that function. In your case, it receives one argument, so you have to pass it inside the parentheses ():
number = 5 # for example
checkio(number) # this is the function call
As Bakuriu commented: If you want to get a result change the order of this lines:
elif sum(lst[start:end+1]) == number:
go.append(lst[start:end+1])
break
return go
To :
elif sum(lst[start:end+1]) == number:
go.append(lst[start:end+1])
return go
break
This will return a value before escaping the while loop. As noted in the comments (thanks Andrea Corbellini) you can also remove the break statement and it will work well. Because after the return statement by definition escapes the function.
Also to run in idle once defined (you copied the code and pressed return), call it as Christian says.
This way you will check if works.
Note that you don't check in the ifelse clauses for the numbers 2, 5, 8 and 9. If you call this function with checkio(5), like suggested by Crhistian, it will not return anything because it doesn't have anything to return!

Categories

Resources