How can i sum co-prime numbers in a pair - python-3.x

I have this list
a = [1,2,3,4,5,6,7,8,9]
I want to find out that how many co-prime pair elements of the list add up to sum=9
Ex, (1+8) = 9 , (2+7) = 9 , (3+6)=9 , (4+5)=9, (5+4)=9 , (6+3)=9, (7+2)=9 , (8+1)=9
Note that i don't want (3+6) as they are prime numbers. And i also don't want (7+2)=9 as it has already occurred (means 2,7 has been already taken in account)
I tried this But it takes repeated values too.
a = [1,2,3,4,5,6,7,8,9]
count=0
for m in a:
for n in a:
total=m+n
if(total==9):
s=str(m) + '+'+ str(n) + "="
print(s , m+n)
count=count+1
print("Count =" ,count)
The result should have count=3

Your mistake is in the way of doing the loops, so you repeat values.
Try this:
#from math import gcd as bltin_gcd
a = [1,2,3,4,5,6,7,8,9]
count = 0
def __gcd(a, b):
# Everything divides 0
if (a == 0 or b == 0): return 0
# base case
if (a == b): return a
# a is greater
if (a > b):
return __gcd(a - b, b)
return __gcd(a, b - a)
# Only python 3
# def coprime(a, b):
# return bltin_gcd(a, b) == 1
for i in range(0,9):
for j in range(i+1,9):
if __gcd(a[i], a[j]) == 1 and a[i] + a[j] == 9:
count += 1
print str(a[i]) + ' ' + str(a[j])
print 'Count = ' + str(count)
In number theory, two integers a and b are said to be relatively prime, mutually prime, or coprime if the only positive integer that divides both of them is 1. Consequently, any prime number that divides one does not divide the other. This is equivalent to their greatest common divisor being 1.

for m in a:
for n in a:
You are not selecting pairs by using this loops, ie. you are picking the first element in both the outer and inner loop during your first iteration.
if(total==9):
You are not checking the condition if the selected pair of numbers are coprime. You are only verifying the sum.

A pythonic solution may be obtained with a one-liner:
from math import gcd
a = [1,2,3,4,5,6,7,8,9]
pairs = [(m,n) for m in a for n in a if n > m and m+n == 9 and gcd(m,n) == 1]
Result :
pairs --> [(1, 8), (2, 7), (4, 5)]
If you are sure to never, never need the pairs but only the number of pairs (as written in the OP), the most efficient solution may be:
count = len([1 for m in a for n in a if n > m and m+n == 9 and gcd(m,n) == 1])
EDIT : I inversed the three conditions in the if statement for improved benefit from lazy boolean evaluation

You can solve this if you have something that calculates your prime factorization in python:
from functools import lru_cache
# cached function results for pime factorization of identical nr
#lru_cache(maxsize=100)
def factors(nr):
# adapted from https://stackoverflow.com/a/43129243/7505395
i = 2
factors = []
while i <= nr:
if (nr % i) == 0:
factors.append(i)
nr = nr / i
else:
i = i + 1
return factors
start_at = 1
end_at = 9
total = 9
r = range(start_at, end_at+1)
# create the tuples we look for, smaller number first - set so no duplicates
tupls = set( (a,b) if a<b else (b,a) for a in r for b in r if a+b == total)
for n in tupls:
a,b = n
f_a = set(factors(a))
f_b = set(factors(b))
# if either set contains the same value, the f_a & f_b will be truthy
# so not coprime - hence skip it
if f_a & f_b:
continue
print(n)
Output:
(2, 7)
(1, 8)
(4, 5)

Related

Why is my python function not working properly when I call it recursively?

I'm doing a question from a previous Waterloo ccc competition (https://cemc.uwaterloo.ca/contests/computing/2020/ccc/juniorEF.pdf problem J5)
and my code isn't working the way I expected
Here's the sample input I'm using:
3
4
3 10 8 14
1 11 12 12
6 2 3 9
Here's my code so far
y_size = int(input())
x_size = int(input())
mat = []
"ok".split()
for i in range(y_size):
row = input().split()
mat.append(row)
pos_list = [[0, 0]]
current_num = int(mat[0][0])
a = 0
def canEscape():
global a
global mat
global pos_list
global current_num
end = y_size * x_size
if y_size -1 * x_size -1 == current_num:
return True
for i in range(y_size):
print("______")
for j in range(x_size):
v = (i + 1) * (j + 1)
print(v)
print(current_num)
if v == current_num:
print("ok")
if v == end:
print("ok")
a += 1
current_num = mat[i][j]
pos_list.append([i, j])
canEscape()
pos_list.pop(-1)
a -= 1
current_num = mat[pos_list[a][0]][pos_list[a][1]]
canEscape()
The problem I'm having is that I expect if v == current_num: to be true when I call it again. Both current_num and v are equal to 8 but the code seems to carry on with the for-in loop and break, without entering the if statement. I've made the output print v followed by current_num for every iteration of the for loop to try and figure out the problem but it seems that both variables == 8 so I really don't know what I did wrong. Did I make a silly mistake or did I structure my whole program wrong?
I'm having trouble following what your program is doing at all. This problem involves integer factoring, and I do not see where you're factoring integers. You definitely are not understanding that aspect of the problem.
When you calculate what cells you can go to you look at the value of your current cell. Lets say it is 6. 6 has the factors 1, 2, 3, and 6 because all of those numbers can be multiplied by another number to equal 6. So, you can go to the cells (1, 6), (6, 1), (2, 3), and (3, 2), because those are the pairs of numbers that can be multiplied together to equal 6.
Also, you never convert the lines of input into integers. When you append to the matrix, you are appending a list of strings that happen to be numbers. You must convert those into integers.
Anyways, this program will solve the problem. I copy and pasted the factoring algorithm from other threads:
n_rows = int(input())
n_cols = int(input())
mat = []
for i in range(n_rows):
mat.append(list(map(lambda x: int(x), input().split()))) # Convert input strings to integers.
def reduce(f, l):
# This is just needed for the factoring function
# It's not relevant to the problem
r = None
for e in l:
if r is None:
r = e
else:
r = f(r, e)
return r
def factors(n):
# An efficient function for calculating factors.
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
def get_pairs(items):
for i in range(len(items) // 2):
yield (items[i],items[len(items) - 1 - i]) # use yield to save memory
if(len(items) % 2 != 0): # This is for square numbers.
n = items[len(items) // 2]
yield (n,n)
checked_numbers = set()
def isPath(r=1, c=1):
# check if the testing row or column is to large.
if r > n_rows or c > n_cols:
return False
y = r - 1
x = c - 1
n = mat[y][x]
# If we've already checked a number with a certain value we dont need to check it again.
if n in checked_numbers:
return False
checked_numbers.add(n)
# Check if we've reached the exit.
if(r == n_rows and c == n_cols):
return True
# Calculate the factors of the number, and then find all valid pairs with those factors.
pairs = get_pairs(sorted(list(factors(n))))
# Remember to check each pair with both combinations of every pair of factors.
# If any of the pairs lead to the exit then we return true.
return any([isPath(pair[0], pair[1]) or isPath(pair[1], pair[0]) for pair in pairs])
if isPath():
print("yes");
else:
print("no");
This works and it is fast. However, it if you are limited on memory and/or have a large data input size your program could easily run out of memory. I think it is likely that this will happen with some of the testing inputs but I'm not sure.. It is surely possible to write this program in a way that would use a fraction of the memory, perhaps by converting the factors function to a function that uses iterators, as well as converting the get_pairs function to somehow iterate as well.
I would imagine that this solution solves most of the testing inputs they have but will not solve the ones towards the end, because they will be very large and it will run out of memory.

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two million

sum_ans=17
for i in range(11,2000000):
for j in range(2,int(i**0.5)):
if i%j==0:
break
else:
sum_ans+=i
print(sum_ans)
The code i have return gives answer 143064094781 and the correct answer is 142913828922 but i can not figure out where i have gone wrong. So can any one help me.
Range's stop parameter is exclusive. This means that your code is only calculating j from 2 to 1 less than i**0.5. To fix this you can add 1, meaning that your end code will look a little like this, providing the correct output of 142913828922:
sum_ans=17
for i in range(11,2000000):
for j in range(2,int(i**0.5+1)):
if i%j==0:
break
else:
sum_ans+=i
print(sum_ans)
What about about this:
def isPrime(x):
prime = True
for i in range(2, x):
if x % i == 0:
prime = False
break
else:
continue
return prime
primes = (a for a in range(2, 2000000) if isPrime(a))
print(sum(primes))
# output
142913828922
This code will take a few minutes to execute. Buckle up!!
def sumPrimes(n):
sum =0
for i in range(2 ,n):
for j in range(2, int(i / 2) +1):
if (i % j) == 0:
break
else:
sum += i
return sum
print(sumPrimes(2000000))
If you iterating over all numbers below 2 million, you might as well sieve them using the Sieve of Eratoshenes:
from math import ceil, sqrt
def sieve(n):
nums = list(range(2,n+1))
primes = []
p = 2
k = 1+ ceil(sqrt(n))
while p < k:
primes.append(p)
nums = [num for num in nums[1:] if num % p > 0]
p = nums[0]
return primes + nums
Then sum(sieve(2000000)) evaluates to 142913828922. It takes about 5 seconds to run on my machine.

Printing first combination among various combinations

So I have a question:
Given an even number (greater than 2), return two prime numbers whose sum will be equal to given number. There are several combinations possible. Print only first such pair
This is for additional reference:
*Input: The first line contains T, the number of test cases. The following T lines consist of a number each, for which we'll find two prime numbers.
Note: The number would always be an even number.
Output: For every test case print two prime numbers space separated, such that the smaller number appears first. Answer for each test case must be in a new line.
Constraints: 1 ≤ T ≤ 70
2 < N ≤ 10000
Example:
Input:
5, 74, 1024, 66, 8, 9990
Output: 3 71, 3 1021, 5 61, 3 5, 17 9973
Here is what I tried:
import math
def prime(n):
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
T = int(input("No of inputs: ")) #T is the no of test cases
input_num = []
for i in range(0,T):
input_num.append(input())
lst2= []
if T in range(1,71):
for i in input_num:
if (i in range(3,1000)) and (i % 2 == 0):
for j in range(0,i):
if prime(j) == True:
lst2.append(j)
for x in lst2:
for y in lst2:
if x + y == j:
print(x,end = ' ')
print(y)
This is only taking inputs but not returning outputs.
Also my code is currently intended for all the combinations but what I want is only the first pair and I am not able to do that
I found a more elegant solution to this problem here. Java, C, C++ etc versions of solution is also present there. I am going to give the python3 solution.
# Python 3 program to find a prime number
# pair whose sum is equal to given number
# Python 3 program to print super primes
# less than or equal to n.
# Generate all prime numbers less than n.
def SieveOfEratosthenes(n, isPrime):
# Initialize all entries of boolean
# array as True. A value in isPrime[i]
# will finally be False if i is Not a
# prime, else True bool isPrime[n+1]
isPrime[0] = isPrime[1] = False
for i in range(2, n+1):
isPrime[i] = True
p = 2
while(p*p <= n):
# If isPrime[p] is not changed,
# then it is a prime
if (isPrime[p] == True):
# Update all multiples of p
i = p*p
while(i <= n):
isPrime[i] = False
i += p
p += 1
# Prints a prime pair with given sum
def findPrimePair(n):
# Generating primes using Sieve
isPrime = [0] * (n+1)
SieveOfEratosthenes(n, isPrime)
# Traversing all numbers to find
# first pair
for i in range(0, n):
if (isPrime[i] and isPrime[n - i]):
print(i,(n - i))
return
# Driven program
n = 74
findPrimePair(n)

How to find number in list which has the biggest number of prime?

I want to write a program that receives 10 entries and at the end it should print the number that has the greatest number of prime factors along with the number of its prime factors in the output. And, if some of the inputs have the same condition, the program will print the biggest one.
The code that I wrote executed all conditions except the final condition.
How should I write a code for a case where two numbers have the same numbers of prime factors (when I want the bigger number to be my output)?
For example both 678 and 84 have 3 prime factors . The output of my code is 84, while I want the output to be 678 (the bigger number).
input:
123
43
54
12
76
84
98
678
543
231
Correct output:
678 3
but my output:
84 3
a = [0,0,0,0,0,0,0,0,0,0]
#a = [123,43,54,12,76,84,98,678,543,231]
b = [0,0,0,0,0,0,0,0,0,0]
def is_first (number):
Prime_number= 0
for m in range(1, (number //2)+1, 1):
if number % m == 0:
Prime_number += 1
if Prime_number > 1:
is_prime = 0
else:
is_prime = 1
return is_prime
for i in range(0,10,1):
a[i] = input()
for j in a:
numbers= 0
for k in range(2, int(j)//2, 1):
if int(j) % k == 0:
if is_first (k) == 1:
numbers += 1
b[a.index(j)] = numbers
index_of_same = [i for i, e in enumerate(b) if e == max(b)]
n = []
for t in index_of_same:
n.append(a[t])
print(str(max(n))+ ' ' + str(max(b)))
When you append the numbers that have the highest number of prime factors to the list n, you are storing them as strings and not integers. Hence when you do the max() function on n, which holds 84,678 and 231, 84 is returned. I would suggest you to convert the numbers using int(), when storing into n and then perform the max()function on it. Just tweak your code as under:
for t in index_of_same:
n.append(int(a[t]))
Your code is cumbersome IMO, so I'd like to suggest a simpler version:
def getNumOfFactors(n):
num = 0
factor = 1
while n > 1:
factor += 1
if n % factor == 0:
num += 1
n /= factor
while n % factor == 0:
n /= factor
return num
def getMaxValue(values):
factors = [getNumOfFactors(n) for n in values]
tuples = zip(factors,values)
sorted_tuples = sorted([tuple for tuple in tuples],key=lambda x: x[0])
max_tuples = [tuple for tuple in sorted_tuples if tuple[0] == sorted_tuples[-1][0]]
sorted_max_tuples = sorted([tuple for tuple in max_tuples],key=lambda x: x[1])
return sorted_max_tuples[-1]
maxValue = getMaxValue([123,43,54,12,76,84,98,678,543,231])
print(maxValue)

Printing on the same line different Permuations of a value

Hey guys so here is my question. I have written code that sums two prime numbers and prints the values less than or equal to 100 and even. How do I write it so that every combination of the number prints on the same line
like so
100 = 3 + 97 = 11 + 89
def isPrime(n):
limit = int(n ** 0.5) +1
for divisor in range (2, limit):
if (n % divisor == 0):
return False
return True
def main():
a = 0
b = 0
for n in range (4, 101):
if (n % 2 == 0):
for a in range (1, n + 1):
if isPrime(a):
for b in range (1, n + 1):
if isPrime(b):
if n == (a + b):
print ( n, "=", a, "+", b)
main()
any ideas?
I don't know too much about strings yet, but I was thinking we could set the string as n == a + b and some how repeat on the same line where n == n print the a + b statement or idk haha
One way to do this is to accumulate a and b pairs in some collection, then print a line containing all the pairs. Here's an example with some comments explaining whats going on and general Python tips:
def main():
for n in range (4, 101, 2): # range() can have third argument -> step
accumulator = []
for a in filter(isPrime, range(1, n + 1)): # filter() is useful if you want to skip some values
for b in filter(isPrime, range (1, n + 1)):
if n == (a + b):
accumulator.append((a,b)) # We accumulate instead of printing
str_accumulator = ["{} + {}".format(i[0], i[1]) for i in accumulator]
joined_accumulator = " = ".join(str_accumulator)
print("{} = {}".format(n, joined_accumulator))
Now, some explanation:
range(4, 101, 2) - as said in comment, it has an optional third argument. Some examples and explanations on how to use range in documentation.
filter() - Very useful generic iterator constructor. You pass a function that returns True/False, a collection, and you receive an iterator that spits out only those elements from the collection that are accepted by the function. See documentation.
str.format - For me, format is the best way to paste values into strings. It has PLENTY options and is very versatile. You should read the whole documentation here.
str.join - When you have a collection of string, and you want to make one string of them, join is what you want. It's much faster than str + str operation, and also you don't have to care if there is one or many elements in the collection. See documentation.

Resources