Wrong Answer to SPOJ PRIME1 in Python - python

I've tried to compare my result to Wolfram Alpha's result by counting primes found.
It seems works well, without error.
But when I submit this solution to SPOJ, it shows the error message "wrong answer".
I also tried to change the final print's end= to '' (blank string), but still got "wrong answer".
Not sure if is there something wrong with my sieve algorithm, or output error.
**edit: link of problem http://www.spoj.pl/problems/PRIME1/
Here is my PRIME1 source code, hope someone can point out my fault. Thanks a lot.
And hope someone can teach me how to write a test to programs like this, I'm still learning, don't know how to do automated tests to programs, but want to learn.
def getPrimeInRange(minNum, maxNum):
#just a variation with skipping step of the Sieve of E's
processingRange = list(range(minNum, maxNum+1))
#prefix, due to 1 is not a prime
if minNum == 1:
processingRange[0] = 0
sqrtOfMaxNum = int(maxNum ** 0.5) + 1
primesUnderSqrt = list(range(sqrtOfMaxNum))
#prefix, due to 1 is not a prime
primesUnderSqrt[1] = 0
#my strategy is flip all numbers that is not a prime to zero, which equals to False.
#for Sieve of E's, all the primes under sqrt of max num are the only needed numbers to sieve primes out.
#so here is a smaller Sieve of E's for numbers under sqrt
for n in primesUnderSqrt:
if n: #which equals to "if n != 0"
nowIndex = n + n
while True:
try:
primesUnderSqrt[nowIndex] = 0
nowIndex += n
except IndexError:
break
#full aspect sieve
for n in primesUnderSqrt:
if n:
#for easier flip processing, I need the offset number for the flipping.
nMultipleMostCloseToMin = n * (minNum // n)
if nMultipleMostCloseToMin == minNum:
nowIndex = 0
elif sqrtOfMaxNum <= minNum:
nowIndex = nMultipleMostCloseToMin + n - minNum
elif sqrtOfMaxNum > minNum:
nowIndex = nMultipleMostCloseToMin + n - minNum + n
#happy flippin'
while True:
try:
processingRange[nowIndex] = 0
nowIndex += n
except IndexError:
break
return processingRange
def main():
todoTimes = int(input())
todoNums = list(range(todoTimes))
stringOutput = ''
for i in range(todoTimes):
todoNums[i] = input().split()
todoNums[i][0] = int(todoNums[i][0])
todoNums[i][1] = int(todoNums[i][1])
for [minNum, maxNum] in todoNums:
#countedNum = 0 #for algo debugging
for n in getPrimeInRange(minNum, maxNum):
if n:
stringOutput += str(n)
#countedNum += 1 #for algo debugging
stringOutput += '\n'
stringOutput += '\n'
#stringOutput += str(countedNum) #for algo debugging
stringOutput = stringOutput.rstrip('\n')
print(stringOutput)
ifMainSucceed = main()

This part of your logic
if nMultipleMostCloseToMin == minNum:
nowIndex = 0
elif sqrtOfMaxNum <= minNum:
nowIndex = nMultipleMostCloseToMin + n - minNum
elif sqrtOfMaxNum > minNum:
nowIndex = nMultipleMostCloseToMin + n - minNum + n
is wrong. Your elif-conditions don't make much sense here. If n is not a divisor of minNum, the smallest multiple of n not less than minNum is nMultipleMostCloseToMin + n, regardless of whether sqrtOfMaxNum is larger than minNum or not. The condition you intended here was n <= minNum, to avoid crossing off the prime itself.

Related

Can't get out of While loop(Python 3.9)

I'm a new at programming, I like solving this euler questions and I know there are solutions for this problem but it's not about the problem at all actually.
So, i managed to create a working function for finding example: 33. triangular number. It works but i couldn't manage to properly desing my while loop. I wanted to make it like, it starts from first triangular checks it's divisors make list of it's divisors, checks the length of the divisors, because problem wants "What is the value of the first triangle number to have over five hundred divisors?" . But i never managed to work the while loop. Thank you for reading.
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n!=0:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if x == len(triangles):
n = 0
return triangles[-1]
counter = 1
while True:
for i in range(1, triangularcreator(counter) + 1):
if triangularcreator(counter) % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangularcreator(counter))
break
counter +=1
divisors.clear()
You should try to change a few things, starting with calculating just once the value of triangularcreator(counter) and assigning this value to a variable that you can use in different points of your code.
Second, you create a loop which will be calculate always triangularcreator(1). At the end of each iteration you increase the value of counter+=1, but then at the beginign of the new iteration you assignt it again value 1, so it will not progress as you expect. Try this few things:
counter = 1
while True:
triangle = triangularcreator(counter)
for i in range(1, triangle + 1):
if triangle % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangle )
break
counter +=1
Also these two arrays nums = [1], triangles = [1] should be declared and initialized inside the def triangularcreator. Otherwise you would be appending elements in each iteration
Edit: I believe it is better to give you my own answer to the problem, since you are doing some expensive operations which will make code to run for a long time. Try this solution:
import numpy as np
factor_num = 0
n = 0
def factors(n):
cnt = 0
# You dont need to iterate through all the numbers from 1 to n
# Just to the sqrt, and multiply by two.
for i in range(1,int(np.sqrt(n)+1)):
if n % i == 0:
cnt += 1
# If n is perfect square, it will exist a middle number
if (np.sqrt(n)).is_integer():
return (cnt*2)-1
else:
return (cnt*2)-1
while factor_num < 500:
# Here you generate the triangle, by summing all elements from 1 to n
triangle = sum(list(range(n)))
# Here you calculate the number of factors of the triangle
factor_num = factors(triangle)
n += 1
print(triangle)
Turns out that both of your while loop are infinite either in triangularcreatorin the other while loop:
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if len(triangles) >= x:
return triangles[-1]
return triangles[-1]
counter = 1
while True:
check = triangularcreator(counter)
for i in range(1, check + 1):
if check % i == 0:
divisors.append(i)
if len(divisors) >= 500:
tr = triangularcreator(counter)
print(tr)
break
counter +=1
Solution
Disclaimer: This is not my solution but is #TamoghnaChowdhury, as it seems the most clean one in the web. I wanted to solve it my self but really run out of time today!
import math
def count_factors(num):
# One and itself are included now
count = 2
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
count += 2
return count
def triangle_number(num):
return (num * (num + 1) // 2)
def divisors_of_triangle_number(num):
if num % 2 == 0:
return count_factors(num // 2) * count_factors(num + 1)
else:
return count_factors((num + 1) // 2) * count_factors(num)
def factors_greater_than_triangular_number(n):
x = n
while divisors_of_triangle_number(x) <= n:
x += 1
return triangle_number(x)
print('The answer is', factors_greater_than_triangular_number(500))

Function doesn't return anything after giving a big number as an argument

I'm learning Python by doing Project Euler questions and am stuck on Problem #3.
I think I've found a solution that works, but when inserting the large number 600851475143 it just doesn't return anything. I believe that it just loads and loads cause even with 6008514 it takes 10 secs to return the answer.
# What is the largest prime factor of the number x?
import math
def isPrime(x):
try:
sqr = math.sqrt(x)
if x == 0 or x == 1:
return 0
for n in range (2 , int(sqr)+1):
if x % n == 0:
return 0
return 1
except:
return 'Give positive numbers.'
def largestPrimeFactor(x):
if isPrime(x) == 1:
return 'This number is prime.'
else:
largest = -1
mid = x/2
for n in range(2,int(mid)+1):
if isPrime(n):
if x % n == 0:
largest = n
if largest == -1:
return 'Enter numbers above 1.'
else:
return largest
print(largestPrimeFactor(600851475143))
This code should work:
import math
def isPrime(x):
try:
sqr = math.sqrt(x)
if x == 0 or x == 1:
return 0
n = 2
highest = x
while n < highest:
if x%n ==0:
return 0
highest = x/ n
n +=1
return 1
except:
return 'Give positive numbers.'
def largestPrimeFactor(x):
if isPrime(x) == 1:
return 'This number is prime.'
n = 2
highest = x
largest = 1
while n < highest:
if x%n == 0:
if isPrime(n):
largest = n
highest = x/n
n +=1
return largest
print(largestPrimeFactor(600851475143))
I made an optimization:
you check if every number is a factor of x while if for example 2 is not a factor of x for sure the maximum factor of x can be x/2. Hence if n is not a factor of x the maximum possible factor of x can just be x/n.
The code for large numbers just takes really long time, as pointed out by comments. I report other bugs.
Bug 1. Inappropriate use of try/except clause. It is recommended that try contains a single command and except catches the error. PEP8 also recommends specifying the type of error. Moreover, for your function, the error is never raised.
Bug 2. Redundancy. If x is not prime, you call isPrime for each value (let's call it i) from 2 to x/2. isPrime cycles for each number from 2 to sqrt(i). Therefore, isPrime(i) takes O(sqrt(i)) time, and we call it for i from 2 to x/2. Roughly, its running time is about O(x^(3/2)). Even if don't know a more optimal approach, this approach asks for memoization.
i have another way:
def Largest_Prime_Factor(n):
prime_factor = 1
i = 2
while i <= n / i:
if n % i == 0:
prime_factor = i
n /= i
else:
i += 1
if prime_factor < n:
prime_factor = n
return prime_factor
it faster than previous
try it:
import math
def maxPrimeFactors (n):
maxPrime = -1
while n % 2 == 0:
maxPrime = 2
n >>= 1
for i in range(3, int(math.sqrt(n)) + 1, 2):
while n % i == 0:
maxPrime = i
n = n / i
if n > 2:
maxPrime = n
return int(maxPrime)
n = 600851475143
print(maxPrimeFactors(n))

Prime numbers using sieve of erathosthenes

So I am new to programming in python(and in general) and was doing some coding challenges. I came across this 'prime numbers using the sieve method' challenge. I have successfully managed to attempt it however I feel like my logic needs improvement.
So what I did was use 3 while loops in python, the code works as intended, gives me a set of prime numbers however I cannot find a way to condense it.
import sys
n = int(sys.argv[1])
ls = []
i = 2
while i <= n:
ls.append(i)
i += 1
i = 0
while i < len(ls):
if i == 0:
pass
else:
ls[i] = ''
i += 2
i = 1
while i < len(ls):
if i == 1:
pass
else:
ls[i] = ''
i += 3
i = 0
while i < len(ls):
if i == 0:
pass
else:
ls[i] = ''
i += 5
i = 0
primes = []
while i < len(ls):
if ls[i] != '':
primes.append(ls[i])
i += 1
for prime in primes:
print(prime,end=', ')
As the ceo of nvidia once said, 'it just works' but clearly not in the best way :D
Your code thinks 49 is prime, which is not awesome. Making a while loop for each prime just doesn't work.
Here's a simple version that does:
import math
def primesLessThan(N):
seive = [True] * N
seive[0] = seive[1] = False
for i in range(2,int(math.sqrt(N))+1):
if (seive[i]): # i is prime
for j in range(2*i,N,i): # all multiples of i >= 2i
seive[j] = False # j is composite since i is a factor
return [p for p in range(2,N) if seive[p]]
print(primesLessThan(500))

Python algorithms nth prime number

Question:
Given the prime number n, output the number of prime numbers
My code:
def kthPrime(self, n):
if n>10 and n%10 not in [1,3,7,9]:
return 0
if n == 2:
return 1
queue = []
num = 2
while num <= n:
if n%num == 0 and num != n:
return 0
if num>10 and num%10 not in [1,3,7,9]:
num += 1
continue
for i in range(2,num/2+1):
if num%i == 0:
num += 1
break
else:
queue.append(num)
num += 1
seq = queue.index(n) + 1
return seq
Error:
Your code ran too much time than we expected. Check your time complexity. Time limit exceeded usually caused by infinite loop if your time complexity is the best.
My Question: how to improve it
as user #Prune said , please read the guide first.
I'm not going to tell you how to improve your function , but I'm just gonna give you a faster way to see whether a number is prime or not and hopefully you will understand how to use the function that I'm gonna give you to improve your own function.
The source code :
class numChecker:
def is_prime(self,n):
if n == 2:
return True
if n % 2 == 0 or n < 2:
return False
self.square_root = int(n ** (1/2))
for divisor in range(3, self.square_root + 1, +2):
if n % divisor == 0:
return False
return True

Python abundant, deficient, or perfect number

def classify(numb):
i=1
j=1
sum=0
for i in range(numb):
for j in range(numb):
if (i*j==numb):
sum=sum+i
sum=sum+j
if sum>numb:
print("The value",numb,"is an abundant number.")
elif sum<numb:
print("The value",numb,"is a deficient number.")
else:
print("The value",numb,"is a perfect number.")
break
return "perfect"
The code takes a number(numb) and classifies it as an abundant, deficient or perfect number. My output is screwy and only works for certain numbers. I assume it's indentation or the break that I am using incorrectly. Help would be greatly appreciated.
I would highly recommend u to create a one function which creates the proper divisor of given N, and after that, the job would be easy.
def get_divs(n):
return [i for i in range(1, n) if n % i == 0]
def classify(num):
divs_sum = sum(get_divs(num))
if divs_sum > num:
print('{} is abundant number'.format(num))
elif divs_sum < num:
print('{} is deficient number'.format(num))
elif divs_sum == num:
print('{} is perfect number'.format(num))
Somewhere you are misinterpreting something. As is you are printing what kind the number is, as many times as the value of the number. I might be missing something but anyway.
The sum of proper divisors can be found naively through using modulo
def classify1(num):
div_sum = sum(x for x in range(1, num) if num % x == 0)
kind = ""
if div_sum < num:
kind = "deficient"
elif div_sum > num:
kind = "abundant"
else:
kind = "perfect"
print("{} is a {} number".format(num, kind))
but for big numbers or maybe numbers this will take a long time. So I welcome you to the divisor function. I just dump it and explain it.
def mark(li: list, x: int):
for i in range(2*x, len(li), x):
li[i] = False
return li
def sieve(lim: int):
li = [True] * lim
li[0] = li[1] = 0
for x in range(2, int(lim ** 0.5) + 1):
if x:
li = mark(li, x)
return [2]+[x for x in range(3, lim, 2) if li[x]]
def factor(num):
divs = list()
for prime in primes:
if prime * prime > num:
if num > 1:
divs += [num]
return divs
while num % prime == 0:
num //= prime
divs += [prime]
else:
return divs
def divisors_sum(num):
"""
Function that implements a geometric series to generate the sum of the
divisors, but it is not the divisor function since removing original
number.
"""
divs = factor(num)
div_sum, s = 1, 0
for div in set(divs):
s = 0
for exponent in range(0, divs.count(div) + 1):
s += div ** exponent
div_sum *= s
else:
return div_sum - num
primes = sieve(limit)
but.. there is not much explaining due, first prime factor the numbers, and use the divisor function to get the proper divisors sum. That is it. However the speed up is ridiculously much fast. This might seem to over kill the problem but it is just that much more cooler and faster.

Categories

Resources