Difference between Python 3.x and Python 2.x in while loop - python-3.x

I have this piece of code, which I had written a few weeks ago. Initially I wrote it for Python 2.7 and it works very well, but I decided some time ago to just abandon it, and move to Python 3.7. Can anyone explain me why this while loop is infnite and doesn't want to fullfill those conditions?
In Python 2.7 this code allows me to browse between my files of data, and those amateurs tricks in my code allows me to handle obstackles such as changing hour after 60 minutes or date after 24 hours. Still have no idea how to convert it to Python 3.
# Input variables
h = "Arctic"
u = 'Denver'
p = 'Patagonia'
Station = input('Enter a station name (Arctic = h, Denver = u, Patagonia = p): ')
Date = input('Enter date time (yyyymmdd): ')
Date_end = input('Enter end date time (yyyymmdd): ')
Start_time_hours = int(input('Enter start time (hh): '))
Start_time_minutes = int(input('Enter start time (mm): '))
End_time_hours = int(input('Enter end time (hh): '))
End_time_minutes = int(input('Enter end time (mm): '))
Save_Print_SavPrin = input('Press s = Save, p = Plot: ')
while Start_time_hours == Start_time_hours and Start_time_minutes == Start_time_minutes and Date == Date:
Start_time_hours += (Start_time_minutes / 60)
Start_time_minutes %= 60
str(Start_time_minutes)
str(Start_time_hours)
str(End_time_minutes)
str(End_time_hours)
Start_time_hours_format = '{:02}'.format(Start_time_hours)
Start_time_minutes_format = '{:02}'.format(Start_time_minutes)
End_time_hours_format = '{:02}'.format(End_time_hours)
End_time_minutes_format = '{:02}'.format(End_time_minutes)
int(Start_time_minutes)
Start_time_minutes += 5
if Save_Print_SavPrin == "p":
print("Showing figures...")
print ("Succesful!")
if Start_time_hours_format == End_time_hours_format and Start_time_minutes_format == End_time_minutes_format and Date == Date_end:
print (Start_time_hours_format, Start_time_minutes_format, End_time_hours_format, End_time_minutes_format)
break

First, your loop condition is an infinite loop, because you're comparing variables to ... themselves. So you can replace by while True: (valable for both python versions)
Now the problematic code is this:
Start_time_hours += (Start_time_minutes / 60)
in python 3, / 60 performs floating point division, even between integer operands. The result is that now Start_time_hours is a float, and can never be equal to End_time_hours, which is an integer (the if Start_time_hours_format == End_time_hours_format test always fails, specially because you're converting both to string).
The fix (works for both versions) is to force integer division:
Start_time_hours += (Start_time_minutes // 60)
Aside, doing str(something) alone on a line isn't going to turn that something into a string unless you assign it back to something. You can remove all those statements, as they're useless anyway.

Related

Just started python and working through Automate The Boring Stuff with Python. Any recommendations on cleaning my code?

New here at stackoverflow. I'm learning python right now and picked up the book Automate the Boring Stuff with Python. Need some recommendations or tips on how to clean up my code. Here is one of the small projects from the book:
Write a function named collatz() that has one parameter named number. If number is even, then collatz() should print number // 2 and return this value. If number is odd, then collatz() should print and return 3 * number + 1. Then write a program that lets the user type in an integer and that keeps calling collatz() on that number until the function returns the value 1.
The output of this program could look something like this:
Enter number:
3
10
5
16
8
4
2
1
Here's the code I came up with. Any recommendations on cleaning up the code or is this good enough? Thank you all!
def collatz(number):
if number % 2 == 0: # Even numbers
print(number // 2)
return number // 2
elif number % 2 == 1: # Odd numbers
result = 3 * number + 1
print(result)
return result
while True: # Made a loop until a number is entered
try:
n = input("Enter a random number: ")
while n != 1:
n = collatz(int(n))
break
except ValueError:
print("Enter numbers only.")
Use else in the place of elif , it will give same reasult.
Optimized for readability and usage, not on performance.
def collatz(number):
print(n)
return number // 2 if number % 2 == 0 else 3 * number + 1
while True: # Made a loop until a number is entered
try:
n = input("Enter a random number: ")
while n != 1: n = collatz(int(n))
break
except ValueError: print("Enter numbers only.")

'You must prompt for the data '-says in python coding problem, but I don't know what's wrong with my code?

Write a program to prompt the user for hours and rate per hour using input to compute gross pay. Pay should be the normal rate for hours up to 40 and time-and-a-half for the hourly rate for all hours worked above 40 hours. Put the logic to do the computation of pay in a function called computepay() and use the function to do the computation. The function should return a value. Use 45 hours and a rate of 10.50 per hour to test the program (the pay should be 498.75). You should use input to read a string and float() to convert the string to a number. Do not worry about error checking the user input unless you want to - you can assume the user types numbers properly. Do not name your variable sum or use the sum() function.
I tried this using my pc IDE and got similar output as required. But I got error that:
You must prompt for the data.
What's the problem? I mean,when do we get such errors?
prompt1 = "Enter Hours:"
prompt2 = "Enter Rate:"
def computepay(h,r):
if h > 40:
pay = ((h -40)*.5 + h)*10.50
else:
pay = h*10.50
return pay
hrs = int(input(prompt1))
rate = float(input(prompt2))
ans = computepay(hrs,rate)
print("Pay",ans)`
Try this :
hrs = input("Enter Hours : ")
rate = input("Enter rate : ")
Fhours = float(hrs)
Frate = float(rate)
def computepay(Fhours,Frate):
if Fhours <= 40 :
p=Fhours*Frate
else:
p=((40 * Frate) + ((Fhours - 40) * (Frate * 1.5)))
return p
p = computepay(Fhours,Frate)
print("Pay",p)
By the way it's an assignment from cousera "python for everybody" :)
Here is what I did for your problem. Hope this helps.
#Beaufuh
#Follow me on Twitter #Beaufuhh
#Try getting the user's input as a number
try:
hours = float(input('Enter hours: '))
rate = float(input('Enter hourly rate: '))
#if user's input is not a number return Entry error.
except ValueError:
print('Entry error. ')
#if the user's input is more than 40, calculate overtime.
if hours > 40:
overtime = float(hours - 40)
#Tell the user how many hours they worekd and what they earned for the week, with overtime considered.'''
print(f'You worked {hours} hours this week and earned ${(hours*rate) + (overtime*(rate*1.5))} dollars.')
#Tell the user how many hours they worked and what they earend for the week.
else:
print(f'You worked {hours} hours this week and earned ${(hours*rate)} dollars.')
The system of py4e require you to get the rate from user. I see you use "10.5" instead of "r" for python to compute, just change the function like this:
if h>=40:
pay = ((h -40)*.5 + h)****r*** (10.5 - r)
return ans
The question requires input from the prompt
But in the existing code a parameterized function is used so we need to change that code to a simple function.
Use the code given below. It will work.
Hrs = input("Enter Hours:")
Pay = input("Enter Pay: ")
hrs = float(Hrs)
pay = float(Pay)
def computepay(hrs,pay):
if hrs <= 40 :
p=hrs*pay
else:
p=((40 * pay) + ((hrs - 40) * (pay * 1.5)))
return p
d = computepay(hrs,pay)
print("Pay",d)
I had a similar issue, the problem was - I was not passing 2 arguments to the function, once that was fixed it worked well. Below is the code.
def computepay(hours,rate_per_hr):
if hours:
grosspay = hours * rate_per_hr
if hours > 40:
grosspay += (hours-40)* rate_per_hr * 0.5
return grosspay
hours = float(input("Enter the hours: "))
rate_per_hr = float(input("Enter the rate: "))
print('Pay',computepay(hours,rate_per_hr))
The error occurred because you have used a given value for the rate which is supposed to be prompted. Try removing the value of 10.50 in your program and replace it with a given variable in your case (r). This has to be prompted by the user, remember that. See this,
p = 40*r +(h-40)*1.5*r
You need to put hrs and rate inside the function
I did it like this and it worked:
def computepay(h, r):
h = int(hrs)
r = float(rate)
if h <= 40:
totalpay = h * r
else:
totalpay = (((h-40) * (r* 1.5)) + (40 * r))
return totalpay
hrs = input("Enter Hours:")
rate = input("Enter Rate:")
p = computepay(hrs, rate)
print("Pay", p)
I've got the same "error" message. So I guess he problem is you count with the fix value for the rate (10.50). Try to use your rate variable instead of the fix10.50 value
you may write the exact amounts in the arguments. Try to write variable names.
Try This:
Code
You will get the desired result!

Why does my solution to problem 3 of the CodeJam 2020 Qualification Round not work?

I would like to receive help in understanding why my solution to Problem 3 of the Google CodeJam 2020 Qualifier does not work.
Link to problem: https://codingcompetitions.withgoogle.com/codejam/round/000000000019fd27/000000000020bdf9
My solution:
High-level overview:
take input
figure out if the given input is impossible by sorting according to start times and then checking if more than 2 subsequent activities are 'active' at once (which is impossible)
if it is, output accordingly; if it isn't, proceed with the procedure below
arbitrarily assign the first person: in my solution I choose Cameron (C).
next, since we know that a solution exists, and the array I iterate through is sorted according to start times, if the very next activity interval (chronologically) overlaps in its duration with the current, assign it to the person who is not currently busy. This is purely because a solution exists, and it clearly cannot be the current person, so it must be the other.
moreover, if the very next activity interval (chronologically) does not overlap with the current activity, then assign it to the person who is currently busy (because he will not be busy for the next activity)
in addition, quoted directly from the problem's official analysis: "If an assignment is possible, there cannot be any set of three activities that pairwise overlap, so by the contrapositive of the the previous argument, we will be able to assign the activity to at least one of Jamie or Cameron at every step."
At this moment, I believe that these arguments suffice to show that my logic is valid, although my code evidently does not always produce the correct answer. I would greatly appreciate any help on this, since I have spent hours trying to debug, un-reason, or find a counter-example to my code to no avail. I have included my code, for reference, below.
Code:
for p in range(int(input())):
s = int(input())
l = []
for i in range(s):
l.append(list(map(int, list(input().split()))))
unsort = l.copy()
l = sorted(l, key=lambda tup: (tup[0],tup[1]))
enumerated = list(enumerate(unsort))
enumerated.sort(key=lambda x: x[1][0])
impossible = False
endings = sorted([(x[1], False) for x in unsort])
startings = sorted([(x[0], True) for x in unsort])
total = sorted(endings + startings, key=lambda tup: (tup[0], tup[1]))
size = 0
for i in total:
if i[1] == True:
size += 1
else:
size -= 1
if size > 2:
impossible = True
def overlap(a,b):
if not max(a[0], b[0]) >= min(a[1], b[1]):
return True
else:
return False
ans = "C"
def opp(a):
if a == "C":
return "J"
else:
return "C"
if impossible == True:
print("Case #" + str(p+1) + ": " + "IMPOSSIBLE")
else:
for i in range(0, s-1):
if overlap(l[i], l[i+1]) == True:
ans = ans + opp(ans[len(ans)-1])
else:
ans = ans + opp(opp(ans[len(ans)-1]))
#the stuff below is to order the activity assignments according to input order
key_value = [(ans[i], l[i]) for i in range(s)]
fans = ""
for i in range(s):
for j in range(s):
if enumerated[j][0] == i:
fans = fans + key_value[j][0]
print("Case #" + str(p + 1) + ": " + fans)

Element-wise manipulation of a two dimensional list in python

I am writing a script to find meeting time for three people. I manage to get their Free/Busy status encoding in a binary format with 0 being free and 1 being busy in increment of 30 minutes for the next three days. I grouped their status by day into a dictionary format as below.
print(date_schedule)
{'Monday, 2020-02-03': ['000000000000000000101101001110110000000000000000',
'000000000000000000001111011100001100000000000000',
'000000000000000011110100011000110000000000000000'],
'Tuesday, 2020-02-04': ['000000000000000000100010000000000000000000000000',
'000000000000000000001111001000110000000000000000',
'000000000000000011111000111100101000000000000000'],
'Wednesday, 2020-02-05': ['000000000000000000111000000000000000000000000000',
'000000000000000001001100110000000000000000000000',
'000000000000000000111100000001001000000000000000']}
Goal: Translate those 0 into a block of thirty minutes intervals.
For Example: 00:00----00:30
00:30----01:00
...
23:30----24:00
Attempted:
#Separate the code into a two dimensional list
schedule = date_free.values()
#Append the block to a new list.
free = []
for value in schedule:
for v in value:
for idx, time in enumerate(v):
if time == '0':
idx = idx/2
end = idx + 0.5
#5 slots, and two decimals
idx = '{:05.2f}'.format(idx).replace('.50','.30').replace('.',':')
end = '{:05.2f}'.format(end).replace('.50','.30').replace('.',':')
free.append((idx + '----' + end))
Problem: free has 372 elements and I don't know how to make it become a two-dimensional-list structure as it was before in schedule (because the number of 0 is different for each v). Is there a way to not creating a new list but directly apply the above logic element-wise to schedule?
Bonus question: I have not gotten there yet, but my next goal is to find the intersection of those 30 time block for each day as demonstrated in the random example below. If you have any suggestions, please let me know
print(date_time_final)
{'Monday, 2020-02-03': ['08:00----08:30','09:30----10:00','12:00----12:30'],
'Tuesday, 2020-02-04' : ['09:00----09:30','10:30----11:00','13:00----13:30','14:00----14:30']
'Wednesday, 2020-02-05' : ['07:00----07:30','14:30----15:00','15:00----15:30','19:00----19:30']}
Thank you in advance for your help!
Is something like this what you were looking for?
schedule = {'Monday, 2020-02-03': ['000000000000000000101101001110110000000000000000',
'000000000000000000001111011100001100000000000000',
'000000000000000011110100011000110000000000000000'],
'Tuesday, 2020-02-04': ['000000000000000000100010000000000000000000000000',
'000000000000000000001111001000110000000000000000',
'000000000000000011111000111100101000000000000000'],
'Wednesday, 2020-02-05': ['000000000000000000111000000000000000000000000000',
'000000000000000001001100110000000000000000000000',
'000000000000000000111100000001001000000000000000']}
combined = {}
for value in schedule:
day = {}
for v in schedule[value]:
for idx, time in enumerate(v):
idx = idx/2
end = idx + 0.5
#5 slots, and two decimals
idx = '{:05.2f}'.format(idx).replace('.50','.30').replace('.',':')
end = '{:05.2f}'.format(end).replace('.50','.30').replace('.',':')
if time == '0':
try: #Only assigns "True" if value does not yet exist and is not already False
if day[idx + '----' + end] == False:
pass
else:
day[idx + '----' + end] = True
except:
day[idx + '----' + end] = True
elif time == '1':
day[idx + '----' + end] = False
combined[value] = day
for day in combined:
print(day)
for time_slot in combined[day]:
print("Time slot %s is free = %s" % (time_slot, str(combined[day][time_slot])))
Instead of lists, I used dictionary format to sort by day and by time slot, maintaining every time slot on record, but giving them a boolean value to determine if its free or not. (True == free, False == busy)
That way you can do whatever you like with the output.

Check if number has a digit multiple times

I've come across a puzzling challenge. I have to check if a number contains the same digit multiple times ex. 11, 424, 66 and so on. at first this seems easy enough but i'm having trouble coming up with a logic to check for this. any ideas?
This is what I've got so far. the function takes in a list. (updated)
arr = [[1,20],[1,10]]
for i in arr:
l = list(range(i[0],i[1]))
for num in l:
if num < 11: continue
for c in str(num):
if str(num).count(c) > 1:
# dont know why code is popping off 12 and 13
print(l.pop(num))
If your ultimate goal is simply detecting if there's a double, this function may help:
def has_doubles(n):
return len(set(str(n))) < len(str(n))
The best way I can think about is converting the number to a string and doing a Counter on it
from collections import Counter
a = 98
c = Counter(str(a))
if any(value > 1 for value in c.values()):
print "The number has repeating digits"
#Two-BitAlchemist thanks for the suggestion
looks like you wanted to create your own algorithm probably researching or a student practice well you just have to understand the properties of numbers divided by 10 where 1/10 = 0.1 10/10 = 1 13/10 = 1 reminder 3 13013/10 = 1301 rem 3 hence we can create a function that stores the reminders in an array an check them against the reminder of next number here is the algorithm in python using recursion, you can achieve the same via loops
def countNumber(foundDigits,number):
next_number = int(number/10);
reminder = number % 10;
if(next_number < 1):
for num in foundDigits:
if(num == number or num == reminder):
return True
return False;
foundDigits.append(reminder);
return countNumber(foundDigits,next_number)
example in interpreter could be
digitsFound = list()
countNumber(digitsFound, 435229)
Solved this! I didn't know pop executes based on position not value! remove is a better fit here.
arr = [[1,40],[1,10]]
for i in arr:
l = list(range(i[0],i[1]))
for num in l:
if num < 11: continue
for char in str(num):
if str(num).count(char) < 2: continue
l.remove(num)
break
print(l)
Here is my solution, its simple and works for 2 digit numbers.
nums = list(input().rstrip().split())
def has_doubles(nums):
for number in nums:
if number[0] == number[1]:
print(number)
else:
continue
has_doubles(nums)

Resources