Python3 Using functions inside other functions? - python-3.x

I'm a bit confused as to how this is supposed to work. For example,
I have these two functions that I've written:
def in_range(par):
if (par >= 50) and (par <= 100):
print(True)
else:
print(False)
def squares_in_range(twoargument):
for a in range(3, 20):
b = (a*a)
print(b, end="")
if a<19:
print(end=",")
Now, I would like to use the first function in the second so to say. It should check if the numbers in the second function are within the 50-100 range and then print out "True" if its within and "False" if out of range for each number so that it becomes a list that might look like this: True, False, False, True... and so on.
How do I go about this?
edit: I am referring to "b" in the second function, not "a". I've tried calling the function but nothing happens. I guess that's because the first functions does not use "return"?

It's not clear to me which numbers, a or b, in the second function you were referring to.
This gets you a list of booleans for checking whether the numbers from a is within the range. You can modify it to check for b.
def in_range(par,alist):
if (par >= 50) and (par <= 100):
print(True)
alist.append(True)
else:
print(False)
alist.append(False)
def squares_in_range(twoargument):
within_range=[]
for a in range(3, 20):
in_range(a,within_range)
b = (a*a)
print(b)
if a<19:
print(",")
print(within_range) # print the final list of booleans
squares_in_range(1) #testing

Just write in_range(b) at some point in the second function.

Related

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two million.(I am not getting what is wrong in this code)

sum = 2
x=3
y=5000
for i in range (x,y):
for j in range (2,i):
if i%j==0:
break
elif i%j!=0 and j==i-1:
sum += i
if i==y-1 and y<2000000:
x=y
y+=5000
else:
continue
print(sum)
**I am not getting what is wrong in this code. By running this I came to know that the Last If and Else statement are not running **
Given your code, there are a couple of things wrong. First, sum is a python function name and should never be used as a variable name. It will get you into trouble in more ways than I care to think about. Second, the last else statement is not needed, because whether the if clause above it is or is not executed executed, the for loop will be executed again. Third, I don't understand the purpose of y and the magical value 5000, unless you are trying to provide an end value for your loop. The problem with this approach is you seem to try and extend it's range in increments of 5000. The problem is that once the initial for loop is executed, it creates a local iterable from x to 5000, and subsequent changes to y do not affect the for loops range.
I would approach the problem differently, by creating a list of primes and then use the python sum method to add all the values. Here is the code:
def sum_primes(max_prime):
""" Return Sum of primes Less than max_prime"""
primes = [2]
indx_num = 3
while primes[-1] <= max_prime:
update = True
for prime in primes:
if indx_num == prime or indx_num % prime == 0:
update = False
break
if update:
primes.append(indx_num)
indx_num += 2
#return summ of all values except the last
return sum(primes[:-1])
Executing sum_primes(2000000)
yields 1709600813

Number of sub sequences of length K having total sum S, given 2d array

I wish to find Number of sub sequences of length K having total sum S, given an array.
Sample Input:
a=[1,1,1,2,2] & K=2 & S=2
Sample Output:
3 {because a[0],a[1]; a[1]a[2]; a[0]a[2] are only three possible for the case}
I have tried to write a recursive loop in Python for starter but it isn't giving output as expected.Please can you help me find a loophole I might be missing on.
def rec(k, sum1, arr, i=0):
#print('k: '+str(k)+' '+'sum1: '+str(sum1)) #(1) BaseCase:
if(sum1==0 and k!=0): # Both sum(sum1) required and
return 0 # numbers from which sum is required(k)
if(k==0 and sum1 !=0): # should be simultaneously zero
return 0 # Then required subsequences are 1
if(k==0 and sum1==0 ): #
return 1 #
base_check = sum1!=0 or k!=0 #(2) if iterator i reaches final element
if(i==len(arr) and base_check): # in array we should return 0 if both k
return 0 # and sum1 aren't zero
# func rec for getting sum1 from k elements
if(sum1<arr[0]): # takes either first element or rejects it
ans=rec(k-1,sum1,arr[i+1:len(arr)],i+1) # so 2 cases in else loop
print(ans) # i is taken in as iterator to provide array
else: # input to rec func from 2nd element of array
ans=rec(k-1, sum1-arr[0], arr[i+1:len(arr)],i+1)+rec(k, sum1, arr[i+1:len(arr)],i+1)
#print('i: '+str(i)+' ans: '+str(ans))
return(ans)
a=[1,1,1,2,2]
print(rec(2,2,a))
I am still unable to process how to make changes. Once this normal recursive code is written I might go to DP approach accordinlgy.
Using itertools.combinations
Function itertools.combinations returns all the subsequences of a given lengths. Then we filter to keep only subsequences who sum up to the desired value.
import itertools
def countsubsum(a, k, s):
return sum(1 for c in itertools.combinations(a,k) if sum(c)==s)
Fixing your code
Your code looks pretty good, but there are two things that appear wrong about it.
What is this if for?
At first I was a bit confused about if(sum1<arr[0]):. I think you can (and should) always go to the else branch. After thinking about it some more, I understand you are trying to get rid of one of the two recursive calls if arr[0] is too large to be taken, which is smart, but this makes the assumption that all elements in the array are nonnegative. If the array is allowed to contain negative numbers, then you can include a large a[0] in the subsequence, and hope for a negative element to compensate. So if the array can contain negative numbers, you should get rid of this if/else and always execute the two recursive calls from the else branch.
You are slicing wrong
You maintain a variable i to remember where to start in the array; but you also slice the array. Pretty soon your indices become wrong. You should use slices, or use an index i, but not both.
# WRONG
ans=rec(k-1, sum1-arr[0], arr[i+1:len(arr)],i+1)+rec(k, sum1, arr[i+1:len(arr)],i+1)
# CORRECT
ans = rec(k-1, sum1-arr[i], arr, i+1) + rec(k, sum1, arr, i+1)
# CORRECT
ans = rec(k-1, sum1-arr[0], arr[1:]) + rec(k, sum1, arr[1:])
To understand why using both slicing and an index gives wrong results, run the following code:
def iter_array_wrong(a, i=0):
if (a):
print(i, a)
iter_array_wrong(a[i:], i+1)
def iter_array_index(a, i=0):
if i < len(a):
print(i, a)
iter_array_index(a, i+1)
def iter_array_slice(a):
if a:
print(a)
iter_array_slice(a[1:])
print('WRONG')
iter_array_wrong(list(range(10)))
print()
print('INDEX')
iter_array_index(list(range(10)))
print()
print('SLICE')
iter_array_slice(list(range(10)))
Also note that a[i:len(a)] is exactly equivalent to a[i:] and a[0:j] is equivalent to a[:j].
Clean version of the recursion
Recursively count the subsequences who use the first element of the array, and the subsequences who don't use the first element of the array, and add the two counts. To avoid explicitly slicing the array repeatedly, which is an expensive operation, we keep a variable start to remember we are only working on subarray a[start:].
def countsubsum(a, k, s, start=0):
if k == 0:
return (1 if s == 0 else 0)
elif start == len(a):
return 0
else:
using_first_element = countsubsum(a, k-1, s-a[start], start+1)
notusing_first_elem = countsubsum(a, k, s, start+1)
return using_first_element + notusing_first_elem

How to handle negative cases for prime check in Python?

With regard to the "xrange" function - ("range" in Python3) what happens when I do a negative check inside a loop? In this case, a negative number could be regarded as an edge case, but always returns None. Any insights?
The problem is you are checking if the number is negative inside the for loop. For instance if x=-3, then you are trying to run a for loop in range(2,-1) which is None. So the for loop never runs and hence returns True.
def isprime(x):
if x<=0:
return(False)
for a in range(2,(x//2)+1):
if(x%a==0):
return(False)
return(True)
By it's elementary school definition, prime numbers are defined for positive numbers only, thus your function should return False for every negative number, for example:
def isprime(x):
if x <= 0:
return False
for a in range(2, (x//2)+1):
if x % a == 0:
return False
return True
That being said, it is possible to extend the definition (as done in some fields in math), to include negative numbers as well (for further discussion see here and here). In this case, for every negative number -n, -n is prime iff n is prime. Therefore your code could be something like:
def isprime(x):
if x <= 0: # or use any |abs| method you'd like, like numpy's
x = -x
for a in range(2, (x//2)+1):
if x % a == 0:
return False
return True

Randomly flipping a coin

I need to write a function called flip_coins(n) that returns the amount of heads. Then I need to to write a program that flips 8 coins a thousand times and returns the amount of times heads comes up three times in a row with a loop. After that I have some calculations on probability of the flips. So far this is what I have, but it wont run. What am I missing?
import random
def flip_coin():
return random.choice("HT")
def flip_coins(n):
for i in range(n):
if flip_coins() == "H":
heads_count +=1
return heads_count
for i in range (1000):
if flip_coins(8) == "3":
multiple_heads_count += 1
return multiple_heads_count
print(multiple_heads_probability)
print(second_probability)
multiple_heads_probability = multiple_heads_count/1000
second_probability = 56/256
This is rather interesting, similar to a dice rolling program I wrote a few months ago to get me back into python!
The first thing I noticed is that the code is trying to print two variables before they are created, you also need to be careful when dividing an integer, it will always return an integer, this meant that without converting to a float first (using float() or adding .0 to the end of an integer) the result will always be zero. So I changed those lines to:
multiple_heads_probability = float(multiple_heads_count)/1000
second_probability = 56.0/256
print(multiple_heads_probability)
print(second_probability)
Secondly, if you want the program to find the probability of throwing a heads three times in a row, then I would suggest adding an else statement after your if flip_coin() == "H": block. Then another if statement to determine whether there have been 3 in a row. Also, in order to add to a variable, you must first initialize them, you can do this using: heads_count = 0 and adding to it later. So I changed your second function to:
def flip_coins(n):
heads_count = 0
heads_rows = 0
for i in range(n):
if flip_coin() == "H":
heads_count +=1
else:
heads_count == 0
if heads_count == 3:
heads_rows += 1
heads_count = 0
else:
pass
return heads_rows
Lastly, the for loop. Why are you using return outside of a function? This is only for use when writing a fruitful (not void) function and not in loops (unless inside a fruitful function). In the line if flip_coins(8) == "3":, you are comparing an integer to a string so it will always return false. Because of the changes to flip_coins() I have also changed the for loop in other ways, it is now:
multiple_heads_count = 0
for i in range (1000):
if flip_coins(8) >= 1: #if there were any occurrences of 3 heads (H) in a row
multiple_heads_count += 1
The corrected and complete code is below, along with 10 possible outputs (out of thousands).
Code:
import random
def flip_coin():
return random.choice("HT")
def flip_coins(n):
# initialize two variables for incrementation
heads_count = 0
heads_rows = 0
for i in range(n): # do n times
if flip_coin() == "H": # if flipped a heads
heads_count +=1 # increment heads_count by one
else: # otherwise
heads_count == 0 # reset heads_count
if heads_count == 3: # if there have been three heads so far
heads_rows += 1 # increment heads_rows by one
heads_count = 0 # reset heads_count
else: # otherwise
pass # do nothing
return heads_rows
multiple_heads_count = 0 # initialize a variable for incrementation
for i in range (1000): # do 1000 times
if flip_coins(8) >= 1: # if there was at least one three heads in a row
multiple_heads_count += 1 # increment multiple_heads_count by one
multiple_heads_probability = float(multiple_heads_count)/1000 # calculate the probability of having at least one heads in a row
second_probability = 56.0/256 # This is the supposed theoretical probability, however I have not checked this yet
print(multiple_heads_probability)
print(second_probability)
Outputs:
0.865
0.21875
0.851
0.21875
0.853
0.21875
0.861
0.21875
0.866
0.21875
0.89
0.21875
0.839
0.21875
0.856
0.21875
0.855
0.21875
0.841
0.21875
I am intrigued as to what 56.0/256 represents, could someone enlighten me in a comment?
It looks like you are calling "flip_coins" from inside itself. You want to call "flip_coin" from inside "flip_coins" like this:
def flip_coins(n):
for i in range(n):
if flip_coin() == "H": ## changed to flip_coin
heads_count +=1
return heads_count
EDIT: There are several more issues here.
Variables must be assigned (i.e. appear on the left-hand side of an = sign) before they are referenced (appear in an expression to be evaluated). This occurs in the function "flip_coins" where you need to assign heads_count=0 before you start you loop. Also multiple_heads_count is never initialized before you try to increment it in the main (the code not inside a function definition). Finally, you are trying to print two variables, multiple_heads_probability and second_probability before you ever assign them.
You are incorrectly trying to compare an integer with a string in your loop
for i in range (1000):
if flip_coin(8) == "3": ## changed to flip_coin()
multiple_heads_count += 1
The value of flip_coin(8) is an integer, but you are checking for equality with the string "3". Strings and integers are never equal. In this case, just remove the quotes from around the 3.
You have a return statement outside of a function
return multiple_heads_count
This statement can be deleted. After running the loop, the value of multiple_heads_count will still be available, because you are still in the same scope, so you can just print it out or use it however you need.
(EDIT: NOTE - this paragraph applies to Python 2.x, but not Python 3.x) Once you fix those syntax errors, you're going to find that your results always print "0". That's because in python, division of two integers produces an integer result (the quotient, with the remainder thrown away). In this case, you're always dividing an integer by a larger integer, so the quotient is always zero. What you want is to divide the integers and get a floating point result, so you can force python to do this by specifying at least one element of the quotient as a floating point:
multiple_heads_probability = multiple_heads_count/1000.0 ## added ".0"
You can add ".0" to any integer value, and it will force floating point division. This is a very important feature of python to be aware of.
Finally, based on your problem statement, your logic is wrong. Your problem states that you should count instances of "three heads in a row" out of 8 coin flips, but your code counts ALL heads out of the 8, and returns the total number of heads. Now, there is some ambiguity here. You are checking for EXACTLY three heads, but is that what the problem states? Even if you fix the logic to look for consecutive heads, you will ignore "HHHH", "HHHHH", etc. because you are testing for exactly three. Also, are you supposed to count "HHHTTHHH" as two instances of three heads in a row?
Python is a great language, and it is a great choice for this kind of problem. Good luck!

Python - Create a recursion function

my question is basically this: Create a recursion function that takes a nested list as a
parameter and returns the sub-list that has minimum difference between its maximum and minimum elements.
For example: Function should return [1,2] for input [[1,199,59],[1,2],[3,8]]
I searched Google and stackoverflow, but i could not find this specific example.
What i would like to get help is with iteration. I want to, using recursion, iterate over each sub-list(can be as many as possible). I have achieved this with a for loop, but i cannot grasp the idea of iteration by using recursion method.
So far, i have this:
def sublist(mylist):
if len(mylist) == 0:
return []
elif len(mylist) == 1:
return mylist
else:
a = (mylist[0][0]) - (mylist[0][-1])
if a < sublist(mylist[1:]):
return mylist[0]
sublist([[1,199,58],[1,2],[3,8]])
This part, ( sublist(mylist[1:]) ) i know is clearly wrong. I'm trying to compare the value a, with the values from the mylist[1:]. I would appreciate much advice here.
Updated:
def differences(mylist):
diff = max(mylist) - min(mylist)
return diff
def sublist(nestedlist):
if len(nestedlist) == 1:
return nestedlist[0]
else:
if differences(nestedlist[0]) < differences(sublist(nestedlist[1:])):
return nestedlist[0]
else:
return sublist(nestedlist[1:])
print(sublist([[1,199,59],[1,2],[3,8]]))
i am assuming that you want to use recursion for the first level of the list. So, without giving you the code 100%, you have to do something like that:
1) create a method e.g diferences(list) that calculates the differences of a list and returns a list with the parameter list and the min difference i.e differences([1,2]) should return [1, [1,2]]. call it once on the first sublist i.e min = differences(mylist[0])
2) create your sublist method like this:
def sublist(initial_list):
# 1) call differences() method for the first sublist of the 'initial_list'
# 2) update 'min' with differences(initial_list[0])if differences(inilitial_list[0])[0] < min[0];
# 3) call sublist() again now removing the sublist you checked before from the arguement
# 4) (the following should be at the start of your sublist() method)
if len(initial_list) = 1:
if differences(initial_list) < min:
return initial_list
else: return min[1]
Hope that helps

Resources