Lucky Name Number Challenge In Python - python

i have to create a lucky name number programme in python but i keep coming across many errors.
if you don't know what a lucky name number is, it is basically where each letter of the alphabet has a value and you add the values toether in your first name and second name so for example
john doe
165 465
1+6+5 = 12
4+6+5 = 15
15 + 12 = 27
2+7 = 8
then 8 = has diplomatic skills
Here is what i have done so far:
#this will go all the way to z
charDict = { 'A' : 1, 'B' : 2, 'C' : 3, 'D' : 4}
# example names - while loop will go here
firstName = 'AAB'
lastName = 'DCDD'
# split the strings into a list of chars
firstNameChars = list(firstName)
lastNameChars = list(lastName)
# sum up values
firstNameSum = 0
lastNameSum = 0
for chr in firstNameChars:
firstNameSum += charDict[chr]
for chr in lastNameChars:
lastNameSum += charDict[chr]
# cast sums to strings. In this example, this would be '2024'
combinedNames = str(firstNameSum) + str(lastNameSum)
# split the string into a list of chars
combinedNameDigits = list(combinedNames)
# sum them up
finalSum = 0
for dgt in combinedNames:
finalSum += int(dgt)
# print the lucky number
print finalSum
So my question is, is where do i go from here, as the numbers don't add up correctly and the values of the letters aren't correct, so basically how do i do the calculations correctly

I really don't undersand how: john doe gives 165 465 and how: AAB DCDD gives 2024.
However, the standard way to convert letters in numbers and to sum the digits of a number is the following:
def letters_to_numbers(name):
sum_ = 0
for letter in name:
sum_ += ord(letter.upper())-64 #ord("A")=65 minus 64 -> 1
return sum_
def sum_digits(number):
sum_ = 0
while number:
sum_ += number%10
number //=10
return sum_
sum_digits(
sum_digits(letters_to_numbers("john"))
+sum_digits(letters_to_numbers("doe")))

This works considering you always split your numbers to the digit level, I let you wrap it in a function and modify the dictionary to add other letters
first = 'aaa'
last = 'bbb'
name = first + last
dicti = {'a':1, 'b':2, '1':1, '2':2 , '3':3 , '4':4 , '5':5 , '6':6 ,
'7':7 , '8':8 , '9':9 , '0':0}
while len(name) >1:
sum = 0
for letter in name:
sum = sum + dicti[letter]
name = str(sum)
final_sum = int(name)

Related

sum of every other digit and doubling the rest

I'm working on a card number check code, for now I created a function that asks for the card number and checks if it is 8 digits or not (it has to be 8) and then calls another function that will do the math and check if the card is valid. For this function:
Starting from the rightmost digit, form the sum of every other digit. For example, if the card number is 1234 5678, then you form the sum 8 + 6 + 4 + 2 = 20
Double each of the digits that were not included in the preview step and then add all digits of the resulting numbers. For example, the digits that were not included are 7 5 3 1, we double the, 14 10 6 2, and then we sum each digit, 1 + 4 + 1 + 0 + 6 + 2 = 14
Add the sums of the two steps, 20 + 14 = 34, if the last digit is 0 then the card is valid, otherwise it is not valid (which is our case)
My problem is that I don't know how to iterate and get the sum of every other digit or double the other number which were not included in step 2. My thought was to use a while loop but then what?
EDIT: since some answers used lists... we didn't study lists yet, so I should not use it, we are only allowed to use sample stuff, loops, functions, etc.. even sum(map()) we didn't study
That is my code for now (its not much but just thought put it anyway)
def getCard():
CardInput = int(input("Enter your 8 digit credit card number: "))
if len(CardInput) == 8:
CardCheck(CardInput)
else:
print("Invalid Input: Should be exactly 8 digits!")
getCard()
def CardCheck(CardNumber):
Position = 0
Sum = 0
DoubleSum = 0
FinalSum = 0
while CardNumber >= 0:
Position += 1
So, the ugly way of doing is, you can write a for loop and use indexing for access specific elements
for i in range(len(CardInput)):
# it will iterate from 0 to 7
print(CardInput[i]) # here you get ith element
if i % 2 == 1:
print("I am other!") # you can sum your things here into another variable
Or with while:
while position < len(CardInput):
print(CardInput[position])
position += 1
It assumes CardInput is str, so I recommend to not convert it earlier.
However pythonic way would be
sum(map(int, CardInput[1::2])))
CardInput[1::2] returns list of every second element starting from second (0 is first).
map converts every element to in.
sum sums elements.
prompt = "Enter the eight-digit number: "
while True:
number = input(prompt)
if len(number) == 8 and number.isdigit():
break
prompt = "Oops, try again: "
first_digits = number[1::2] # If the user entered '12345678', this will be the substring '2468'
first_sum = sum(map(int, first_digits)) # Take each digit (character), map it to a single-digit integer, and take the sum of all single-digit integers
second_digits = number[0::2] # If the user entered '12345678', this will be the substring '1357'
doubled_ints = [int(char) * 2 for char in second_digits] # Take each digit (character), turn it into an integer, double it, and put it in a list.
second_sum = sum(map(int, "".join(map(str, doubled_ints)))) # Merge all integers in 'doubled_ints' into a single string, take each character, map it to a single digit integer, and take the sum of all integers.
total_sum = first_sum + second_sum
total_sum_last_digit = str(total_sum)[-1]
is_valid_card = (total_sum_last_digit == '0')
if is_valid_card:
print("Your card is valid (total sum: {})".format(total_sum))
else:
print("Your card is NOT valid (total sum: {})".format(total_sum))
def getCard():
CardInput = input("Enter your 8 digit credit card number: ")
if len(CardInput) == 8:
CardCheck(CardInput)
else:
print("Invalid Input: Should be exactly 8 digits!")
getCard()
def CardCheck(CardNumber):
list_CardNumber = [x for x in "25424334"]
Sum = sum(int(x) for x in list_CardNumber[1:8:-2])
DoubleSum = 2*sum(int(x) for x in list_CardNumber[0:8:-2])
FinalSum = Sum + DoubleSum
if str(FinalSum)[-1] == "0":
print("Valid Input")
else:
print("Invalid Input")
To get you started, you should check out enumerate(), it'll simplify things if you're just going to use loops by giving you easy access to both the index and value every loop.
step1 = 0
for i, x in enumerate(number):
if i % 2:
print('index: '+ str(i), 'value: '+ x)
step1 += int(x)
print('step 1: ', step1)
Output:
index: 1 value: 2
index: 3 value: 4
index: 5 value: 6
index: 7 value: 8
step 1: 20
You can use:
# lets say
CardNumber = '12345678'
# as mentioned by kosciej16
# get every other digit starting from the second one
# convert them to integers and sum
part1 = sum(map(int, CardNumber[1::2]))
# get every other digit starting from the first one
# convert them to integers and double them
# join all the digits into a string then sum all the digits
part2 = sum(map(int,''.join(list(map(lambda x: str(int(x)*2), CardNumber[0::2])))))
result = part1 + part2
print(result)
Output:
34
Edit:
Only with loops you can use:
# lets say
CardNumber = '12345678'
total_sum = 0
for idx, digit in enumerate(CardNumber):
if idx % 2 == 1:
total_sum += int(digit)
else:
number = str(int(digit)*2)
for d in number:
total_sum += int(d)
print(total_sum)
output:
34
Since you need to iterate over the digits, it's actually easier IMO if you leave it as a string, rather than converting the input to an int; that way you can just iterate over the digits and convert them to int individuall to do math on them.
Given an 8-digit long string card, it might look like this, broken into steps:
even_sum = sum(int(n) for n in card[1::2])
double_odds = (2 * int(n) for n in card[0::2])
double_odd_sum = sum(int(c) for do in double_odds for c in str(do))
All together with some logic to loop while the input is invalid:
def get_card() -> str:
"""Returns a valid card number, or raises ValueError."""
card = input("Enter your 8 digit credit card number: ")
if len(card) != 8 or not card.isdecimal():
raise ValueError("Invalid input: Should be exactly 8 digits!")
card_check(card)
return card
def card_check(card: str) -> None:
"""Raises ValueError if card checksum fails, otherwise returns None."""
even_sum = sum(int(n) for n in card[1::2])
double_odds = (2 * int(n) for n in card[::2])
double_odd_sum = sum(int(c) for do in double_odds for c in str(do))
if (even_sum + double_odd_sum) % 10:
raise ValueError("Card checksum failed!")
while True:
try:
print(f"{get_card()} is a valid card number!")
except ValueError as e:
print(e)

Trying to use zfill and increment characters with Python

Hello lovely stackoverflowians!
I am fairly new to programming. Only have been programming a little under 2 months using CS50 which uses C and MITx Python. I went on Codewars and am trying to solve a problem where you basically get an id and then come out with a license plate number like this aaa001...aaa999, aab001...zzz999
if you catch my drift. For some reason my code compiles but when I run it I get this error.
File "/Users/pauliekennedy/Desktop/temp.py", line 9, in find_the_number_plate
a_str = (a_numb.zfill(3), range(0, 10))
AttributeError: 'int' object has no attribute 'zfill'
Because of this I am not able to test my code. If you could help me with this problem I would be much appreciated. As well, if you have anything to say about my code in general, tips, advice how to make it better, and if it will achieve this goal at all. Here is my code thanks again all.
#set number to 1 to start
a_numb = 1
#incrementing loop when 999 go back set back 0
while a_numb <1001:
a_numb += 1
a_str = str(a_numb)
# giving the number 00 or just 0 in front
if a_numb < 100:
a_str = (a_numb.zfill(3), range(0, 10))
#resetting the number back to 1
if a_numb == 999:
a_numb = 1
# Setting i to 0 and incrementing the characters
i = 0
ch = 'a'
ch2 = 'a'
ch3 = 'a'
#looping through alphabet
for i in range(26):
ch = chr(ord(ch) + 1)
print(ch)
if i == 26:
i = 0
if ch == 'z':
ch2 = chr(ord(ch) + 1)
if ch == 'z' & ch2 == 'z':
ch3(ord(ch) + 1)
# Adding results together and returning the string of them all
letter_plate = str(ch3 + ch2 + ch)
plate = str(a_numb) + str(letter_plate)
return plate```
Maybe you could consider using f-string string formatting instead:
def find_the_number_plate(customer_id):
number_part = customer_id % 999 + 1
customer_id //= 999
letter_part = ['a', 'a', 'a']
i = 0
while customer_id:
letter_part[i] = chr(ord('a') + customer_id % 26)
customer_id //= 26
i += 1
return f"{''.join(letter_part)}{number_part:03}"
You could use product from itertools to form the license plate numbers from 3 letters and numbers from 1 to 999 formatted with leading zeros:
from itertools import product
letter = "abcdefghijklmnopqrstuvwxyz"
numbers = (f"{n:03}" for n in range(1,1000))
plates = [*map("".join,product(letter,letter,letter,numbers))]
for plate in plates: print(plate)
aaa001
aaa002
aaa003
aaa004
aaa005
aaa006
aaa007
aaa008
...
If you only need to access a license place at a specific index, you don't have to generate the whole list. You can figure out which plate number will be at a given index by decomposing the index in chunks of 999,26,26,26 corresponding to the available option at each position/chunk of the number.
def plate(i):
letter = "abcdefghijklmnopqrstuvwxyz"
result = f"{i%999+1:03}"
i //= 999
for _ in range(3):
result = letter[i%26] + result
i //= 26
return result
output:
for i in range(10):print(plate(i))
aaa001
aaa002
aaa003
aaa004
aaa005
aaa006
aaa007
aaa008
aaa009
aaa010
plate(2021) # aac024

numerology .. how to shorten code..?

I have written this code for finding the numerological value of a name. Is there any way in which i can shorten the code, or nest one loop inside the other?
alphabets = {"A":1,"I":1,"J":1, "Q":1,"Y":1,"B":2,"K":2,"R":3,"C":3,"G":3,"L":3,"S":3,"D":4,"M":4,"T":4,"H":5,"E":5,"N":5,"X":5,"U":6,"V":6,"W":6,"O":7, "Z":7,"P":8,"F":8}
word =input("your numerology score is :") #since i am using python 3 to code this
def digit_sum(n):
#prepare a list of numbers in n convert to string and reconvert
numbers=[]
for digit in str(n):
numbers.append(int(digit))
# add up the total of numbers
total=0
for number in numbers:
total += number
return total
def numerology(word):
total = 0
for letter in word.upper():
total += alphabets[letter]
total = digit_sum(total)
return total
print (numerology(word))
To understand what is meant by numerological value, please see https://en.wikipedia.org/wiki/Numerology#Latin_alphabet_systems.
alphabets = {"A":1,"I":1,"J":1, "Q":1,"Y":1,"B":2,"K":2,"R":3,"C":3,"G":3,"L":3,"S":3,"D":4,"M":4,"T":4,"H":5,"E":5,"N":5,"X":5,"U":6,"V":6,"W":6,"O":7, "Z":7,"P":8,"F":8}
name = "this is a sample name"
digits = str(sum([alphabets[l] for l in name.upper() if l in alphabets.keys()]))
numerological_value = int(digits) % 9
if numerological_value == 0:
numerological_value = 9
print(numerological_value)
Comprehensions allow you to have a short hand for creating various data types.
In this case you want to build generators.
This is as you don't need to build every number before reducing the list, to a single number.
Wrapping one in sum can allow you to significantly shorten digit_sum. Which can become:
def digit_sum(n):
return sum(int(digit) for digit in str(n))
You can also change numerology to be a little shorter, if you combine the addition and assignment.
def numerology(word):
total = 0
for letter in word.upper():
total = digit_sum(total + alphabets[letter])
return total
If you want, you can use functools.reduce to make this span a total of six lines.
def numerology(word):
return functools.reduce(
lambda a, b: sum(int(digit) for digit in str(a + b)),
(alphabets[letter] for letter in word.upper()),
0
)
One-liner for laughs.
alphabets = {"A":1,"I":1,"J":1, "Q":1,"Y":1,"B":2,"K":2,"R":3,"C":3,"G":3,"L":3,"S":3,"D":4,"M":4,"T":4,"H":5,"E":5,"N":5,"X":5,"U":6,"V":6,"W":6,"O":7, "Z":7,"P":8,"F":8}
print("Your numerology score is "+ str((int(sum([alphabets[l] for l in input("Type your name:").upper() if l in alphabets.keys()])) % 9) or 9))
this one !!!
a= input()
b= 0
c= len(a)
d= {"a":1, "b":2, "c":3, "d":4, "e":5, "f":6, "g":7, "h":8, "i":9, "j":10, "k":11, "l":12, "m":13, "n":14, "o":15, "p":16, "q":17, "r":18, "s":19, "t":20, "u":21, "v":22, "w":23, "x":24, "y":25, "z":26, " ":0}
for i in range(c):
b= b+d[a[i]]
print(b)
gematria
i'm sure you can chain the reducer functions a bit better but...
const charMap = {A:1, J:1, S:1, B:2, K:2, T:2, C:3, L:3, U:3, D:4,
M:4, V:4, E:5, N:5, W:5, F:6, O:6, X:6, G:7, P:7, Y:7, H:8,
Q:8, Z:8, I:9, R:9};
let name = prompt ("Type your name in CAPS"); //for example: TOM
let wordScore = Array.from(name).reduce((nameScore, element) => {
let curValue = charMap[element]
return (nameScore + curValue)
},0)
let finalScore = Array.from(String(wordScore), Number).reduce((score, element) => {
return score > 10 ? score + element : score
})
alert(finalScore)

convert following iterative code to recursive Python

6174 is known as Kaprekar's constant[1][2][3] after the Indian mathematician D. R. Kaprekar. This number is notable for the following property:
Take any four-digit number, using at least two different digits. (Leading zeros are allowed.)
Arrange the digits in descending and then in ascending order to get two four-digit numbers, adding leading zeros if necessary.
Subtract the smaller number from the bigger number.
Go back to step 2.
Dattaraya Ramchandra Kaprekar
number="0011"
print(" helo world, lets do this: " , number)
i = 0
while number != "6174":
sortedS = sorted(number)
String[] sortedString = array[4] av strangen number
reversed = sorted(number, reverse=True)
sortedIntMin = int(sortedS[0]+sortedS[1]+sortedS[2]+sortedS[3])
reversedIntMax = int(reversed[0]+reversed[1]+reversed[2]+reversed[3])
i += 1
number = str(reversedIntMax - sortedIntMin)
reversedIntMax - sortedIntMin
print("det behovdes " , i , "iterationer for processen")
This is my unsuccessful attempt
def Kaprekar(number, i):
if number == 6174:
return
elif number != 6174:
sortedString = sorted(number)
reversedString = sorted(number, reverse=True)
sortedIntMin = int(sortedString[0]+sortedString[1]+sortedString[2]+sortedString[3])
reversedIntMax = int(reversedString[0]+reversedString[1]+reversedString[2]+reversedString[3])
num = reversedIntMax - sortedIntMin
print("processen kors", num )
return 1 + Kaprekar(str(num), i)
print(" helo world, lets do this: ")
print("det behovdes " , Kaprekar("1547", 0) , "iterationer for processen")
there are three things that are wrong: -
You don't need i. remove it from function definition.
The variable you are passing is a string and you are comparing it with an integer, convert it to a string while comparing.
You need to return 1 when number='6174', while you are returning None.
Also, it can be done a bit clearer if list is joined after sorted and it can be directly converted to integer, (thanks endzior for the edit)
try this : -
def Kaprekar(number):
if number == '6174':
return 1
elif number != '6174':
sortedString = ''.join(sorted(number))
reversedString = ''.join(sorted(number, reverse=True))
sortedIntMin = int(sortedString)
reversedIntMax = int(reversedString)
num = reversedIntMax - sortedIntMin
print("processen kors", num )
return 1 + Kaprekar(str(num))
print(" helo world, lets do this: ")
print("det behovdes " , Kaprekar("1547") , "iterationer for processen")
number is a string, so in the first 2 if statements :
if number == '6174':
return 1
else:
And as in another answer i variable is not needed here.

Add numbers in hexadecimal base without converting bases?

I need to write a function which gets two numbers in hexadecimal base, and calculates the sum of both of them, I'm not allowed to convert them to decimal base, the code is supposed to calculate it "manually" using loops.
for example this is how it should work:
1
1 f 5 (A)
+ 5 a (B)
-------------
= 2 4 f
Here is an input example:
>>> add("a5", "17")
'bc'
I've started building my code but I got stuck, I thought I would divide into three ifs, one that would sum up only numbers, other sums numbers and letters, and the third one sums letters, but I don't know how to continue from here:
def add_hex(A,B):
lstA = [int(l) for l in str(A)]
lstB = [int(l) for l in str(B)]
if len(A)>len(B):
A=B
B=A
A='0'*(len(B)-len(A))+A
remainder=False
result=''
for i in range(len(B)-1)
if (A[i]>0 and A[i]<10) and (B[i]>0 and B[i]<10):
A[i]+B[i]=result
if A[i]+B[i]>10:
result+='1'
Any help is greatly appreciated, I have no clue how to start on this!
You can have a sub-function that adds two single-digit hex numbers and returns their single-digit sum and a carry (either 0 or 1). This function will take three inputs: two numbers you want to add and a carry-in. You can then loop through the digits of the two numbers you want to add from least significant to most significant, and apply this function for every pair of digits while taking into account the carry at each stage.
So let's try your example:
A 5
1 7 +
We start at the least significant digits, 5 and 7, and perform the 1-digit addition. 516 + 716 = 1210. 1210 is less than 1610, so the output of our 1-digit add is 1210 = C16 with a carry of 0.
Now we add A and 1 (our carry-in is 0 so we can just add them normally). A16 + 116 = 1110. 1110 is less than 1610, so the output of our 1-digit add is 1110 = B16 with a carry of 0. (If we had a non-zero carry-in, we would just add 1 to this value.)
Hence, our overall result is:
A 5
1 7 +
-----
B C
I think we just remember the pattern of addition. Like following.
"0" + "0" = "0"
"0" + "1" = "1"
"0" + "2" = "2"
.
.
.
"f" + "d" = "1b"
"f" + "e" = "1c"
"f" + "f" = "1e"
We have dictionary of all of the pattern because we've learned it in school or somewhere. And we've also learned carry.
So I think this seems like manual addition algorithm.
Remembering the pattern include carry.
Calculating
Translate two digit to one digit(a+b->c).
Treat carry correctly.
And here is my code for that. But it may be a bit tricky.
import itertools
def add_hex(A,B):
A = "0"+A
B = "0"+B
#Remember all pattern include carry in variable d.
i2h = dict(zip(range(16), "0123456789abcdef"))
a = [(i,j) for i in "0123456789abcdef" for j in "0123456789abcdef"]
b = list(map(lambda t: int(t[0],16)+int(t[1],16), a))
c = ["0"+i2h[i] if i<16 else "1"+i2h[i-16] for i in b]#list of digit include carry
d = dict(zip(a,c))#d={(digit,digit):digit,,,}
#Calculate with variable d.
result = ""
cur = "0"
nex = "0"
for i in itertools.izip_longest(A[::-1], B[::-1], fillvalue = "0"):
cur = d[(nex, d[i][1])][1] #cur = carry + digit + digit
if d[i][0]=='1' or d[(nex, d[i][1])][0]=='1':#nex = carry = carry + digit + digit
nex = "1"
else:
nex = "0"
result += cur
return result[::-1]
#Test
A = "fedcba"
B = "012346"
print add_hex(A,B)
print hex(int(A,16)+int(B,16))#For validation
I hope it helps. :)

Categories

Resources