How do I make this Loop? - python

So here are the directions for this step in my program:
Create a loop that traverses through the dice list.
Inside the loop add one to the appropriate index value in the counts list for each value in the dice list. When the loop is done, the counts list should have the number of times each value occurs in the dice list. Heres what I have:
# Step 1
from random import randint
class Dice(object):
def __init__(self):
self.dice = []
x = 0
while x < 5:
self.dice.append(str(randint(1,6)))
x += 1
hand = Dice() # Creates a Dice object
print hand.dice # Prints the instance variable dice (5 random numbers)
# Step 2
class Dice(object):
def __init__(self):
self.dice = []
def roll(self,how_many):
for i in range(how_many):
self.Dice.append(randint(1,6))
hand.roll = ([0,2,3]) # Change the numbers in index positions 0, 2, and 3.
print hand.dice # Prints the instance variable dice (5 random numbers)
#Step 3
def score(self):
self.counts = [0, 0, 0, 0, 0, 0, 0]
for i in range(counts):
index + 1
print i

Use enumerate:
>>> lst = [4, 4, 5, 2, 6]
>>> counts = [0] * 7
>>> for i, e in enumerate(lst):
... counts[e] += 1
...
>>> print counts
[0, 0, 1, 0, 2, 1, 1]

Related

2D List not calculating properly

I'm trying to do a game of life. There's this weird bug I can't really fix because I don't really know where the problem is? I'm guessing it's in the loop? I don't really know. I tried to debug it using the if total > 0 print(total), and the total is only 2 when it should've been 3. I'm sorry if i'm explaining it confusing because i'm also confused.
def test():
board = [[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0]]
#Tracking the neighbor, it shows that there is 3 alive neighbors in
#here.
print(board[2][1])
print(board[2-1][1+1])
print(board[2][1+1])
print(board[2+1][1+1])
return board
def update(grid, N):
newGrid = grid.copy()
for i in range(N):
if i == 0 or i == 4:
continue
for j in range(N):
if j == 0 or j == 4:
continue
total = 0
total = total + grid[i][j-1] #
total = total + grid[i][j+1] #
total = total + grid[i-1][j] #
total = total + grid[i+1][j] #
total = total + grid[i-1][j-1] #
total = total + grid[i-1][j+1] #
total = total + grid[i+1][j-1] #
total = total + grid[i+1][j+1] #
# In here it only states that there's only 2 alive neighbors
# when there should've been 3
if total > 0:
print(total)
# apply Conway's rules
if grid[i][j] == 1:
if (total < 2) or (total > 3):
newGrid[i][j] = 0
elif total == 3:
newGrid[i][j] = 1
else:
if total == 3:
newGrid[i][j] = 1
grid[:] = newGrid[:]
return(grid)
f = 0
zboard = test()
while f <= 3:
print("Generation: " + str(f))
gen = update(zboard, 5)
for i in gen:
print(i)
f += 1
You need to use deepcopy.
When you do newGrid = grid.copy(), since you have a 2D-list, the sublists in newGrid will not be independent from the sublists from grid. Your problem was that grid was updated each time you updated newGrid.
You need to replace this:
newGrid = grid.copy()
by this :
import copy
newGrid = copy.deepcopy(grid)
Here is an example to show you what was happening. cop_1 is a dependent copy whereas cop_2 is an independent one :
board = [[0, 0],
[0, 0]]
cop_1 = board.copy()
import copy
cop_2 = copy.deepcopy(board)
board[0][0] = 3 # change a value of board
print("cop_1[0][0] =", cop_1[0][0])
# cop_1[0][0] = 3
print("cop_2[0][0] =", cop_2[0][0])
# cop_2[0][0] = 0
If you run the code like you posted, you get a mistake because you didn't indent the lines after your function def test(): until return board

How to return an argument if a certain condition is met in a loop?

import random
def lottery(lucky_numbers, run):
i = 0
while i < run:
x = random.uniform(0, 1) #prints out a random number between 0 and 1
numbers = lucky_numbers
NewNumbers = numbers[-1:] + numbers[:-1] #shifts each element in the to the right
lucky_numbers = NewNumbers
print(lucky_numbers, x)
i += 1
lottery([1, 2, 0], 3)
This code prints out something like:
>>>>>>>>>>
[0, 1, 2] 0.33016179294984127
[2, 0, 1] 0.7797639530009745
[1, 2, 0] 0.6292245916315391
>>>>>>>>>>
The x values will always be different because they are random numbers between 0 and 1.
I am trying to add a function that says if x is the lowest value(min) in the loop then the programme should print the list of that iteration, for example in this case the lowest value of x in this loop is 0.33016179.. , the program should therefore print the list [0, 1, 2]
I would just save the info in a variable and print it after the loop ends:
import random
def lottery(lucky_numbers, run):
i = 0
min_x = 1
while i < run:
x = random.uniform(0, 1) #prints out a random number between 0 and 1
numbers = lucky_numbers
NewNumbers = numbers[-1:] + numbers[:-1] #shifts each element in the to the right
lucky_numbers = NewNumbers
if x < min_x:
min_x = x
min_lucky_numbers = lucky_numbers
i += 1
print(min_lucky_numbers, min_x)
lottery([1, 2, 0], 3)
You can create a "cache" that stores all the x values then call the lowest value.
cache = []
for _ in range(3):
x = random.uniform(0, 1)
cache.append(x)
print min(cache)
to do what you want, you have just to store your items in two different lists, sort them and display the firt elements of each one :
import random
luckiest_num = list()
luckiest_list = list()
def lottery(lucky_numbers, run):
i = 0
while i < run:
x = random.uniform(0, 1)
numbers = lucky_numbers
NewNumbers = numbers[-1:] + numbers[:-1]
print(NewNumbers, x)
i += 1
luckiest_num.append(x)
luckiest_list.append(NewNumbers)
lottery([1, 2, 0], 3)
luckiest_num.sort()
luckiest_list.sort()
print ("The luckiest item is : ")
print(luckiest_num[0],luckiest_list[0])

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!

Finding majority votes on -1s, 1s and 0s in list - python

How to find the majority votes for a list that can contain -1s, 1s and 0s?
For example, given a list of:
x = [-1, -1, -1, -1, 0]
The majority is -1 , so the output should return -1
Another example, given a list of:
x = [1, 1, 1, 0, 0, -1]
The majority vote would be 1
And when we have a tie, the majority vote should return 0, e.g.:
x = [1, 1, 1, -1, -1, -1]
This should also return zero:
x = [1, 1, 0, 0, -1, -1]
The simplest case to get the majority vote seem to sum the list up and check whether it's negative, positive or 0.
>>> x = [-1, -1, -1, -1, 0]
>>> sum(x) # So majority -> 0
-4
>>> x = [-1, 1, 1, 1, 0]
>>> sum(x) # So majority -> 1
2
>>> x = [-1, -1, 1, 1, 0]
>>> sum(x) # So majority is tied, i.e. -> 0
0
After the sum, I could do this check to get the majority vote, i.e.:
>>> x = [-1, 1, 1, 1, 0]
>>> majority = -1 if sum(x) < 0 else 1 if sum(x)!=0 else 0
>>> majority
1
>>> x = [-1, -1, 1, 1, 0]
>>> majority = -1 if sum(x) < 0 else 1 if sum(x)!=0 else 0
>>> majority
0
But as noted previously, it's ugly: Python putting an if-elif-else statement on one line and not pythonic.
So the solution seems to be
>>> x = [-1, -1, 1, 1, 0]
>>> if sum(x) == 0:
... majority = 0
... else:
... majority = -1 if sum(x) < 0 else 1
...
>>> majority
0
EDITED
But there are cases that sum() won't work, #RobertB's e.g.
>>> x = [-1, -1, 0, 0, 0, 0]
>>> sum(x)
-2
But in this case the majority vote should be 0!!
I am assuming that votes for 0 count as votes. So sum is not a reasonable option.
Try a Counter:
>>> from collections import Counter
>>> x = Counter([-1,-1,-1, 1,1,1,1,0,0,0,0,0,0,0,0])
>>> x
Counter({0: 8, 1: 4, -1: 3})
>>> x.most_common(1)
[(0, 8)]
>>> x.most_common(1)[0][0]
0
So you could write code like:
from collections import Counter
def find_majority(votes):
vote_count = Counter(votes)
top_two = vote_count.most_common(2)
if len(top_two)>1 and top_two[0][1] == top_two[1][1]:
# It is a tie
return 0
return top_two[0][0]
>>> find_majority([1,1,-1,-1,0]) # It is a tie
0
>>> find_majority([1,1,1,1, -1,-1,-1,0])
1
>>> find_majority([-1,-1,0,0,0]) # Votes for zero win
0
>>> find_majority(['a','a','b',]) # Totally not asked for, but would work
'a'
You could use statistics.mode if you were using python >= 3.4 ,catching a StatisticsError for when you have no unique mode:
from statistics import mode, StatisticsError
def majority(l):
try:
return mode(l)
except StatisticsError:
return 0
The statistics implementation itself uses a Counter dict:
import collections
def _counts(data):
# Generate a table of sorted (value, frequency) pairs.
table = collections.Counter(iter(data)).most_common()
if not table:
return table
# Extract the values with the highest frequency.
maxfreq = table[0][1]
for i in range(1, len(table)):
if table[i][1] != maxfreq:
table = table[:i]
break
return table
def mode(data):
"""Return the most common data point from discrete or nominal data.
``mode`` assumes discrete data, and returns a single value. This is the
standard treatment of the mode as commonly taught in schools:
>>> mode([1, 1, 2, 3, 3, 3, 3, 4])
3
This also works with nominal (non-numeric) data:
>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
'red'
If there is not exactly one most common value, ``mode`` will raise
StatisticsError.
"""
# Generate a table of sorted (value, frequency) pairs.
table = _counts(data)
if len(table) == 1:
return table[0][0]
elif table:
raise StatisticsError(
'no unique mode; found %d equally common values' % len(table)
)
else:
raise StatisticsError('no mode for empty data')
Another way using a Counter and catching an empty list:
def majority(l):
cn = Counter(l).most_common(2)
return 0 if len(cn) > 1 and cn[0][1] == cn[1][1] else next(iter(cn),[0])[0]
You can count occurences of 0 and test if they are majority.
>>> x = [1, 1, 0, 0, 0]
>>> if sum(x) == 0 or x.count(0) >= len(x) / 2.0:
... majority = 0
... else:
... majority = -1 if (sum(x) < 0) else 1
... majority
0
This solution is based on counting occurrences and sorting:
import operator
def determineMajority(x):
'''
>>> determineMajority([-1, -1, -1, -1, 0])
-1
>>> determineMajority([1, 1, 1, 0, 0, -1])
1
>>> determineMajority([1, 1, 1, -1, -1, -1])
0
>>> determineMajority([1, 1, 1, 0, 0, 0])
0
>>> determineMajority([1, 1, 0, 0, -1, -1])
0
>>> determineMajority([-1, -1, 0, 0, 0, 0])
0
'''
# Count three times
# sort on counts
xs = sorted(
[(i, x.count(i)) for i in range(-1,2)],
key=operator.itemgetter(1),
reverse=True
)
if xs[0][1] > xs[1][1]:
return xs[0][0]
else:
# tie
return 0
if __name__ == '__main__':
import doctest
doctest.testmod()
Additionally, there is one if statements. As mentioned in the comments it is undefined what happens with
x = [1, 1, 0, 0, -1]
# These are your actual votes
votes = [-1, -1, -1, -1, 0]
# These are the options on the ballot
ballot = (-1, 0, 1)
# This is to initialize your counters
counters = {x: 0 for x in ballot}
# Count the number of votes
for vote in votes:
counters[vote] += 1
results = counters.values().sort()
if len(set(values)) < len(ballot) and values[-1] == values [-2]:
# Return 0 if there's a tie
return 0
else:
# Return your winning vote if there isn't a tie
return max(counters, key=counters.get)
A very simple approach.
a = [-1, -1, -1, -1, 0] # Example
count = {}
for i in a:
if i not in count:
count[i] = 1
else:
count[i] += 1
m_count = max(count.values())
for key in count:
if count[key] == m_count:
print key
In the above example the output will be -1,
however if there is a tie, both the keys will be printed.
I believe this works for all provided test cases. Please let me know if I did something wrong.
from collections import Counter
def fn(x):
counts = Counter(x)
num_n1 = counts.get(-1, 0)
num_p1 = counts.get(1, 0)
num_z = counts.get(0, 0)
if num_n1 > num_p1:
return -1 if num_n1 > num_z else 0
elif num_p1 > num_n1:
return 1 if num_p1 > num_z else 0
else:
return 0
from collections import Counter
result = Counter(votes).most_common(2)
result = 0 if result[0][1] == result[1][1] else result[0][0]
Error handling for empty votes lists or votes lists with a set cardinality of 1 is trivial and left as an exercise for the reader.
This works with any number of candidates. If there is a tie between two candidates it returns zero else it returns candidate with most votes.
from collections import Counter
x = [-1, -1, 0, 0, 0, 0]
counts = list((Counter(x).most_common())) ## Array in descending order by votes
if len(counts)>1 and (counts[0][1] == counts[1][1]): ## Comparing top two candidates
print 0
else:
print counts[0][0]
We compare only two candidates because if there is a tie between two candidates it should return 0 and it doesn't depend on third candidate value
An obvious approach is making a counter and updating it according to the data list x. Then you can get the list of numbers (from -1, 0, 1) that are the most frequent. If there is 1 such number, this is what you want, otherwise choose 0 (as you requested).
counter = {-1: 0, 0: 0, 1: 0}
for number in x:
counter[number] += 1
best_values = [i for i in (-1, 0, 1) if counter[i] == max(counter.values())]
if len(best_values) == 1:
majority = best_values[0]
else:
majority = 0
You don't need anything but built-in list operators and stuff, no need to import anything.
votes = [ -1,-1,0,1,0,1,-1,-1] # note that we don't care about ordering
counts = [ votes.count(-1),votes.count(0),votes.count(1)]
if (counts[0]>0 and counts.count(counts[0]) > 1) or (counts[1]>0 and counts.count(counts[1])>1):
majority=0
else:
majority=counts.index(max(counts))-1 # subtract 1 as indexes start with 0
print majority
3d line puts counts of respective votes in a new list, and counts.index() shows us which list position we find the max votes.
I would dare to say that this should be about as pythonic as it can, without getting into eye-gouging oneliners.
Upd: rewrote without text strings and updated to return 0 in case of several equal results (didnt notice this in the original post), added an IF for case if only one vote, eg votes=[-1]
from collections import Counter
def find_majority_vote(votes):
counter = Counter(votes)
most_common = counter.most_common(2)
if len(most_common)==2:
return 0 if most_common[0][1] == most_common[1][1] else most_common[0][0]
else:
return most_common[0][0]
import numpy as np
def fn(vote):
n=vote[np.where(vote<0)].size
p=vote[np.where(vote>0)].size
ret=np.sign(p-n)
z=vote.size-p-n
if z>=max(p,n):
ret=0
return ret
# some test cases
print fn(np.array([-1,-1, 1,1,1,1,0,0,0,0,0,0,0,0]))
print fn(np.array([-1, -1, -1, 1,1,1,0,0]))
print fn(np.array([0,0,0,1,1,1]))
print fn(np.array([1,1,1,1, -1,-1,-1,0]))
print fn(np.array([-1, -1, -1, -1, 1, 0]))

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

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)

Categories

Resources