Python - Head or Tail Exercise [duplicate] - python

This question already has answers here:
Selection sort program python
(2 answers)
Closed 7 years ago.
I need a small tips to finished this exercise.
The program should display head or tail after the for loop generate a sequence of 0 and 1. This module contains a number of random number generators:
import random
# function to determine head or tail of printed random number
def flip(coin):
# if the coin is zero, then print head
if coin == 0:
print("heads!")
# else print tail
else:
print("Tail!")
# simple repeat loop that calls flip() 10 times to generate a random
# sequence of 10 heads and tails
def main():
for coin in range(10):
print (random.randrange(2))
main()

you need to call the flip function. Also I would recommend using random.randint()
import random
#function to determine head or tail of printed random number
def flip(coin):
#if the coin is zero, then print head
if coin == 0:
print("heads!")
#else print tail
else:
print("Tail!")
#simple repeat loop that calls flip() 10 times to generate a random
#sequence of 10 heads and tails
def main():
for coin in range(10):
flip(random.randint(0, 1))
main()

You need to call the flip function, passing it the result of that random.randrange(2) call:
print (flip(random.randrange(2)))
As Padraic points out in comments, your code will also output None, because it's printing the returned value from the called function, and no return statement produces an implicit None. You can fix this in one of two ways: either have flip return the result instead of printing it, or call it without printing.
if coin == 0:
return "heads!"
# else print tail
else:
return "Tail!"
or:
flip(random.randrange(2))

Related

How to keep track the amount of even integers when looking through randomized list using recursion

Sorta newbie here. So in trying to wrap my head around using recursive functions I wanted to try to make a program that:
1: Generates a list containing 10 random integers ranging from 0 - 20
2: Using a recursive function goes trough the list and finds out what elements of the list are even integers
3: Prints out only the aformentioned even numbers
Where I have gotten stuck is in how to print out the result. I can't seem to figure out what value i want to put inside the function when calling it ( F(?) )
I tried to integrate a counter that kept track on how many times the program found a even number but it always resulted in an error that the variable is not defined no matter how hard I tried to make it global.
How could I go about this? Am I totally in the wrong?
import random
numL = []
for i in range(10):
x = random.randint(0,20)
numL.append(x)
print(numL)
def F(x):
if numL[x] % 2 == 0:
return numL[x]
else:
return F(x+1)
print(F( ??? ))
First question asked on this forum, hopefully I did okay, appreciate any help!
Assuming you want to return a list of the even numbers then you have 4 cases to consider
This is the last number in the list and its even so return this number
This is the last number in the list and its odd dont retrun this number
There are more numbers to check and this number is even so return
this plus the function result
There are more numbers to check and this number is odd to return
only the function result and not this num
So we can code this as
import random
def get_even_nums(nums):
num = nums[0]
#This is our terminating case we definitivly return a value here
if len(nums) == 1:
return [num] if num % 2 == 0 else []
else:
#If we got here we will be recursivly calling the function
#If its even number return that number plus the result of the function
#it its not even then just return the reult of the function and not this num
if num % 2 == 0:
return [num] + get_even_nums(nums[1:])
else:
return get_even_nums(nums[1:])
numL = [random.randint(0, 20) for _ in range(10)]
print(numL)
print(get_even_nums(numL))
OUTPUT
[3, 6, 5, 10, 20, 18, 5, 0, 3, 9]
[6, 10, 20, 18, 0]
So I took your function and changed it up slightly (using a slightly different approach). There's no need to a global list, though you could do that as well, if you wanted. The problem that you have is the lack of a base case or rather an incorrect one.
If you run your original function with an argument 0, which basically is the first element of your generated array, the fucntion will run until it hits one even number. At that point it'll exit recursion, because the base case basically stops recursive calls once you hit an even number.
Now, to fix this, you have to approach the problem differently. I would put your generated array as the input argument to your function, then ask myself "What would be a good base case?" Probably one that stops your recursive calls once you reach the end of the input list.
if len(numL) == 0:
return ...
Also, we need a way to return the even numbers that we found during our search through the list. For that reason I'd introduce a new acc list, where we would append the even numbers that we found. Thus the function input arguments would be
def F(numL, acc):
...
Now, in the recursive call we should check wether the current element is even or not. If it is, great, we add it to the acc list and continue into the recursive call. If it's not, we don't add anything to the acc but just continue with recursion.
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
Putting it all together, we get:
def F(numL, acc):
if len(numL) == 0:
return acc
else:
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
where numL represents your generated list and acc represents the resulting list we'll return after we traverse the list.
This is your function (as I understand it, you wanted this):
import random
def F(i):
r = random.randint(0,20)
if r % 2 == 0:
print(r)
i += 1
if i != 10:
F(i)
F(0)

How does this while-loop compute? (x = function(x))

I'm doing a quiz from "Automate the Boring Stuff with Python", and after tinkering with the problem for a bit, I finally found a solution that worked (with a little help from a comp-sci buddy of mine). The quiz asks me to make program that executes a Collatz-sequence.
I understand the logic behind all of the code, EXCEPT for the final line.
Here's my code with a few comments:
def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
elif number % 2 == 1:
print(3 * number + 1)
return 3 * number + 1
guess = input("Your guess please ")
while guess != 1:
guess = collatz(int(guess))
The output of the program is a sequence of numbers, as the while-loop somehow re-iterates over the returned value of the function, and uses that for another computation.
My problem is with the last line. Here's how I understand it:
Once I enter the while-loop, my function "collatz" is called, using my input-value
The function is run, and my input is computed, and based on the input, I get either the even or odd calculation in return
Here's where my brain hurts!
Is the line "guess = collatz(...)" now constantly updating "guess" to be equal to the retuned value from the function? If this is the case, then I completely understand the flow. If it's not the case, then I don't understand how the returned value is constantly being used for new calculations.
Also, is this what is called "recursion"?
Short answer:
Yes.
Longer answer: (still short)
The collatz function is returning a value which is assigned to guess.
Also, this is not called recursion, recursion is a function which calls itself.
First, no, this is not a recursion. Recursion is a function that calls itself.
For instance this is a recursion:
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
return fibonacci(n-1) + fibonacci(n-2)
As you can see here fibonacci function will call fibonacci function ... But it also has an exit condition (n == 0, and n == 1). Without that, this would cause runtime error with message that maximum recursion depth exceeded. But if I am not mistaken, you can check what is the maximum depth of recursion with following command:
import sys
print(sys.getrecursionlimit())
On my computer, this number is 1000. If this number is to small for you, you can also set it with this command:
sys.setrecursionlimit(n)
About other thing. Your function is returning some calculated value and in your main loop, this is assigned to variable guess. So everytime, that main loop will go through, value of guess will also update

Finding multiples using recursion

Given 1 to 100 numbers, for multiples of 3 it should print "he" ,for multiples of 5 it should print "llo" ,for both multiples of 3 and 5 it should print "hello".
This is what I have:
for i in range (1,100):
if(i%3==0):
print("he")
elif(i%5==0):
print("llo")
elif(i%3==0 and i%5==0):
print("hello")
How would I do this recursively?
How about the code below?
def find_multiples(current, last_num=100):
# Base Case
if current > last_num:
return
result = ""
if current % 3 == 0:
result += "he"
if current % 5 == 0:
result += "llo"
if result:
print(f"{current}: {result}")
find_multiples(current+1, last_num)
find_multiples(1)
Base case is if current reaches last_num or the maximum number you'd like to check.
Here is a general outline for doing simple recursive things in python:
BASE_CASE = 1 #TODO
def f(current_case):
if current_case == BASE_CASE:
return #TODO: program logic here
new_case = current_case - 2 #TODO: program logic here ("decrement" the current_case somehow)
#TODO: even more program logic here
return f(new_case) + 1 #TODO: program logic here
Of course, this doesn't handle all possible recursive programs. However, it fits your case, and many others. You would call f(100), 100 would be current_value, you check to see if you've gotten to the bottom yet, and if so, return the appropriate value up the call stack. If not, you create a new case, which, in your case, is the "decrement" logic normally handled by the "loop" construct. You then do things for the current case, and then call the function again on the new case. This repeated function calling is what makes it "recursive". If you don't have an "if then" at the beginning of the function to handle the base case, and somewhere in the function recall the function on a "smaller" value, you're probably going to have a bad time with recursion.
This recursive function prints multiples of a number! hope it helps
def multi(n,x):
if x == 12:
print(n*x)
else :
print(n*x,end =",")
multi(n,x+1)
print(multi(4,1));

Change range start in Python 'for loop' for each iteration

I'm a novice and learning python (using 2.7). I'm attempting some simple scripts to test how python handles different types of loops.
My question is: can python change the starting point of the "range" function on each iteration if the start point is assigned to a variable? Here is an example of my code:
def build(n, period):
n2 = n
for digit in range(int(n2), 20):
print "At the top i is %d" % n
digit += period
numbers.append(digit)
print "Numbers now:", numbers
print "At the bottom i is %d" % digit
print "The Numbers:"
n2 += period
for num in numbers:
print num
key = raw_input("Press 1 to call function \"build\", press any other key to quit.")
if key == "1":
i = raw_input("What integer is our start value?")
amt = raw_input("What is the common difference?")
numbers = [int(i)]
build(int(i),int(amt))
else:
quit()
I tried to use a second local variable 'n2' inside the function so I could keep the initial value of 'n' constant and then redefine the range for each iteration. The very first number in the appended list moves by the common difference but after that it always steps by +1 integer. I can easily make this happen with a 'while' loop but curious if a 'for' loop can be used to accomplish this?
range creates a fixed list the moment you call that function at the beginning of your for loop. You can think of the top of the for loop as assigning n2 to the next element of that list no matter what you do inside the loop. If you want to change the period of the range, use the third argument:
range(n, 20, period)
will move in steps of size period through the range instead of steps of size one.
It won't work in a way you expect. Expression range(int(n2), 20) gets evaluated only one time in the beginning of for-loop. You can't change the scope of a for-loop that way.
What you can modify is a step parameter in range function, but it does not change your starting point - it only defines what is the next element in the iteration process.

Randomly calling functions to execute

I have made this short questionnaire:
from random import randint
def pancakes():
q = raw_input("Do you like pancakes?")
if q == "yes":
print("Great!")
elif q == "no":
print("Hmmm...")
def french_toast():
q = raw_input("Do you like french toast?")
if q == "yes":
print("Oh!")
elif q == "no":
print("Same here!")
def random():
num = 2
while num > 0:
random = randint(1, 2)
if random == 1:
num = num -1
pancakes()
elif random == 2:
num = num -1
french_toast()
random()
My goal here was to get the questions in a random order. But sometimes the same question will be asked twice since it's randomly chosen.
So how can I make it ask the same question only once?
Instead of a while loop, I'd suggest you use a for loop in conjunction with random.sample. Create a list of functions before-hand to provide to sample:
from random import sample
funcs = [french_toast, pancakes]
for func in sample(funcs, len(funcs)):
func()
this will now loop through all functions randomly selecting a function in each iteration.
Alternatively, you could shuffle the list (performs in-place) with random.shuffle and then iterate through it, that will be faster too (though, speed shouldn't be the biggest concern here):
from random import shuffle
funcs = [french_toast, pancakes]
shuffle(funcs)
for func in funcs:
func()
Put these in a function if so required:
from random import shuffle
# use *funcs for passing arbitrary number of
# functions as positional arguments.
def call_funcs_randomly(funcs):
shuffle(funcs)
for func in funcs:
func()
and call them:
call_funcs_randomly([french_toast, pancakes])
As a comment noted, don't use random as a function name, it has the possibility of masking the module random leading to odd looking errors.
I would use random.sample Link. Just create a list of indices to your questions and sample 2 of them.
EDIT:
additionally, you could use random.shuffle Link:
random.shuffle(questions)
for question in questions:
# process your random question once
how about this for your last question (random is not a good name! you might overwrite the module of the same name [although you are fine the way do do it right now])
def random_questions():
eligible_questions = [pancakes, french_toast]
while eligible_questions:
question = random.choice(eligible_questions)
eligible_questions.remove(question)
question()
put the questions in a list, select one with random.choice, remove it from the list and execute it. stop if the question list is empty. this way every question is selected exactly once.
this is easily extended if you want to add more questions.
on second thought: the shuffle version in Jim Fasarakis-Hilliard's answer is a lot cleaner!

Categories

Resources