Gaussian Addition - Python Challenge - python

I am currently working on some beginner python challenges, I just finished a gaussian addition challenge. I was able to get the output that the challenge was looking for, but it seems like I over complicated things.
The challenge is as follows:
Write a program that passes a list of numbers to a function.
The function should use a while loop to keep popping the first and last numbers from the list and calculate the sum of those two numbers.
The function should print out the current numbers that are being added, and print their partial sum.
The function should keep track of how many partial sums there are.
The function should then print out how many partial sums there were.
The function should perform Gauss' multiplication, and report the final answer.
Prove that your function works, by passing in the range 1-100, and verifying that you get 5050.
gauss_addition(list(range(1,101)))
Your function should work for any set of consecutive numbers, as long as that set has an even length.
Bonus: Modify your function so that it works for any set of consecutive numbers, whether that set has an even or odd length.
My function is as follows:
def gauss(numbers):
for number in numbers:
while len(numbers) > 0:
num1 = numbers.pop(0)
print(num1)
num2 = numbers.pop(-1)
print(num2)
calc = num1 + num2
print(str(num1) + " + " + str(num2) + " = " + str(calc))
print("Final answer is: " + str(num1 * calc))
gauss(list(range(1,101)))
Can someone explain how I can simplify this function without the use of python modules? I understand how the function that I wrote is working, but I also want to know if there is an easier, "more condensed" way of achieving this.
I should specify that I only know the basics of python...

Using list to approach this problem seems to be too expensive, for the reason of repeatedly pop will be costly as cited in early notes.
So instead of it, you can consider using collections module deque which will allow you to do the operations (pop) in both end efficiently.
Note - it will work well if the list is even-sized, but that's part of requirements already.
So the solution will be like this:
#
from collections import deque
dq = deque(range(1, 101)) # create a list (dq list)
total = 0
count = 0
while dq:
x, y = dq.popleft(), dq.pop()
print(x, y, x+y, end='\t')
count += 1 # how many partial sum?
print(count)
total += (x+y)
print(f' final total: {total} ')
Outputs: (partial - it's too long)
1 100 101 1
2 99 101 2
3 98 101 3
4 97 101 4
5 96 101 5
...........
...........
48 53 101 48
49 52 101 49
50 51 101 50
final total: 5050

Related

I tried to solve this about factorials but it's not giving the right answer

this is the question:
Write a python code to find all the integers less than 50,000 that equal to
the sum of factorials of their digits. As an example: the number 7666 6=
7! + 6! + 6! + 6! but 145=1!+4!+5!
note: im not allowed to use any specific factorial function.
my solution:
import math
from numpy import *
for i in range(5):
for j in range(10):
for k in range(10):
for l in range(10):
for m in range(10):
x=1*m+10*l+100*k+1000*j+10000*i
def fact(m):
fact=1
for i in range(1,m+1):
fact=fact*i
return fact
y=fact(i)+fact(j)+fact(k)+fact(l)+fact(m)
if x==y :
print(x)
Hint 1
The reason this does not give you a correct answer is because there will be times where your code considers 0 to be a digit.
For example
fact(0)+fact(0)+fact(1)+fact(4)+fact(5) gives 147
because fact(0) is 1.
Hint 2
While your manner of iterating is interesting and somewhat correct, it is the source of your bug.
Try iterating normally from 1 to 50000 then figure out the sum of the digits a different way.
for i in range(50000):
# ...
Solution
Since this is StackOverflow, I offer a solution straightaway.
Use a function like this to find the sum of digits of a number:
def fact(m):
fact=1
for i in range(1,m+1):
fact=fact*i
return fact
def sumOfFactOfDigits(x):
# This function only works on integers
assert type(x) == int
total = 0
# Repeat until x is 0
while x:
# Add last digit to total
total += fact(x%10)
# Remove last digit (always ends at 0, ie 123 -> 12 -> 1 -> 0)
x //= 10
return total
for i in range(50000):
if i == sumOfFactOfDigits(i):
print(i)
Note
You should move your definition of fact outside of the loop.

What's the problem with my Python script?

I'm trying to use Python to solve my maths homework (you have a two digit number ab, and ab+ba=88) and my program doesn't work.
a=10
b=10
for i in range(100):
a+=1
for i in range(100):
b+=1
if int(str(a+b))+int(str(b+a))==88:
print((str(a+b))+"+"+str(b+a))
It gives the output of 44. This isn't the good answer, because a and b have to be different numbers, but I didn't code that restriction yet. More important, the code should find 26;62 and other solutions. How can I find all the solutions?
I know the answers, but I want to solve it in this way too.
If I understand correctly, you have a two digit number ab such that ab + ba = 88
Ex) For "ab" = 26 --> 26 + 62 = 88.
If that is the case, this is the solution I propose the solution:
for a in range(10): # Iterate over ten's place values [0 to 9]
for b in range(10): # Iterate over one's place values [0 to 9]
ab = str(a)+str(b) # Construct the string "ab"
if (int(ab) + int(ab[::-1]) == 88): # Test if ab + ba = 88
print(ab + " + " + ab[::-1]) # Print the successful value of ab
The logic is that you construct a string ab by combining the possible values of 0 to 10 in each of the ten's and one's place of the two digit number. Then, test if the integer value of ab and its reverse, ba, are equal to 88.
OUTPUT:
08 + 80
17 + 71
26 + 62
35 + 53
44 + 44
53 + 35
62 + 26
71 + 17
80 + 08
NOTE: This method uses a string from the get go in order to avoid the many calls to int(str()).
NOTE: In Python, the operator [::-1] returns the reverse of the string. Just a convenient trick!
You have a couple of logic problems here. The first is your loop control. You start with
a=10
for i in range(100):
a+=1
This will run a over the range 10 to 10+100. Now, for each value of a, you do:
b=10
...
for i in range(100):
b+=1
First of all, you've changed the value of i, which the outer loop is still trying to use. This is the first problem, the one that's killing your current program. Second, if you fix this by changing the loop index to j (for instance), then you will increment b 100*100 times, so it ends up at 10010.
On top of this, a and b are never individual digits! You've started each as a 2-digit number.
Instead, make two changes:
Put the values you actually want into the for loop.
Use strings, not integers, if that's what you're trying to do.
for a in "0123456789":
for b in "0123456789":
if int(a+b) + int(b+a) == 88:
This code makes 2-digit strings. Another way is to work with the single-digit integers, but then use algebra to make the 2-digit numbers:
if (10*a + b) + (10*b + a) == 88:
Finally, you can simplify the entire process by doing basic algebra on the above expression:
(10*a + b) + (10*b + a) == 88
11*a + 11*b == 88
a + b = 8
From here, you note simply that b = 8-a, and you can reduce your program to a single loop.
Let's walk through what your code does.
First you assign both a and b to be 10
a=10
b=10
Then you start a loop that will run 100 times, each time it runs it will increment a by one
for i in range(100):
a+=1
Then you start a nested loop which will run 100 times each time the outer loop runs once and increments b on each loop. It is important to note that because you have defined b outside of the scope of this loop, it will keep growing. The second time the outer loop runs, b is going to start at 110
What you need to know here is that python is a weakly typed language. Variables take on the same type as the data assigned to them. a and b are integers, so you can already perform mathematical operations on them. Also, there's no reason to typecast the same variable twice in one spot. you should write the if statement like this:
if a + b + b +a == 88:
You can see more easily now that all it is checking is if (a + b) * 2 is equal to 80
Finally you output your answer but, do to the commutative property of addition, you're always going to show the same sum + itself
print((str(a+b))+"+"+str(b+a))
What I would recommend doing here, besides cleaning up your if statement, is resetting b each time the outer loop runs. I'm also unclear why you've instantiated your variable to equal 10 but that's your business.
Try this:
a=10
for i in range(100):
b=10
a+=1
for i in range(100):
b+=1
if a+b == 88:
print((str(a))+"+"+str(b))
Use this code to understand:
a=10
b=10
for i in range(100):
a+=1
for i in range(100):
b+=1
if int(str(a+b))+int(str(b+a))==88:
print(a)
print(b)
print((str(a+b))+"+"+str(b+a))
break;
Output:
11
33
44+44
So:
A = 11
B = 33

Make change for n dollars with m coins

I'm trying to implement a solution to the following problem:
Given a number of dollars, n, and a list of dollar values for m
distinct coins, find and print the number of different ways you can
make change for n dollars if each coin is available in an infinite
quantity.
The complete problem statement is here
Before presenting my solution, I should say that I know dynamic programming is probably the optimal way to solve this problem. The solution I've come up with does not use dynamic programming, and I know it is far from the most efficient solution out there. However, as far as I can tell it is correct.
The problem is that my solution underestimates the number of ways to make change. For example given n = 75 and {25 10 11 29 49 31 33 39 12 36 40 22 21 16 37 8 18 4 27 17 26 32 6 38 2 30 34} as coin values, the solution returns 182 when it should return 16694. It seems to work for smaller test cases, though.
def make_change(coins, n):
solns = 0
num_coins = len(coins)
for i in range(num_coins):
solns = solns + make_change_rec(coins, n-coins[0], coins[0])
# We've found all solutions involving coin. Remove it
# from consideration
coins.pop(0)
return solns
def make_change_rec(coins, n, parent):
# If n == 0 we've found a solution
if n == 0:
return 1
solns = 0
# For each coin
for coin in coins:
# If coin > n, can't make change using coin
if coin > n or coin < parent: # coin < parent rule ensures we don't count same solution twice
continue
# Use the coin to make change
solns = solns + make_change_rec(coins, n-coin, coin)
return solns
Can someone help me understand what I'm doing wrong? I'm using Python 3.
I think the only change you need to do is to sort the coins array. Now your recursion its going to run out of time for sure. So I recommend you to go with classic dynamic programming.
def make_change(coins, n):
dp = [1] + [0] * n
for coin in coins:
for i in range(coin, n + 1):
dp[i] += dp[i - coin]
return dp[n]
You need to sort your coins before you input them. If your recursion runs slow for larger values (which it will) you can add memoization like this:
from functools import lru_cache
#leave your function as it is, but add this:
#lru_cache(maxsize=None)
def make_change_rec(coins, n, parent):

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