Python multiplication table syntax differences - python

So I'm learning python as a beginner and have been using How to Think Like a Computer Scientist for python 3. I'm on the chapter about iteration, doing the coding from my own brain instead of copy/pasting so I remember it easier.
When doing the last part of the multiplication table section, I got the same output as the lesson showed, but it seems like mine is cleaner (fewer arguments). I'm still trying to get the hang of tracing programs, so I'm having a hard time wrapping my head around the differences. I was hoping someone could let me know if my code is less efficient or more error prone somehow than the text's version and help end this headache ;).
def print_multiples(n, high): #This is the e-book version
for i in range(1, high+1):
print(n * i, end=' ')
print()
def print_mult_table(high):
for i in range(1, high+1):
print_multiples(i, i+1) #They changed high+1 to i+1 to halve output
Source
It seems like their result would have too many +1's, since i+1 would become 'high' in print_multiples and then end up adding +1 again in print_multiples' loop. (I also noticed they kept the end=' ' instead of a end='\t' which threw off alignment.
def print_multiples(n): #n is the number of columns that will be made
'''Prints a line of multiples of factor 'n'.'''
for x in range(1, n+1): #prints n 2n 3n ... until x = n+1
print(n * x, end='\t') #(since x starts counting at 0,
print() #n*n will be the final entry)
def print_mult_table(n): #n is the final factor
'''Makes a table from a factor 'n' via print_multiples().
'''
for i in range(1, n+1): #call function to print rows with i
print_multiples(i) #as the multiplier.
This is mine. The elementary comments were for my benefit trying to keep the tracing straight in my head. My functions make a lot more sense to me, but there could be some difference. I don't really understand why the book decided to make two arguments for print_multiples() since 1 seems sufficient to me...I also changed most of the variables since they were using 'i' and 'high' multiple times to demonstrate local vs global. I re-used n, though, since it would be the same final number in both cases.
There might be more efficient ways to do this type of thing, but I'm still on iteration. Just hoping to try to get a feel for what works and what doesn't and this one is bugging me.

(Note: right, you're running Python 3.x)
Your code is simpler and makes more sense to me, too.
Theirs is correct, but its intention is not quite the same, so its output is different.
Carefully compare the outputs of both and see if you can notice the pattern of difference.
Your code is slightly more "efficient", but printing stuff to the screen takes a (relatively) long time, and your program prints slightly less than theirs.
To measure efficiency, you can "profile" code in Python to see how long things take.
Below is the code I ran to
a) inspect the difference in source text and output
b) profile the code to see which was faster.
You might try running it. Good luck!
import cProfile
def print_multiples0(n, high): #This is the e-book version
for i in range(1, high+1):
print(n * i, end=' ')
print()
def print_mult_table0(high):
for i in range(1, high+1):
print_multiples0(i, i+1) #They changed high+1 to i+1 to halve output
def print_multiples1(n): #n is the number of columns that will be made
'''Prints a line of multiples of factor 'n'.'''
for x in range(1, n+1): #prints n 2n 3n ... until x = n+1
print(n * x, end='\t') #(since x starts counting at 0,
print() #n*n will be the final entry)
def print_mult_table1(n): #n is the final factor
'''Makes a table from a factor 'n' via print_multiples().
'''
for i in range(1, n+1): #call function to print rows with i
print_multiples1(i) #as the multiplier.
def test( ) :
print_mult_table0( 10)
print_mult_table1( 10)
cProfile.run( 'test()')

Related

Determine the time complexity based on my codes and do some alteration

I have a question regarding time complexity in my codes. I tried to refer to a number of sites and tutorials and also stackoverflow explanations but still could not understand how we calculate or determine the time complexity of codes. If possible, is it ok to check my codes and explain based on it and also provide some EASY examples or links (Im still learning) to study it.
I tried this code and try to submit it but the time complexity is high so it is not accepted. Is there a way to reduce the time complexity too?
question is from this link
def large_element(array):
stack = []
took = False
for i in range(len(array)):
s_integer = array[i+1:]
if i != len(array)-1:
for ii in range(len(s_integer)):
if array[i] < s_integer[ii] and took == False:
stack.append(s_integer[ii])
took = True
elif array[i] > s_integer[ii] and took == False and ii == len(s_integer)-1:
stack.append(-1)
took = True
took = False
else:
stack.append(-1)
return stack
import time
start_time = time.time()
integer = [4,3,2,1]
print(large_element(integer))
My current understanding is that my code have 2 times for loop to loop each element so this will be O(n2)?
By the way, the output is:
[-1, -1, -1, -1]
A simplified yet powerful way of doing this is giving each line of code a cost and count how many times this line is run. Of course, you should keep your lines of code simple for this to make sense.
The cost of a line does not need to be precise, as constants are ignored in Big O notation.
Simple example:
n equals the size of the list x
def print_list(x : list):
for i in x: # cost = c1; count = n
print(i) # cost = c2; count = n
print('done') # cost = c3; count = 1
The line with the for is called n times because although the for is executed only once, the comparison to decide if the loop should continue is made n times.
The time complexity of this function is equal to the sum of the products of the cost of each line and the amount of times it is repeated:
complexity = c1×n + c2×n + c3×1 = O(n)
In this case, the costs are ignored because they happened to be constants. However, the cost of an instruction can be dependent of the size of the input, most of times when the instructions calls a subroutine.
Also, in the example I gave, each instruction was at most called n times, but in places like nested loops this count may be n², log(n), etc.
I would recommend reading the book Introduction to Algorithms by Cormen, Leiserson, Rivest and Stein. This explanation is mostly based on what the books says in the first chapters.

python project euler 6 with any number

I'm having trouble with Project Euler #6. The question is as follows:
Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
I'm trying to write my code in such a way that what is being asked in Euler(all numbers up to and including 100) can be substituted for any number you like (all numbers up to and including x). I decided that in order to do this, you would need 3 functions. Code is:
#the sumSquare function squares every number from 0 to number called
#in the function and adds each term to a list. the function returns the sum
#of all numbers in this list
def sumSquare(num):
list1 = []
for i in range(num+1):
x = i^2
list1.append(x)
return sum(list1)
#the squareSum function adds every whole number from 0 up to and including
#the number called in the function to list2. It returns the sum squared of #every number in the list
def squareSum(num):
list2 = []
for i in range(1,num+1):
list2.append(i)
return (sum(list2) * sum(list2))
def ans(num):
return squareSum(num) - sumSquare(num)
print ans(100)
My output is 2549748 but I'm reading online that the correct solution is 25164150. Does anyone see where I am going wrong. I am just learning to code so I may be missing something that would be easy to spot by someone more experienced. But as far as I can tell, the lists are being filled with what would be the appropriate numbers before they are summed.
This
i^2
Is not a square in Python. Use i*i or i**2 for a square.
Your code is anylanguage code. But with sintax error.
Really power in Python is **
So.
Python-style code looks like that one:
print(sum(range(1, 101))**2 - sum([i**2 for i in range(1, 101)]))
Thats why they love the Python (R)
Thanks to everyone for the input. After thinking a bit more I realized just how overly convoluted this code was. I realized that if all three functions are taking the same variable to solve the problem, it can be simplified into one function that takes care of each step on its own. Came up with this solution which is obviously much more efficient:
import time
def ans(num):
numSq = []
for i in range(1, num+1):
numSq.append(i**2)
return ((sum(range(1, num+1))**2)-sum(numSq))
start_time = time.time()
print ans(100)
print "This program took {} seconds to execute.".\
format(time.time() - start_time)
Running the program you get:
25164150
This program took 0.00800013542175 seconds to execute.
Again, thanks for the input on my first post!
def diffSum():
sumSquares = 0
squareSum = 0
sumT = 0
for i in range(1,101):
sumSquares = sumSquares + (i * i)
for i in range(1,101):
sumT = sumT + i
squareSum = sumT * sumT
return squareSum - sumSquares
#sumsquares gets all the summation of the square numbers of the first 100 numbers
#sumT stores the summation of the first 100 numbers
#squareSum squares the summation of the first 100 numbers
#returns the difference between sumSquares and squareSum

Python program find sum of consecutive number values equal to number n?

I want to find consecutive digits in a string that sum to a given number.
Example:
a="23410212" number is=5 — output 23,41,410,0212,212.
This code is not working. What do I need to fix?
def find_ten_sstrsum():
num1="2825302"
n=0;
total=0;
alist=[];
ten_str="";
nxt=1;
for n in range(len(num1)):
for n1 in range(nxt,len(num1)):
print(total)
if(total==0):
total=int(num1[n])+int(num1[n1])
ten_str=num1[n]+num1[n1]
else:
total+=int(num1[n1])
ten_str+=num1[n1]
if(total==10):
alist.append(ten_str)
ten_str=""
total=0
nxt+=1
break
elif(total<10):
nxt+=1
return alist
This (sort-of) one-liner will work:
def find_ten_sstrsum(s, n):
return list( # list call only in Python 3 if you don't want an iterator
filter(
lambda y: sum(map(int, y))==n,
(s[i:j] for i in range(len(s)) for j in range(i+1, len(s)+1)))
)
>>> find_ten_sstrsum('23410212', 5)
['23', '41', '410', '0212', '212']
This uses a nested generator expression over all possible slices and filters out the ones with the correct digit-sum.
This is, of course, far from optimal (especially for long strings) because the inner loop should be stopped as soon as the digit-sum exceeds n, but should give you an idea.
A more performant and readable solution would be a generator function:
def find_ten_sstrsum(s, n):
for start in range(len(s)):
for end in range(start+1, len(s)+1):
val = sum(map(int, s[start:end]))
if val > n:
break
if val == n:
yield s[start:end]
>>> list(find_ten_sstrsum('23410212', 5))
['23', '41', '410', '0212', '212']
Definitely read up on sum and map, as well.
Your function has several problems. Most of all, you have no way to give it different data to work on. You have it hard-coded to handle one particular string and a total of 10. You've even written variable names with "ten" in them, even though your example uses n=5. Your function should have two input parameters: the given string and the target sum.
NOTE: schwobaseggl just posted a lovely, Pythonic solution. However, I'll keep writing this, in case you need a function closer to your present learning level.
You have several logic paths, making it hard to follow how you handle your data. I recommend a slightly different approach, so that you can treat each partial sum cleanly:
for start in range(len(num1)):
total = 0 # Start at 0 each time you get a new starting number.
sum_str = ""
for last in num1[start:]:
print(total)
# Don't create separate cases for the first and other additions.
this_digit = num1[last]
total += int(this_digit)
ten_str += this_digit
# If we hit the target, save the solution and
# start at the next digit
if(total == target):
alist.append(ten_str)
break
# If we passed the target, just
# start at the next digit
elif(total > target):
break
return alist
Now, this doesn't solve quite all of your problems, and I haven't done some of the accounting work for you (variable initializations, def line, etc.). However, I think it moves you in the right direction and preserves the spirit of your code.

This detects violations of my minimum spacing, but does not produce a new list

I need to generate 10 random numbers with a minimum spacing of 0.15 between any two of them. What I am trying is this:
r=[]
for i in range(0,10):
x=random.uniform(1,6)
r.insert(i,x)
print(r)
for j in range(0,9):
for k in range(0,j):
h=m[j]-m[k]
if h<0.15:
print(h)
else:
continue
The above code generates 10 random numbers, then I print the difference between pairs when that difference is less than 0.15. This detects violations of my minimum spacing, but does not produce a new list.
You're missing a very basic thing, you don't try to recreate the list when it violates your constraints.
I also prefer to break things apart more than this, Python makes it so easy. I've moved your constraint checking into its own function.
def meets_constraints(m):
for j in range(0,9):
for k in range(0,j):
h=abs(m[j]-m[k])
if h<0.15:
print(h)
return False
return True
while True:
r=[]
for i in range(0,10):
x=random.uniform(1,6)
r.insert(i,x)
print(r)
if meets_constraints(r):
break
This keeps generating a new list until you obtain one where all of the elements are at least 0.15 apart. Note that this is incredibly inefficient, since checking all the elements is an n^2 algorithm and you will keep performing the test some random number of times until you happen across a sequence that passes. A better algorithm would guarantee the constraint as you're building the list in the first place.
P.S. I've also added an abs in the difference calculation, since I think that was a bug in your original code.
something like?
min_interval=0.15
last=0
for n in range(0,10):
num=last+random()+0.15
print num
last=num

Python: speed up removal of every n-th element from list

I'm trying to solve this programming riddle and although the solution (see code below) works correctly, it is too slow for succesful submission.
Any pointers as how to make this run
faster (removal of every n-th element from a list)?
Or suggestions for a better algorithm to calculate the same; seems I can't think of anything
else than brute-force for now...
Basically, the task at hand is:
GIVEN:
L = [2,3,4,5,6,7,8,9,10,11,........]
1. Take the first remaining item in list L (in the general case 'n'). Move it to
the 'lucky number list'. Then drop every 'n-th' item from the list.
2. Repeat 1
TASK:
Calculate the n-th number from the 'lucky number list' ( 1 <= n <= 3000)
My original code (it calculated the 3000 first lucky numbers in about a second on my machine - unfortunately too slow):
"""
SPOJ Problem Set (classical) 1798. Assistance Required
URL: http://www.spoj.pl/problems/ASSIST/
"""
sieve = range(3, 33900, 2)
luckynumbers = [2]
while True:
wanted_n = input()
if wanted_n == 0:
break
while len(luckynumbers) < wanted_n:
item = sieve[0]
luckynumbers.append(item)
items_to_delete = set(sieve[::item])
sieve = filter(lambda x: x not in items_to_delete, sieve)
print luckynumbers[wanted_n-1]
EDIT: thanks to the terrific contributions of Mark Dickinson, Steve Jessop and gnibbler, I got at the following, which is quite a whole lot faster than my original code (and succesfully got submitted at http://www.spoj.pl with 0.58 seconds!)...
sieve = range(3, 33810, 2)
luckynumbers = [2]
while len(luckynumbers) < 3000:
if len(sieve) < sieve[0]:
luckynumbers.extend(sieve)
break
luckynumbers.append(sieve[0])
del sieve[::sieve[0]]
while True:
wanted_n = input()
if wanted_n == 0:
break
else:
print luckynumbers[wanted_n-1]
This series is called ludic numbers
__delslice__ should be faster than __setslice__+filter
>>> L=[2,3,4,5,6,7,8,9,10,11,12]
>>> lucky=[]
>>> lucky.append(L[0])
>>> del L[::L[0]]
>>> L
[3, 5, 7, 9, 11]
>>> lucky.append(L[0])
>>> del L[::L[0]]
>>> L
[5, 7, 11]
So the loop becomes.
while len(luckynumbers) < 3000:
item = sieve[0]
luckynumbers.append(item)
del sieve[::item]
Which runs in less than 0.1 second
Try using these two lines for the deletion and filtering, instead of what you have; filter(None, ...) runs considerably faster than the filter(lambda ...).
sieve[::item] = [0]*-(-len(sieve)//item)
sieve = filter(None, sieve)
Edit: much better to simply use del sieve[::item]; see gnibbler's solution.
You might also be able to find a better termination condition for the while loop: for example, if the first remaining item in the sieve is i then the first i elements of the sieve will become the next i lucky numbers; so if len(luckynumbers) + sieve[0] >= wanted_n you should already have computed the number you need---you just need to figure out where in sieve it is so that you can extract it.
On my machine, the following version of your inner loop runs around 15 times faster than your original for finding the 3000th lucky number:
while len(luckynumbers) + sieve[0] < wanted_n:
item = sieve[0]
luckynumbers.append(item)
sieve[::item] = [0]*-(-len(sieve)//item)
sieve = filter(None, sieve)
print (luckynumbers + sieve)[wanted_n-1]
An explanation on how to solve this problem can be found here. (The problem I linked to asks for more, but the main step in that problem is the same as the one you're trying to solve.) The site I linked to also contains a sample solution in C++.
The set of numbers can be represented in a binary tree, which supports the following operations:
Return the nth element
Erase the nth element
These operations can be implemented to run in O(log n) time, where n is the number of nodes in the tree.
To build the tree, you can either make a custom routine that builds the tree from a given array of elements, or implement an insert operation (make sure to keep the tree balanced).
Each node in the tree need the following information:
Pointers to the left and right children
How many items there are in the left and right subtrees
With such a structure in place, solving the rest of the problem should be fairly straightforward.
I also recommend calculating the answers for all possible input values before reading any input, instead of calculating the answer for each input line.
A Java implementation of the above algorithm gets accepted in 0.68 seconds at the website you linked.
(Sorry for not providing any Python-specific help, but hopefully the algorithm outlined above will be fast enough.)
You're better off using an array and zeroing out every Nth item using that strategy; after you do this a few times in a row, the updates start getting tricky so you'd want to re-form the array. This should improve the speed by at least a factor of 10. Do you need vastly better than that?
Why not just create a new list?
L = [x for (i, x) in enumerate(L) if i % n]

Categories

Resources