Python Ordinal Number Script - python

We have an assignment that I'm stumped on. We have to write a function called int2ordinal that solves the following tasks:
Any number that ends in 11, 12 or 13 uses a th suffix
All remaining numbers that end in 1 use an st suffix
All remaining numbers that end in 2 use an nd suffix
All remaining numbers that end in 3 use an rd suffix
All remaining numbers use a th suffix
So basically write a function named int2ordinal that takes an integer as its only parameter and returns the number with its appropriate suffix as its result (stored in a string). For example, if the function is passed the
integer 1 then it should return the string "1st". If it is passed the integer 12 then it should return the string "12th". If it is passed 2003 then it should return the string "2003rd".
We're using the remainder operator to extract the last digit of an integer by computing the remainder when the integer is divided by 10, and we're doing the same to extract the last two digits of an integer divided by 100. For example 29 % 10 is 9 while 1911 %100 is 11. We can then construct the string that needs to be returned by the function by converting the integer parameter into a string and concatenating the appropriate suffix using the + operator.
This is the code we have so far, we think the first half is totally incorrect:
def int2ordinal(day, month, year):
if day % 10 == 1: return (str(day + "st"))
if day % 10 == 2: return (str(day + "nd"))
if day % 10 == 3: return (str(day + "rd"))
if month % 10 == 1: return (str(month + "st"))
if month % 10 == 2: return (str(month + "nd"))
if month % 10 == 3: return (str(month + "rd"))
if year % 100 == 1: return (str(year + "st"))
if year % 100 == 2: return (str(year + "nd"))
if year % 100 == 3: return (str(year + "rd"))
for i in range (11, 13): return (str(day + "th"))
for i in range (11, 13): return (str(month + "th"))
for i in range (11, 13): return (str(year + "th"))
else: return (str(day + "th", month + "th", year + "th"))
def main():
day = int(input("Enter a day between 1 and 31: "))
month = int(input("Enter a month between 1 and 12: "))
year = int(input("Enter a year between 1 and 2100: "))
print("On the", int2ordinal(day), "day of the", int2ordinal(month), \
"month of the", int2ordinal(year), "year, something amazing happened!")
main()
Any help would be amazing!

Why not keep it more simple?
You can find this below and use it in all your codes by using pip install mknxgn_essentials then using asordinal = essentials.GetOrdinal(my_num)
def GetOrdinal(number):
if type(number) != type(1):
try:
number = int(number)
except:
raise ValueError("This number is not an Int!")
lastdigit = int(str(number)[len(str(number))-1])
last2 = int(str(number)[len(str(number))-2:])
if last2 > 10 and last2 < 13:
return str(number) + "th"
if lastdigit == 1:
return str(number) + "st"
if lastdigit == 2:
return str(number) + "nd"
if lastdigit == 3:
return str(number) + "rd"
return str(number) + "th"

Why not keep it simple? Although untested, this should work.
def int2ordinal(num):
def formatted_num(suffix): # Nested function.
return str(num) + suffix
end_digits = int(num[-2:]) # Gets last 2 chars of the string. Instead of repeating this operation on every if clause, better do it here.
# You only really need to check if it either finishes with 1,2,3 - remaining values will have a th suffix.
if end_digits in [1]:
return formatted_num('st')
elif end_digits in [2]:
return formatted_num('nd')
elif end_digits in [3]:
return formatted_num('rd')
else:
return formatted_num('th')
def main():
day = input("Enter a day between 1 and 31: ")
month = input("Enter a month between 1 and 12: ")
year = input("Enter a year between 1 and 2100: ")
print("On the", int2ordinal(day), "day of the", int2ordinal(month), \
"month of the", int2ordinal(year), "year, something amazing happened!")
main()
Based on your answer in the comments then do this:
def int2ordinal(num):
num = str(num)
if len(num) > 2: # Will be a year, not necessarily consisting of four digits. Could be 333
end_digits = int(num) % 100
else: # Will be month / day
end_digits = int(num) % 10
if end_digits == 1: return (num + "st")
if end_digits == 2: return (num + "nd")
if end_digits == 3: return (num + "rd")
else: return (num + "th")
def main():
day = input("Enter a day between 1 and 31: ")
month = input("Enter a month between 1 and 12: ")
year = input("Enter a year between 1 and 2100: ")
print("On the", int2ordinal(day), "day of the", int2ordinal(month), \
"month of the", int2ordinal(year), "year, something amazing happened!")
main()
In general, try to avoid repeating code as much as you can. If you look at your original code, you're running num % 10/100 on every clause and also casting to str on every single return (no performance loss here, but repeating logic). Better avoid repeating such calls as much as possible, even if this code is not resource intensive, as you say you are an amateur: The earlier you learn this, the better.
Also, a reason your original code would always have failed is that it had three arguments, you were always passing a day to it. Named arguments work like this:
def foo(a,b,c):
pass
foo(a=0)
foo(b=1)
foo(c=2)
Doing:
foo(3)
Results in foo() getting argument a, b and c will be None.

Related

Digit of Life in Python

I'm trying to create a method that will return a digit of life when receiving input of a date of birth in the following format: YYYYMMDD. The requirements are as follows (see image below):
I have tried the following:
def split(word):
return [char for char in word]
date = input("Enter your date of birth in YYYYMMDD format: > ")
sum_list = []
def digitOfLife(date):
sum = 0
if(len(date) > 8):
print("Input data too long")
return
else:
date_list = []
for char in date:
date_list.append(int(char))
while len(date_list) >= 1:
print(len(date_list))
for num in date_list:
if sum > 9:
sum = 0
sum+=num
date_list.pop()
return sum
print(digitOfLife(date))
However, I am not getting the result that is supposed to be produced with this algorithm. I know it has something to do with my logic which adds the digits of the list after it's been popped, but I'm not sure what it is.
Any insight would be greatly appreciated.
It looks like you would only need to perform modulo 10 on cumulative additions:
def dol(N): return N if N < 10 else dol(N//10+N%10)
date = "19991229"
dol(int(date)) # 6
while len(date_list) >= 1:
print(len(date_list))
# check if it's over 9
if sum > 9:
sum =0
num = date_list.pop()
sum += num
Check the above code maybe this would help you. And also check the documentation of pop() function from here
Pop function removes the last element from the list and returns it. Like this :
L = [1, 2, 3]
x = L.pop()
print(x) # this will return 3
***This afterwards occured me that you can also add them straightforward and apply modulo by ten.
A .pop() inside loop may cause a problem because size of the list is changing during the iterations.
Besides .pop() removes the last element.
I would suggest the following solution:
def digitOfLife(date):
sum_ = 0
if (len(date) > 8):
print("Input data too long")
return
else:
date_list = []
for char in date:
date_list.append(int(char))
sum_ = sum(date_list) # calculate the sum of list of digits
while len(str(sum_)) > 1: # repeat while the sum has more than 1 digit
sum_ = sum(date_list)
date_list = [int(x) for x in str(sum_)]
return sum_
Also "sum" is a reserved word, so I renamed variable to sum_
Starting from your piece of code:
you should use a for loop istead of the while loop with pop .. this will make things easier.
then when sum > 9, you should not reset the sum to 0, but add the digits together.
This gives you the following piece of code:
def split(word):
return [char for char in word]
date = input("Enter your date of birth in YYYYMMDD format: > ")
sum_list = []
def digitOfLife(date):
sum = 0
if(len(date) > 8):
print("Input data too long")
return
else:
date_list = []
for char in date:
date_list.append(int(char))
for num in date_list:
sum+=num
if sum > 9:
sum = sum%10 +sum//10
return sum
print(digitOfLife(date))
This will output what you expect:
Enter your date of birth in YYYYMMDD format: > 19991229
6
Other improvements are still possible, but this shows you the easier change to make in your code.
Short way for digit of life:
def digitoflife(date):
if len(date) > 8:
print("date inputed is long")
else:
num = num2 = 0
for digit in date:
num += int(digit)
for i in str(num):
num2 += int(i)
return num2
date = str(input('Enter the date: '))
print("The digit of life is: ",digitoflife(date))
Code:
def bd_digit(string):
total = 0
for digit in string:
total+=int(digit)
if total >=10:
return bd_digit(str(total))
else:
return total
print(bd_digit('19991229'))
This may help you with recursion
I did the same exercise today like this.
date = '19991229'
list1=[]
for i in date:
list1.append(int(i))
date2 = str(sum(list1))
list2 = []
for i in date2:
list2.append(int(i))
total = sum(list2)
print(total)
def digitsoflife(number):
sum_ = [i for i in str(number)]
sum_ = sum(list(map(int, sum_)))
sum_total = 0
while len(str(sum_)) > 1:
for i in str(sum_):
sum_total += int(i)
sum_ = sum_total
print(sum_total)
break
else:
print(sum_)

Find ordinal numbers with loop dynamically: find th - st - nd - rd

I would like to find dynamically the correct ordinal number root for instance:
111 = 111st
112 = 112nd
113 = 113rd ...
I tried other solutions but I can't find a good one.
This is my code:
for number in range(1, 114):
print(number)
ex1 = 11
ex2 = 12
ex3 = 13
if number == ex1:
print("is the " + str(number) + "th number.")
elif number % 10 == 1 or not ex1:
print("is the " + str(number) + "st number.")
elif number == ex2:
print("is the " + str(number) + "nd number.")
elif number % 10 == 2 or not ex2:
print("is the " + str(number) + "nd number.")
elif number == ex3:
print("is the " + str(number) + "rd number.")
elif number % 10 == 3 or not ex3:
print("is the " + str(number) + "rd number")
else:
print("is the " + str(number) + "th number.")
Note that 11, 12 and 13 have th suffix.
Also note you can change the end of the line in print function (default \n):
print('text', end=' ')
print('another text')
Then, I suggest you to use formatted string using f"{data} constant text" or "{} constant text".format(data).
Here is my solution to your problem:
def getSuffix(n):
if n < 0: raise Exception("Ordinal negative numbers are not allowed")
if n % 100 in [11, 12, 13]: return 'th'
if n % 10 == 1: return 'st'
if n % 10 == 2: return 'nd'
if n % 10 == 3: return 'rd'
return 'th'
for number in range(1, 114):
print(f"{number} is the {number}{getSuffix(number)} number")
I hope I was helpful.
So, the problem is that 111 gets displayed as 111st instead of 111th.
You have 11 as ex1, I assume short for "exception 1", but your condition:
if number == ex1:
Clearly doesn't match 111.
Instead you could do:
if number % 100 == ex1:
Which will be true for 11, 111, 211 etc.
On a side note:
elif number % 10 == 1 or not ex1:
Clearly isn't what you intended. This is interpreted as:
elif (number % 10 == 1) or (not ex1):
not ex1 does not depend on number and will always evaluate the same way (False). But since you're already checking ex1 separately, it would be redundant to do it correctly here.
If you wanted to correct that, so that you don't need to check ex1 twice, you'd do this:
if number % 10 == 1 and number % 100 != 11:
I think in this case using != is clearer than not and I don't think there is any benefit from assigning a variable to 11.
This is a pretty good solution:
ordinal = lambda n: "%d%s" % (n, "tsnrhtdd"[(n // 10 % 10 != 1) * (n % 10 < 4) * n % 10::4])
for number in range(1, 114):
print(f'the {ordinal(number)} number. :) ')
EDIT For Human Beings
NOTE: Variables name aren't meant to be used in a production environment, I tried to make it more explicit what each step on the lambda function does!
def get_ordinal(n):
hacking_string = "tsnrhtdd" # 1)
is_num_divisible_by_ten = (n // 10 % 10 != 1) # 2)
is_num_reminder_0_3= (n % 10 < 4) # 3)
are_both_false_or_both_true= is_num_divisible_by_ten * is_num_between_0_3 # 4)
get_index = are_both_false_or_both_true* n % 10 # 5)
return f'{number}{hacking_string[get_index::4]}' #6) ---> starts at t | s | n | r
for number in range(1, 114):
print(f'the {get_ordinal(number)} number. :) ')
Considerations
The solution found is very Hacky and smart and I probably would never come up my self, is using some clever math tricks to find the off sets of the number.
As requested I however simplified the function and added some explanation to it.
Step 1. This string is better seen it as this "tsnr" "htdd" | On the left side you heve the "root" of the string, on the right the end. (more explanation below)
Step 2. is_num_divisible_by_ten --> using a floor division the result is True or False.
Step 3. is_num_reminder_0_3 If checking if the reminder of N and 10 is between 0 & 3, returns a True / False Flag.
Step 4. are_both_false_or_both_true is multiplying 2 bool value, in Python True is a 1 and False is a 0, so is like do --> 1 * 0. The Variable is True only if both values are True or both are False, otherwise is always False.
Step 5. get_index - > Returns either 0 or 1 or 2 or 3.
Step 6. Here the hacky part, with the received index from get_index, is laverage the hacking_string variable with indexing-and-slicing:
The get_index value is always one of these: "tsnr" and the steps taken (4) any of these "rhtdd" hence the possible combination are:
get_index = 0 = "th"
get_index = 1 = "st"
get_index = 2 = "nd"
get_index = 3 = "rd"
Finally
The exact mathematics that goes behind it may be better asked on math.stackexchange or if someone knows it would be good to either add a comment or edit my answer!
References (It wasn't my solution)
Ordinal numbers replacement
outputting ordinal numbers 1st,2nd,3rd
Guides
python-lambda
python-string-formatting
python-booleans-as-numbers
You can do it like that:
for number in range(1, 114):
printedString = str(number)+' is the '+str(number)
if str(number) == '1' or (str(number)[-1] == '1' and str(number)[-2] != '1'):
printedString += 'st'
elif str(number) == '2' or (str(number)[-1] == '2' and str(number)[-2] != '1'):
printedString += 'nd'
elif str(number) == '3' or (str(number)[-1] == '3' and str(number)[-2] != '1'):
printedString += 'rd'
else:
printedString += 'th'
print(printedString+' number.')

Python: Create two lists from loop and sum both

I'm working on a credit project of CS50 and I have some problem with the verification of the credit card.
Here the function I create:
def main():
while True :
cardnumber = input("Please enter a credit card number: ")
if cardnumber.isdecimal() and int(cardnumber) > 0 :
break
count = len(cardnumber)
if count != 13 and count != 15 and count != 16:
print("INVALID")
else:
check(count, cardnumber)
def check(length, number):
lenght_max = 15
if length == 15 and int(number[0]) == 3 and (int(number[1]) == 4 or int(number[1]) == 7):
if validator(number):
print("AMEX")
elif length == 16 and int(number[0]) == 5 and int(number[1]) <= 5:
if validator(number):
print("MASTERCARD")
elif length == 16 or length == 13 and int(number[0]) == 4:
if validator(number):
print("VISA")
else:
print("INVALID")
return number
def validator(num):
sum = 0
while num > 0:
sum += num % 10
num = num // 10
return sum
odd = [int(num[i]) * 2 for i in range(1, len(num), 2)]
even = [int(num[i]) for i in range(0, len(num), 2)]
new_sum = sum(validator(x) for x in odd) + sum(even)
if(new_sum % 10 == 0):
return True
else:
print("INVALID")
main()
I found the way to print the evens and the odds(multiply also time 2) but now I have to sum booth and check if the remainder is 0
Here the complete instruction:
http://docs.cs50.net/problems/credit/credit.html
Write a helper function to sum your digits. You'll need to use it extensively.
def dig_sum(num):
sum = 0
while num > 0:
sum += num % 10
num = num // 10
return sum
num = '378282246310005' # your credit card number
odd = [int(num[i]) * 2 for i in range(1, len(num), 2)] # these two remain the same
even = [int(num[i]) for i in range(0, len(num), 2)]
new_sum = sum(dig_sum(x) for x in odd) + sum(even)
if(new_sum % 10 == 0):
print('Valid') #valid!
sum(dig_sum(x) for x in odd) will get the digit sum for each number in your odd list and sum(...) that finds the resultant sum.
Input:
'378282246310005'
Output:
Valid
A first problem with your function is that you do not store the even/odd digits somewhere: you construct a list with one element each time, and print that element.
Now since two times a digit, can only result in a two digit number, we can use:
def sum2(x):
return (2*x)//10 + (2*x)%10
You can construct a list of all the digits at odd index with:
odd = [int(number[i]) for i in range(1,length,2)]
The same for digits at even index:
even = [int(number[i]) for i in range(0,length,2)]
Now we can simply use the sum(..) builtin function to sum up the digits:
total = sum(sum2(oddi) for oddi in odd) + sum(even)
and check if it is a multiple of 10:
return total%10 == 0
Or putting it all together:
def validator(number, length):
odd = [int(number[i]) for i in range(1,length,2)]
even = [int(number[i]) for i in range(0,length,2)]
total = sum(sum2(oddi) for oddi in odd) + sum(even)
return total%10 == 0
Or we can use a the following one liner for experts:
from itertools import zip_longest
def validator(number,length):
numbi = iter(numbi)
return sum(x+sum2(y) for x,y in zip_longest(numbi,numbi,fillvalue=0))%10 == 0

Python3.4 - math with index numbers

My objective was to use the index of a list to do addition/subtraction with. Where by I turned the even index positive, and the odd index negative.
EX1: 1234508 Should be answered by a 0: 1-2+3-4+5-0+8 = 11, then the while loops it again and I get 1-2+1 = 0
Ex2: 12345 Should be answered by a 3: 1-2+3-5 = 3, so it shouldn't go through the loop again.
Ex3: 121 Should be answered by a 0: 1-2+1 = 0, so it shouldn't go throught he loop again.
def main():
print()
print("Program to determine if a number is evenly\ndivisible by 11")
print()
indexed = input("Enter a number: ",)
total = 0
num = 0
while num >= 10:
for item in indexed:
if num %2 == 0:
total = total + int(item)
else:
total = total - int(item)
num = num + 1
print(total)
main()
Note that this print statement above is a place holder for a if statement which is inactive on my code, but was printing as large bold print here.
Let's say you have a string st whose characters are all digits, and that you want to have the sum of these digits. You then define the following function
def sd(st):
return sum(int(d) for d in st)
that we can test in the interpreter
In [30]: sd('10101010101010101010')
Out[30]: 10
In [31]: sd('101010101010101010101')
Out[31]: 11
What you really want is to sum the odd digits and subtract the even ones, but this is equivalent to sum the odds, sum separately the evens and then take the difference, isn't it? so what you want is
step_1 = sd(odds(st)) - sd(evens(st))
How can you separate the odd digits from the even ones? Ah! no need for a function, we can use slices
step_2 = sd(st[::2]) - sd(st[1::2])
Now we want to test the slices in the interpreter
In [32]: '101010101010101010101'[::2]
Out[32]: '11111111111'
In [33]: '101010101010101010101'[1::2]
Out[33]: '0000000000'
But step_2 could be a negative number, that I don't want to manage... I'd rather use the abs builtin
step_3 = abs(sd(st[::2]) - sd(st[1::2]))
and this is exactly what you were looking for.
Eventually we can put all the above together, but we may need to iterate until the difference is less than 11 --- we'll use an infinite loop and a break statement to exit the loop when we'll have found the answer
def sd(st):
return sum(int(d) for d in st)
number = input('Give me a number: ')
trial = number
while True:
n = abs(sd(trial[::2]) - sd(trial[1::2]))
if n < 11: break
trial = str(n)
if n > 0:
...
else:
...
what exactly do you want to do with this?
evenindex = evenindex int(item)
"list" is a type, means the list type in python, so it cannot be the name of a variable. Furthermore, you have not defined this variable in your code.
I have figured out the answer to the question I asked above. As such, my answer here is in the event anyone stumbles upon my above question.
def main():
indexed = input("Enter a number: ",)
total = 0
num = 0
while num <= 10:
for item in indexed:
if num %2 == 0:
total = abs(total + int(item))
else:
total = abs(total - int(item))
num = num + 1
if total == 0:
print(indexed, "is evenly divisible by 11 \ncheck since", indexed, "modulus 11 is", int(indexed) % 11)
else:
print(indexed, "is not evenly divisible by 11 \ncheck since", indexed, "modulus 11 is", int(indexed) % 11)
input()
main()

Collatz sequence

How can I take an integer as input, of which the output will be the Collatz sequence following that number. This sequence is computed by the following rules:
if n is even, the next number is n/2
if n is odd, the next number is 3n + 1.
e.g. when starting with 11
11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
This is my code now:
n = int(raw_input('insert a random number'))
while n > 1:
if n%2 == 0:
n_add = [n/2]
collatz = [] + n_add
else:
n_add2 = [3*n + 1]
collatz = [] + n_add2
print collatz
if I execute this and insert a number, nothing happens.
You are never changing the number n, so it will be the same each time round. You are also only printing if the number is odd. Also, square brackets [] indicate an array - I'm not sure what your goal is with this. I would probably rewrite it like this:
n = int(raw_input('insert a random number'))
while n > 1:
if n%2 == 0:
n = n/2
else:
n = 3*n + 1
print n
You might want to take some time to compare and contrast what I'm doing with your instructions - it is almost literally a word-for-word translation (except for the print
It is a little unclear from your code if you want to just print them out as they come out, or if you want to collect them all, and print them out at the end.
You should be modifying n each time, this will do what you want:
n = int(raw_input('insert a random number'))
while n > 1:
n = n / 2 if not n & 1 else 3 * n + 1 # if last bit is not set to 1(number is odd)
print n
## -- End pasted text --
insert a random number11
34
17
52
26
13
40
20
10
5
16
8
4
2
1
Using your own code to just print out each n:
n = int(raw_input('insert a random number'))
while n > 1:
if n % 2 == 0:
n = n / 2
else:
n = 3 * n + 1
print n
Or keep all in a list and print at the end:
all_seq = []
while n > 1:
if n % 2 == 0:
n = n / 2
else:
n = 3 * n + 1
all_seq.append(n)
print(all_seq)
def collatz(number):
while number != 1:
if number % 2 == 0:
number = number // 2
print(number)
elif number % 2 == 1:
number = number * 3 + 1
print(number)
try:
num = int(input('Please pick any whole number to see the Collatz Sequence in action.\n'))
collatz(num)
except ValueError:
print('Please use whole numbers only.')
I've also been working on it for a while now, and here's what I came up with:
def collatz (number):
while number != 1:
if number == 0:
break
elif number == 2:
break
elif number % 2 == 0:
number = number // 2
print (number)
elif number % 2 == 1:
number = 3 * number + 1
print (number)
if number == 0:
print ("This isn't a positive integer. It doesn't count")
elif number == 2:
print ("1")
print ("Done!")
elif number == 1:
print ("1")
print ("Done!")
try:
number = int(input("Please enter your number here and watch me do my magic: "))
except (ValueError, TypeError):
print ("Please enter positive integers only")
try:
collatz(number)
except (NameError):
print ("Can't perform operation without a valid input.")
Here is my Program:
def collatz(number):
if number % 2 == 0:
print(number//2)
return number // 2
elif number % 2 == 1:
print(3*number+1)
return 3*number+1
else:
print("Invalid number")
number = input("Please enter number: ")
while number != 1:
number = collatz(int(number))`
And the output of this program:
Please enter number: 12
6
3
10
5
16
8
4
2
1

Categories

Resources