I'm programming a single line calculator in python. It needs to be able to take in an expression of any length and with multiple operators. It then returns the answer while following the order of operations.
i.e. "2 / 4 - 2 * 3 + 4" and it returns -1.5
This is what I have so far
def findNextOpr(s): #DONE
#this function is used to find the next operator in the string s
if len(s)<=0 or not isinstance(s,str):
print("type mimatch error: findNextOpr")
return "type mimatch error: findNextOpr"
s = list(s) #converts s to a list
operator = ["+", "-", "/", "*"]
for i in s:
if i in operator:
return i
else:
return -1
def isNumber(s): #DONE
#this function is used to check if it's a number
#checks if string s meets the requirements
if len(s)==0 or not isinstance(s, str):
print("type mismatch error: isNumber")
return "type mismatch error: isNumber"
#strip string of all whitespace.
s = s.strip(" ")
s = s[0:] #removes minus signs but only from the front of string
try: #checks to make sure s2 is a number and doesn't have more than 1 period
s=float(s)
return True
except:
return False
def getNextNumber(expr, pos): #DONE
#checks to make sure expr and pos match the requirements. returns error if they don't
if len(expr)==0 or not isinstance(expr, str) or pos<0 or pos>=len(expr) or not isinstance(pos, int):
print("type mismatch error: getNextNumber")
return None, None, "type mismatch error: getNextNumber"
s = expr[pos:] #sets string1 equal to position that was passed
op=['-','+','*','/']
newOpr = findNextOpr(s) #newOpr equals left-most operator, calls findNext to achieve this
if newOpr in op:
if expr.find(newOpr,pos)>=pos:
oprPos=expr.find(newOpr,pos)
else:
newOpr=None
if newOpr==None:
oprPos = None
if isNumber(expr[pos:oprPos]): #checks to make sure if string is actually a #
newNumber = float(expr[pos:oprPos])
else:
newNumber = None #if it is a #, assigns value to newNumber
return newNumber, newOpr, oprPos
def exeOpr(num1, opr, num2):
#This is a simple utility function skipping type check
if opr=="+":
return num1+num2
elif opr=="-":
return num1-num2
elif opr=="*":
return num1*num2
elif opr=="/":
return num1/num2
else:
return None
def calc(expr):
#the below line checks if expr is a string
if not isinstance(expr, str) or len(expr) <= 0:
print("argument error: line A in eval_expr")
return "argument error: line A in eval_expr"
#below line creates three variables
#sets them equal to whatever is returned by the getNextNumber function
#the getNextNumber function is called. It passes the expr and integer 0
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
#if newNumber is none, return error
#if newOpr is none, return newNumber
#if newOpr is add/sub set mode=add, create addResult=newNumber and mulResult = None
#if newOpr is mult/div set mode=mul, crate addResult=0 and mulResult=newNumber
if newNumber is None:
print("input formula error: line B in eval_expr")
return "input formula error: line B in eval_expr"
elif newOpr is None:
return newNumber
elif newOpr=="+" or newOpr=="-":
mode="add"
addResult=newNumber #saves # at first index to addResult if 1st operator is + or -
mulResult=None
elif newOpr=="*" or newOpr=="/":
mode="mul"
addResult=0
lastOpr = "+"
mulResult=newNumber #saves # at first index to mulResult if 1st operator is + or -
#pos and opr are created
pos=oprPos+1 #current positon
opr=newOpr #current operator
while True:
newNumber, newOpr, oprPos = getNextNumber(expr, pos)
#--- code while loop ---#
while True:
newNumber, newOpr, oprPos=getNextNumber(expr, pos)
#if expr[pos:] == " 3- 2*1":
# pdb.set_trace()
if newNumber== None and pos>=len(expr):
return "Expression error"
elif newOpr== None and mode=='add':
return exeOpr(addResult, opr, newNumber)
elif newOpr== None and mode=='mul':
return exeOpr(mulResult, opr, newNumber)
elif (newOpr== "+" or newOpr=='-') and mode=='add' :
addResult= exeOpr(addResult,opr,newNumber)
pos= oprPos+1
opr=newOpr
elif (newOpr=="*" or newOpr=='/') and mode=='add':
addResult= newNumber
lastOpr= opr
mulResult= exeOpr(addResult,newOpr, newNumber)
mode='mul'
pos= oprPos+1
opr=newOpr
elif (newOpr=="*" or newOpr=="/") and mode=="mul":
mulResult= exeOpr(mulResult, opr, newNumber)
pos= oprPos+1
opr=newOpr
elif (newOpr=="-" or newOpr=='+') and mode=="mul":
mulResult=exeOpr(mulResult,opr, newNumber)
addResult= exeOpr(mulResult, lastOpr, newNumber)
mode="add"
pos= oprPos+1
opr=newOpr
#--- end of function ---#
expr = "2 / 4 - 2 * 3 + 4"
print(calc(expr))
Everything works except the output. When I run the program I get an answer of 13.0
I know the error is in the calc function. Can anyone figure out what I'm doing wrong.
Thanks.
Your calc is not working as you expected
HINT:
def exeOpr(num1, opr, num2):
#This is a simple utility function skipping type check
if opr=="+":
print "{} + {}".format(num1, num2)
return num1+num2
elif opr=="-":
print "{} - {}".format(num1, num2)
return num1-num2
elif opr=="*":
print "{} * {}".format(num1, num2)
return num1*num2
elif opr=="/":
print "{} / {}".format(num1, num2)
return num1/num2
else:
return None
OUTPUT
2.0 / 4.0
0.5 + 4.0
2.0 * 2.0
4.0 * 3.0
12.0 - 3.0
9.0 + 4.0
13.0
Related
I am trying to make a calculator that doesn't use eval() and take the whole equation as a string. Also I can't use any libraries, modules, etc. I've managed to make something but I can't figure out how to make it to first do the multiplication and division and then the rest.
It doesn't give me an error but it does this:
4 + 4 = 8
4 + 4 * 4 = 20
4 + 4 * 4 + 4 = 4
Edit: So I found where the problem was, but it still doesn't function right. The problem was that the code doesn't even reach the part where it finds the "*". I'll mark with an arrow where it doesn't reach it.
Here is the code and thanks in advance:
print("Calculator")
# All the numbers
def numbers(num):
return(
num == "0"
or num == "1"
or num == "2"
or num == "3"
or num == "4"
or num == "5"
or num == "6"
or num == "7"
or num == "8"
or num == "9"
)
# All the operators
def operator(oprt):
return(
oprt == "+"
or oprt == "-"
or oprt == "*"
or oprt == "/"
)
# Removes all the spaces
def remove_spaces(string):
string = string.replace(" ", "")
return string
# Does the math between two numbers
def operation(string, num1, num2):
if string == "+":
return num1 + num2
if string == "-":
return num1 - num2
if string == "*":
return num1 * num2
if string == "/":
return num1 / num2
# Tests how long the number is
def test_number(numstr):
n = 0
num = ""
try:
while numbers(numstr[n]):
num += numstr[n]
n += 1
except:
pass
return(int(num), n)
# Solves the equation
def eval_equation(eq):
negative = False
# Removes the spaces
eq = remove_spaces(eq)
while True:
try:
# Checks if the first number is negative
if eq[0] == "-":
negative = True
eq = eq[1:]
# Solves the multiplication first
i = 0
eqTemp = ""
if "*" in eq:
try:
while i < len(eq):
if eq[i] == "+" or eq[i] == "-" or eq[i] == "/":
eqTemp = eqTemp + eq[:i + 1]
print(f"eqTemp = {eqTemp}")
eq = eq[i + 1:]
print(f"eq = {eq}")
elif eq[i] == "*": # <-------this is the problem----
break
print(f"eqTemp = {eqTemp}")
print(f"eq = {eq}")
i += 1
except:
i = 0
# Checks the lenght of the number
number1 = test_number(eq)[0]
# Returns the "-" in the negative number
if negative == True:
number1 = -number1
negative = False
# Removes the first number from the string to continue with the next
endNumber1 = test_number(eq)[1]
eq = eq[endNumber1:]
# Checks for any more numbers
if eq == "":
return number1
# This is the operator sign
op = eq[0]
eq = eq[1:]
# Repeats the same process with the other number
number2 = test_number(eq)[0]
endNumber2 = test_number(eq)[1]
result = operation(op, number1, number2)
# Takes the result and passes it as to the first number along with the rest of the equation
number1 = result
eq = str(number1) + eq[endNumber2:]
eq = eqTemp + eq
except Exception as error:
print(error)
break
return number1
# Main function
if __name__ == "__main__":
while True:
equation = input(": ")
print(eval_equation(equation))
Edit: Sorry, gotta get back to work, wasn't able to figure out your exact problem. I would suggest starting over on the eval_equation function as it's quite messy, and will be prone to bugs if you continue adding to it.
Unrelated to the actual question, here's an example of how you might improve a couple of functions a bit. Note the use of in, the docstrings, as well as a more clear function name.
def is_num(num):
"""Determine if the character is a number."""
return num in '0123456789'
def is_oprt(oprt):
"""Determine if the character is an operator."""
return oprt in '+-*/'
Your test_number function also can be optimised a little by iterating over the string rather than using while with try/except. It's a bit more personal preference but this is how I'd do it:
def get_num(numstr):
"""Gets the number at the start of a string."""
num = []
for i, c in enumerate(numstr):
if not is_num(c):
break
num.append(c)
try:
return int(''.join(num)), i + 1
except ValueError:
return 0, 0
One other syntax suggestion:
number2 = test_number(eq)[0]
endNumber2 = test_number(eq)[1]
Is the same as:
number2, endNumber2 = test_number(eq)
So I fixed it. I'm not sure how... but I fixed it. I just need to figure out how to add variables to the equation now :) . Here is the code and thanks to everybody who gave ideas:
print("Calculator")
# All the numbers
def numbers(num):
return num in {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
# All the operators
def operator(oprt):
return oprt in {"+", "-", "*", "/"}
# Removes all the spaces
def remove_spaces(string):
string = string.replace(" ", "")
return string
# Does the math between two numbers
def operation(string, num1, num2):
if string == "+":
return num1 + num2
if string == "-":
return num1 - num2
if string == "*":
return num1 * num2
if string == "/":
return int(num1 / num2)
# Tests how long the number is
def test_number(numstr):
n = 0
num = ""
try:
while numbers(numstr[n]):
num += numstr[n]
n += 1
except:
pass
return(int(num), n)
# Solves the equation
def eval_equation(eq):
negative = False
# Removes the spaces
eq = remove_spaces(eq)
while True:
try:
# Checks if the first number is negative
if eq[0] == "-":
negative = True
eq = eq[1:]
# Solves the multiplication first
i = 0
eqTemp = ""
if "*" in eq:
try:
while i < len(eq):
if eq[i] in {"+", "-", "/"}:
eqTemp = eqTemp + eq[:i + 1]
#print(f"eqTemp = {eqTemp}")
eq = eq[i + 1:]
#print(f"eq = {eq}")
pass
if numbers(eq[i]) == True:
pass
if eq[i] == "*":
break
i += 1
except IndexError:
i = 0
# Solves the division first
i = 0
eqTempDiv = ""
if "/" in eq:
try:
while i < len(eq):
if eq[i] in {"+", "-", "*"}:
eqTempDiv = eqTempDiv + eq[:i + 1]
#print(f"eqTemp = {eqTemp}")
eq = eq[i + 1:]
#print(f"eq = {eq}")
pass
if numbers(eq[i]) == True:
pass
if eq[i] == "/":
break
i += 1
except IndexError:
i = 0
# Checks the lenght of the number
number1 = test_number(eq)[0]
# Returns the "-" in the negative number
if negative == True:
number1 = -number1
negative = False
# Removes the first number from the string to continue with the next
endNumber1 = test_number(eq)[1]
eq = eq[endNumber1:]
# Checks for any more numbers
if eqTempDiv == "":
if eqTemp == "":
if eq == "":
return number1
# This is the operator sign
op = eq[0]
eq = eq[1:]
# Repeats the same process with the other number
number2 = test_number(eq)[0]
endNumber2 = test_number(eq)[1]
result = operation(op, number1, number2)
# Takes the result and passes it as to the first number along with the rest of the equation
number1 = result
eq = str(number1) + eq[endNumber2:]
eq = eqTemp + eqTempDiv + eq
#print(f"eqTemp final = {eqTemp}")
#print(f"eq final = {eq}")
except Exception as error:
print(error)
break
return number1
# Main function
if __name__ == "__main__":
while True:
equation = input(": ")
print(eval_equation(equation))
I have created the following pop function:
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
And it worked correctly until I used it in order to reverse order of a stack of numbers and operators:
"3 6 2 + * 14 3 4 + + /"
into
"/ + + 4 3 14 * + 2 6 3".
In first iteration of while loop shown below it pushed "/" operator to the auxiliary stack and deleted it from the top of entry, which is OK - but in the second iteration it deleted "+" sign from the middle of the entry instead of the plus sign with the highest index.
def evaluation(eq):
entryunsplit = errpostfix(eq)
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
Could someone please explain me why didn't it delete the last element and how can I avoid that error?
I am putting the whole code below in case some other element turns out to be significant.
stack1 = []
max_size = 30
def push(arr,a):
if len(arr) < max_size:
arr.append(a)
def isempty(arr):
if len(arr) == 0:
return True
else:
return False
def top(arr):
if not isempty(arr):
return arr[len(arr)-1]
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
def errpostfix(eq):
entry = eq.split()
opstack = []
exit = []
priorities = { "+": 1, "-": 1, "*": 0, "/": 0 }
for token in entry:
if token == "(":
push(opstack,token)
elif token == "*" or token == "/" or token == "+" or token == "-":
if top(opstack) == "*" or top(opstack) == "/" or top(opstack) == "+" or top(opstack) == "-":
while not isempty(opstack) and priorities[top(opstack)] >= priorities[token]:
push(exit,pop(opstack))
isempty(opstack)
push(opstack,token)
elif token == ")":
while top(opstack) != "(":
push(exit,pop(opstack))
pop(opstack)
else:
push(exit,token)
while not isempty(opstack):
push(exit, pop(opstack))
output = " ".join(exit)
return output
def isop(ch):
if ch == "+" or ch == "-" or ch == "*" or ch == "/":
return True
else:
return False
def evaluation(eq):
entryunsplit = "3 6 2 + * 14 3 4 + + /"
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
The remove() operation on a list will delete the first occurrence of an item in that list, is not "random" (check the docs). If there are several repeated elements, the first one encountered will be the one that gets deleted. To delete the last element, simply use the built-in pop() method:
def pop(arr):
if not isempty(arr):
topelement = arr[-1]
arr.pop()
return topelement
I'm a beginner Python learner and I'm currently working on Luhn Algorithm to check credit card validation. I wrote most of the code, but I'm stuck with 2 errors I get 1st one is num is referenced before assignment. 2nd one I'm getting is object of type '_io.TextIOWrapper' has no len(). Further help/ guidance will be greatly appreciated.
These are the steps for Luhn Algorithm (Mod10 Check)
Double every second digit from right to left. If this “doubling” results in a two-digit number, add the two-digit
number to get a single digit.
Now add all single digit numbers from step 1.
Add all digits in the odd places from right to left in the credit card number.
Sum the results from steps 2 & 3.
If the result from step 4 is divisible by 10, the card number is valid; otherwise, it is invalid.
Here's what my output is supposed to be
Card Number Valid / Invalid
--------------------------------------
3710293 Invalid
5190990281925290 Invalid
3716820019271998 Valid
37168200192719989 Invalid
8102966371298364 Invalid
6823119834248189 Valid
And here is the code.
def checkSecondDigits(num):
length = len(num)
sum = 0
for i in range(length-2,-1,-2):
number = eval(num[i])
number = number * 2
if number > 9:
strNumber = str(number)
number = eval(strNumber[0]) + eval(strNumber[1])
sum += number
return sum
def odd_digits(num):
length = len(num)
sumOdd = 0
for i in range(length-1,-1,-2):
num += eval(num[i])
return sumOdd
def c_length(num):
length = len(num)
if num >= 13 and num <= 16:
if num [0] == "4" or num [0] == "5" or num [0] == "6" or (num [0] == "3" and num [1] == "7"):
return True
else:
return False
def main():
filename = input("What is the name of your input file? ")
infile= open(filename,"r")
cc = (infile.readline().strip())
print(format("Card Number", "20s"), ("Valid / Invalid"))
print("------------------------------------")
while cc!= "EXIT":
even = checkSecondDigits(num)
odd = odd_digits(num)
c_len = c_length(num)
tot = even + odd
if c_len == True and tot % 10 == 0:
print(format(cc, "20s"), format("Valid", "20s"))
else:
print(format(cc, "20s"), format("Invalid", "20s"))
num = (infile.readline().strip())
main()
You just forgot to initialize num
def main():
filename = input("What is the name of your input file? ")
infile= open(filename,"r")
# initialize num here
num = cc = (infile.readline().strip())
print(format("Card Number", "20s"), ("Valid / Invalid"))
print("------------------------------------")
while cc!= "EXIT":
even = checkSecondDigits(num)
odd = odd_digits(num)
c_len = c_length(num)
tot = even + odd
if c_len == True and tot % 10 == 0:
print(format(cc, "20s"), format("Valid", "20s"))
else:
print(format(cc, "20s"), format("Invalid", "20s"))
num = cc = (infile.readline().strip())
First, maybe you should remove the extra characters:
def format_card(card_num):
"""
Formats card numbers to remove any spaces, unnecessary characters, etc
Input: Card number, integer or string
Output: Correctly formatted card number, string
"""
import re
card_num = str(card_num)
# Regex to remove any nondigit characters
return re.sub(r"\D", "", card_num)
After check if credit card is valid using the Luhn algorithm:
def validate_card(formated_card_num):
"""
Input: Card number, integer or string
Output: Valid?, boolean
"""
double = 0
total = 0
digits = str(card_num)
for i in range(len(digits) - 1, -1, -1):
for c in str((double + 1) * int(digits[i])):
total += int(c)
double = (double + 1) % 2
return (total % 10) == 0
This is a very simpler version of code it is based on lunh's algorithm
def validator(n):
validatelist=[]
for i in n:
validatelist.append(int(i))
for i in range(0,len(n),2):
validatelist[i] = validatelist[i]*2
if validatelist[i] >= 10:
validatelist[i] = validatelist[i]//10 + validatelist[i]%10
if sum(validatelist)%10 == 0:
print('This a valid credit card')
else:
print('This is not valid credit card')
def cardnumber():
result=''
while True:
try:
result = input('Please enter the 16 digit credit card number : ')
if not (len(result) == 16) or not type(int(result) == int) :
raise Exception
except Exception:
print('That is not a proper credit card number. \nMake sure you are entering digits not characters and all the 16 digits.')
continue
else:
break
return result
def goagain():
return input('Do you want to check again? (Yes/No) : ').lower()[0] == 'y'
def main():
while True:
result = cardnumber()
validator(result)
if not goagain():
break
if __name__ == '__main__':
main()
Old thread but the answer concerns me... and the real issue wasn't identified.
Actually, the error is that you have used the identifier (num) for the parameter when defining checkSecondDigits as the identifier/name of the argument when calling the function in the mainline. The function should be called in main() by
even = checkSecondDigits(cc) so the value in cc (which is the argument) is passed into num (as the parameter) for use within the function.
The same rookie error is made with odd_digits and cc_length.
This question (and the initially suggested answer) demonstrates a fundamental mis-understanding of passing arguments to parameters...
The suggested 'declaring' of num just hides this error/misunderstanding and also obfuscates the local and global scopes of num (which should only be local) and cc (which is global) so whilst the suggestion works in this case, it works for the wrong reason and is poor style and bad programming.
Further,
num should not appear anywhere in main() as it should be local to (only appear inside of) the functions called...
The last line in this code should be the same as the first, but the last line incorrectly assigns the data to num instead of cc
cc = (infile.readline().strip())
print(format("Card Number", "20s"), ("Valid / Invalid"))
print("------------------------------------")
while cc!= "EXIT":
even = checkSecondDigits(num)
odd = odd_digits(num)
c_len = c_length(num)
tot = even + odd
if c_len == True and tot % 10 == 0:
print(format(cc, "20s"), format("Valid", "20s"))
else:
print(format(cc, "20s"), format("Invalid", "20s"))
num = (infile.readline().strip())
you can use my code for card validation it is 100% dynamic because of the card structure is stored in CSV file, so it is easy to update here is the code on GitHub profile, python file link, code explanation file link and CSV for datafile link
python code:
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 10 20:55:30 2019
#author: Preyash2047#gmail.com
"""
import csv
import numpy as np
#csv file imported and storf in reader
reader = csv.DictReader(open("card_data.csv"))
#input card number
card_number = input("Enter the card No: ")
#global variable declaration
min_digits=0
max_digits=0
card_number_list = list(card_number)
card_number_list_reverse=card_number_list[::-1]
card_number_length=len(card_number_list)
first_digit = int(card_number_list[0])
#global variable for final output
card_provider_list_number = 0
result_found = False
card_number_digits = 0
mit_name=""
#list
start=[]
end=[]
name=[]
c_d=[]
number_length=[]
min_max_digits_list=[]
#append the list from csv
for raw in reader:
start.append(raw['start'])
end.append(raw['end'])
name.append(raw['name'])
c_d.append(raw['c_d'])
number_length.append(raw['number_length'])
#initialize the value of min_digits & max_digits
def min_max_digits():
global min_digits
global max_digits
for i in range(len(start)):
available_length=number_length[i].split(',')
for j in range(len(available_length)):
min_max_digits_list.append(available_length[j])
min_max_digits_array = np.array(min_max_digits_list)
np.unique(min_max_digits_array)
min_digits=int(min(min_max_digits_array))
max_digits=int(max(min_max_digits_array))
#list to int
def list_to_int(noofdigits):
str1 = ""
return int(str1.join(noofdigits))
#card validation
def iin_identifier():
first_six_digit = list_to_int(card_number_list[0:6])
for i in range(len(start)):
if(first_six_digit >= int(start[i]) and first_six_digit <= int(end[i])):
available_length=number_length[i].split(',')
for j in range(len(available_length)):
if(card_number_length == int(available_length[j])):
global card_provider_list_number
card_provider_list_number = i
global card_number_digits
card_number_digits = available_length[j]
global result_found
result_found = True
#Major Industry Identifier (MII) identification
def mit_identifier():
global first_digit
global mit_name
switcher = {
1: "Airlines",
2: "Airlines",
3: "Travel and Entertainment",
4: "Banking and Financial Services",
5: "Banking and Financial Services",
6: "Merchandising and Banking",
7: "Petroleum",
8: "Health care, Telecommunications",
9: "National Assignment"
}
mit_name=switcher.get(first_digit, "MIT Identifier Not Found")
#Luhn Algorithm or modulo-10 Algorithm
def luhn_algorithm():
for i in range(card_number_length):
if(i%2!=0 and i!=0):
card_number_list_reverse[i]=int(card_number_list_reverse[i])*2
#print(str(i)+" "+ str(card_number_list_reverse[i]))
if(len(str(card_number_list_reverse[i]))==2):
even_number_2=list(str(card_number_list_reverse[i]))
card_number_list_reverse[i] = int(even_number_2[0])+int(even_number_2[1])
#print("\tsubsum "+str(i)+" "+str(card_number_list_reverse[i]))
else:
card_number_list_reverse[i]=int(card_number_list_reverse[i])
division_int = int(sum(card_number_list_reverse)/10)
division_float=sum(card_number_list_reverse)/10
if(division_int-division_float==0):
return True
#initial level number length validation
def card_number_validation():
min_max_digits()
if(card_number_length>= min_digits and card_number_length <= max_digits and first_digit != 0):
iin_identifier()
mit_identifier()
if(result_found and luhn_algorithm()):
print("\nEntered Details are Correct\n")
print("\nHere are the some details we know about you card")
print("\nNo: "+card_number)
print("\nIssuing Network: "+name[card_provider_list_number])
print("\nType: "+c_d[card_provider_list_number]+" Card")
print("\nCategory of the entity which issued the Card: "+mit_name)
else:
print("\nCard Number is Invalid\nPlease renter the number!\n")
else:
print("\nCard Number is Invalid\n")
#method called to run program
card_number_validation()
n = input("Enter 16-digit Credit Card Number:")
lst = []
for i in range(16):
lst.append(n[i])
# print(lst)
# list1 = n.split()
# print(list1)
def validate_credit_card():
global lst
if len(lst) == 16:
for i in range(0, len(lst)):
lst[i] = int(lst[i])
# print(lst)
last = lst[15]
first = lst[:15]
# print(first)
# print(last)
first = first[::-1]
# print(first)
for i in range(len(first)):
if i % 2 == 0:
first[i] = first[i] * 2
if first[i] > 9:
first[i] -= 9
sum_all = sum(first)
# print(first)
# print(sum_all)
t1 = sum_all % 10
t2 = t1 + last
if t2 % 10 is 0:
print("Valid Credit Card")
else:
print("Invalid Credit Card!")
else:
print("Credit Card number limit Exceeded!!!!")
exit()
if __name__ == "__main__":
validate_credit_card()
So my task is to see and check a positive integer if its a palindrome. I've done everything correctly but need help on the final piece. And that the task of generating a new a palindrome from the one given given by the user. Am i on the right track with the while loop or should i use something else? So the result is if you put 192 it would give back Generating a palindrome....
483
867
1635
6996
"""Checks if the given, positive number, is in fact a palindrome"""
def palindrome(N):
x = list(str(N))
if (x[:] == x[::-1]):
return True
else: return False
"""Reverses the given positive integer"""
def reverse_int(N):
r = str(N)
x = r[::-1]
return int(x)
def palindrome_generator():
recieve = int(input("Enter a positive integer. "))
if (palindrome(recieve) == True):
print(recieve, " is a palindrome!")
else:
print("Generating a palindrome...")
while palindrome(recieve) == False:
reverse_int(recieve) + recieve
If I understand your task correctly, the following should do the trick:
def reverse(num):
return num[::-1]
def is_pal(num):
return num == reverse(num)
inp = input("Enter a positive number:")
if is_pal(inp):
print("{} is a palindrome".format(inp))
else:
print("Generating...")
while not is_pal(inp):
inp = str(int(inp) + int(reverse(inp)))
print(inp)
The variable inp is always a string and only converted to int for the arithmetic.
I've been using this solution for many years now to check for palindromes of numbers and text strings.
def is_palindrome(s):
s = ''.join(e for e in str(s).replace(' ','').lower() if e.isalnum())
_len = len(s)
if _len % 2 == 0:
if s[:int(_len/2)] == s[int(_len/2):][::-1]:
return True
else:
if s[int(_len/2+1):][::-1] == s[:int(_len/2)]:
return True
return False
This one is using Complement bitwise and Logical AND and OR operators
_input = 'Abba' # _input = 1221
def isPalindrome(_):
in_str = str(_).casefold() # Convert number to string + case insensitive
for _ in range(int(len(in_str) / 2)): # Loop from 0 till halfway
if in_str[_] != in_str[~_]:
return False
return True
print(_input, isPalindrome(_input) and ' is palindrome' or ' is not palindrome')
Abba is palindrome
So first, the assignment given was to make the function "compute" solves it and returns the value. If the given sting is not a valid equation, returns "None"
def compute(side):
val=int(side[0])
lastop=0
for i in range(1,len(side)):
if side[i].isdigit():
if lastop=='+':
val+=int(side[i])
elif lastop=='-':
val-=int(side[i])
elif lastop=='x':
val*=int(side[i])
elif lastop=='/':
val/=int(side[i])
else:
lastop=side[i]
return val
So at this point the value would be returned. But if the function is run for ("22-11x4"), it gives 0 not 44. I've turned them into integers and why would they still give me the wrong value?
def evaluate():
val=int(side[0])
lastop=0
for i in range(1,len(side)):
if side[i].true():
print('Congrats')
elif side[i].false():
print('Try again')
And when it gets to this evaluate function, it gives the error of "invalid literal for int() with base 10: '+'" and I am not too sure what this means and how to solve.
def solve():
pass
This function "solve" I was going to get to later after I have fixed the problems in the functions before.
def main():
print("22-11x4 =", compute("22-11x4"),"(expect 44)")
print("+11x4 =", compute("+11x4"),"(expect None)")
print("22-11x4 ?= 7x5+9", evaluate("22-11x4=7x5+9"),"(expect True)")
print("solving 288/24x6=18x13x8 :", solve("288/24x6=18x13x8"))
main()
The compute function you wrote does operation by digit, also you forgot to do one, last operation after for was finished:
2 - 1 - 1 x 4 = 0
this why you got this return from the function
Here is the correct function
def compute(side):
val = 0
buf = 0
lastop = '+'
for i in range(0, len(side)):
if side[i].isdigit():
buf = buf * 10 + int(side[i])
else:
val = op(val, buf, lastop)
lastop = side[i]
buf = 0
val = op(val, buf, lastop)
return val
def op(val, buf, lastop):
if lastop == '+':
val += buf
elif lastop == '-':
val -= buf
elif lastop == 'x':
val *= buf
elif lastop == '/':
val /= buf
return val
Also in your testing string:
print("+11x4 =", compute("+11x4"),"(expect None)")
why do you expect None? it should be 44?
PS. this function could be improved yet, but I had no time to do it. anyway it works.