1

I'm working in Python 3, Windows 10, PyCharm.

I'm building a small program that lets you input your age and returns "Happy {age}{termination, eg: st, nd}!"

The thing is that I want to somehow avoid the situation where you will write your age as 1041 and it'll say "Happy 1041th!". So I used list(range(21, 1001, 10)) for the termination "st", for instance. However, I'd like to be able to use infinite instead of 1001. If I use math.inf, that's a float and it's not accepted in my code. Also, I can't convert it to int.

I'm thinking of using a n number that should be higher than say, 100, and have list(range(21, n, 10)), but I'm too much of a beginner to know how to do that. Thanks for the help. Here's my code:

age = int(input('Type age: '))
if int(age) == 1:
    term = 'st'
elif int(age) == 2:
    term = 'nd'
elif int(age) == 3:
    term = 'rd'
elif int(age) in list(range(21, 1001, 10)):
    term = 'st'
elif int(age) in list(range(22, 1002, 10)):
    term = 'nd'
elif int(age) in list(range(23, 1003, 10)):
    term = 'rd'
else:
    term = 'th'
if int(age) >= 130:
    print("C'mon! you can't be THAT old, you geezer!\nStill, here you go:")
message = f"Happy {age}{term} birthday!"

print(message)
Ovidiu Leonte
  • 45
  • 1
  • 1
  • 7

3 Answers3

3

Modulo arithmetic is a better (and completely general) solution to this problem:

age = int(input('Type age: '))
if 11 <= (age % 100) <= 13:
    term = 'th'
elif age % 10 == 1:
    term = 'st'
elif age % 10 == 2:
    term = 'nd'
elif age % 10 == 3:
    term = 'rd'
else:
    term = 'th'
if age >= 130:
    print("C'mon! you can't be THAT old, you geezer!\nStill, here you go:")
message = f"Happy {age}{term} birthday!"

print(message)
Nick
  • 138,499
  • 22
  • 57
  • 95
  • 1
    First statement is a very neat solution. – Harun Yilmaz Jun 12 '20 at 13:16
  • Just need an addition to exclude 11, 12, 13: `elif age % 10 == 1 and age != 11:` Same with the rest. In case `if 11<= (age % 100) <= 13:` was meant to do that, I don't understand how it would work. Thank you so much! – Ovidiu Leonte Jun 12 '20 at 13:22
  • 1
    @OvidiuLeonte that's what the first line in the `if` statement does see this demo: https://rextester.com/RVKS70128 – Nick Jun 12 '20 at 13:23
  • I thought so too it just doesn't work when I run it in my code, like [Vinay](https://stackoverflow.com/users/6399721/vinay-gupta) says – Ovidiu Leonte Jun 12 '20 at 13:28
  • 1
    You do have `elif age % 10 == 1` not just `if age % 10 == 1`? – Nick Jun 12 '20 at 13:34
  • 1
    @OvidiuLeonte no worries - I'm glad we got it sorted out. – Nick Jun 12 '20 at 13:38
  • @Nick, so if there's two lines of `if` in the same function, the last `if` surpasses the first? Meaning, the last `if` doesn't play the role of `elif`, but it cancels the assumption of the previous one? Thank you. – Ovidiu Leonte Jun 14 '20 at 11:34
  • 1
    @OvidiuLeonte if there are two `if` statements they execute independently. In this case, the second `if` had conditions (e.g. `age % 10 == 1`) that matched those in the first (`11 <= age`), so the actions from the first `if` were overwritten. – Nick Jun 14 '20 at 11:53
  • Thank you. I now get it. – Ovidiu Leonte Jun 14 '20 at 13:18
  • 1
    @OvidiuLeonte was there a reason you decided against this code? I'm curious? – Nick Jun 16 '20 at 07:22
  • @Nick I used the `endswith` suggestion in the end. This is also great, but it's just that I found the other one more elegant (even though maybe it isn't, I don't know; this is how I feel about it). I didn't mean no disrespect neither towards the help you gave me, nor the effort you put into this. Honestly, I would chose both this and the `endswith` solution if it'd make sense to use two solutions. Of course, this doesn't mean I didn't learn from what you offered. Our entire thread of discussion clearly suggests it. And I thank yo for that. – Ovidiu Leonte Jun 17 '20 at 08:47
3

There is no reason to check membership in a massive list which will eat up a ton of memory. You can just check what you age endswith.

age = input('Type age: ')
if age.endswith('11') or age.endswith('12') or age.endswith('13'):
    term = 'th'
elif age.endswith('1'):
    term = 'st'
elif age.endswith('2'):
    term = 'nd'
elif age.endswith('3'):
    term = 'rd'
else:
    term = 'th'

if int(age) >= 130:
    print("C'mon! you can't be THAT old, you geezer!\nStill, here you go:")
message = f"Happy {age}{term} birthday!"

print(message)
Axe319
  • 4,255
  • 3
  • 15
  • 31
  • 1
    I had no idea about `endswith`. Thank you so much! – Ovidiu Leonte Jun 12 '20 at 13:24
  • I actually think this is the best approach. It opens a lot of other opportunities. How did you find such a gem? – Ovidiu Leonte Jun 12 '20 at 13:35
  • 1
    It's been a while, but probably just reading the docs here. https://docs.python.org/3.8/library/stdtypes.html#string-methods There's also a `str.startswith()` that can be really helpful. – Axe319 Jun 12 '20 at 13:45
1

You don't need change to be list, if you change it to be list it may will be error. You just input age in range(s, e, i). If you want higher like as infinity use like this age in range(21, sys.maxsize**100, 10)

import sys
inf = sys.maxsize**10
age = int(input('Type age: '))
if int(age) == 1: term = 'st'
elif int(age) == 2: term = 'nd'
elif int(age) == 3: term = "rd"
elif int(age) in range(21, inf, 10): term = 'st'
elif int(age) in range(22, inf, 10): term = "nd"
elif int(age) in range(23, inf, 10): term = 'rd'
else: term = 'th'

if int(age) >= 130:
    print("C'mon! you can't be THAT old, you geezer!\nStill, here you go:")
message = f"Happy {age}{term} birthday!"
print(message)

But, why you want to use range if there is easier than it? Like make it to be string and then check the last number.

age = int(input("Type age: "))
term = ["st", "nd", "rd", "th"][3 if age%10 > 3 or age%100 in range(10, 20) else age%10-1]
if age > 130: message = "blah-blah-blah"
print(message)

Yes, I know the result is defferent. But, the next code I show you it's also can handle higher than hundred. Such as 101, on your code will be 101th; I think isn't correct. Variable term I have input ternary operator or conditional expression. In Python [if_true] if [condition] else [if_false] In JS condition? if_true:if_false

Looping from 1 to infinity in Python

Transamunos
  • 101
  • 4
  • I solved it with `age.endswith('1')` and so forth, but some things here are interesting, even though not for something that has such an easy solution as the aforementioned one. It'll just take me a while to process it, as I'm a bit at the beginning. Thank you. – Ovidiu Leonte Jun 12 '20 at 14:34
  • 1
    There is 3 Condition with "th" last digit with, 0, 1x, and 4-9. For 1x `age%100 in range(10,20)` and for 0 and 4-9 `age%10 not in range(4)`. Combine them and then become `if age%100 in range(10, 20) or age%10 not in range(4): term = "th"` Now for st, nd, and rd: `else: term = ["", "st", "nd", "rd"][age%10]`. – Transamunos Jun 12 '20 at 15:13
  • 1
    On my answer I use `ternary operator`. Don't worry, I'll explain. If we make list `t = ["st", "nd", "rd", "th"]`, so "th" in index 3 `t[3]`. Ternary operator is `3 if age%100 in range(10, 20) or age%10 not in range(3) else arg%10-1`. We combine the both condition (see code in comment above). The final result is `term = ["st", "nd", "rd", "th"][3 if age%100 in range(10,20) or age%10 not in range(4) else age%10-1]` – Transamunos Jun 12 '20 at 15:26
  • 1
    I had some time to play with your solution. `inf = sys.maxsize**10` issues this error: _OverflowError: Python int too large to convert to C ssize_t_ I presume `**10` is there to enlarge the `sys.maxsize` number. I tried without it, left `sys.maxsize` instead. Got me this error: _OverflowError: Python int too large to convert to C ssize_t_ I am getting to the other solution you proposed, because I think there's something to learn from it. However, I hope you can tell me something about these errors. Thank you so much. – Ovidiu Leonte Jun 14 '20 at 11:39
  • 1
    Also, I don't understand the concept behind `term = ["st", "nd", "rd", "th"][3 if age%10 > 3 or age%100 in range(10, 20) else age%10-1]` I know it's probably trivial, but I didn't get to learn something like that. It seems to me that `term` equals two lists, one of them clearly having 4 elements, order DOES matter, and the second is an `if` statement that includes `or`, `not`, `and` operators. It's this `if` statement that I don't understand at all. I know I'm asking much, but do you think you could point me in the right direction? I really love this solution and I'd like to understand it. – Ovidiu Leonte Jun 14 '20 at 11:59
  • 1
    Yes, I told you. If you convert it to list you will gey error. Because it's too large. Don't do this: `age in list(range(101, sys.maxsize**10, 10))`. Do this: `age in range(101, sys.maxsize**10, 10)`. You may don't know about list. If we input `term = ["st", "nd", "rd", "th"][3]` same as `term = ["st", "nd", "rd", "th"]; term = term[3]`. For the next indise `[]` is known as `conditional expression`. `h = "Hi, Mister!" if age > 30 else "Hi, Bro!"`, this code same as `if age > 30: h = "Hi, Mister!"; else: h = "Hi, Bro!"` – Transamunos Jun 14 '20 at 17:05
  • OK, it worked. I just got really scared. It's A LOT I don't know. No, I didn't know about conditional expression. That's similar to _list comprehension_, isn't it? Anyway, thank you. And... I'll keep digging in what you gave me here. – Ovidiu Leonte Jun 15 '20 at 07:44