Multiples of 3 and 5 | Appending multiples to lists - python

I'v been studying Python for less than a month and am currently working on Project Euler.
So ironically I'm stuck on the first question. Check out my app road below and I would love some input as to where I have messed up. Or using the wrong logic.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
My Logic/Code Flow
sum = multiple_three + multiple_five
multiple_three = []
multiple_five = []
def multiple_three(bignumber):
for number in range(bignumber):
if number % 3 == 0:
multiple_three.append(number)
def multiple_five(bignumber):
for number in range(bignumber):
if number % 5 == 0:
multiple_five.append(number)
bignumber = 1000
multiple_five(bignumber)
multiple_three(bignumber)
print multiple_three
print multiple_five

Let's see.
We can start by using the fact that range has a step argument. So something like range(0,10,3) would get you 0,3,6,9.
So, for starters, we have
sum(range(0,1000,3)) + sum(range(0,1000,5))
But wait! Numbers divisible by 15 are divisible by both 5 and 3! We're counting them twice! Uh, uh, let's subtract them out
sum(range(0,1000,3)) + sum(range(0,1000,5)) - sum(range(0,1000,15))
Hum. I think we're still missing something here. Is there an easier way to add together an arithmetic progression? Could have sworn that there was...
something like (a_0 + a_n)*n/2, where n is the number of terms, maybe...
def sum_of_arithmetic_progression(start,stop,step):
n = (stop-start)//step #floor division :P
end = start + step*n
return (start + end)*n/2.0
sum_of_arithmetic_progression(0,1000,3)+sum_of_arithmetic_progression(0,1000,5)-sum_of_arithmetic_progression(0,1000,15)

This is what worked for me. Let me know if it worked for you too.
def multiples_of_3_or_5():
for number in xrange(1000):
if not number % 3 or not number % 5:
yield number
print sum(multiples_of_3_or_5())

You are not printing sum. But apart from that, you are counting numbers like 15 twice, i.e as a multiple of 3 as well as 5.
A quick solution would be to
print(sum(set(multiple_three+multiple_five)))
Here multiple_three+multiple_five gives a concatenated list. set identifies the unique elements, and sum will output the sum. Better would be to use "or"operator and append the numbers in a single loop as #Destry Amiott has suggested.

Related

Euler Project problem #12 Python code gives weird results

I was trying to solve problem number 12 of Project Euler. This is the problem:
The sequence of triangle numbers is generated by adding the natural
numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7
= 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five
divisors.
What is the value of the first triangle number to have over five
hundred divisors?
I defined two functions to do the job:
1) allfactor(x): This gives us all the factors of a given number in a list form. Example: allfactor(10) gives us [1, 2, 5, 10]
2)TriangularNo(x): This gives us the nth Triangular number. Example TriangularNo(5) gives us 5
Here is the complete code which I wrote:
facs=[]
def allfacof(x):
for i in range(1,int(x/2)+1):
if x%i==0:
facs.append(i)
else:
pass
facs.append(x)
return(facs)
def TriangularNo(x):
no=0
for i in range(1,x+1):
no=no+i
return(no)
a=0 # a will tell us the number of iterations
while True:
a+=1
N=TriangularNo(a)
length=(len(allfacof(N)))
if int(length)>=500:
print(N)
break
else:
pass
When I run this code I get 1378 as the output which is clearly wrong because len(allfacof(1378)) turns out to be 8 and not 500 as demanded in the question.
Notice in the while loop, I use if int(length)>=500: So this means that when my code runs, length somehow gets the value = 500 but when I run the function separately it says that it's length is 8.
I am just not able to find out the error. Please help me
The problem is you are using facs as a global variable and you are only appending to the item. You should make it a member of allfacof() so that it clears out after each value.
If you look into facs then you will find it equals
1, 1, 3, 1, 2, 3, 6, 1, 2, 5, 10 ...
Although moving facs into all_factors_of() solves your immediate problem, the next problem with this code is performance. Let's consider triangle number generation first. The optimization that #Voo suggests:
def TriangularNo(n):
return n * (n + 1) / 2
is fine if we're looking for arbitrary triangle numbers -- but we're not. We're looking for sequential triangle numbers, so in this case the formula slows down our code! When going sequentially, you only need do a couple of additions to get the next triangle number -- but using the formula, you need to do an addition, a multiplication and a division! More expensive if you're going sequentially. Since we are going sequentially, this seems a perfect use of a Python generator:
def triangular_number_generator():
triangle = number = 1
while True:
yield triangle
number += 1
triangle += number
Which makes clear the two additions needed to get to the next triangle number. Now let's consider your factorization function:
Your factorization function loses performance in the way that it produces factors in order. But we're only concerned with the number of factors, order doesn't matter. So when we factor 28, we can add 1 and 28 to the factors list at the same time. Ditto 2 and 14 -- making 14 our new upper limit. Similarly 4 and 7 where 7 becomes the new upper limit. So we collect factors faster and quickly reduce the upper limit that we need to check. Here's the rest of the code:
def factors_of(number):
divisor = 1
limit = number
factors = []
while divisor <= limit:
if number % divisor == 0:
factors.append(divisor)
remainder = number // divisor
if remainder != divisor:
factors.append(remainder)
limit = remainder - 1
divisor += 1
return factors
triangular = triangular_number_generator()
number = next(triangular)
factors = factors_of(number)
while len(factors) <= 200:
number = next(triangular)
factors = factors_of(number)
print(number)
How does it compare? If we run your fixed code with a lower limit of > 200 factors, it takes about a minute to come up with the answer (2031120). The above code takes about 1/3 of a second. Now consider how long it'll take both to reach > 500 factors. Finally, to meet the stated goal:
What is the value of the first triangle number to have over five
hundred divisors?
this comparison in your original code:
if int(length)>=500:
would instead need to be:
if length > 500:
Though the way the count of factors jumps, it makes no difference for 500. But for smaller limits, for testing, it can make a difference.

python - print the sum of items in list whose total is the largest and is odd

It's a simple problem I have been trying to solve. First of all I take input with a list of positive integers. I want to choose items from them in such a way that their total is maximum possible and their sum is odd. If no combination is possible I want to print -1. I have written the code and it is not working properly.
l = sorted(list(map(int, input().split())))
if sum(l)%2 == 1:
print(sum(l))
else:
m = 0
for x in range(len(l)):
a = l
a.pop(x)
if sum(a)%2 == 1 and sum(a) > m:
m = sum(a)
For example, for the input 2 3 4 5, it's printing 9 where it should print 11.
Any help would be appreciated.
So, from the list of numbers, you want to get the largest possible sum which is odd. This is actually rather simple and can be solved pretty easily. What you need to do is take the sum of all numbers as that is the maximum sum that you could possibly get from those numbers. Now, we have two options:
The sum is odd: In that case, we’re already done. The largest possible sum is also odd, so we have our result.
The sum is even: In that case, we have the largest possible sum but we are not odd. In order to fix that we need to remove the smallest odd number from the sum. So we look at the sorted list of numbers and pick the first odd number from it. By removing an odd number from an even sum, we get an odd number again, and since we picked the smallest possible number, we know our new sum is the largest odd sum. So that’s the result.
In code, this could look like this:
def largestOddSum(numbers):
s = sum(numbers)
if s % 2 == 1:
return s
for x in sorted(numbers):
if x % 2 == 1:
return s - x
return -1
Used like this:
>>> largestOddSum([2, 3, 4, 5])
11
In a easy way :
sum all and subtract the minimum odd number if first sum is even :
if sum(l)%2 == 1:
print(sum(l))
else:
print(sum(l) - [i for i in sorted(l) if i%2==1][0])
I think the best way to tackle this is by remembering that:
even + even = even
odd + even = odd
odd + odd = even
With this in mind, you can always include all even numbers. You can also always include all odd numbers, as long as the number of odd numbers is not even. If the number of odds IS even, just leave the smallest out.

Number of multiples less than the max number

For the following problem on SingPath:
Given an input of a list of numbers and a high number,
return the number of multiples of each of
those numbers that are less than the maximum number.
For this case the list will contain a maximum of 3 numbers
that are all relatively prime to each
other.
Here is my code:
def countMultiples(l, max_num):
counting_list = []
for i in l:
for j in range(1, max_num):
if (i * j < max_num) and (i * j) not in counting_list:
counting_list.append(i * j)
return len(counting_list)
Although my algorithm works okay, it gets stuck when the maximum number is way too big
>>> countMultiples([3],30)
9 #WORKS GOOD
>>> countMultiples([3,5],100)
46 #WORKS GOOD
>>> countMultiples([13,25],100250)
Line 5: TimeLimitError: Program exceeded run time limit.
How to optimize this code?
3 and 5 have some same multiples, like 15.
You should remove those multiples, and you will get the right answer
Also you should check the inclusion exclusion principle https://en.wikipedia.org/wiki/Inclusion-exclusion_principle#Counting_integers
EDIT:
The problem can be solved in constant time. As previously linked, the solution is in the inclusion - exclusion principle.
Let say you want to get the number of multiples of 3 less than 100, you can do this by dividing floor(100/3), the same applies for 5, floor(100/5).
Now to get the multiplies of 3 and 5 that are less than 100, you would have to add them, and subtract the ones that are multiples of both. In this case, subtracting multiplies of 15.
So the answer for multiples of 3 and 5, that are less than 100 is floor(100/3) + floor(100/5) - floor(100/15).
If you have more than 2 numbers, it gets a bit more complicated, but the same approach applies, for more check https://en.wikipedia.org/wiki/Inclusion-exclusion_principle#Counting_integers
EDIT2:
Also the loop variant can be speed up.
Your current algorithm appends multiple in a list, which is very slow.
You should switch the inner and outer for loop. By doing that you would check if any of the divisors divide the number, and you get the the divisor.
So just adding a boolean variable which tells you if any of your divisors divide the number, and counting the times the variable is true.
So it would like this:
def countMultiples(l, max_num):
nums = 0
for j in range(1, max_num):
isMultiple = False
for i in l:
if (j % i == 0):
isMultiple = True
if (isMultiple == True):
nums += 1
return nums
print countMultiples([13,25],100250)
If the length of the list is all you need, you'd be better off with a tally instead of creating another list.
def countMultiples(l, max_num):
count = 0
counting_list = []
for i in l:
for j in range(1, max_num):
if (i * j < max_num) and (i * j) not in counting_list:
count += 1
return count

Project Euler: #2 in Python

The problem presented is as follows:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
I have tried a few variations on the code you see below. I am currently getting the number 2,435,424 as the answer from the code I have written, however Project Euler is saying that number is incorrect. I have tried changing looking in to reasons my code is failing, and I'm stumped. Any advice would be appreciated. Code is as follows:
fibonacci = [2]
i = 0
number_1 = 1
number_2 = 2
number_3 = 0
while (number_3 <= 4000000):
number_3 = number_1 + number_2
fibonacci.append(number_3)
if i % 2 != 0:
number_1 = number_3
i += 1
elif i % 2 == 0:
number_2 = number_3
i += 1
total = 0
for numbers in fibonacci:
if numbers % 2 == 0:
total += numbers
print total
Consider the many ways you can write a Fibonacci sequence in Python.
The most 'Pythonic', IMHO, is a generator:
def fib():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
You can modify that with the limit and the test of a % 2:
def Fib_in_even(lim):
a, b = 0, 1
while a < lim:
if not a % 2:
yield a
a, b = b, a + b
Then use sum to add up the modified Fibonacci series to 'the answer':
>>> sum(Fib_in_even(4000000))
the_answer...
For one thing, your loop appends one value too many to your list. Consider what happens if number_3 equals 4 million. Your loop will then compute a new value of number_3, which will exceed 4 million because one of number_1 or number_2 will have just been set equal to number_3, and add it to your list. The same holds true for any number_3 such that number_3 <= 4000000 but number_3 + min(number_1, number_2) > 4000000, I'm just using 4 million as a value that easily demonstrates the error.
I make no comment on the general algorithm - working on that is part of the point of Project Euler. But it's worth considering what you might do if the end value were not 4 million, but something too large to keep all the Fibonacci terms in memory at once.
You're mixing doing the sum that project euler is asking for and the actual calculation of the fibonacci numbers. In the process of mixing this, you mess up both halves.
Let's do it one at a time:
fibonacci = [1, 2]
number_1 = 1
number_2 = 2
number_3 = 3
while (number_3 <= 4000000):
number_1, number_2, number_3 = number_2, number_3, number_1 + number_2
fibonacci.append(number_3)
Now, we have a list of fibonacci numbers. Let's sum the even ones.
total = 0
for numbers in fibonacci:
if numbers % 2 == 0:
total += numbers
Or more simply:
total = sum(x for x in fibonacci if x % 2 == 0)
And you'll absolutely want to apply the advice in Peter DeGlopper's answer.
You replace number_2 on the first iteration. That is not correct.
There is no need to evaluate an extra if in this case! an integer %2 is either 0 or 1, so use else.
On top of that using if/else doesn't make much sense here, you could just do a rotation instead. Try doing it by hand and you'll see.
Project Euler is more about learning to find the solution with good code and shortcuts (4 million was originally a lot and couldn't be acquired through a bad recursion that goes through both branches). So I will not include the exact solution to any Project Euler question here but point you into the right direction instead.
I highly suggest learning about python generators (see dawg's answer), since this is the easiest example to learn and understand them.
Also, it would be best to keep the running total inside your main loop so you don't have to go through them again.
Note regarding Project Euler: Python is not restricted with respect to integers (you can have infinite precision if you want) so some of the questions will not make as much sense. Also, RAM and CPU have increased exponentially; so consider doing this problem with 4 billion instead of 4 million and you will learn much more. That's where a useless elif could be expensive, and looping over something twice even worse because you have to keep track of the whole structure.
Think of it this way: can you solve the problem without keeping more than the bare-necessary variables in memory? That's where generators, xrange, etc come in very handy (python 2.x).
def FibSeries(first,second):
yield first
while True:
first,second = second,first+second
yield first
fib_lt_4mil = itertools.takewhile(lambda n:n<4000000,FibSeries(1,1))
even_fib_lt_4mil = [n for n in fib_lt_4mil if n%2 == 0]
print sum(even_fib_lt4mil)
at least I think
def EvenFibonacciNumbersSum(n):
a = 1
b = 2
temp = 0
sum =0
while(a<=n):
if(a%2 ==0):
sum = sum + a
#print(sum)
temp = a
a = b
b = temp+b
return sum
if __name__ == '__main__':
print(EvenFibonacciNumbersSum(4000000))

Writing a Python program that finds the square of a number without using multiplication or exponents?

thank you for reading and hopefully responding to my question. I'm stuck trying to write this Python program that finds a number's square without using multiplication or exponents. Instead, I have to get the summation of the first odd n numbers starting from 1. This is what I have so far:
def square():
print("This program calculates the square of a given number")
print("WITHOUT using multiplication! ")
odd = 1
n = eval(input("Enter a number: "))
for odd in range(0, n + 1, 2):
odd = odd + 2
final_square = n + odd
print(n, "squared is", final_square, ".")
EDIT: Hi guys, I can't do 4 + 4 + 4 + 4. I have to do 1 + 3 + 5 + 7, and I'm not sure how. It gives me 4 squared is 11 or something.
Just some tips:
Try not to use eval(), it will evaluate any input given and so it can do something you don't want to do. Instead, use int().
Remember that, say 4*4, is just 4 + 4 + 4 + 4. You're on the right track with a for-loop, but now make the loop iterate n times adding n to itself.
new = 0
for _ in range(n):
new += n
Note that this won't work with negative numbers. If you're going to be dealing with those, perhaps get the absolute value of n at the beginning:
def square(n):
n = abs(n)
....
Since you have been told you have to get the answer by producing the first n odd numbers, then you need to think about how to do that - certainly your loop isn't doing that :
several issues :
you do odd =1, and then use odd in your for loop, the two can't co-exist, so the initial value of odd = 1 is overwritten.
Your loop doesn't produce the first n odd numbers that I can see.
My suggest would be to rework your loop : the first 'n' odd numbers are in the form :
1, 3, 5, ... n*2-1
(Counting from 1 not from zero)
so a loop like this :
final = 0
for c in range(1, n+1): #start counting from 1 to do 1 to n+1
odd = c*2 -1 #Use the series above to generate each odd number.
final += odd
should work
a much more 'pythonic' way to do this is :
final = sum(c*2-1 for c in range(1,n))
This uses a generator to create all of the odd numbers (the equivalent of the loop), and sum the values as they get created.
Go back to the original definition of multiplication.
Just add the number n to itself n times. What's so hard? It's inefficient has hell, but it'll work.
I'm sure there's a more Pythonic way:
def square(n):
sum = 0
for i in range(0,n):
sum = sum + n
return sum

Categories