How do I split this into maybe 2 or 3 functions? - python

I was just wondering how do I split this into different functions say like maybe 2 or 3 functions? I'm not that good with passing parameters with functions yet. Would you recommend doing that or should I keep it the way it is in one function since it's a while loop? By the way it's for a beginner programming class so that's why its pretty long.
def sumOfDoublePlace(userChoice):
lenChecker = len(str(userChoice))
counter = 0
sumNumber = 0
userChoice = int(userChoice)
while counter < lenChecker-1:
counter += 1
endDigit, userChoice = divmod(userChoice, 10)
if counter % 2 == 0:
evenNumber = endDigit * 2
if evenNumber < 10:
sumNumber = sumNumber + evenNumber
else:
oddDigit = endDigit % 10
firstDigit = endDigit // 10
oddSum = oddDigit + firstDigit
sumNumber = sumNumber + oddSum
else:
sumNumber = sumNumber + endDigit
if sumNumber % 10 == 0:
print('This card is valid')
else:
print('This card is invalid')

Overall, I think this should be a single routine. However, you are taking a somewhat tortuous path to the solution. You're doing a lot of work to pull digits out of the integer version of the card number, when they're perfectly accessible in the original text.
Here's a start on accessing the string positions you need:
def isValidCardNumber(cardNumber):
num_len = len(cardNumber)
last = int(cardNumber[-1]) # grab the last digit; convert to integer
odds = cardNumber[0:-1:2] # positions 0, 2, 4, ... last-1
evens = cardNumber[1:-1:2] # positions 1, 3, 5, ... last-1
# For each list of digits, make a list of their integer equivalents.
# ... and immediately take the sum of those integers.
odd_sum = sum([int(digit) for digit in odds])
even_sum = sum([int(digit) for digit in evens])
I leave the rest of this to you. :-)

Related

Finding number with specified collatz sequence length

I need to make a program that finds a number with specified collatz sequence length. However, there is always a problem that the program is too slow. For example my current best score that i could get was number with collatz sequence length of 1200 (I need to be able to get number with collatz sequence length of 1800).
I tried a lot of diffrent methods, but the best one so far was trying to recreate collatz number tree.Here is an example from wiki. As I said before i need to be able to get a number with collatz sequence length of 1800 but I cant get more than 1200.
That's my current solution (I know it's complicated but other methods I tried so far were able to get collatz sequence length up to 500 only):
A = int(input())
limit = 1000000000000000000
def runCollaz(ciag):
steps = 0
while ciag != 1:
if (ciag % 2 == 0):
ciag /= 2
else:
ciag *= 3
ciag += 1
steps+=1
return steps
def makeChainLess(number):
if (number % 2 == 0):
return number / 2
else:
return ((number * 3) + 1)
collatzTree = [[1, 1]]
finallAns = "None"
def getAns(collatzTree, what):
awnser = "None"
if (collatzTree[0][0] < limit and collatzTree[0][1] == A):
awnser = collatzTree[0][0]
while (len(collatzTree) > 250):
currentHigh = collatzTree[0][0]
highIndex = 0
index = 0
for x in collatzTree:
if (x[0] > currentHigh):
currentHigh = x[0]
highIndex = index
index += 1
collatzTree.pop(highIndex)
if (collatzTree[0][0] > 4):
if (collatzTree[0][0] - 1) % 3 == 0:
if (collatzTree[0][0] - 1) % 2 != 0:
collatzTree += [[(collatzTree[0][0] - 1) / 3, int(collatzTree[0][1]) + 1]]
collatzTree += [[collatzTree[0][0] * 2, int(collatzTree[0][1]) + 1]]
collatzTree.pop(0)
else:
collatzTree += [[collatzTree[0][0] * 2, int(collatzTree[0][1]) + 1]]
collatzTree.pop(0)
else:
collatzTree += [[collatzTree[0][0] * 2, int(collatzTree[0][1]) + 1]]
collatzTree.pop(0)
if (what == "C"):
return collatzTree
else:
return awnser
while finallAns == "None":
finallAns = getAns(collatzTree, "A")
collatzTree = getAns(collatzTree, "C")
print(int(finallAns))
If anyone could help i would really appricate it.
Here is a simple code that takes only a few minutes to run for 10 million. It just needs more computing power, which is kind of the story on Collatz.
'''
This code finds numbers that have the specified Collatz sequence length
(by brute force)
'''
import time
start = time.time() #start code timer
n = 1 #set low end of range
for number in range (10000000, n-1, -1): #work down from max range
num = number
trial = 0
while number > 1: #set up looping until 1 is reached
if number % 2 == 0: #set up normal Collatz sequence comp.
number = number // 2
else:
number = (number * 3) + 1
trial = trial+1 #update counter for each loop
if number == 1 and trial == 500 or trial == 600: #set target numbers
#print all numbers where specified target occured:
print("Number with sequence "
"length of {0}: {1}".format(trial, num))
if number == n:
print("end of range") #tells user that code has ended
end = time.time()
print("elapsed time: ",end - start)

How do I keep a loop going with a variable that changes in every loop

So I'm new to coding and I'm struggling with the following exercise
So we start with a random number and we have to count the even numbers and the odd numbers. With this, we make a second number that starts with the amount of the even numbers, amount of the odd numbers, and the amount of numbers in total. We should continue this until the number 123 is reached.
For example:
number = 567421 --> odd numbers = 3 , even numbers = 3 , total numbers = 6 --> new number = 336 -->...
I had an idea to write it like this:
number = input()
evennumbers = ''
oddnumbers = ''
a = len(number)
while number != '123':
for i in str(number):
if int(i) % 2 == 0:
evennumbers += i
else:
oddnumbers += i
b = len(evennumbers)
c = len(oddnumbers)
number = input(print(f"{b}{c}{a}"))
But I have no idea how to keep this loop going with the variable 'number' until 123 is reached
You need your variable initialization to be inside the while loop, and remove the input(print(... on the final line.
number = '567421'
while number != '123':
print(number)
evennumbers = ''
oddnumbers = ''
a = len(number)
for i in str(number):
if int(i) % 2 == 0:
evennumbers += i
else:
oddnumbers += i
b = len(evennumbers)
c = len(oddnumbers)
number = f"{b}{c}{a}"
You could simplify like this:
while number != '123':
print(number)
total = len(number)
odds = sum(int(digit) % 2 for digit in number)
evens = total - odds
number = f"{evens}{odds}{total}"

hailstone program in python

i have to write a hailstone program in python
you pick a number, if it's even then half it, and if it's odd then multiply it by 3 and add 1 to it. it says to continue this pattern until the number becomes 1.
the program will need methods for the following:
accepting user input
when printing the sequence, the program should loop until the number 1.
print a count for the number of times the loop had to run to make the sequence.
here's a sample run:
prompt (input)
Enter a positive integer (1-1000). To quit, enter -1: 20
20 10 5 16 8 4 2 1
The loop executed 8 times.
Enter a positive integer (1-1000). To quit, enter -1: 30
30 15 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1
The loop executed 19 times.
Enter a positive integer (1-1000). To quit, enter -1: -1
Thank you for playing Hailstone.
right now i have this:
count = 0
def hailstone(n):
if n > 0
print(n)
if n > 1:
if n % 2 == 0:
hailstone(n / 2)
else:
hailstone((n * 3) + 1)
count = count + 1
i don't know what to do after this
Try to think in a modular way, make two functions: check_number() and user_call(). Check_number will verify if the current number in the loop is odd or even and the user_call() just wraps it to count how many times the loop did iterate.
I found the exercise in a great book called Automate Boring Stuff with Python, you have to check it out, if you don't know it already.
Here's my code. Try to use what serves you the best.
from sys import exit
def check_number(number):
if number % 2 ==0:
print(number // 2)
return(number // 2)
else:
print(number*3+1)
return number*3+1
def user_call(number):
count = 0
while number != 1:
count += 1
number = check_number(number)
return count
if __name__ == "__main__":
try:
number = int(input('Give a number \n'))
count = user_call(number)
print('count ',count)
except Exception as e:
exit()
you can use global
visit https://www.programiz.com/python-programming/global-keyword to learn more
import sys
res = []
def hailstone(number):
global res
if number > 1:
if number % 2 == 0:
res.append( number // 2 )
hailstone(res[len(res)-1])
else:
res.append(number * 3 + 1)
hailstone(res[len(res)-1])
return res
number = int(input('Enter a positive integer. To quit, enter -1: '))
if number <= 0 or number == 0:
print('Thank you for playing Hailstone.')
sys.exit()
else:
answers = hailstone(number)
for answer in answers:
print(answer)
print('The loop executed {} times.'.format(len(answers) + 1))
I used recursion to solve the problem.
Heres my code:
Edit: All criteria met
count = 0
list_num = []
def input_check():
number = int(input("Enter a positive integer (1-1000). To quit, enter -1: "))
if number >= 1 and number <= 1000:
hailstone_game(number)
elif number == -1:
return
else:
print("Please type in a number between 1-1000")
input_check()
def hailstone_game(number):
global count
while number != 1:
count += 1
list_num.append(number)
if number % 2 == 0:
return hailstone_game(int(number/2))
else:
return hailstone_game(int(number*3+1))
list_num.append(1) # cheap uncreative way to add the one
print(*list_num, sep=" ")
print(f"The loop executed {count} times.")
return
input_check()
Additional stuff that could be done:
- Catching non-integer inputs using try / except
Keep in mind when programming it is a good habit to keep different functions of your code separate, by defining functions for each set of 'commands'. This leads to more readable and easier to maintain code. Of course in this situation it doesn't matter as the code is short.
Your recursive function is missing a base/terminating condition so it goes into an infinite loop.
resultArray = [] #list
def hailstone(n):
if n <= 0: # Base Condition
return
if n > 0:
resultArray.append(n)
if n > 1:
if n % 2 == 0:
hailstone(int(n/2))
else:
hailstone((n * 3) + 1)
# function call
hailstone(20)
print(len(resultArray), resultArray)
Output
8 [20, 10, 5, 16, 8, 4, 2, 1]
Here's a recursive approach for the problem.
count=0
def hailstone(n):
global count
count+=1
if n==1:
print(n)
else:
if n%2==0:
print(n)
hailstone(int(n/2))
else:
print(n)
hailstone(3*n+1)
hailstone(21)
print(f"Loop executed {count} times")

Nested Triangle in Python

My assingment
At each level the complete triangle for the previous level is placed into an extra outer triangle. The user should be asked to input the two characters to be used and the width of the innermost triangle, which must be odd. In addition to the test for negative input the function should test whether the supplied number is odd and display an appropriate message if it is not.
I need to print 3 triangles but every one of them includes other. It needs to get printed with two different character(like *-) and the user have to specify the length of innermost triangle and which has to be an odd number. Example,
Example output for 5 value
Ok, let me explain my way,
Every triangle should be in dictionary.
tri1 = {1:"*****", 2:"***", 3:"*"}
tri2 = {1:"..........", ...}
And couldn't find how I can deal with user input?
If enter 5,
length - 5 unit, height 3 unit
length - 11 unit, height 6 unit
length - 23 unit, height 12 unit.
How can i know? What is the logic?
Ok lets say if I did. I understand I should put a tringle in another triangle with nested loop, can simply iterate it another dictionary but, I need to check second character's position.
Thanks in advance.
My code,
ch1, ch2 = input("Please enter the characters you want to use: ")
num = int(input("Please specify the length of innermost triangle(only odd number): "))
if (num % 2 == 0) or (num < 3):
print("Number can not be even, less then 3 and negative")
num2 = (2 * num) + 1
num3 = (2 * num2) +1
tri1 = {}
tri2 = {}
tri3 = {}
for i in range(3):
tri1[i] = ch1*num
num -= 2
check = 1
cont = 0
var = 1
for ii in range(6):
tri2[ii] = ch2*check
check += 2
if (ii >= 3):
tri2[ii] = ch2*var + tri1[cont] + ch2*var
cont += 1
var += 2
for i in tri1:
print('{:^5}'.format(tri1[i]))
for i in tri2:
print('{:^11}'.format(tri2[i]))
The dictionary can be created using a simple function:
def create_tri_dict(tri_chars, tri_height):
level_str = {0:tri_chars[0]}
for i in range(1,tri_height):
level_length = i *2 +1
tri_char = tri_chars[i%2]
level_str[i] = level_str[i-1] + '\n' + tri_char * level_length
return level_str
Then the main logic of your program could be:
tri_chars = input('Input triangle characters: ')
tri_length = int(input('Input triangle base length: '))
tri_height = (tri_length + 1)//2
if tri_length %2 == 0:
raise Exception('Triangle base length not odd')
tri_dict = create_tri_dict(tri_chars, tri_length)
Then to print the final 3(?) triangles:
print(tri_dict[tri_height-2])
print(tri_dict[tri_height-1])
print(tri_dict[tri_height])

Do I cover all possible scenarios in this basic maths & subtraction Python script?

I'm currently learning maths through Khan Academy and I'm creating a program in Python's IDLE to give me randomized questions so that I can practice maths. So far I've just done addition and subtraction and would like to check that I'm covering all possible sum scenarios under 7 digits (9999999). This is the basic addition script:
def one_digit_addition():
counter = 0
target = 5
while counter < target:
random_digit_one = random.randint(0, 9)
random_digit_two = random.randint(0, 9)
print "What is %s + %s?" % (random_digit_one, random_digit_two)
answer = random_digit_one + random_digit_two
userAnswer = int(raw_input("Answer: "))
if userAnswer == answer:
counter = counter + 1
print "\n*CORRECT*, your score is %s. Next question...\n" % counter
elif userAnswer != answer:
counter = counter - 5
print "\n*INCORRECT*! Your score is %s. Next question...\n" % counter
if counter == 5:
print "**CONGRATULATIONS, you've passed one digit addition. Now loading two digit addition...**\n"
two_digit_addition()
After this one_digit_addition function I have functions of the copied code above going right up to seven digit addition. The only difference is is that I've added an extra 9 to both the random integer variables each time. Here's the subtraction script:
def one_digit_subtraction():
counter = 0
target = 5
while counter < target:
random_digit_one = random.randint(0,9)
random_digit_two = random.randint(0,9)
if random_digit_one > random_digit_two:
print "What is %s - %s?" % (random_digit_one, random_digit_two)
answer = random_digit_one - random_digit_two
else:
print "What is %s - %s?" % (random_digit_two, random_digit_one)
answer = random_digit_two - random_digit_one
userAnswer = int(raw_input("Answer: "))
if userAnswer == answer:
counter = counter + 1
print "\n*CORRECT*, your score is %s. Next question...\n" % counter
elif userAnswer != answer:
counter = counter - 5
print "\n*INCORRECT*! Your score is %s. Next question...\n" % counter
if counter == 5:
print "**CONGRATULATIONS, you've passed one digit subtraction. Now loading two digit subtraction...**\n"
two_digit_subtraction()
It's the same for this script. I've copied the code and added a 9 integer to the number variables. My main concern is that I'm missing out certain sums with this current formula. I basically would like there to be a chance of there being every possible sum combination <= 999999999. I hope this question was worded better than my last one.
Try to parametrise your function in order to avoid the repetitions.
For instance with this:
import random
import operator
ops = {'+' : operator.add, '-': operator.sub, '*': operator.mul}
def quiz (operator, digits):
start = 10 ** (digits - 1) if digits > 1 else 0
a = random.randint (start, 10 ** digits - 1)
b = random.randint (start, 10 ** digits - 1)
if operator == '-' and a < b: a, b = b, a
r = input ('What is {} {} {}? '.format (a, operator, b) )
try: return int (r) == ops [operator] (a, b)
except ValueError: return False
You can ask for a 2-digit addition with quiz('+', 2) for a three digit subtraction with quiz('-', 3) or for a 1-digit multiplication with quiz('*', 1). In each case the function returns True iff the user answered correctly.
For python2 replace input with raw_input.

Categories