Problem doing multiplication tables with while function - python

I am a new programmer and this is my first question here so excuse me if its pretty easy.
M doing a multiplication table but each time it stops after the 1 and it doesnt increment the number
I am trying to do it with 2 while loops
nb = 1
i = 0
while nb<10 :
while i<=10 :
print(nb * i)
i+=1
nb+=1
with that code I only have the 1 multiplication table then the program stops

Reset variable inside loop. Variable i reaches its max value after the first iteration of inner loop, which we need to set back to 0 for the next iteration to work:
nb = 1
while nb < 10 :
i = 0
while i <= 10 :
print(nb * i)
i += 1
nb += 1
You can do the same using for, which in my opinion is more readable and you don't need to worry about incrementing/resetting variables:
for x in range(1, 10):
for y in range(11):
print(x * y)

Related

Python - Different result from while loop than when in a user defined function

I am trying to create a code that returns a approximation of pi given n iterations that the user will give. The higher n the more accurate.
I created a while loop to do this, and it works fine:
import math
x = 1
k = 0
n = int(input("Enter n:"))
while x <= n:
k=k+(1/x**2) # summation of 1/k**2 for every n times
y=k*6 # multiply k by 6 like in formula
fin = math.sqrt(y) # find sqrt of y like in the formula
x += 1
print(fin)
But now I'm trying to make this into a function. This is what I've come up with:
import math
def pi(n):
x = 1
k = 0
#n = int(input("Enter n:"))
while x <= n:
k=k+(1/x**2) # summation of 1/k**2 for every n times
y=k*6 # multiply k by 6 like in formula
fin = math.sqrt(y) # find sqrt of y like in the formula
x += 1
return fin
g=pi(int(input("Enter n:")))
print(g)
For some reason I get different answers... why is it when I use the function that the answer becomes inaccurate?
You have your return inside the loop, hence the block inside the while is executed only once and the rest of approximations are never calculated, put your return out of your cycle:
while x <= n:
k=k+(1/x**2) # summation of 1/k**2 for every n times
y=k*6 # multiply k by 6 like in formula
fin = math.sqrt(y) # find sqrt of y like in the formula
x += 1
return fin
I tested it, now it returns the same result with both approaches.
Have a good day! :D

How can I improve my spiral index function?

Introduction
I am taking an online Introduction to Computer Science course for which I was given the task to create a function that takes in a coordinate and returns its corresponding "spiral index". I have a working function, but the online learning platform tells me that my code takes too long to execute (I am currently learning about code complexity and Big O notation).
The Problem Statement
All numbers on an infinite grid that extends in all four directions can be identified with a single number in the following manner:
Where 0 corresponds with the coordinate (0, 0), 5 corresponds with the coordinate (-1, 0), and 29 with (3, 2).
Create a function which returns the spiral index of any pair of coordinates that are input by the user.
Examples:
spiral_index(10, 10) returns 380.
spiral_index(10, -10) returns 440.
spiral_index(3, 15) returns 882.
spiral_index(1000, 1000) returns 3998000.
My Approach
def spiral_index(x, y):
if x == 0 and y == 0:
return 0
pos = [1, 0]
num = 1
ring_up = 0
ring_left = 0
ring_down = 0
ring_right = 0
base = 3
while pos != [x, y]:
if ring_up < base - 2:
pos[1] += 1
ring_up += 1
num += 1
elif ring_left < base - 1:
pos[0] -= 1
ring_left += 1
num += 1
elif ring_down < base - 1:
pos[1] -= 1
ring_down += 1
num += 1
elif ring_right < base:
pos[0] += 1
ring_right += 1
num += 1
else:
base = base + 2
ring_up = 0
ring_left = 0
ring_down = 0
ring_right = 0
return num
The above code is able to find the correct index for every coordinate, and (on my laptop) computes spiral_index(1000, 1000) in just over 2 seconds (2.06).
Question
I have seen some solutions people have posted to a similar problem. However, I am wondering what is making my code so slow? To my knowledge, I believe that it is executing the function in linear time (is that right?). How can I improve the speed of my function? Can you post a faster function?
The course told me that a for loop is generally faster than a while loop, and I am guessing that the conditional statements are slowing the function down as well.
Any help on the matter is greatly appreciated!
Thanks in advance.
First of all, your solution takes two coordinates, A and B, and is O(AB), which can be considered quadratic. Second of all, the similar problem involves constructing the entire spiral, which means there is no better solution. You only have to index it, which means there's no reason to traverse the entire spiral. You can simply find which ring of the spiral you're on, then do some math to figure out the number. The center has 1 element, the next ring has 8, the next 16, the next 24, and it always increases by 8 from there. This solution is constant time and can almost instantly calculate spiral_index(1000, 1000).
def spiral_index(x, y):
ax = abs(x)
ay = abs(y)
# find loop number in spiral
loop = max(ax, ay)
# one less than the edge length of the current loop
edgelen = 2 * loop
# the numbers in the inner loops
prev = (edgelen - 1) ** 2
if x == loop and y > -loop:
# right edge
return prev + y - (-loop + 1)
if y == loop:
# top edge
return prev + loop - x + edgelen - 1
if x == -loop:
# left edge
return prev + loop - y + 2 * edgelen - 1
if y == -loop:
# bottom edge
return prev + x + loop + 3 * edgelen - 1
raise Exception("this should never happen")

debug of an function

The "Faculty " function, should return the faculty of the number it receives as a parameter. The faculty of a number n is 1 * 2 * 3 * 4 * ... * n. For example, faculty (5) should be 1 * 2 * 3 * 4 * 5 = 120. The function as it is written now always returns 0, no matter what number it receives as a parameter.
So, how do I fix the problem? (I'm just trying to learn, I'm new)
def faculty(integer):
result = 1
for i in range(integer):
result *= i
return result
The range statement takes a 0 as starting point. Therefore, the result is directly set to 0. You could change it to:
def faculty(integer):
result = 1
for i in range(1, integer+1):
result *= i
return result
The method range(stop) generates the values [0;stop[ so you have the 0 which kill everything, and not stop.
What you need is range(start, stop) with range(1, integer+1) to generates [1;value+1[
def faculty(integer):
result = 1
for i in range(1, integer+1):
result *= i
return result
When debugging, a nice way is in most time to use print to see what values are used to understand the behaviour of the code
Consider what values your loop is looping over.
for i in range(integer):
print(i)

Project Euler/Python: find sum of multiples of 3 and 5. Program not proceeding past input

I'm new to programming and i'm doing the Project Euler challenges to give me a reason to learn.
Find below my very simple python code
x = 1
thirdDivide = 0
fifthDivide=0
total = 0
print('Enter the max value')
maxValue = input()
while (x != maxValue):
thirdDivide = x / 3
fifthDivide = x / 5
if (thirdDivide).is_integer():
total = total + x
x = x + 1
elif (fifthDivide).is_integer():
total = total + x
x = x + 1
print ("The sum of the multiples of 3 and 5 between 0 and " + maxValue + " is " + total)
When I run it it asks for my max value, then ceases doing anything.
Thanks!
Assuming you are in Python 3, the fixes for using strings instead of floats, or floats instead of strings, infite loop is following:
x = 1
thirdDivide = 0
fifthDivide=0
total = 0
maxValue = float(input('Enter the max value: '))
while (x != maxValue):
thirdDivide = x / 3
fifthDivide = x / 5
if (thirdDivide).is_integer():
total = total + x
elif (fifthDivide).is_integer():
total = total + x
x = x + 1
print("The sum of the multiples of 3 and 5 between 0 and " + str(maxValue) + " is " + str(total))
Note, I dont check for correctness of your algoritm and whether it calculates what it is supposed to do. But now it produces some results and compiles.
You can solve it with a functional approach using filter and reduce:
def f(acc, v): return acc + v
def g(x): return x % 3 == 0 or x % 5 == 0
print reduce(f, filter(g, range(1000)))
How it works:
filter: takes two arguments:
The first is a function g applied for every element of range(1000). g takes one argument x and check if is multiple of 3 or 5 (checking the remainder of the modulo operation %).
The second is the range from 0 to 1000.
reduce: takes two arguments:
The first is a function f that takes two arguments: an accumulator acc and a variable v that represents the current element in the list.
The second argument is the filtered range returned before by filter.
Output:
with range(10) = 23
with range(1000) = 233168
Using lambda functions (same logic just different syntax):
print reduce(lambda acc, v: acc + v, filter(lambda x: x % 3 == 0 or x % 5 == 0, range(1000)))
You only increment x if thirdDivide.is_integer() or fifthDivide.is_integer() are true. So if neither it true, you'll just loop infinitely on the same value of x.
If neither thirdDivide nor fifthDivide is an integer, x is never updated -- you enter an infinite loop. You need to make sure you have a "base case" so that the iteration variable is always changing. Here's a slightly cleaner algorithm:
total = 0
for i in range(0, x):
if i % 3 == 0 or i % 5 == 0:
total += i
I think you'll find that for most iteration, for loops are easier to reason about. Happy coding!
As many said before, you are stuck in an infinite loop with x not being incremented. If you added a "else" statement at the end and printed the output you could see what they are talking about. You can do this in one line of code.
print(sum(x for x in range(maxValue) if x % 3 == 0 or x % 5 == 0))

What are the errors inside this random walking code? [duplicate]

This question already has an answer here:
Random walk's weird outcome in python 3?
(1 answer)
Closed 6 years ago.
I am having unexpected outputs with the following code:
import random
N = 30 # number of steps
n = random.random() # generate a random number
x = 0
y = 0
z = 0
count = 0
while count <= N:
if n < 1/3:
x = x + 1 # move east
n = random.random() # generate a new random number
if n >= 1/3 and n < 2/3:
y = y + 1 # move north
n = random.random() # generate a new random number
if n >= 2/3:
z = z + 1 # move up
n = random.random() # generate a new random number
print("(%d,%d,%d)" % (x,y,z))
count = count + 1
When I run the code, the problem is:
Code output displays 31 coordinates, 1 more than the number of steps (N) variable.
Each iteration for 1 step should take only 1 step but it sometimes take multiple steps.
When I tested the code, the problem is ensured. To test the code, I assigned N = 1, and saw the following output:
(-1,0,1) This should be the initial step, but it took multiple steps (both x-1 and z+1), how could this happen?
(-2,0,1) Number of step variable (N) = 1 but this is the second output, why was it displayed?
Thanks for helping
N is 30, so count goes from 0 to 30. Since 30 <= 30 you will run the loop for count=0, 1, ..., 29 AND 30 which is 31 times
When you take a step, you don't ensure that another step is NOT taken. If random happens, you could enter the second or third if after already being in a previous one in the same loop iteration
You are dividing two ints which will only result in another int. So basically your code is do the following:
if n < 0:
x = x + 1 # move east
n = random.random() # generate a new random number
if n >= 0 and n < 1:
y = y + 1 # move north
n = random.random() # generate a new random number
if n >= 1:
z = z + 1 # move up
n = random.random()
fix by changing each if line to include a floating point number
if n < 1.0/3

Categories