NameError in Credit - pset6 CS50x - python

I am new to Python. My only background in Python is CS50(Week 6). I am trying to implement Credit from pset6. In this, we have to implement Luhn's Algorithm.
But, I am getting the undermentioned error and I am not able to understand why:
Traceback (most recent call last):
File "credit.py", line 57, in <module>
main()
File "credit.py", line 9, in main
if IfAmex(arr_number):
File "credit.py", line 27, in IfAmex
if Luhn(card_n):
File "credit.py", line 50, in Luhn
sum2 = sum(int(c) for c in str(2 * card_n[i]) for i in range(1, len(card_n), 2))
NameError: name 'i' is not defined
Here is my code:
from sys import exit
from cs50 import get_int
def main():
number = get_int("Number: ")
# Converting the number into a list
arr_number = [int(x) for x in str(number)]
if IfAmex(arr_number):
print("AMEX")
exit(0)
elif IfMasCard(arr_number):
print("MASTERCARD")
exit(0)
elif IfVisa(arr_number):
print("VISA")
exit(0)
else:
print("INVALID")
exit(0)
def IfAmex(card_n):
if not len(card_n) == 15:
return False
if not (card_n[0] * 10 + card_n[1]) in [34, 37]:
return False
if Luhn(card_n):
return True
def IfMasCas(card_n):
if not len(card_n) == 16:
return False
if not (card_n[0] * 10 + card_n[1]) in range(51, 56):
return False
if Luhn(card_n):
return True
def IfVisa(card_n):
if not len(card_n) in [13, 16]:
return False
if not card_n[0] == 4:
return False
if Luhn(card_n):
return True
def Luhn(card_n):
# Reversing the digits
card_n = card_n[::-1]
sum1 = sum(card_n[::2])
sum2 = sum(int(c) for c in str(2 * card_n[i]) for i in range(1, len(card_n), 2)) # The Error Line
luhnsum = sum1 + sum2
return luhnsum % 10 == 0
if __name__ == '__main__':
main()
And the test case I used was(along with the correct output):
$ python credit.py
Number: 378282246310005
AMEX
Also, please tell me whether I am using exit() correctly or not.

You use i here as an index of card_n array. But you forgot to define it.
Define it and assign it to a value before using.
sum2 = sum(int(c) for c in str(2 * card_n[i])

Related

CS50 Introduction to Programming with Python: Problem with Check50 in PSet4

I'm taking CS50 Introduction to Programming with Python. I have problem with PSet4 (Little Professor). I don't have any problem while running, but when check50 running it keeps giving this error: "Little Professor accepts valid level timed out while waiting for program to exit." While I’m manually running the program, it accepts any level value lower than 4. But the check50 says otherwise. Here is my code:
import random
def main():
try:
level = input("Level: ")
first, second = get_level(level)
game_on(first, second, 0, 2, 0, level)
except WrongInputError:
main()
def get_level(x):
try:
x = int(x)
if 0 < x < 4:
first = generate_integer(x)
second = generate_integer(x)
return first, second
else:
raise WrongInputError
except ValueError:
raise WrongInputError
class WrongInputError(Exception):
"""You entered something wrong, try again """
def generate_integer(level):
if level == 1:
integer = random.randrange(10)
return integer
elif level == 2:
x = str(random.randrange(1, 10))
y = str(random.randrange(10))
integer = int(x + y)
return integer
elif level == 3:
x = str(random.randrange(1, 10))
y = str(random.randrange(10))
z = str(random.randrange(10))
integer = int(x + y + z)
return integer
def game_on(x , y, count, lives, score, level):
game_set = [x, y]
try:
if count < 10:
calculation = int(input(f"{x} + {y} = "))
count += 1
if calculation == sum(game_set):
score +=1
first, second = get_level(level)
game_on(first, second, count, 3, score, level)
elif calculation == sum(game_set):
print("EEE")
if lives > 0:
lives -= 1
count -= 1
game_on(x, y, count, lives, score, level)
elif lives == 0:
print(f"{x} + {y} = {sum(game_set)}")
first, second = get_level(level)
game_on(first, second, count, 2, score, level)
else:
print(f"Score: {score}")
except ValueError:
print("EEE")
if lives > 0:
lives -= 1
game_on(x, y, count, lives, score, level)
elif lives == 0:
print(f"{x} + {y} = {sum(game_set)}")
first, second = get_level(level)
game_on(first, second, count, 2, score, level)
if __name__ == "__main__":
main()
main()
import sys
import random
def main():
num = get_level()
errors = 1
score = 0
for i in range(10):
x = generate_integer(num)
for j in range(1):
y = generate_integer(num)
answer = x + y
equation = input(f"{x} + {y} = ")
if int(equation) == answer:
score += 1
while int(equation) != answer:
errors += 1
print("EEE")
equation = input(f"{x} + {y} = ")
if errors >= 3:
print(answer)
sys.exit("Score: " + str(score))
print("Score: " + str(score))
# prompt for level and reprompt if needed
def get_level():
levelChoice = input("Level: ")
if levelChoice.isalpha() or int(levelChoice) <= 0 or int(levelChoice) > 3:
input("Level: ")
else:
levelChoice = int(levelChoice)
for i in [1,2,3]:
if levelChoice == i:
return levelChoice
# generate int from level choice
def generate_integer(level):
try:
if level == 1:
return random.randint(0, 9)
elif level == 2:
return random.randint(10, 99)
elif level == 3:
return random.randint(100, 999)
except:
raise ValueError
if __name__ == "__main__":
main()

how can I find the average length of inputed lists/names from a user

def myNames():
b = []
while True:
a = input("Enter Name: ")
if a != "done":
b.append(a)
elif a == "done":
break
myNames()
def all_lengths(myNames):
all_lengths = []
num_of_strings = len(myNames)
for item in myNames:
string_size = len(item)
all_lengths.append(string_size)
total_size = sum(all_lengths)
ave_size = float(total_size) / float(num_of_strings)
print (ave_size)
all_lengths(myNames)
I am trying to find how I can find the average length of lists/names inputed by a user for ex: john, sam, Samantha. (all inputed from a user) and it should give me the average length (in numbers) for how much letters there are in the names
Traceback (most recent call last):
File "main.py", line 23, in <module>
all_lengths(myNames)
File "main.py", line 15, in all_lengths
num_of_strings = len(myNames)
TypeError: object of type 'function' has no len()
that is the error I keep getting
You are calling the function expecting the result to be a part of the function. This is not how python works. You should return the result:
def myNames():
b = []
while True:
a = input("Enter Name: ")
if a != "done":
b.append(a)
else:
return b
def all_lengths(myNames):
num_of_strings = len(myNames)
total_size = 0
for item in myNames:
total_size += len(item)
ave_size = float(total_size) / float(num_of_strings)
print(ave_size)
all_lengths(myNames())
You are passing the function not its result, you forgot the brackets: all_lengths(myNames())

Syntax error in python code to find Prime-factors. Id appreciate if someone could help me

I have been getting a syntax error with code which does prime-factorization
The is this Code
from sys import argv
from os import system, get_terminal_size
from math import sqrt
number = int(argv[1])
width = get_terminal_size().columns
prime_numbers = []
prime_factors = []
_ = system('clear')
print()
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return True
if is_prime(number):
print(f"It is a prime number \nIts only factors are 1 and itself \n1, {number}")
exit()
x = len(str(number))
for i in range(2, int(sqrt(number))):
if is_prime(i):
prime_numbers.append(i)
#print(f"found ")
#print(prime_numbers)
i = 0
while True:
if (number % prime_numbers[i] != 0):
i += 1
continue
prime_factors.append(prime_numbers[i])
print("%2d | %3d".center(width) % (prime_numbers[i], number))
print("_________".center(width))
number /= prime_numbers[i]
if number == 1:
break
print("1".center(width))
print("Answer ")
i = len(prime_factors)
j = 1
for k in prime_factors:
if j == i:
print(k)
break
print(f"{k}", end=" X ")
j += 1
This works for small numbers , less than 4 or 5 digits but gives an index error for bigger ones.
If I remove the sqrt function on line 24 it starts taking too long.
The errors look like this
Traceback (most recent call last):
File "prime-factor.py", line 33, in <module>
if (number % prime_numbers[i] != 0):
IndexError: list index out of range
real 0m0.049s
user 0m0.030s
sys 0m0.014s
(base) Souravs-MacBook-Pro-5:Fun-Math-Algorithms aahaans$ time python3 prime-factor.py 145647
I am unable to resolve this issue, Id appreciate it if you could help me.
No need to rebuild what's already available primePy
from primePy import primes
primes.factors(101463649)
output
[7, 23, 73, 89, 97]
There are two basic issues with the code. One with the for loop for prime numbers, you have to check until int(sqrt(number))+1. And, in the while loop after that, you have to break when the number is below sqrt of the original number, for which another variable should be used. The corrected code is:
from sys import argv
from os import system, get_terminal_size
from math import sqrt
number = int(argv[1])
width = get_terminal_size().columns
prime_numbers = []
prime_factors = []
_ = system('clear')
print()
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return True
if is_prime(number):
print(f"It is a prime number \nIts only factors are 1 and itself \n1, {number}")
exit()
x = len(str(number))
limit = int(sqrt(number))
for i in range(2, limit+1):
if is_prime(i):
prime_numbers.append(i)
i = 0
while True:
if i == len(prime_numbers)-1:
# prime_factors.append(int(number))
break
if (number % prime_numbers[i] != 0):
i += 1
continue
prime_factors.append(prime_numbers[i])
print("%2d | %3d".center(width) % (prime_numbers[i], number))
print("_________".center(width))
number /= prime_numbers[i]
prime_factors.append(int(number))
print("%2d | %3d".center(width) % (number, number))
print("_________".center(width))
print("1".center(width))
print("Answer ")
i = len(prime_factors)
j = 1
for k in prime_factors:
if j == i:
print(k)
break
print(f"{k}", end=" X ")
j += 1
If my explanation wasn't clear, look at the changes in the code.
I wrote a small number factorization engine that can factor numbers.
import math
def LLL(N):
p = 1<<N.bit_length()-1
if N == 2:
return 2
if N == 3:
return 3
s = 4
M = pow(p, 2) - 1
for x in range (1, 100000):
s = (((s * N ) - 2 )) % M
xx = [math.gcd(s, N)] + [math.gcd(s*p+x,N) for x in range(7)] + [math.gcd(s*p-x,N) for x in range(1,7)]
try:
prime = min(list(filter(lambda x: x not in set([1]),xx)))
except:
prime = 1
if prime == 1:
continue
else:
break
#print (s, x, prime, xx)
return prime
Factor:
In [219]: LLL(10142789312725007)
Out[219]: 100711423
from https://stackoverflow.com/questions/4078902/cracking-short-rsa-keys
I also made Alpertons ECM SIQs engine work in python if you want factorization at that (over 60 digits level): https://github.com/oppressionslayer/primalitytest

Python generator confusing behavior

This question arises when I read a generator tutorial https://realpython.com/introduction-to-python-generators/. is_palindrome(101) returns True, but the code didn't print 101. I debugged and saw yield 101 led the execution back to the main for loop, which immediately went back to the generator, which is very confusing. The generator yields 101, hence it should be an element of for j in pal_gen:, isn't it?
def is_palindrome(num):
# Skip single-digit inputs
if num // 10 == 0:
return False
temp = num
reversed_num = 0
while temp != 0:
reversed_num = (reversed_num * 10) + (temp % 10)
temp = temp // 10
if num == reversed_num:
return True
else:
return False
def infinite_palindromes():
num = 0
while True:
if is_palindrome(num):
i = (yield num)
if i is not None:
num = i
num += 1
if __name__=='__main__':
pal_gen = infinite_palindromes()
for j in pal_gen:
print(f'j={j}')
digits = len(str(j))
if digits == 5:
pal_gen.close()
pal_gen.send(10 ** (digits))
Currently the output is:
j=11
j=111
j=1111
j=10101
Traceback (most recent call last):
File "generator.py", line 33, in <module>
pal_gen.send(10 ** (digits))
StopIteration
You'll notice it is skipping one between each. 101 is missing, 1001 is missing. 10001 is missing. I'm pretty sure send leads the generator to run to the next yield statement. For example, use the following code:
if __name__=='__main__':
pal_gen = infinite_palindromes()
for j in pal_gen:
print('j={}'.format(j))
digits = len(str(j))
if digits == 5:
pal_gen.close()
print(pal_gen.send(10 ** (digits)))
This will print out the missing values between the "j's":
j=11
101
j=111
1001
j=1111
10001
j=10101
Consider redoing your for statement with a while:
if __name__=='__main__':
pal_gen = infinite_palindromes()
j=next(pal_gen)
digits=0
while digits<5:
print('j={}'.format(j))
digits = len(str(j))
j = pal_gen.send(10 ** (digits))
else:
pal_gen.close()

Why is is python throwing error at the second method in of this class?

Why is is python throwing error at the second method in of this class?
class Lutany:
formulaa = 0
formulab = 0
def __init__(self,num):
self.num = num
self.formulaa = self.formulaA()
self.formulab = self.formulaB
def formulaA(self):
q = 0
num = self.num
while num > 0 :
q += num + (num - 1)
num = num - 1
return q
self.formulab = formulaB()
def formulaB(self):
num = self.num
q = 0
while num > 0 :
q = q + (num * num)
num = num - 1
return (0.5 * q)
if(__name__ == '__main__'):
l = Lutany(675)
p = l.formulaa
q = l.formulab
print " FormunlA returned " , str(p) , " for 675 "
print " FormulaB returned " , str(q) , " for 675 "
When running I have the following error:
~$ python lutany.py
Traceback (most recent call last):
File "lutany.py", line 30, in <module>
l = Lutany(675)
File "lutany.py", line 7, in init
self.formulab = self.formulaB
AttributeError: Lutany instance has no attribute 'formulaB'
You've indented the block for the formulaB() method too much (although the edit to the question has destroyed evidence of this). Make sure that it is at the indent level directly beneath the class indent, not that of the previous method.
You're missing parentheses here: self.formulab = self.formulaB. Should be self.formulab = self.formulaB().
When you say, in formalaA self.formulab = formulaB() did you mean self.formulab = self.formulaB()?

Categories

Resources