Hello I am doing the following programming exercise: Squad number generator. The statement is:
At the start of each season, every player in a football team is assigned their own unique squad number. Due to superstition or their history certain numbers are more desirable than others.
Write a function generateNumber() that takes two arguments, an array of the current squad numbers (squad) and the new player's desired number (n). If the new player's desired number is not already taken, return n, else if the desired number can be formed by adding two digits between 1 and 9, return the number formed by joining these two digits together. E.g. If 2 is taken, return 11 because 1 + 1 = 2. Otherwise return null.
Note: Often there will be several different ways to form a replacement number. In these cases the number with lowest first digit should be given priority. E.g. If n = 15, but squad already contains 15, return 69, not 78.
We would like to learn how the following algorithm could be improved:
def generate_number(squad, n): #☘️
print("squad: ",squad)
print("n: ",n)
if n not in squad: return n
firstDigit = n%9
secondDigit = 9
squadNumber = int(str(firstDigit)+str(secondDigit))
while squadNumber <= 99 and squadNumber in squad:
print("squadNumber: ",squadNumber)
firstDigit+=1
secondDigit-=1
while(firstDigit+secondDigit != n):
print("inside squadNumber: ",squadNumber)
firstDigit+=1
secondDigit-=1
squadNumber = int(str(firstDigit)+str(secondDigit))
squadNumber = int(str(firstDigit)+str(secondDigit))
return squadNumber if squadNumber <= 99 else None
The question would be: how do we get a two digits combination which summed are n?
For example:
n = 11 -> 11%9 = 2 -> 2+9 = 11 -> 29
n = 16 -> 16%9 = 7 -> 7+9 = 16 -> 79
n = 10 -> 10%9 = 1 -> 1+9 = 10 -> 19
However what would happen if n is 18 and it is currently being in the squad. The algorithm should return the next lowest, which would be 99...
But our code's trace would be:
squad: [1, 2, 3, 4, 6, 9, 10, 11, 15, 18, 23, 69]
n: 18
squadNumber: 9
inside squadNumber: 9
inside squadNumber: 27
inside squadNumber: 36
inside squadNumber: 45
inside squadNumber: 54
inside squadNumber: 63
inside squadNumber: 72
inside squadNumber: 81
inside squadNumber: 90
Traceback (most recent call last):
File "main.py", line 23, in <module>
Test.assert_equals(generate_number([1, 2, 3, 4, 6, 9, 10, 11, 15, 18, 23, 69], 18), 99)
File "/home/codewarrior/solution.py", line 16, in generate_number
squadNumber = int(str(firstDigit)+str(secondDigit))
ValueError: invalid literal for int() with base 10: '10-1'
So the following test would fail:
Test.it("should return next lowest, two-digit combination, if n is already taken")
Test.assert_equals(generate_number([1, 2, 3, 4, 6, 9, 10, 11, 15, 18, 23, 69], 18), 99)
We have thought the direct approach: loop from 11 to 99 and return the lowest one which digits sum n:
def generate_number(squad, n):
print("squad: ",squad)
print("n: ",n)
if n not in squad: return n
for twoDigitsNumber in list(range(11,100)):
if "0" in str(twoDigitsNumber): continue
print("twoDigitsNumber: ",twoDigitsNumber)
firstDigit=int(str(twoDigitsNumber)[0])
secondDigit=int(str(twoDigitsNumber)[1])
summed=firstDigit+secondDigit
print("summed: ",summed)
if twoDigitsNumber not in squad and summed==n: return twoDigitsNumber
return None
We have read: