Python - explain function parameters - python

So I understand this simple for loop:
sum = 0
for number in {1,2,3,4}:
sum = sum + number
print sum
>>>
1
3
6
10
>>>
Then here is a neat little code that combines a for loop and a function I found on the interwebs:
def sum_list(l):
sum = 0
for number in l:
sum = sum + number
return sum
print sum_list([1, 7, 4])
>>>
12
What I don't understand is how python interprets this code (rather how Python knows to add the 3 arguments 1,7,4 together).
I would really help if you can break it down for me!
To tack on another question for you guys to review:
sum = 0
for number in {1,2,3,4}:
sum = sum + number
return sum
Spits out an error. print sum will list the results as 1,3,6,10
Error says: Syntaxerror: 'return' outside of function
[EDIT] #sshashank124
For example: This code spits out 3 answers. It prints out:
sum = 0
for number in {1,7,4}:
sum = sum + number
print sum
>>>
1
8
12
>>>
But this:
def sum_list(l):
sum= 0
for number in l:
sum = sum + number
print sum
print sum_list([1, 7, 4])
>>>
12
none
Spits out only 1 answer, 12. My question is why that occurs.

for number in l:
This iterates over the l, and number will have each and every element of l on every iteration. You can check that like this
for number in l:
print number
# 1
# 7
# 4
You are adding those numbers to the sum variable. You can check that like this
sum = 0
for number in l:
sum = sum + number
print sum
# 1
# 8
# 12
I believe you are doing this for educational purpose. If you actually wanted to find the sum of an iterable, then you can use the builtin sum function, like this
sum([1, 7, 4])

It knows to add them together, because you tell it to do that.
Let me rewrite the code a bit to show what's happening. Rewrite one, adding 1,7,4 and then 2,8,5, but adding more numbers requires more lines:
sum = 0
sum = sum + 1
sum = sum + 7
sum = sum + 4
print sum
sum = 0
sum = sum + 2
sum = sum + 8
sum = sum + 5
print sum
Rewrite two - using a loop. Two lines shorter, but it can now handle lists of more items - adding four, five, even ten numbers, without adding more lines of code, just by making the lists longer:
sum = 0
for number in [1,7,4]:
sum = sum + number
print sum
sum = 0
for number in [2,8,5]:
sum = sum + number
print sum
Rewrite three - moving the lists out of the loop. The code got longer again, but something interesting happened - see how the loop code is now identical both times:
myList = [1,7,4]
sum = 0
for number in myList:
sum = sum + number
print sum
myList = [2,8,5]
sum = 0
for number in myList:
sum = sum + number
print sum
Rewrite four - now it's identical, why does it have to be there twice? Can't we ... write it once, and use it twice? That way if we need to change it, we only have to change it in one place. Yes - make it a function and call the function:
def sum_list():
sum = 0
for number in myList:
sum = sum + number
print sum
myList = [1,7,4]
sum_list()
myList = [2,8,5]
sum_list()
Rewrite five - what's happening above works fine, because you called everything 'myList' it all works. But if you write bigger programs like that it gets messy fast - one myList could be several pages of code away from another, we'll tend to forget that something pages and pages away could be affecting things. So we humans can keep track of what's going on, we need to clearly and explicitly give the function something to work on, and not have it just reaching far away and pulling things out of the rest of the code.
def sum_list(working_list): # working_list is whatever the function gets
sum = 0 # by a different name
for number in working_list:
sum = sum + number
print sum
myList1 = [1,7,4]
sum_list(myList1)
myList2 = [2,8,5]
sum_list(myList2)
See in the above code, I've called them myList1 and myList2 - yet whatever you give to the function, the function sees it called 'working_list'. The names don't have to match.
But because sum_list has it's own name for whatever you give it, you don't have to have a name for what you give it. You can just give it a list directly without a name:
def sum_list(working_list):
sum = 0
for number in working_list:
sum = sum + number
print sum
sum_list([1,7,4])
sum_list([2,8,5])
The next move is, once you're feeding things into sum_list, sum_list is looking away and writing to the screen. We can't have that. For the sake of humans tracking what's happening, that's a bad idea - you want to give functions some work to do and have them give you back an answer. That way you know you can use them anytime you need, without worrying about them printing to the screen unexpectedly. That's where 'return' comes in:
def sum_list(working_list):
sum = 0
for number in working_list:
sum = sum + number
return sum
result = sum_list([1,7,4])
print result
result = sum_list([2,8,5])
print result
Now sum_list is a self contained adder, it does nothing else. You can trust it. It's not reading from names all over your code, it's only reading explicitly what you gave to it. It's not writing to the screen at surprise times, or anything. You give it a list, you get a result, it's isolated, limited, controlled, predictable, easy to work with, easy to reuse. And like the list names, if all you do is get the result and print it, you don't need to give that a name either:
def sum_list(working_list):
sum = 0
for number in working_list:
sum = sum + number
return sum
print sum_list([1,7,4])
print sum_list([2,8,5])
Edit: I hope that explains several of your questions.
What that code is doing
Why it prints one answer instead of three - because you are giving it one thing (a list).
Why it makes no sense to use return on its own - because you have to call a function and then return from the function, and you can bring something back with you or you can go somewhere and bring nothing back (function with no return). But you can't bring something back if you don't go anywhere first.

In Python you will realise that when you initialise a variable you don't need to assign a type to it, you can just initialise anything in there.
in this case l was interoperated as an object, or an array to be specific.
as for the loop.
for number in l:
is like a for each statement, it goes through each of the elements. and stores it in number, then iterates after the block is executed, moving on to the next l.
Hope that helped? (if i understand your question.

The for number in l: line takes each of the elements in [1,7,4] and adds them to the sum variable which represents the total sum of the elements in the list.
This is what it looks like:
Take first element of l: 1
Add to sum --> sum is now 1
Take second element of l: 7
Add to sum --> sum is now 8
Take third element of l: 4
Add to sum --> sum is now 12
Return sum --> sum is 12
Might I suggest that sum([1,7,4]), the builtin python method would also work.

Related

Creating a function that returns prime numbers under a given maximum?

Instructions are to write a function that returns all prime numbers below a certain max number. The function is_factor was already given, I wrote everything else.
When I run the code I don't get an error message or anything, it's just blank. I'm assuming there's something I'm missing but I don't know what that is.
def is_factor(d, n):
""" True if `d` is a divisor of `n` """
return n % d == 0
def return_primes(max):
result = []
i = 0
while i < max:
if is_factor == True:
return result
i += 1
You should test each i against all divisors smaller than math.sqrt(i). Use the inner loop for that. any collects the results. Don't return result right away, for you should fill it first.
def return_primes(max):
result = []
for i in range(2, max):
if not any(is_factor(j, i) for j in range(2, int(math.sqrt(i)) + 1)):
result.append(i)
return result
print(return_primes(10))
As a side note, use for and range rather than while to make less mistakes and make your code more clear.
The reason that your code is returning blank when you run it, is because you are comparing a function type to the value of True, rather than calling it.
print(is_factor)
<function is_factor at 0x7f8c80275dc0>
In other words, you are doing a comparison between the object itself rather than invoking the function.
Instead, if you wanted to call the function and check the return value from it, you would have to use parenthesis like so:
if(is_factor(a, b) == True):
or even better
if(is_factor(a, b)):
which will inherently check whether or not the function returns True without you needing to specify it.
Additionally, you are not returning anything in your code if the condition does not trigger. I recommend that you include a default return statement at the end of your code, not only within the condition itself.
Now, in terms of the solution to your overall problem and question;
"How can I write a program to calculate the prime numbers below a certain max value?"
To start, a prime number is defined by "any number greater than 1 that has only two factors, 1 and itself."
https://www.splashlearn.com/math-vocabulary/algebra/prime-number
This means that you should not include 1 in the loop, otherwise every single number is divisible by 1 and this can mess up the list you are trying to create.
My recommendation is to start counting from 2 instead, then you can add 1 as a prime number at the end of the function.
Before going over the general answer and algorithm, there are some issues in your code I'd like to address:
It is recommended to use a different name for your variable other than max, because max() is a function in python that is commonly used.
Dividing by 0 is invalid and can break the math within your program. It is a good idea to check the number you are dividing by to ensure it is not zero to make sure you do not run into math issues. Alternatively, if you start your count from 2 upwards, you won't have this issue.
Currently you are not appending anything into your results array, which means no results will be returned.
My recommendation is to add the prime number into the results array once it is found.
Right now, you return the results array as soon as you have calculated the first result. This is a problem because you are trying to capture all of the prime numbers below a specific number, and hence you need more than one result.
You can fix this by returning the results array at the end of the function, not in between, and making sure to append each of the prime numbers as you discover them.
You need to check every single number between 2 and the max number to see if it is prime. Your current code only checks the max number itself and not the numbers in between.
Now I will explain my recommended answer and the algorithm behind it;
def is_factor(d, n):
print("Checking if " + str(n) + " is divisible by " + str(d))
print(n % d == 0)
return n % d == 0
def return_primes(max_num):
result = []
for q in range(2, max_num+1):
count_number_of_trues = 0
for i in range(2, q):
if(i != q):
if(is_factor(i, q)):
print("I " + str(i) + " is a factor of Q " + str(q))
count_number_of_trues += 1
if(q not in result and count_number_of_trues == 0):
result.append(q)
result.append(1)
return sorted(result)
print(return_primes(10))
The central algorithm is that you want to start counting from 2 all the way up to your max number. This is represented by the first loop.
Then, for each of these numbers, you should check every single number from 2 up to that number to see if a divisor exists.
Then, you should count the number of times that the second number is a factor of the first number, and if you get 0 times at the end, then you know it must be a prime number.
Example:
Q=10
"Is I a factor of Q?"
I:
9 - False
8 - False
7 - False
6 - False
5 - True
4 - False
3 - False
2 - True
So for the number 10, we can see that there are 2 factors, 5 and 2 (technically 3 if you include 1, but that is saved for later).
Thus, because 10 has 2 factors [excluding 1] it cannot be prime.
Now let's use 7 as the next example.
Example:
Q=7
"Is I a factor of Q?"
I:
6 - False
5 - False
4 - False
3 - False
2 - False
Notice how every number before 7 all the way down to 2 is NOT a factor, hence 7 is prime.
So all you need to do is loop through every number from 2 to your max number, then within another loop, loop through every number from 2 up to that current number.
Then count the total number of factors, and if the count is equal to 0, then you know the number must be prime.
Some additional recommendations:
although while loops will do the same thing as for loops, for loops are often more convenient to use in python because they initialize the counts for you and can save you some lines of code. Also, for loops will take care of the incrementing process for you so there is no risk of forgetting.
I recommend sorting the list when you return it, it looks nicer that way.
Before adding the prime factor into your results list, check to see if it is already in the list so you don't run into a scenario where multiples of the same number is added (like [2,2,2] for example)
Please note that there are many different ways to implement this, and my example is but one of many possible answers.

How do i optimize this code to run for larger values? [duplicate]

This question already has answers here:
Elegant Python code for Integer Partitioning [closed]
(11 answers)
Closed 1 year ago.
I'm writing a python function that takes an integer value between 3 and 200 as input, calculates the number of sums using unique nonzero numbers that will equal the number and prints the output.
For example; with 3 as input 1 will be printed because only 1 + 2 will give 3, with 6 as input 3 will be printed because 1+2+3, 1+5 and 2+4 equal 6.
My code works well only for numbers less than 30 after which it starts getting slow. How do I optimize my code to run efficiently for all input between 3 and 200.
from itertools import combinations
def solution(n):
count = 0
max_terms = 0
num = 0
for i in range(1,n):
if num + i <= n:
max_terms += 1
num = num + i
for terms in range(2,max_terms + 1):
for sample in list(combinations(list(range(1,n)),terms)):
if sum(sample) == n:
count += 1
print(count)
Generating all combinations is indeed not very efficient as most will not add up to n.
Instead, you could use a recursive function, which can be called after taking away one partition (i.e. one term of the sum), and will solve the problem for the remaining amount, given an extra indication that future partitions should be greater than the one just taken.
To further improve the efficiency, you can use memoization (dynamic programming) to avoid solving the same sub problem multiple times.
Here is the code for that:
def solution(n, least=1, memo={}):
if n < least:
return 0
key = (n, least)
if key in memo: # Use memoization
return memo[key]
# Counting the case where n is not partitioned
# (But do not count it when it is the original number itself)
count = int(least > 1)
# Counting the cases where n is partitioned
for i in range(least, (n + 1) // 2):
count += solution(n - i, i + 1)
memo[key] = count
return count
Tested the code with these arguments. The comments list the sums that are counted:
print(solution(1)) # none
print(solution(2)) # none
print(solution(3)) # 1+2
print(solution(4)) # 1+3
print(solution(5)) # 1+4, 2+3
print(solution(6)) # 1+2+3, 1+5, 2+4
print(solution(7)) # 1+2+4, 1+6, 2+5, 3+4
print(solution(8)) # 1+2+5, 1+3+4, 1+7, 2+6, 3+5
print(solution(9)) # 1+2+6, 1+3+5, 2+3+4, 1+8, 2+7, 3+6, 4+5
print(solution(10)) # 1+2+3+4, 1+2+7, 1+3+6, 1+4+5, 2+3+5, 1+9, 2+8, 3+7, 4+6
your question isn't clear enough. So, I'm making some assumptionns...
So, what you want is to enter a number. say 4 and then, figure out the total combinations where two different digits add up to that number. If that is what you want, then the answer is quite simple.
for 4, lets take that as 'n'. 'n' has the combinations 1+3,2+2.
for n as 6, the combos are - 1+5,2+4,3+3.
You might have caught a pattern. (4 and 6 have half their combinations) also, for odd numbers, they have combinations that are half their previous even number. i.e. - 5 has (4/2)=2 combos. i.e. 1+4,2+3 so...
the formula to get the number for comnbinations are -
(n)/2 - this is if you want to include same number combos like 2+2 for 4 but, exclude combos with 0. i.e. 0+4 for 4
(n+1)/2 - this works if you want to exclude either the combos with 0 i.e. 0+4 for 4 or the ones with same numbers i.e. 2+2 for 4.
(n-1)/2 - here, same number combos are excluded. i.e. 2+2 wont be counted as a combo for n as 4. also, 0 combos i.e. 0+4 for 4 are excluded.
n is the main number. in these examples, it is '4'. This will work only if n is an integer and these values after calculations are stored as an integer.
3 number combos are totally different. I'm sure there's a formula for that too.

Python list first n entries in a custom base number system

I am sorry if the title is a misnomer and/or doesn't properly describe what this is all about, you are welcome to edit the title to make it clear once you understand what this is about.
The thing is very simple, but I find it hard to describe, this thing is sorta like a number system, except it is about lists of integers.
So we start with a list of integers with only zero, foreach iteration we add one to it, until a certain limit is reached, then we insert 1 at the start of the list, and set the second element to 0, then iterate over the second element until the limit is reached again, then we add 1 to the first element and set the second element 0, and when the first element reaches the limit, insert another element with value of 1 to the start of the list, and zero the two elements after it, et cetera.
And just like this, when a place reaches limit, zero the place and the places after it, increase the place before it by one, and when all available places reach limit, add 1 to the left, for example:
0
1
2
1, 0
1, 1
1, 2
2, 0
2, 1
2, 2
1, 0, 0
The limit doesn't have to be three.
This is what I currently have that does something similar to this:
array = []
for c in range(26):
for b in range(26):
for a in range(26):
array.append((c, b, a))
I don't want leading zeroes but I can remove them, but I can't figure out how to do this with a variable number of elements.
What I want is a function that takes two arguments, limit (or base) and number of tuples to be returned, and returns the first n such tuples in order.
This must be very simple, but I just can't figure it out, and Google returns completely irrelevant results, so I am asking for help here.
How can this be done? Any help will truly be appreciated!
Hmm, I was thinking about something like this, but very unfortunately I can't make it work, please help me figure out why it doesn't work and how to make it work:
array = []
numbers = [0]
for i in range(1000):
numbers[-1] += 1
while 26 in numbers:
index = numbers.index(26)
numbers[index:] = [0] * (len(numbers) - index)
if index != 0:
numbers[index - 1] += 1
else:
numbers.insert(0, 1)
array.append(numbers)
I don't quite understand it, my testing shows everything inside the loop work perfectly fine outside the loop, the results are correct, but it just simply magically will not work in a loop, I don't know the reason for this, it is very strange.
I discovered the fact that if I change the last line to print(numbers) then everything prints correctly, but if I use append only the last element will be added, how so?
from math import log
def number_to_base(n,base):
number=[]
for digit in range(int(log(n+0.500001,base)),-1,-1):
number.append(n//base**digit%base)
return number
def first_numbers_in_base(n,base):
numbers=[]
for i in range(n):
numbers.append(tuple(number_to_base(i,base)))
return numbers
#tests:
print(first_numbers_in_base(10,3))
print(number_to_base(1048,10))
print(number_to_base(int("10201122110212",3),3))
print(first_numbers_in_base(25,10))
I finally did it!
The logic is very simple, but the hard part is to figure out why it won't work in a loop, turns out I need to use .copy(), because for whatever reason, doing an in-place modification to a list directly modifies the data reside in its memory space, such behavior modifies the same memory space, and .append() method always appends the latest data in a memory space.
So here is the code:
def steps(base, num):
array = []
numbers = [0]
for i in range(num):
copy = numbers.copy()
copy[-1] += 1
while base in copy:
index = copy.index(base)
copy[index:] = [0] * (len(copy) - index)
if index != 0:
copy[index - 1] += 1
else:
copy.insert(0, 1)
array.append(copy)
numbers = copy
return array
Use it like this:
steps(26, 1000)
For the first 1000 lists in base 26.
Here is a a function, that will satisfy original requirements (returns list of tuples, first tuple represents 0) and is faster than other functions that have been posted to this thread:
def first_numbers_in_base(n,base):
if n<2:
if n:
return [(0,)]
return []
numbers=[(0,),(1,)]
base-=1
l=-1
num=[1]
for i in range(n-2):
if num[-1]==base:
num[-1]=0
for i in range(l,-1,-1):
if num[i]==base:
num[i]=0
else:
num[i]+=1
break
else:
num=[1]+num
l+=1
else:
num[-1]+=1
numbers.append(tuple(num))#replace tuple(num) with num.copy() if you want resutl to contain lists instead of tuples.
return numbers

Breaking an iterative function in Python before a condition turns False

This is for a school assignment.
I have been tasked to define a function determining the largest square pyramidal number up to a given integer(argument). For some background, these are square pyramidal numbers:
1 = 1^2
5 = 1^2+2^2
14 = 1^2+2^2+3^2
So for a function and parameter largest_square_pyramidal_num(15), the function should return 14, because that's the largest number within the domain of the argument.
I get the idea. And here's my code:
def largest_square_pyramidal_num(n):
sum = 0
i = 0
while sum < n:
sum += i**2
i += 1
return sum
Logically to me, it seemed nice and rosy until I realised it doesn't stop when it's supposed to. When n = 15, sum = 14, sum < n, so the code adds one more round of i**2, and n is exceeded. I've been cracking my head over how to stop the iteration before the condition sum < n turns false, including an attempt at break and continue:
def largest_square_pyramidal_num(n):
sum = 0
for i in range(n+1):
sum += i**2
if sum >= n:
break
else:
continue
return sum
Only to realise it doesn't make any difference.
Can someone give me any advice? Where is my logical lapse? Greatly appreciated!
You can do the following:
def largest_pyr(x):
pyr=[sum([i**2 for i in range(1,k+1)]) for k in range(int(x**0.5)+1)]
pyr=[i for i in pyr if i<=x]
return pyr[-1]
>>>largest_pyr(15)
14
>>> largest_pyr(150)
140
>>> largest_pyr(1500)
1496
>>> largest_pyr(15000)
14910
>>> largest_pyr(150000)
149226
Let me start by saying that continue in the second code piece is redundant. This instruction is used for scenario when you don't want the code in for loop to continue but rather to start a new iteration (in your case there are not more instructions in the loop body).
For example, let's print every number from 1 to 100, but skip those ending with 0:
for i in range(1, 100 + 1):
if i % 10 != 0:
print(i)
for i in range(1, 100 + 1):
if i % 10 == 0:
# i don't want to continue executing the body of for loop,
# get me to the next iteration
continue
print(i)
The first example is to accept all "good" numbers while the second is rather to exclude the "bad" numbers. IMHO, continue is a good way to get rid of some "unnecessary" elements in the container rather than writing an if (your code inside if becomes extra-indented, which worsens readability for bigger functions).
As for your first piece, let's think about it for a while. You while loop terminates when the piramid number is greater or equal than n. And that is not what you really want (yes, you may end up with a piramid number which is equal to n, but it is not always the case).
What I like to suggest is to generate a pyramid number until in exceedes n and then take a step back by removing an extra term:
def largest_square_pyramidal_num(n):
result = 0
i = 0
while result <= n:
i += 1
result += i**2
result -= i ** 2
return result
2 things to note:
don't use sum as a name for the variable (it might confuse people with built-in sum() function)
I swapped increment and result updating in the loop body (such that i is up-to-date when the while loop terminates)
So the function reads like this: keep adding terms until we take too much and go 1 step back.
Hope that makes some sense.
Cheers :)

Define a function using a variable?

I am trying to define a function that will include a variable n where n will be a string of numbers e.g. "3884892993", the definition of the function starts as is_true(n), however if n is going to be a string should it be is_true(n) and then once the string is defined I can test the function with an example string such as n = "3884892993". I get a syntax error when I use is_true(n) however. And I am just wondering how I would go about testing this function with an example string for n.
My entire function to define is shown here: http://oi44.tinypic.com/282i3qo.jpg but bear in mind I am an absolute novice so there will most probably be many mistakes, but I would appreciate some help from some experts if at all possible :)
def is_valid("n"): #n is the number to be checked.
number =
[int(y) for y in A] #converts the string into a list of useable digits.
altern1 = integer[-2::-2] #sets altern1 as one set of alternating digits.
double = [x*2 for x in altern1] #doubles each element of the list altern1.
sum1 = sum(double) # adds together all the doubled items of the list.
altern2 = integer[-1::-2] #sets altern2 as the other set of alternating digits.
return sum2 = sum(altern2)#sums the other set of alternating digits.
sumtotal = sum1 + sum2 #works out the total sum to be worked with.
for mod = sumtotal % 10: #works out remainder when sumtotal is divided by 10
if mod == 0 : #if remainder is zero sumtotal is a multiple of 10
print 'True' #sumtotal is a multiple of 10 therefore n is a credit card number
else:
print 'False' #sumtotal is NOT a multiple of 10 therefore not a valid credit card number
Here is the actual question:
The algorithm for verifying a number is as follows:
(a) Starting with the penultimate digit, and working towards the rst digit, double each alternating digit.
(b) Sum the doubled digits, treating 13 as 1+3, etc, and add the result to the sum of the undoubled
digits
(c) If the sum is divisible by 10 the number is a valid credit card number.
Write and test a function is_valid() which takes as an argument a credit card number as a string
(eg is valid("49927398716")) and returns True or False depending on whether the number is a
valid credit card number.
Quotes are only used for string literals, you wouldn't enclose a variable or parameter name in quotes to indicate that it will be a string. The function definition would look like:
def is_true(n):
And then in the body of the function you use n to reference the value that is passed in by the caller.
To call the function on a specific value, you do:
is_true("3884892993")
Side suggestion: Think of more explanatory names for your functions and variables. For instance, it seems like your function might be reasonably called is_valid_card_number.
I am not sure what is your question, but if you are trying to:
correctly define the function:
pay attention to the indentation (this is required by Python!),
see here for examples of function definitions,
convert a string variable into integer, you can do this:
new_var = int(old_var)
Generally please pay attention to types, because it is not like in some other dynamically typed languages and strings are not dynamically converted into numbers - you should do it explicitly.
read the value of the variable, based on its name:
my_var = vars().get('variable_name')
(where variable_name is the name of the variable and optionally you can give context within brackets after vars - see help(vars) for details)
Did any of the above solve your problem?
EDIT (based on the clarification):
This should solve your problem:
def is_true(my_variable):
# Here the variable named "my_variable" is accessible
If you want to do something "in-place" on the passed variable, I have a bad news: strings and integers are immutable in Python, thus you are not able to simply change them - you should probably return them as a result of the function (there are at least two workarounds, but I do not recommend them if you are a novice in Python).
EDIT (for proper code styling):
You should probably read PEP 8 to get familiar with what is the coding standard for Python scripts - this is commonly used across Python community and you should follow that (at some point you should appreciate it).
From the Wikipedia article on the Luhn algorithm:
def is_luhn_valid(cc):
num = map(int, str(cc))
return sum(num[::-2] + [sum(divmod(d * 2, 10)) for d in num[-2::-2]]) % 10 == 0
I have no idea what your function is supposed to do, but here are some remarks.
First of all, if you define the function then you use the following syntax
def is_true(n):
# do something
you can call this function like this is_true("3884892993"), i.e. you can pass string as n. Your function now need to treat variable n as a string. So you can use
number = [int(d) for d in n]
which will result in converting string into a list of digits.
One more remark: you used a return statement inside your is_true function. This statement will stop executing the function and return the value. Every code below return will never be executed.
May be like this. I leave your comments
def is_valid(n): #n is the number to be checked.
numbers = [int(y) for y in n] #converts the string into a list of useable digits.
double_alt = [sum([int(i) for i in str(x*2)]) for x in numbers[-2::-2]] #doubles and sum if more than 10each element of the list altern1.
sum1 = sum(double_alt) # adds together all the doubled items of the list.
sum2 = sum(numbers[-1::-2]) #sums the other set of alternating digits.
sumtotal = sum1 + sum2 #works out the total sum to be worked with.
return not sumtotal % 10
Here an implementation of the luhn algorithm that I had to make recently.
def is_valid_luhn(cc):
return not sum([sum(divmod(int(d) * 2, 10)) for d in cc[-2::-2]] + [int(d) for d in cc[-1::-2]]) % 10
# | double | |--- every -2th --| |--- every -1th --|
# |--------- step 1 -----------------|
# |------------- sum doubled digits --------------| |-- sum undoubled digits --|
# |---------------------- step 2: sum doubled/undoubled digits -----------------------|
# |-------------------------- step 3: sum % 10 == 0 --> not sum % 10 --------------------------|
Or if you'd like a more verbose version:
def is_valid_luhn(cc):
total = 0
# Double and sum every 2nd digit starting at -2.
for d in cc[-2::-2]:
# divmod(d*2, 10) returns (d*2 // 10, d*2 % 10)
# sum(divmod) return (d*2 // 10) + (d*2 % 10)
total += sum(divmod(int(d) * 2, 10))
# Sum every 2nd digit starting at -1.
for d in cc[-1::-2]:
total += int(d)
# Check module 10 of total: total % 10 == 0 --> not total % 10
return not total % 10

Categories

Resources