What Does This Instruction Do? - python

I'm new to Python and I don't understand an instruction in the following program:
n = int(input("enter an number : ")
b = 3
p = 1
while n > 0:
n,r = n//2,n%2
p* = b**r
b = b*b
print(p)
I don't understand this statement: n,r = n//2,n%2. What does it do?

Most of the answers are incorrect.
a, b = c, d is a Pythonic concept called "tuple unpacking".
n,r=n//2,n%2 does mean "assign n//2 to n" and "assign n % 2 to r" but n,r is a tuple. In tuple unpacking, all expressions on the RHS are evaluated before assignments. Thus n is not mutated by n//2 before n%2 is evaluated.
Proof of concept for order of operations in tuple unpacking:
a = 1
b = 2
a, b = b, a
if (a==2 and b==1):
print("look ma, I can swap values without needing a temporary variable!")

It is tuple assignment. The each value in the tuple on the left is assigned to the respective value in the tuple on the right. Since the values on the right side are evaluated before any assignment occurs, the value of n before the statement is used. So the line is equivalent to:
tmp = n
n = tmp // 2
r = tmp % 2

It's a parallel assignment:
n, r = n // 2, n % 2
n equals n divided by 2 using integer division, and r equals n modulo 2. It's the same as:
t1 = n // 2
t2 = n % 2
n = t1
r = t2
The values to the right are evaluated, and after that they're assigned, to defer overwriting the original values until we no longer need them.

Related

Python and Modular Arithmetic

Suppose a and b are odd integers. Then a^2 + b^2 is either 2 or 10 modulo 16. My question is the following: Is there a way of writing a script whose assumptions are a%2 == 1 and b%2 == 1 so that the output (a^2 + b^2) % 16 gives the tuple (2,10)?
Edit: Here's my unsuccessful approach:
def test():
aList=[]
bList=[]
for a in range(0,16):
for b in range(0,16):
if a%2==1 and b%2==1:
aList.append(a)
bList.append(b)
print a^2+b^2%16
This of course will not return a tuple. My hope is to output the tuple (2,10).
As I understand, you want to collect the distinct residues modulo 16 of a**2 + b**2 (note the ^ operator is not what you want here) into a tuple. So instead of printing each residue out, you should add them to a set in order to collect the distinct values. The set can then be converted to a tuple, using sorted to get them in order:
residues = set()
for a in range(0, 16):
for b in range(0, 16):
if a % 2 == 1 and b % 2 == 1:
residues.add((a**2 + b**2) % 16)
residues = tuple(sorted(residues))
print(residues)
The result is (2, 10) as expected.
This code can be simplified somewhat: instead of generating all integers in the range and just keeping the odd ones, you can generate odd integers using a range starting from 1 with a step size of 2; and you can use a set comprehension for brevity.
residues = {
(a**2 + b**2) % 16
for a in range(1, 16, 2)
for b in range(1, 16, 2)
}
residues = tuple(sorted(residues))
print(residues)

How to find numbers which GCD equal to 1 and those numbers are less than given in python

I am trying to write code which gives you numbers which are less than given or entered number , and their GCD equal to 1 . I wrote this code but I don't know if works or why not . For example I chose number 6. array will be like [1,2,3,4,5]. And my point is to filter numbers that GCD equals to 1. So it will be [1,5]. And their amount is two.
a is input number and b is list numbers that are less than entered one and not equal to zero . And then print it .
a = int(input("enter number \n"))
b = list(range(1,a))
print (b)
Then I convert list to array
for i in range(1, len(b)):
b[i] = int(b[i])
and then this
r = a % b[i]
q = int ( a / b[i])
while(r!=0):
a = b[i]
b[i] = r
q = int ( a / b[i])
r = a - (b[i] * q)
print ( a , b[i], r )
break
I am beginner .
A few comments about your code:
You should always encapsulate code like this in a function; write a function find_coprimes which takes an argument n and returns the list you want;
In order to test the correctness of your function, write a reference function find_coprimes_ref which does the same thing, but uses library functions to make sure there is no error; this will teach you to look for relevant library functions, and you can compare the results of the two functions;
The initial loop for i in range(1, len(b)): b[i] = int(b[i]) is wrong for two reasons; 1) It has no effect, as b is already a list of integers. 2) Lists are 0-indexed, so a correct iterations on every element of b would be for i in range(0, len(b)): or simply for i in range(len(b)):;
Your code has two nested loops: a while-loop executing repeatedly inside a for-loop; whenever there are nested loops like this, you must make sure that variables are reinitialised the way you intend them to at the beginning of the outer loop; in your case, variable a is modified inside the while-loop, and as a result, its value is wrong at the beginning of the next iteration of the for-loop.
The break statement at the end of the while-loop makes no sense; in general, break statements only make sense if they are encapsulated in an if conditional, and they act as a substitute for the loop condition; but it's always possible to write loops without using break at all and I recommend you forget about break entirely.
After performing the gcd calculation using q and r, your code is missing something to tell it whether or not to keep b[i] or not in the final result;
For integer division in python, it is better to use // rather than int(... / ...).
Code
import math
def find_coprimes_ref(n):
return [x for x in range(1,n) if math.gcd(x,n) == 1]
def find_coprimes(n):
result = []
for x in range(1, n):
a = n
b = x
r = a % b
q = a // b
while (r > 1):
a = b
b = r
q = a // b
r = a - b * q
if (r == 1):
result.append(x)
return result
# TESTING
for n in range(1, 31):
coprimes_ref = find_coprimes_ref(n)
coprimes = find_coprimes(n)
if coprimes_ref != coprimes:
print(n, coprimes_ref, coprimes)
Note how my code never modifies n or x in the loop; instead, I make copies called a and b and modify the copies.
Encapsulating even further
Note how function find_coprimes_ref is so much easier to read than function find_coprimes? This is not just because we used library function math.gcd. It's because library function math.gcd is a cleanly-encapsulated function with a name that explains clearly what it does. Your code contains a while loop inside a for loop and it's a bit hard to keep track of every variable and everything that is going on and not lost track of our sub-objective and overall objective.
To make your function both easier to read, easier to code and easier to debug, You should encapsulate the gcd calculation inside a function called gcd:
def gcd(a, b):
r = a % b
q = a // b
while (r > 1):
a = b
b = r
q = a // b
r = a - b * q
return r
def find_coprimes(n):
result = []
for x in range(1, n):
if gcd(a, b) == 1:
result.append(x)
return result
# TESTING GCD
for b in range(1, 31):
for a in range(b, 31):
r1 = math.gcd(a, b)
r2 = gcd(a, b)
if r1 != r2:
print(a, b, r1, r2)
# TESTING FIND_COPRIMES
for n in range(1, 31):
coprimes_ref = find_coprimes_ref(n)
coprimes = find_coprimes(n)
if coprimes_ref != coprimes:
print(n, coprimes_ref, coprimes)
There are two reasons why the code is easier to debug now:
The logic for gcd and for find_coprimes is cleanly separated, which means you can reason about gcd clearly without any risk of messing up the list and the other variables used in find_coprimes;
You can test separately your function gcd and your function find_coprimes; and if something doesn't work correctly, you'll know more precisely where to look for the issue rather than just thinking "well, something is wrong somewhere in the code but I have no idea where".
There are a few errors in your code like, break inside while loop. I have refactored your code and also added inbuilt math.gcd function to compare results.
import math
def math_inbuilt_gcd(a, b):
gcd_one = []
for x in b:
if math.gcd(x, a) == 1:
gcd_one.append(x)
print("gcd_one_math_fun:", gcd_one)
def gcd_my_fun(a, b):
gcd_arr = []
for i in range(len(b)):
x, y = a, b[i] # taking x, y just to make things clear
r = x % y # remainder
q = int(x / y) # quotient
while(r != 0):
x = y
y = r
q = int(x/y)
r = x % y
if y == 1:
gcd_arr.append(b[i])
print("gcd_one_my_fun:", gcd_arr)
a = int(input("Enter number: "))
b = list(range(1, a))
print("b:", b)
math_inbuilt_gcd(a, b)
gcd_my_fun(a, b)
Output:
Enter number: 10
b: [1, 2, 3, 4, 5, 6, 7, 8, 9]
gcd_one_math_fun: [1, 3, 7, 9]
gcd_one_my_fun: [1, 3, 7, 9]

Python lambda dp calculation

I am trying to understand below code snippet, for each value of i, what are all the two arguments passed to min()? appreciate if you could explain how the dp[i] computation could be expanded?
class Solution(object):
def coinChange(self, coins, amount):
MAX = float('inf')
dp = [0] + [MAX] * amount
print(dp)
for i in range(1, amount + 1):
dp[i] = min([dp[i - c] if i - c >= 0 else MAX for c in coins]) + 1
print(dp)
return [dp[amount], -1][dp[amount] == MAX]
A lot of things are happening here.
The min() method is receiving a python list as an argument.
This python list is created through list comprehension. It helps to start from the back. The list comprehension is saying "For every value c in the iterable coins, append the value dp[i - c] to my list if the boolean i - c >=0 is True. Otherwise, append the value MAX.
In other words, the line [dp[i - c] if i - c >= 0 else MAX for c in coins] is equivalent to
def makelist(dp,i,MAX,coins):
ret = []
for c in coins:
if i - c >= 0:
ret.append(dp[i-c])
else:
ret.append(MAX)
return ret
The min() method will be performed on this list once it is complete, which simply find the smallest value in the list

Logic on printing Fibonacci numbers in Python

This is been killing me. When using the following code to print the Fib number, it gives the right output:
a = 0
n = 1
while n < 55:
print(n)
a,n = n,a+n
but when I change to this:
a = 0
n = 1
while n < 55:
print(n)
a = n
n = a+n
The output is totally different.
I've even run it thru pythontutor.com to watch stepping.
What are I missing.
There is a difference in the way variable values are interpreted and assigned between the two code snippets.
In case of the first snippet, while assigning the value to "n", the new value of a is not used, rather the value of a from the previous iteration is used.
But, in case of the second snippet, the value of "a" is first updated and then used for the second statement.
Let's take an example:
For the first iteration where n is 1,
First Code Snippet: At the end of the iteration, the value of a will be 1 and value of n also will be 1. (For n = a+n, value of a is considered 0)
Second Code Snippet: At the end of the iteration, the value of a will be 1 and value of n will be 2. (For n = a+n, value of a is considered 1)
The key point to be noted about the Python Comma Operator is that, all the expressions to the right of the assignment operator are evaluated first before the assignments are actually made and this causes the difference in output between the two.
Well, the initial assignment
a,n = n,a+n
means
old_a = a
a = n
n = old_a + n # saved a value (old_a) used
Please, notice that n = old_a + n, not a + n == 2 * n
Let's call a_i and n_i the values of a and n at the i-th iteration.
In the first code you are assigning to n_i+1 the value a_i + n_i, instead in the second code you are assignign to n_i+1 the value a_i+n_i+n_i.
This happen because you are assigning a before n in the second code, while this happen simultaneously in the first one. To solve this issue save in a temporary variable the old value of n or a.
Alternatively, with just a bit of math, you can do the following without saving any temporary variable:
a = 0
n = 1
while n < 55:
print(n)
n = a+n
a = n-a
which is equivalent to: a_i+1 = n_i+1 - a_i = a_i + n_i - a_i = n_i.

Getting index error in the code in python

def fact(n):
fac = 1
while (n>1):
fac = fac*n
n -= 1
return fac
z = 0
t = int(raw_input())
nz = []
for i in range(0,t):
c = 0
n = int(raw_input())
z = fact(n)
z = list(str(z))
for j in range(len(z)-1,1,-1):
if z[j] != '0':
break
else:
c +=1
nz[i].append(c)
for k in range(0,t):
print nz[k]
Hello I am getting
Indexerror : index out of range at " nz[i].append(c)
This program should calculate trailing zeros in the factorial of N.
Can you also please help me optimize my code, so it can run also for large values of N?
nz is empty list. It doesn't have any elements, so nz[i] would always raise IndexError. Perhaps you meant nz.append(c) ie. add c at the end of nz.
This is how does append() work:
list.append(x)
Add an item to the end of the list; equivalent to a[len(a):] = [x].
so you may want to change nz[i].append(c) to nz.append(c), since your i index is already handled by the append function. You're actually assuming you have an i element in your list, which is false, since you are using an empty list
About optimizing, your problem is probably due to your recursion limit. Try import sys; sys.getrecursionlimit() in your python shell, you should see something like 1000 as result.
Swapping for an iterative version of the factorial function could be a start
def fact(n):
r = 1
for x in range (n):
r = r * (x+1)
return r

Categories

Resources