Get "None" Instead of Zero Value in a Python Function - python

I want to make a program which puts an array(1x9 has numbers from 0 to 9) in memory and I want to check if an array I created is previously used. There will be 2 functions I will use.
addMemory(list,previousStates) adds the newly created array into memory and checkMemory(list,previousStates) checks if the array is previously used or not. It returns 1 if the array is used and 0 if it is not.
I convert the array to a number by assuming that every element of the array is a digit for a 9-digit number.
Ex: [2,5,3,4,1,6,8,9,7] is stored as 253.416.897. I want to test my functions. First print has the empty memory and the memory is checked and the array is added and the new memory is checked.
The output should have been
0
1
but I get
None
1
Why I get 'None' instead of 0? Can you help please?
def addMemory(newlist,previousStates):
count = 0
for i in range(0,8):
count += count + newlist[i] * 10**(8-i)
previousStates.append(count)
return previousStates
def checkMemory(newlist,previousStates):
count = 0
for i in range(0,8):
count += count + newlist[i] * 10**(8-i)
for i in range(len(previousStates)):
if(previousStates[i] == count):
return 1
return 0
def main():
a = [5,3,4,7,8,9,1,2,6]
previousStates = []
print(checkMemory(a,previousStates))
addMemory(a,previousStates)
print(checkMemory(a,previousStates))
main()

In your checkMemory function, because len(previousStates) is zero at first, your for statement is never executed and hence your function never reaches any return

Related

How to count number of times we can halve a number until it reaches 1?

I want to have a number that halves until it reaches 1, then it should return a count of how many times it halved.
example:
halve(4)
2
halve(11)
3
since 4/2 = 2 and 2/2= 1, hence it halved twice before reaching 1, and this is what I want it to return but my code isn't working, why? Can a modification be made ?
Here's my code
Python
def halve(n):
i = 0
for i in range(n,1):
if float(i/2) >=1:
i+=1
return i
Thanks,
It seems to me you can employ some math and just write:
import math
def halve(n):
return math.floor(math.log(n, 2))
You attempt is wrong for three reasons.
You are returning from within the loop. Thus it will never execute more than once.
Your loop will never execute unless n is 0 because range needs a third parameter as a negative number to increment "backwards."
The i assigned by your loop is shadowing the i you have previously assigned. Let's just use a while loop.
def halve(n):
i = 0
while n/2 >= 1:
i += 1
n /= 2
return i
Since you wanted to know what is wrong with your code:
First, immediate problem is that you return on first loop iteration. You need to return only when the number is smaller than 1 (so if condition is not met):
else:
return i
Now, there is another problem - you are iterating over range(n,1) which... doesn't really make sense. You need way less than n divisions to reach number smaller than 1. Use a while loop instead - this way you loop as long as you need. You're also using i as an iterator, but also seem to be dividing it to see if it's more than one - shouldn't you use n there? You're also not reducing n, so you'd actually never reach n < 1.
Taking all of those your code might look like this:
while True:
if float(n/2) >=1:
i+=1
n /= 2
else:
return i
We can improve it even further - as you want your code to end if the condition is not met, we can simply move that to while condition:
def halve(n):
i = 0
while float(n/2) >=1:
i+=1
n /= 2
return i
As #Sembei Norimaki commented, a while loop is a more natural fit for this use case.
def halve(n):
halves = 0
while n > 1:
n /= 2
halves += 1
return halves
This loop can be summarized "As long as n is greater than one, cut it in half and add one to the number of halves we have performed."

Python list first n entries in a custom base number system

I am sorry if the title is a misnomer and/or doesn't properly describe what this is all about, you are welcome to edit the title to make it clear once you understand what this is about.
The thing is very simple, but I find it hard to describe, this thing is sorta like a number system, except it is about lists of integers.
So we start with a list of integers with only zero, foreach iteration we add one to it, until a certain limit is reached, then we insert 1 at the start of the list, and set the second element to 0, then iterate over the second element until the limit is reached again, then we add 1 to the first element and set the second element 0, and when the first element reaches the limit, insert another element with value of 1 to the start of the list, and zero the two elements after it, et cetera.
And just like this, when a place reaches limit, zero the place and the places after it, increase the place before it by one, and when all available places reach limit, add 1 to the left, for example:
0
1
2
1, 0
1, 1
1, 2
2, 0
2, 1
2, 2
1, 0, 0
The limit doesn't have to be three.
This is what I currently have that does something similar to this:
array = []
for c in range(26):
for b in range(26):
for a in range(26):
array.append((c, b, a))
I don't want leading zeroes but I can remove them, but I can't figure out how to do this with a variable number of elements.
What I want is a function that takes two arguments, limit (or base) and number of tuples to be returned, and returns the first n such tuples in order.
This must be very simple, but I just can't figure it out, and Google returns completely irrelevant results, so I am asking for help here.
How can this be done? Any help will truly be appreciated!
Hmm, I was thinking about something like this, but very unfortunately I can't make it work, please help me figure out why it doesn't work and how to make it work:
array = []
numbers = [0]
for i in range(1000):
numbers[-1] += 1
while 26 in numbers:
index = numbers.index(26)
numbers[index:] = [0] * (len(numbers) - index)
if index != 0:
numbers[index - 1] += 1
else:
numbers.insert(0, 1)
array.append(numbers)
I don't quite understand it, my testing shows everything inside the loop work perfectly fine outside the loop, the results are correct, but it just simply magically will not work in a loop, I don't know the reason for this, it is very strange.
I discovered the fact that if I change the last line to print(numbers) then everything prints correctly, but if I use append only the last element will be added, how so?
from math import log
def number_to_base(n,base):
number=[]
for digit in range(int(log(n+0.500001,base)),-1,-1):
number.append(n//base**digit%base)
return number
def first_numbers_in_base(n,base):
numbers=[]
for i in range(n):
numbers.append(tuple(number_to_base(i,base)))
return numbers
#tests:
print(first_numbers_in_base(10,3))
print(number_to_base(1048,10))
print(number_to_base(int("10201122110212",3),3))
print(first_numbers_in_base(25,10))
I finally did it!
The logic is very simple, but the hard part is to figure out why it won't work in a loop, turns out I need to use .copy(), because for whatever reason, doing an in-place modification to a list directly modifies the data reside in its memory space, such behavior modifies the same memory space, and .append() method always appends the latest data in a memory space.
So here is the code:
def steps(base, num):
array = []
numbers = [0]
for i in range(num):
copy = numbers.copy()
copy[-1] += 1
while base in copy:
index = copy.index(base)
copy[index:] = [0] * (len(copy) - index)
if index != 0:
copy[index - 1] += 1
else:
copy.insert(0, 1)
array.append(copy)
numbers = copy
return array
Use it like this:
steps(26, 1000)
For the first 1000 lists in base 26.
Here is a a function, that will satisfy original requirements (returns list of tuples, first tuple represents 0) and is faster than other functions that have been posted to this thread:
def first_numbers_in_base(n,base):
if n<2:
if n:
return [(0,)]
return []
numbers=[(0,),(1,)]
base-=1
l=-1
num=[1]
for i in range(n-2):
if num[-1]==base:
num[-1]=0
for i in range(l,-1,-1):
if num[i]==base:
num[i]=0
else:
num[i]+=1
break
else:
num=[1]+num
l+=1
else:
num[-1]+=1
numbers.append(tuple(num))#replace tuple(num) with num.copy() if you want resutl to contain lists instead of tuples.
return numbers

Breaking an iterative function in Python before a condition turns False

This is for a school assignment.
I have been tasked to define a function determining the largest square pyramidal number up to a given integer(argument). For some background, these are square pyramidal numbers:
1 = 1^2
5 = 1^2+2^2
14 = 1^2+2^2+3^2
So for a function and parameter largest_square_pyramidal_num(15), the function should return 14, because that's the largest number within the domain of the argument.
I get the idea. And here's my code:
def largest_square_pyramidal_num(n):
sum = 0
i = 0
while sum < n:
sum += i**2
i += 1
return sum
Logically to me, it seemed nice and rosy until I realised it doesn't stop when it's supposed to. When n = 15, sum = 14, sum < n, so the code adds one more round of i**2, and n is exceeded. I've been cracking my head over how to stop the iteration before the condition sum < n turns false, including an attempt at break and continue:
def largest_square_pyramidal_num(n):
sum = 0
for i in range(n+1):
sum += i**2
if sum >= n:
break
else:
continue
return sum
Only to realise it doesn't make any difference.
Can someone give me any advice? Where is my logical lapse? Greatly appreciated!
You can do the following:
def largest_pyr(x):
pyr=[sum([i**2 for i in range(1,k+1)]) for k in range(int(x**0.5)+1)]
pyr=[i for i in pyr if i<=x]
return pyr[-1]
>>>largest_pyr(15)
14
>>> largest_pyr(150)
140
>>> largest_pyr(1500)
1496
>>> largest_pyr(15000)
14910
>>> largest_pyr(150000)
149226
Let me start by saying that continue in the second code piece is redundant. This instruction is used for scenario when you don't want the code in for loop to continue but rather to start a new iteration (in your case there are not more instructions in the loop body).
For example, let's print every number from 1 to 100, but skip those ending with 0:
for i in range(1, 100 + 1):
if i % 10 != 0:
print(i)
for i in range(1, 100 + 1):
if i % 10 == 0:
# i don't want to continue executing the body of for loop,
# get me to the next iteration
continue
print(i)
The first example is to accept all "good" numbers while the second is rather to exclude the "bad" numbers. IMHO, continue is a good way to get rid of some "unnecessary" elements in the container rather than writing an if (your code inside if becomes extra-indented, which worsens readability for bigger functions).
As for your first piece, let's think about it for a while. You while loop terminates when the piramid number is greater or equal than n. And that is not what you really want (yes, you may end up with a piramid number which is equal to n, but it is not always the case).
What I like to suggest is to generate a pyramid number until in exceedes n and then take a step back by removing an extra term:
def largest_square_pyramidal_num(n):
result = 0
i = 0
while result <= n:
i += 1
result += i**2
result -= i ** 2
return result
2 things to note:
don't use sum as a name for the variable (it might confuse people with built-in sum() function)
I swapped increment and result updating in the loop body (such that i is up-to-date when the while loop terminates)
So the function reads like this: keep adding terms until we take too much and go 1 step back.
Hope that makes some sense.
Cheers :)

Python - explain function parameters

So I understand this simple for loop:
sum = 0
for number in {1,2,3,4}:
sum = sum + number
print sum
>>>
1
3
6
10
>>>
Then here is a neat little code that combines a for loop and a function I found on the interwebs:
def sum_list(l):
sum = 0
for number in l:
sum = sum + number
return sum
print sum_list([1, 7, 4])
>>>
12
What I don't understand is how python interprets this code (rather how Python knows to add the 3 arguments 1,7,4 together).
I would really help if you can break it down for me!
To tack on another question for you guys to review:
sum = 0
for number in {1,2,3,4}:
sum = sum + number
return sum
Spits out an error. print sum will list the results as 1,3,6,10
Error says: Syntaxerror: 'return' outside of function
[EDIT] #sshashank124
For example: This code spits out 3 answers. It prints out:
sum = 0
for number in {1,7,4}:
sum = sum + number
print sum
>>>
1
8
12
>>>
But this:
def sum_list(l):
sum= 0
for number in l:
sum = sum + number
print sum
print sum_list([1, 7, 4])
>>>
12
none
Spits out only 1 answer, 12. My question is why that occurs.
for number in l:
This iterates over the l, and number will have each and every element of l on every iteration. You can check that like this
for number in l:
print number
# 1
# 7
# 4
You are adding those numbers to the sum variable. You can check that like this
sum = 0
for number in l:
sum = sum + number
print sum
# 1
# 8
# 12
I believe you are doing this for educational purpose. If you actually wanted to find the sum of an iterable, then you can use the builtin sum function, like this
sum([1, 7, 4])
It knows to add them together, because you tell it to do that.
Let me rewrite the code a bit to show what's happening. Rewrite one, adding 1,7,4 and then 2,8,5, but adding more numbers requires more lines:
sum = 0
sum = sum + 1
sum = sum + 7
sum = sum + 4
print sum
sum = 0
sum = sum + 2
sum = sum + 8
sum = sum + 5
print sum
Rewrite two - using a loop. Two lines shorter, but it can now handle lists of more items - adding four, five, even ten numbers, without adding more lines of code, just by making the lists longer:
sum = 0
for number in [1,7,4]:
sum = sum + number
print sum
sum = 0
for number in [2,8,5]:
sum = sum + number
print sum
Rewrite three - moving the lists out of the loop. The code got longer again, but something interesting happened - see how the loop code is now identical both times:
myList = [1,7,4]
sum = 0
for number in myList:
sum = sum + number
print sum
myList = [2,8,5]
sum = 0
for number in myList:
sum = sum + number
print sum
Rewrite four - now it's identical, why does it have to be there twice? Can't we ... write it once, and use it twice? That way if we need to change it, we only have to change it in one place. Yes - make it a function and call the function:
def sum_list():
sum = 0
for number in myList:
sum = sum + number
print sum
myList = [1,7,4]
sum_list()
myList = [2,8,5]
sum_list()
Rewrite five - what's happening above works fine, because you called everything 'myList' it all works. But if you write bigger programs like that it gets messy fast - one myList could be several pages of code away from another, we'll tend to forget that something pages and pages away could be affecting things. So we humans can keep track of what's going on, we need to clearly and explicitly give the function something to work on, and not have it just reaching far away and pulling things out of the rest of the code.
def sum_list(working_list): # working_list is whatever the function gets
sum = 0 # by a different name
for number in working_list:
sum = sum + number
print sum
myList1 = [1,7,4]
sum_list(myList1)
myList2 = [2,8,5]
sum_list(myList2)
See in the above code, I've called them myList1 and myList2 - yet whatever you give to the function, the function sees it called 'working_list'. The names don't have to match.
But because sum_list has it's own name for whatever you give it, you don't have to have a name for what you give it. You can just give it a list directly without a name:
def sum_list(working_list):
sum = 0
for number in working_list:
sum = sum + number
print sum
sum_list([1,7,4])
sum_list([2,8,5])
The next move is, once you're feeding things into sum_list, sum_list is looking away and writing to the screen. We can't have that. For the sake of humans tracking what's happening, that's a bad idea - you want to give functions some work to do and have them give you back an answer. That way you know you can use them anytime you need, without worrying about them printing to the screen unexpectedly. That's where 'return' comes in:
def sum_list(working_list):
sum = 0
for number in working_list:
sum = sum + number
return sum
result = sum_list([1,7,4])
print result
result = sum_list([2,8,5])
print result
Now sum_list is a self contained adder, it does nothing else. You can trust it. It's not reading from names all over your code, it's only reading explicitly what you gave to it. It's not writing to the screen at surprise times, or anything. You give it a list, you get a result, it's isolated, limited, controlled, predictable, easy to work with, easy to reuse. And like the list names, if all you do is get the result and print it, you don't need to give that a name either:
def sum_list(working_list):
sum = 0
for number in working_list:
sum = sum + number
return sum
print sum_list([1,7,4])
print sum_list([2,8,5])
Edit: I hope that explains several of your questions.
What that code is doing
Why it prints one answer instead of three - because you are giving it one thing (a list).
Why it makes no sense to use return on its own - because you have to call a function and then return from the function, and you can bring something back with you or you can go somewhere and bring nothing back (function with no return). But you can't bring something back if you don't go anywhere first.
In Python you will realise that when you initialise a variable you don't need to assign a type to it, you can just initialise anything in there.
in this case l was interoperated as an object, or an array to be specific.
as for the loop.
for number in l:
is like a for each statement, it goes through each of the elements. and stores it in number, then iterates after the block is executed, moving on to the next l.
Hope that helped? (if i understand your question.
The for number in l: line takes each of the elements in [1,7,4] and adds them to the sum variable which represents the total sum of the elements in the list.
This is what it looks like:
Take first element of l: 1
Add to sum --> sum is now 1
Take second element of l: 7
Add to sum --> sum is now 8
Take third element of l: 4
Add to sum --> sum is now 12
Return sum --> sum is 12
Might I suggest that sum([1,7,4]), the builtin python method would also work.

how to make a list of functions execute in python?

I am trying to save the results of 10 function calls into a list. however, when I want to access this numerical data, I keep getting type errors, because the list is really a list of function calls. How do I make it do stuff so I can have numbers to do compare?
I tried setting temp variable to result of each spot in the list, but it still shows as a function.
Output should show the average for different # of dice, and return the best amount of dice to roll
def calculator(fn, num_samples=1000): # this is the function I'm trying to call
def print_and_return(*args):
total3 = 0
for _ in range(num_samples):
total3 += (fn(*args))
return float(total3)/num_samples
return print_and_return
def find_average(dice=six_sided):
avglist = []
k, spot = 0, 0
bob = roll_dice(k+1, dice)
passed_function = calculator(bob, 1000)
print(passed_function)
while k <= 10:
avglist.append((passed_function)) # <==trying to save the results when I check with 1-10 dice rolls
if k == 0:
spot = 1
else:
temp = 0
max = 0
i = 0
while i <= len(avglist):
temp = avglist[i]
if max > temp:
max = temp
i +=1
if (avglist[k] > temp):
spot = k
print(k, "dice scores", avglist[k], "on average")
k +=1
return spot
You are not calling passed_function. Calling a function with no arguments still reqires the ().
Your calculator function returns a function, not a plain value. You therefore need to call passed_function in order to get your result.
Based on the arguments to your call to roll_dice, it looks like you want the k argument to vary in the loop. As written now, it will not. I suspect you are tripping yourself up a bit. The code could be written a whole lot simpler without so many function references being passed around.

Categories

Resources