while loop, try except and other functions having issues - python

I am creating a bingo/housie ticket creator in python. The tickets have 9 rows and 3 columns. It means 27 spaces on a 9*3 grid. 9 rows vertically and 3 columns horizontally. Each row can only hold 3 random numbers. The first row can hold a random number from 1,9. The second row can hold a random number from 10,19. The third row can hold a random number from 20,29. The fourth row can hold a random number from 30,39. The fifth row can hold a random number from 40,49. The sixth row can hold a random number from 50,59. The seventh row can hold a random number from 60,69. The eighth row can hold a random number from 70,79. The ninth row can hold a random number from 80,90. Here is a reference image of the ticket.
I am planning to create a random ticket in python. Here is the script I created for it. It has all the comments for better understanding.
import random
# print("Script is ready")
# Variables
global numOfNums # This tells that only 15 numbers can be added to the ticket
numOfNums = 15
global allNum # this is the list containing all 90 numbers
global numToBedone # this is just for adding nums to the list
allNum = []
numToBedone = 1
global row1, row2, row3, row4, row5, row6, row7, row8, row9 # all the rows
row1, row2, row3, row4, row5, row6, row7, row8, row9 = [], [], [], [], [], [], [], [], []
global row1Num, row2Num, row3Num, row4Num, row5Num, row6Num, row7Num, row8Num, row9Num # all the nums row can have
# Filling the List
while numToBedone<91:
allNum.append(numToBedone)
numToBedone = numToBedone+1
# Generating number for row 1
def ranRow1NumGen():
global numOfNums
row1Num = random.randint(1,9)
try:
allNum.remove(row1Num)
except:
ranRow1NumGen()
row1.append(row1Num)
numOfNums = numOfNums - 1
# Generating number for row 2
def ranRow2NumGen():
global numOfNums
row2Num = random.randint(10,19)
try:
allNum.remove(row2Num)
except:
ranRow2NumGen()
row2.append(row2Num)
numOfNums = numOfNums - 1
# Generating number for row 3
def ranRow3NumGen():
global numOfNums
row3Num = random.randint(20,29)
try:
allNum.remove(row3Num)
except:
ranRow3NumGen()
row3.append(row3Num)
numOfNums = numOfNums - 1
# Generating number for row 4
def ranRow4NumGen():
global numOfNums
row4Num = random.randint(30,39)
try:
allNum.remove(row4Num)
except:
ranRow4NumGen()
row4.append(row4Num)
numOfNums = numOfNums - 1
# Generating number for row 5
def ranRow5NumGen():
global numOfNums
row5Num = random.randint(40,49)
try:
allNum.remove(row5Num)
except:
ranRow5NumGen()
row5.append(row5Num)
numOfNums = numOfNums - 1
# Generating number for row 6
def ranRow6NumGen():
global numOfNums
row6Num = random.randint(50,59)
try:
allNum.remove(row6Num)
except:
ranRow6NumGen()
row6.append(row6Num)
numOfNums = numOfNums - 1
# Generating number for row 7
def ranRow7NumGen():
global numOfNums
row7Num = random.randint(60,69)
try:
allNum.remove(row7Num)
except:
ranRow7NumGen()
row7.append(row7Num)
numOfNums = numOfNums - 1
# Generating number for row 8
def ranRow8NumGen():
global numOfNums
row8Num = random.randint(70,79)
try:
allNum.remove(row8Num)
except:
ranRow8NumGen()
row8.append(row8Num)
numOfNums = numOfNums - 1
# Generating number for row 9
def ranRow9NumGen():
global numOfNums
row9Num = random.randint(80,90)
try:
allNum.remove(row9Num)
except:
ranRow9NumGen()
row9.append(row9Num)
numOfNums = numOfNums - 1
# Main function for creating a ticket
def ticketGen():
global row1, row2, row3, row4, row5, row6, row7, row8, row9
global numOfNums
#Adding 1 number to all the rows
ranRow1NumGen()
ranRow2NumGen()
ranRow3NumGen()
ranRow4NumGen()
ranRow5NumGen()
ranRow6NumGen()
ranRow7NumGen()
ranRow8NumGen()
ranRow9NumGen()
# After we put 1 number in each row we have to put the rest in the random rows
# I cant understand how to do that
# I used this way but it has some issues
# sometimes a row can get more than 3 num which isnt possible in the ticket
# also some numbers repeat but I cant understand how as I have a try except statement
u = 0
while u < 6:
randomNumGiver = random.randint(1,9)
if numOfNums > 0:
if randomNumGiver == 1 and len(row1) < 3:
ranRow1NumGen()
elif randomNumGiver == 2 and len(row2) < 3:
ranRow2NumGen()
elif randomNumGiver == 3 and len(row3) < 3:
ranRow3NumGen()
elif randomNumGiver == 4 and len(row4) < 3:
ranRow4NumGen()
elif randomNumGiver == 5 and len(row5) < 3:
ranRow5NumGen()
elif randomNumGiver == 6 and len(row6) < 3:
ranRow6NumGen()
elif randomNumGiver == 7 and len(row7) < 3:
ranRow7NumGen()
elif randomNumGiver == 8 and len(row8) < 3:
ranRow8NumGen()
elif randomNumGiver == 9 and len(row9) < 3:
ranRow9NumGen()
else:
pass
u = u+1
# printing all the rows and the remaining numbers in the list
print(row1, row2, row3, row4, row5, row6, row7, row8, row9)
pass
ticketGen()
I have gotten some mixed output :
Incorrect output given by the code :
[8] [14] [21, 25, 21] [32] [42, 47, 42] [55] [60, 66, 60] [76] [82]
Correct way and the output given by the code :
[7, 2] [16, 14] [28] [34] [40] [59, 56, 52] [68, 61, 64] [77] [83]
As you can see it has a mixed output. The issue with the first output is the numbers can't be repeated and also a row can't have more than 3 numbers. I can't find how this bug is happening as I have set a try-except statement for the repetition and an if statement for having less than 3 numbers. If you can find any issue and know the way to resolve it please do so. It would mean a lot to me. Thank you.
Edit - The code has now been changed according to the first answer but I got these results. Also at one point it clearly had more than 3 numbers in a row and they were duplicate numbers. Can't figure out a way please HELP

In your while loop, change this -
while u < 6:
randomNumGiver = random.randint(1,9)
if randomNumGiver == 1 and numOfNums > 0 and row1.__len__() < 3:
ranRow1NumGen()
elif randomNumGiver == 2 and numOfNums > 0 and row2.__len__() < 3:
ranRow2NumGen() ..........
To -
while u < 6:
randomNumGiver = random.randint(1,9)
if numOfNums > 0:
if randomNumGiver == 1 and len(row1) < 3:
ranRow1NumGen()
elif randomNumGiver == 2 and len(row2) < 3:
ranRow2NumGen()
elif randomNumGiver == 3 and len(row3) < 3:
ranRow3NumGen()
elif randomNumGiver == 4 and len(row4) < 3:
ranRow4NumGen()
elif randomNumGiver == 5 and len(row5) < 3:
ranRow5NumGen()
elif randomNumGiver == 6 and len(row6) < 3:
ranRow6NumGen()
elif randomNumGiver == 7 and len(row7) < 3:
ranRow7NumGen()
elif randomNumGiver == 8 and len(row8) < 3:
ranRow8NumGen()
elif randomNumGiver == 9 and len(row9) < 3:
ranRow9NumGen()
else:
pass
u = u+1
Make the line numOfNums common and then use len() instead because it is better practice not to use .__len__()
Result: (No repetition and more than 3 when I tried it many times for any wrong result)
Script is ready
2 is selected for row1
12 is selected for row2
22 is selected for row3
35 is selected for row4
48 is selected for row5
56 is selected for row6
64 is selected for row7
75 is selected for row8
90 is selected for row9
[2] [12] [22] [35] [48] [56] [64] [75] [90]
19 is selected for row2
60 is selected for row7
39 is selected for row4
55 is selected for row6
53 is selected for row6
56 is selected for row6
[2] [12, 19] [22] [35, 39] [48] [56, 55, 53] [64, 60] [75] [90]
[1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 49, 50, 51, 52, 54, 57, 58, 59, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89]

Related

Finding the longest interval with a decrease in value

I have a list of values for some metric, e.g.:
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
[50, 52, 58, 54, 57, 51, 55, 60, 62, 65, 68, 72, 62, 61, 59, 63, 72]
I need to find the longest interval over which the value has decreased. For the above list such interval is from index 7 to 14 (and it's length is 8). An O(n²) solution to this is simple:
def get_longest_len(values: list[int]) -> int:
longest = 0
for i in range(len(values)-1):
for j in range(len(values)-1, i, -1):
if values[i] > values[j] and j - i > longest:
longest = j - i
break
return longest + 1
Is there any way to improve it's time complexity?
O(n log n):
from itertools import accumulate
from bisect import bisect
def get_longest_len(values: list[int]) -> int:
maxi = list(accumulate(values, max))
return max(
i - bisect(maxi, value) + 1
for i, value in enumerate(values)
)
First I compute the prefix maxima. For your example:
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
values = [50, 52, 58, 54, 57, 51, 55, 60, 62, 65, 68, 72, 62, 61, 59, 63, 72]
maxi = [50, 52, 58, 58, 58, 58, 58, 60, 62, 65, 68, 72, 72, 72, 72, 72, 72]
Then for each value, I can use binary search in these maxima to find the earliest larger value. For example the 59 at index 14 in values: We find that the earliest number in maxi larger than 59 is the 60 at index 7.
Correctness testing with 100 lists of 1000 randomized ascending values (the two numbers for each test case are your result and mine, and the boolean says whether they match):
True 461 461
True 360 360
True 909 909
...
True 576 576
True 312 312
True 810 810
100 out of 100 correct
Code:
from itertools import accumulate
from bisect import bisect
from random import randint, sample
def get_longest_len0(values: list[int]) -> int:
longest = 0
for i in range(len(values)-1):
for j in range(len(values)-1, i, -1):
if values[i] > values[j] and j - i > longest:
longest = j - i
break
return longest + 1
def get_longest_len(values: list[int]) -> int:
maxi = list(accumulate(values, max))
return max(
i - bisect(maxi, value) + 1
for i, value in enumerate(values)
)
cases = 100
correct = 0
for _ in range(cases):
values = [i + randint(-10, 10) for i in range(1000)]
for _ in range(5):
i, j = sample(range(1000), 2)
values[i], values[j] = values[j], values[i]
expect = get_longest_len0(values)
result = get_longest_len(values)
correct += result == expect
print(result == expect, expect, result)
print(correct, 'out of', cases, 'correct')
Attempt This Online!

Start a new line after 4th element in list

I've written a code to print a Fibonacci sequence up to a certain value input by the user. I need the output to start a new line after every 4th element.
Here is my code:
number = int(input("Enter a positive number: \n"))
f1, f2 = 0, 1
count = 1
fibonacci = [f1]
while count < number:
fn = f1 + f2
f1 = f2
f2 = fn
fibonacci.append(f1)
count += 1
print(fibonacci)
While not changing priginal fibonacci list, you can print your values like this.
Instead of
print(fibonacci)
you could use this:
for i in range(0, len(fibonacci), 4):
print(fibonacci[i:i+4])
number = int(input("Enter a positive number: "))
def fabronic(n):
if n<=1:
return n
else:
return fabronic(n-1)+fabronic(n-2)
count,n=0,0
while n<number:
print(fabronic(n),end=' ')
count+=1
if count==4:
print()
count=0
n=n+1
input=Enter a positive number: 15
output=
0 1 1 2
3 5 8 13
21 34 55 89
144 233 377
By using list
n=0
mylist=[]
while n<number:
mylist.append(fabronic(n))
n=n+1
for item in range(0,len(mylist),4):
print(mylist[item:item+4],sep=' ',end='\n')
output=
Enter a positive number: 15
[0, 1, 1, 2]
[3, 5, 8, 13]
[21, 34, 55, 89]
[144, 233, 377]
You already have a counter so I guess what you want is that every time it reaches a multiple of 4, use print('\n')

Writing the data on the same line

I want to write the other card's values in the same line with 'else'. E.g card number 2 equals 2, card number 3 equals 3...
btw from 1 to 13 is from ace to king and 15, 16, 17, 18 are suites.
def get_value(num, suit):
if (suit == 18 or suit == 15) and num == 7:
return -21
elif suit == 16 and num == 7:
return -11
elif num == 1 and (suit== 15 or suit==16 or suit==17 or suit==18):
return 11
elif (num == 12 or num == 13) and (suit== 15 or suit==16 or suit==17 or suit==18):
return 10
elif num == 11 and (suit== 15 or suit==16 or suit==17 or suit==18):
return 25
If I understand correctly you want to return the value of the card, where ace, jack, queen and king and 7 of a particular suit returns special values, otherwise just the numeric value.
Assuming the 15-18 are the only valid suits we do not need to check if the suit is one of those if all return the same value, we only need to treat the special cases.
def get_value(num, suit):
if num==7 and suit in (15,18): # suit is either 15 or 18
return -21
elif num==7 and suit==16:
return -11
elif num==1: # suit doesnt matter for ace
return 11
elif num in (12, 13): # queen or king
return 10
elif num==11: # ace
return 25
else: # all other cases - return num as value
return num
I'm guessing the final else statement is what you were looking for, where the value you get out is just the number on the card in in the general case where none of the special cases trigger, eg get_value(3, 15) would return 3.
I think this is what you want:
def get_value(num, suit):
return -21 if (suit == 18 or suit == 15) and num == 7 else -11 if suit == 16 and num == 7 else 11 if num == 1 and (suit== 15 or suit==16 or suit==17 or suit==18) else 10 if (num == 12 or num == 13) and (suit== 15 or suit==16 or suit==17 or suit==18) else 25 if num == 11 and (suit== 15 or suit==16 or suit==17 or suit==18) else None
Because this is very messy and chaotic, I think checking against a dict of constraints would be better:
def get_value(num, suit):
constraints = {((18, 15), (7,)): -21, ((16,), (7,)): -11, ((15, 16, 17, 18), (1,)): 11, ((15, 16, 17, 18), (12, 13)): 10, ((15, 16, 17, 18), (11,)): 25}
for x in constraints:
if suit in x[0] and num in x[1]:
return constraints[x]
A constraint tuple (ex. ((18, 15), (7,)) ) is only fulfilled if its first tuple (ex. (18, 15) ) contains suit and its second tuple (ex. (7,) ) contains num.
Additionally you could return a default value if the args passed in don't match the constraints.

How can I print the random list of grades without copying the same grade of the other students?

I am having a trouble on how can I print the grades of the students using random package without copying the same grade of the other students. The program requires functions to make. please help
import random
def get_values():
list = []
q = 1
i = 4
for num in range(i):
data = random.randint(1, 100)
list.append(data)
#print("Quiz no.", q)
#print(data)
q += 1
return list
def validate(ctr):
while ctr > 50:
print("Maximum of 50 students only")
exit()
return ctr
def grade(x):
FG = sum(x) / 4
return FG
def EQ(FG):
if FG < 60:
s = float(5.0)
print(s)
elif FG >= 60 and FG < 75:
s = float(3.0)
print(s)
elif FG >= 75 and FG < 90:
s = float(2.0)
print(s)
elif FG >= 90 and FG <= 100:
s = float(1.0)
print(s)
return s
def main():
list_high = []
list_low = []
ls=[]
repeat = 'Y'
ctr = 1
while repeat.upper() == 'Y':
validate(ctr)
x = get_values()
y = grade(x)
z = EQ(y)
high = list_high.append(max(x))
low = list_low.append(min(x))
print("Student # Quiz 1 Quiz2 Quiz 3 Quiz4 Grade EQ")
q = 1
for num in range(ctr - 1):
print("\n ", q, end='')
for c in range(len(x)):
print(" ", x[c], end="")
q += 1
print(" ", y, " ", z, end=" ")
ctr += 1
# average_high = sum(list_high) / len(list_high)
#average_low = sum(list_low) / len(list_low)
repeat = input("\n Enter Y to input another students score: ")
main()
the output of my program
Student # Quiz 1 Quiz2 Quiz 3 Quiz4 Grade EQ
1 17 95 5 92 52.25 5.0
2 17 95 5 92 52.25 5.0
3 17 95 5 92 52.25 5.0
4 17 95 5 92 52.25 5.0
5 17 95 5 92 52.25 5.0
6 17 95 5 92 52.25 5.0
Enter Y to input another students score:
You're overthinking it. Also, try to iterate over a collection of objects rather than a range-based for-loop, if you can.
Here is something that might be helpful:
def main():
from random import sample
number_of_quizzes = 4
scores = sample(range(1, 100), number_of_quizzes)
print(scores)
if __name__ == "__main__":
main()
Output:
[10, 93, 66, 46]
>>>
Then, if you have, for example, five students, and each student has four quizzes, you can extend it like so:
def main():
from random import sample
number_of_students = 5
number_of_quizzes = 4
for current_scores in (sample(range(1, 100), number_of_quizzes) for _ in range(number_of_students)):
print(current_scores)
if __name__ == "__main__":
main()
Output:
[25, 82, 87, 13]
[91, 12, 76, 65]
[96, 90, 19, 34]
[82, 67, 4, 8]
[6, 91, 47, 68]
>>>
EDIT - This is closer to what you've written:
def get_random_scores():
from random import randint
number_of_scores = 4
scores = []
for _ in range(number_of_scores):
score = randint(1, 100)
scores.append(score)
return scores
def get_highest_score_for_quiz_n(students_scores, *, n):
return max(list(zip(*students_scores))[n-1])
def main():
number_of_students = 5
students_scores = []
for _ in range(number_of_students):
students_scores.append(get_random_scores())
print("The scores are:")
for scores in students_scores:
print(scores)
max_third_quiz_score = get_highest_score_for_quiz_n(students_scores, n=3)
print(f"The highest score on the third quiz was {max_third_quiz_score}")
if __name__ == "__main__":
main()

Difference between elements of N list of size n. Python [duplicate]

This question already has answers here:
Python: Finding differences between elements of a list
(12 answers)
Closed 9 years ago.
Say I have N lists of size n, eg, 5 tuples of size 3:
p = [[9, 9, 9], [17, 14, 18], [14, 15, 17], [14, 15, 17], [14, 15, 15]]
How can I find the difference between indexes of the lists, for example the index 0:
17-9 = 8
14-17 = -3
14-14 = 0
14-14 = 0
then for index 1:
14-9 = 5
15-14 = 1
15-15 = 0
15-15 = 0
then index 2, 3, 4.
I need the code to be able to do this dynamically so I can change N and n at will.
Any help will be greatly appreciated.
EDIT:
I have tried this thus far:
for i in range(10):
for j, k in product(range(i+1), repeat=2):
if j!=k:continue
else:
print p[i][j]-p[i-1][j]
This code is for tuples of size 2.
Try this:
>>> for x in zip(*p):
for i in range(len(x)-1):
print '{0} - {1} = {2}'.format(x[i+1],x[i],x[i+1]-x[i])
17 - 9 = 8
14 - 17 = -3
14 - 14 = 0
14 - 14 = 0
14 - 9 = 5
15 - 14 = 1
15 - 15 = 0
15 - 15 = 0
18 - 9 = 9
17 - 18 = -1
17 - 17 = 0
15 - 17 = -2
ugly as hell, not pythonic, prone to all the errors of this world, but yet working (and at least should show you a basic logic for what you need):
In [6]: for i in range(len(p[0])):
for j in range(1,len(p)):
print "%d - %d = %d" % (p[j][i], p[j-1][i], p[j][i]-p[j-1][i])
...:
17 - 9 = 8
14 - 17 = -3
14 - 14 = 0
14 - 14 = 0
14 - 9 = 5
15 - 14 = 1
15 - 15 = 0
15 - 15 = 0
18 - 9 = 9
17 - 18 = -1
17 - 17 = 0
15 - 17 = -2
explanation
row 1: checks for the length of your sublists, based on the first element of your max list.
row 2: does the same, starting from index one (so you can do p[1]-p[0] without worrying about out of bounds problems)
row 3: prints what you want
you could start from this to tinker around
It can easily be done using numpy:
p = numpy.array([[9, 9, 9], [17, 14, 18], [14, 15, 17], [14, 15, 17], [14, 15, 15]])
numpy.diff(p.T)
This should do it:
for xyz in zip(*p):
for curr_idx in xrange(len(xyz)-1):
print xyz[curr_idx+1]-xyz[curr_idx]
try this
p = ((9, 9, 9), (17, 14, 18), (14, 15, 17), (14, 15, 17), (14, 15, 15))
index=0
for d in range(1,len(p)):
print "p["+str(d)+"]["+str(index)+"]-p["+str(d)+"]["+str(index)+"]=",
print p[d][index]-p[d-1][index]
output is
p[1][0]-p[1][0]= 8
p[2][0]-p[2][0]= -3
p[3][0]-p[3][0]= 0
p[4][0]-p[4][0]= 0

Categories