I'm brand new to Python as of a few weeks ago for a class I am taking. I am currently writing a program that is designed to take a four digit integer, take the absolute differences of each number, and then sum them. Meaning, you enter a four digit PIN, the program takes the absolute values of (number 1- number 2), (2-3), and (3-4) and then sums them and prints the sum.
I am supposed to write a for loop in order to do this after converting the integer to a string.
I was told to structure the loop using for char in value: but I am confused as to how to set this up. I understand basic slicing, and I assume I need to use that in my answer.
This is what I have so far for my code:
def main():
print("This program is designed to determine the weight of a four-digit PIN by calculating the sum of the absolute difference between each digit.")
# Prompt user for PIN
x = input("Enter your PIN: ")
# Call the weight function providing the four digit pin as an argument
weight(x)
# Weight function
def weight(x):
# Convert integer to string
str(x)
# Initialize variables
a, b, c, d = x
# Setup for a loop that uses digits as sequence, sum differences between each digit in integer
# Print sum
The loop is the part that is messing me up. I know there’s other ways to solve this without using a loop, but for my assignment I am supposed to.
I was told to structure the loop using for char in value: but I am confused as to how to set this up.
The way you are assigning x with x = input("Enter your PIN: "), x is already a string. The for loop should be used to convert each character to an integer before returning the weighted sum. Here is one way using a list to store the integers:
def weight(value):
int_values = [] # Create an empty list to store the integers.
for char in value:
int_values.append(int(char)) # Converts char to int and adds to list.
return abs(int_values[0] - int_values[1]) + abs(int_values[1] - int_values[2]) + abs(int_values[2] - int_values[3])
pin = ''
while len(pin) != 4 or not pin.isdigit(): # Make sure PIN is 4 digits.
pin = input("Enter your PIN: ")
pin_weight = weight(pin)
print('Weight of {} is {}'.format(pin, pin_weight))
The problem is that you're converting x to a string but not storing the return value of the str(x) call. You can fix this by storing the value of str(x) in the x variable.
def weight(x):
x = str(x)
a, b, c, d = x
# continue with loop
You can clean this up a little bit by storing the return value of str(x) straight into a, b, c, d
def weight(x):
a, b, c, d = str(x)
# continue with loop
The final option that I think you should consider trying out is looping through the digits in the pin without storing them in the variables a, b, c, d. To get you started, you can try this out:
# PIN = 8273
def weight(x):
for i in range(len(str(x))): # loop through indices in x
print(x[i]) # prints 8, 2, 7, 3
some may want to avoid mixing str operations in a numerical formula
num = 1234
digits = []
for _ in range(4):
num, rem = divmod(num, 10)
digits.append(rem)
digits
[4, 3, 2, 1]
breaks up the number into a list of the 4 digits - the reverse order dosen't matter for your weight calc
Related
I want to write a code for this question:
write a code which creates a new number 'n2' which consists reverse order of digits of a number 'n' which divides it without any remainder for example if input is 122
it will print 221 because 1,2,2 can divide 122 without any remainder another example is 172336 here 1,2,3,3,6 can divide it without any remainder so the output should be 63321(reverse order).
my code is:
n = str(input())
x = ""
z = 0
for z in range(len(n)):
if int(n)%int(n[z])==0:
x = n[z] + ""
else:
n.replace(n[z],"")
z = z+1
print(x[::-2])
if I input the number 122 here i get the output 2 but i should be getiing output of 221 why.
The reason why you are not getting the desired output in this code is because of several logical and syntactical errors in your code. Here are some of them:
You are using x = n[z] + "" to append the digits that divide n without any remainder, but this will overwrite the previous value of x every time. You should use x = x + n[z] instead.
You are using n.replace(n[z],"") to remove the digits that do not divide n without any remainder, but this will not modify the original value of n, since strings are immutable in Python. You should assign the result of n.replace(n[z],"") to a new variable, or use a different approach to filter out the unwanted digits.
You are using z = z+1 to increment the loop variable, but this is unnecessary and redundant, since the for loop already does that for you. You can remove this line.
You are using print(x[::-2]) to print the reversed value of x, but this will skip every other digit, since the negative step of -2 means you are slicing the string from the end to the beginning with a step of 2. You should use print(x[::-1]) instead, which will reverse the whole string. A possible corrected version of your code is:
python
n = str(input())
x = ""
for z in range(len(n)):
if int(n)%int(n[z])==0:
x = x + n[z]
print(x[::-1])
This code will print the reversed order of the digits of n that divide it without any remainder, as expected. For example, if the input is 122, the output will be 221.
The code works by iterating over each digit of the input number n, which is converted to a string for convenience. For each digit, it checks if it divides n without any remainder, using the modulo operator %. If it does, it appends the digit to the end of the string x, using the + operator. If it does not, it ignores the digit. After the loop, it prints the reversed value of x, using the slicing notation [::-1], which means start from the end and go backwards until the beginning.
This should do the Trick
num = input()
new_num = ""
for i in num:
if int(num)%int(i) == 0:
new_num += i
print(new_num[::-1])
I want to make a function that gets the sum of the squares of its each digits. Although, I have seen some solutions in the internet, the one I have seen is "getting the sum of the squares of its digits" but given a list. For example, instead of starting at the integer 133, they use [1,3,3] as an input. I tested this function and it works great, but I want to use an integer as an input and not a list.
Edit: For example the given is 123. So the function must return 14. (1^2 + 2^2 + 3^2)
My idea is:
def squarer(x): # where x is an integer (not a list)
# <insert a recursive formula>
# return the sum
One simple way to make a recursive function is, to always square the first digit and then call the same function with the remaining digits.
def squarer(x: int) -> int:
if x < 10: # trivial case, when x has only one digit
return x**2
first_digit = int(str(x)[0]) # extract the first digit
return first_digit**2 + squarer(int(str(x)[1:])) # recursive call
Here, I used the functions int() and str() to always access the individual digits and cast the the variable back to an integer.
You can use an integer as an input and transform it into a list.
arr = [int(x) for x in input("Enter a number: ")]
and then you pass your list into your function.
def squarer(arr): # where arr is a list
# <insert a recursive formula>
# return the sum
Try to convert your number to string so you can iterate by each digit. And after you can convert string to list or just convert each digit to int before you apply other logic
If I understood the question correctly, this code should solve your problem
It is not of the highest quality but it works :)
def sq(x):
sum = 0
while x > 0:
y = x/10
r = y*10
r = x-r
r = r*r
sum = sum+r
x = y
return sum
print(sq(12))
Recursive and without any transformations:
def squarer(n):
if n <= 0:
return 0
rest, first_digit = divmod(n, 10)
return first_digit**2 + squarer(rest)
Place value (positional) encoded numbers
To make it possible to multiply a number in a place value based fashion, I have encoded numbers in a list format, digit by digit in reverse order. Say for example 34 is [4 3] and 12 is [2 1].
To encode numbers I use:
def eN(n):
return list(map(int, reversed(str(n))))
To decode I use:
def dN(l):
return int(''.join(map(str, reversed(l))))
So that: dN(eN(34)) -> 34
Positive integers can be from 0 to any digits long.
Multiplication constraints
Now, I need to create a multiplication algorithm with the next constraints:
1.
Division method to find out integer and remainder part of the divided number that satisfy this function:
from math import floor
# div(5, 3) -> [1, 2]
def div(n, base = 10):
return [floor(n / base), n % base]
only permitted arithmetic operations are div, * and + methods, which however can be used in conjunction with recursion
numbers must be encoded as stated above except the base is given as a native integer from 2 and up
at any part of the algorithm numbers cannot exceed two digits. For example 9+9 = 18 or 9*9=81 are good, but 100 is too much
result should also be a list of numbers encoded in a reverse list format. numbers in a list must be in single digits so that we can use decode function (dN) to transform it back to native integer
algorithm should work with any number base by using div or builtin Python divmod as suggested by #ShadowRanger.
Maybe other restrictions becomes necessary to stress, when answers are suggested.
Alleged algorithm
I would think of a root function similar to this, where two encoded numbers are given as arguments, plus an optional base number, default is 10:
def mul(a, b, base = 10):
def _(c, d, e):
# arithmetics, carrying digits, list processing, recursive calls goes here
pass
# initially, the first digit of the number a is reduced and 10^0 parts of the both numbers are multiplied and "div"ided
return _(a[1:], b, div(a[0]*b[0], base))
Finally, the expected result is:
mul(eN(34), eN(12)) # [8, 0, 4]
or
dN([8, 0, 4]) # 408
If necessary, I can add more to the multiplication _ function, which only has pass at the moment...
Added later...
Working, but messy and unoptimized version of the algo
One might want to use this as a starting point for optimization. I should note, that this should already do the job exactly as I need, but other approaches are welcome:
def mul(a, b, base = 10):
# init function with some default values
def _(c, d, f = [], g = [], h = [], e = 0):
# if there are no more items in list d, this is the end result
if not d:
return h + f
# if there are items in list list c, get integer and reminder parts and other stuff
# and proceed with the rest of the list c
if c:
x = divmod(c[0] * d[0] + (f.pop(1) if len(f) > 1 else 0) + e, base)
return _(c[1:], d, f, g + [x[1]], h, x[0])
# else we have reached the end of the list c and must begin again with the rest of the list d!
# also append reminders to the result lists h and f, not that content of f comes from g at this point
return _(a, d[1:], (g + [e] if e else g), [], (h + [f[0]] if f else h))
# start calling the recursive function and return the end result
return _(a, b)
I will accept any answer that does the same job, even the ones using above code, if solution makes good improvements like minifies the need of lists i.e. usage of memory, or other way simplifies and explains the solution.
This is my function:
def repeat(x,Y):
A = list(str(x)) #makes a list, A, of each digit: 101 becomes ['1','0','1']
A = map(int,A) #converts each value of the new list to integers
for i in range(0,10):
b = A.count(i) #counts how many times each digit is present
if b>1: #if there is repetition
Y.remove(x)
This seems to be fine when run in idle for a single number, however when applied to a list using a for loop, the function misses one value.
B = []
for i in range(100,1000): #needs to be a 3 digit number (100 until 999)
if i%17 == 0:
B.append(i) #creates list of factors of 17
for j in B: #removes any values that have digits that occur more than once
repeat(j,B)
This returns a list which includes the number 663. When the function is re-run in the new list, that value is removed. Also when it is applied to a different list, 3 digit numbers with 13 as a factor, the same occurs, one value with a repeating digit.
Its not a major inconvenience, just a really annoying one.
255 which comes immediately before 272 is removed but 272 gets skipped. Similarly, 663 is skipped as 646 directly before it is removed.
I suspect it could do with in-place modification of the array as #interjay says.
ETA: With debugging statements put in, you can see that the numbers that come immediately after numbers that were removed, are skipped over:
def repeat(x,Y):
A = list(str(x)) #makes a list, A, of each digit: 101 becomes ['1','0','1']
A = map(int,A) #converts each value of the new list to integers
print 'Proceessing', x
for i in range(0,10):
b = A.count(i) #counts how many times each digit is present
if b>1: #if there is repetition
print 'Removed', x
Y.remove(x)
B = []
for i in range(100,1000): #needs to be a 3 digit number (100 until 999)
if i%17 == 0:
B.append(i) #creates list of factors of 17
print B
for j in B: #removes any values that have digits that occur more than once
repeat(j,B)
print B
As the comments suggest, don't modify a list while iterating over it. Also, Python provides Counter to count iterables, so you don't need to implement it yourself. Finally, since you are repeatedly filtering an iterable, it is sensible to use filter.
import collections
def norepeats(x):
counts = collections.Counter(str(x))
return not any(ci > 1 for ci in counts.values())
threedigit = range(100,1000)
b1 = filter(lambda x: 0==x%17, threedigit)
b2 = filter(norepeats, b1)
print b2 #the result you expected
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