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

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.')

Related

"super" number in python

I have a problem with the task. The task is:
We say that number 1 is a super number. If a number x is super, then
the numbers 2x and 3x are also super. For example, since the number 1
is super, then the numbers 2 and 3 are super. As 2 and 3 are super,
then the numbers 4, 6 and 9 are super, and so on. At the same time,
numbers 10 and 7 are not super. Write a program that asks the user to
enter a natural number n. The program prints whether the entered
number is super.
And this is what I have done so far
num = int(input("Enter a natural number "))
if num <= 0:
print("That is not a natural number")
else:
if num % 5 == 0 or num % 7 == 0 or num % 11 == 0 or num % 13 == 0:
print("Number is not super.")
elif num == 1 or num % 2 == 0 or num % 3 == 0 or num % 8 == 0 or num % 9 == 0:
print("Number is super")
else:
print("Number is not super.")
The problem is that for some numbers like 62 it says that it is a super number, but it ain't..
Just following the definition of super number:
def is_super(k):
if k == 1: return True
if k % 2 == 0:
return is_super(k / 2)
if k % 3 == 0:
return is_super(k / 3)
return False
Some testing
print(is_super(9))
True
print(is_super(14))
False
print(is_super(32))
True
print(is_super(62))
False
To me it looks like you jumped in without first figuring out how you'd work it out manually.
Personally, I think the easiest way to start this would be recursively, though it'll be very inefficient with large numbers, so it's up to you if you then want to go and optimise it after doing the first version. I got it working pretty easily, but since it's a problem you need to solve, I'm not going to just copy and paste the answer.
It works something like this (psuedocode):
def is_super(i):
if i is below 1: not a super
if i is 1: is a super
if i is above 1: check if i/2 or i/3 is a super
There are some nice recursive solutions here, I'll propose a non-recursive one. As some of the comments hint, super numbers have a tell-tale factorization: they are all of the form 2x * 3y for x, y >= 0, and every integer of that form is a super number. This should become clear after some study because the only way to get a super number is to multiply an existing one by 2 or 3, and we start with 1. That leads to the following code to test for superness:
def is_super(n: int) -> bool:
if n < 1:
return False
while n % 3 == 0:
n //= 3
return n & (n - 1) == 0; // Suggested by #KellyBundy
I tried to find shortcut way to test for superness but failed to find anything better than this.
num = int(input("Enter a natural number "))
if num <= 0:
print("That is not a natural number")
else:
if num % 3 == 0:
while num % 3 == 0:
num = num / 3
print(num)
if num == 1 or num % 2 == 0 or num % 3 == 0:
print("Number is super")
else:
print("Number is not super")
elif num % 2 == 0:
while num % 2 == 0:
num = num / 2
print(num)
if num == 1 or num % 2 == 0 or num % 3 == 0:
print("Number is super")
else:
print("Number is not super")
else:
print("Number is not super")
This is what I've done so far but I don't think it will work for large numbers ?

Python Ordinal Number Script

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.

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

Taking away from nearest 10

Okay, i have made my code so that a user can input 7 numbers and times them by 1 for the odd index numbers and 3 for the even:
num = str(input("Please enter 7 numbers")
length = len(num)
while length < 7 or length ? 7:
num = input("Only enter 7 numbers")
string = ''
for t in range(1,8):
if t % 2 == 0:
string += str(t * 3)
else:
string += str(t) + ' '
print(string)
This works fine, but now i need to add all the numbers up and take it away from the highest 10 so for example, all the numbers add up to 53 i need to take that away from 60 which leaves me 7, that will be my eight number, then after i have got that number i print it out, how do i get it to add the numbers up and the take it away from the highest 10 and output the difference of the two into the numbers i already have?
Thanks
Brad
If you have a number, x, which is equal to 53, then going up should be math.ceil(x) except that math.ceil() rounds for 1. To account for that, we divide by 10, use math.ceil(), and then multiply by 10 again:
import math
rounded_up = math.ceil(x / 10) * 10
result = rounded_up - x
Brad could you clarify your question? Also your above code does not work.
Missing a bracket on the first line and this isn't valid while length < 7 or length ? 7:
I believe this is what you're looking for:
def take_away_from_nearest(number, nearest):
return nearest - (number % nearest)
Usage:
>>> take_away_from_nearest(53, 10)
7
edit:
If I understand you correctly, this would be the entire code:
while True:
# this is just an easy way to keep asking until the input is correct
num = input("Please enter 7 numbers: ")
if len(num) == 7:
break
weird_sum = 0 #here's where we're gonna sum up the numbers; the "eighth number"
for index, character in enumerate(num):
if index % 2 == 0: # index is odd, so count the character thrice
print(3 * int(character))
weird_sum += 3 * int(character)
else: # index is even
print(int(character))
weird_sum += int(character)
print(10 - (weird_sum % 10)) # 10 minus (weird_sum modulo 10)
# and finally, adding them all up and checking whether it ends with 0:
print((10-(weird_sum % 10) + weird_sum) % 10 == 0) # prints True

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()

Categories

Resources