I'm working on the following problem:
You are driving a little too fast, and a police officer stops you. Write code to compute the result, encoded as an int value: 0=no ticket, 1=small ticket, 2=big ticket. If speed is 60 or less, the result is 0. If speed is between 61 and 80 inclusive, the result is 1. If speed is 81 or more, the result is 2. Unless it is your birthday -- on that day, your speed can be 5 higher in all cases.
I came up with the following code:
def caught_speeding(speed, is_birthday):
if is_birthday == True:
if speed <= 65:
return 0
elif speed <= 85:
return 1
else:
return 2
else:
if speed <= 60:
return 0
elif speed <= 80:
return 1
else:
return 2
I feel like checking each one individually is a bit inefficient, or is it ok?
You gotta love the bisect module.
def caught_speeding(speed, is_birthday):
l=[60,80]
if is_birthday:
speed-=5
return bisect.bisect_left(l,speed)
I have no problems with your code. It is readable and clear.
If you want to go for less lines then you can do something like this:
def caught_speeding(speed, is_birthday):
adjustment = 5 if is_birthday else 0
if speed <= 60 + adjustment:
return 0
elif speed <= 80 + adjustment:
return 1
else:
return 2
You can do this:
def caught_speeding(speed, is_birthday):
if is_birthday:
speed = speed - 5
if speed <= 60:
return 0
elif speed <= 80:
return 1
else:
return 2
Doing is_birthday == True means you didn't quite get booleans yet ;-)
Check this one. It is optimised:
def caught_speeding(speed, is_birthday):
if speed in range(0,66 if is_birthday else 61):
return 0
elif speed in range(0,86 if is_birthday else 81):
return 1
return 2
Assuming that speed is an integer, and that efficiency means speed of running, not speed of understanding:
>>> def t(speed, is_birthday):
... speed -= 5 * is_birthday
... return speed // 61 + speed // 81
...
>>> for s in xrange(58, 87):
... print s, t(s, False), t(s, True)
...
58 0 0
59 0 0
60 0 0
61 1 0
62 1 0
63 1 0
64 1 0
65 1 0
66 1 1
67 1 1
68 1 1
69 1 1
70 1 1
71 1 1
72 1 1
73 1 1
74 1 1
75 1 1
76 1 1
77 1 1
78 1 1
79 1 1
80 1 1
81 2 1
82 2 1
83 2 1
84 2 1
85 2 1
86 2 2
>>>
def caught_speeding(speed, is_birthday):
speed -= 5 * is_birthday
return 0 if speed < 61 else 2 if speed > 80 else 1
Related
Sam is a professor at the university and likes to round each student's
according to these rules:
1) If the difference between the grades and the next multiple of 5 is less than 3, round up to the next multiple of 5
2)If the value of grade is less than 38, no rounding occurs as the result will still be a failing grade.
def gradingStudents(grades):
# Write your code here
gr = [None]*len(grades)
j = 0
for i in grades:
e = 5- (i% 5)
if e < 3 and i+e >= 40 and i+e <= 100:
gr[j] = i + e
else:
gr[j] = i
j += 1
return gr;
Sample Input 0
4
73
67
38
33
Sample Output 0
75
67
40
33
I want
proc format;
value RNG
low - 24 = '1'
24< - 35 = '2'
35< - 44 = '3'
44< - high ='4'
I need this in python pandas.
If you are looking for equivalent of the mapping function, you can use something like this.
df = pd.DataFrame(np.random.randint(100,size=5), columns=['score'])
print(df)
output:
score
0 73
1 90
2 83
3 40
4 76
Now lets apply the binning function for score column in dataframe and create new column in the same dataframe.
def format_fn(x):
if x < 24:
return '1'
elif x <35:
return '2'
elif x< 44:
return '3'
else:
return '4'
df['binned_score']=df['score'].apply(format_fn)
print(df)
output:
score binned_score
0 73 4
1 90 4
2 83 4
3 40 3
4 76 4
I'd like to run simultaneously 3 different counters following a very specific pattern:
counter_3 displays the number of iteration from 0 to 2144
counter_1 increases by 1 every 65 iterations
counter_2 goes from 1 to 65, then starts back from 2 to 65, then from 3 to 65 ...
The result should look like this:
counter_1 counter_2 counter_3
0 1 0
0 2 1
0 3 2
0 4 3
0 5 4
... ... ...
0 65 64
1 2 65
1 3 66
1 4 67
... ... ...
1 65 128
1 3 129
2 4 130
2 5 131
... ... ...
32 64 2142
32 65 2143
32 65 2144
I know how to run these counters separately.
For counter_1 and counter_3 (refered below as i):
counter_1 = 0
for i, e in enumerate(range(2145)):
if i > 1 and i % 65 == 0:
counter_1 += 1
print(counter_1, i)
For counter_2 (refered below as e):
n = 0
g = 1
while n <= 2145:
for e in np.arange(g, 66):
print(e)
g += 1
n += 1
QUESTION: How can i run these 3 counters simultaneously ?
You have the right general idea: determine when you have to fiddle with the counters. However, note that coutner1 is a value you can derive simply from counter3 with integer division. Just worry about counter2, and you're fine. Here's a solution more at your level of coding:
c2 = 65
c2_new = 0 # Track where to start counter2 next time
for c3 in range(2145):
if c2 == 65:
c2 = c2_new
c2_new += 1
c2 += 1
c1 = c3 // 65 # Simple division gets the c1 value
print c1, c2, c3
Third counter is just the index and first counter is index/65. Only the middle counter is a little less trivial, so I'd use that one to drive this.
for c, b in enumerate(b for start in range(1, 66) for b in range(start, 66)):
print c / 65, b, c
And an itertools version:
for c, (_, b) in enumerate(combinations(range(66), 2)):
print c / 65, b, c
Not looking for the simplest or slickest specific answer to your question, I wanted to offer a pattern that might be applied more broadly.
You could use a generator to provide each of the series of numbers that you want, then combine them. This means that you could test them independently. It also means that you could parameterise each of them to allow for smaller numbers during testing. Here, for instance, Counter_1 is parameterised so with the number of repetitions allowed before its behaviour changes.
Counter_2 is almost certainly more complicated than it needs to be. My brain is in a fog.
def Counter_1(rep=65):
n = -1
while True:
n += 1
k = n//rep
yield k
def Counter_2(rep=65):
n = 0
inc = 0
while True:
n += 1
if n==rep:
k = n//rep
yield n
inc += 1
n = inc
else:
yield n
counter_1 = Counter_1()
counter_2 = Counter_2()
for counter_3 in range(2145):
c_1 = next(counter_1)
c_2 = next(counter_2)
print (c_1, c_2, counter_3)
if counter_3>10:
break
Another iterative approach using generator functions (in Python 3).
Code
import itertools as it
def counter1(item=0):
"""Yield increments every 65 iterations."""
for _ in range(1, 66):
yield item
yield from counter1(item+1)
def counter2(item=1, stop=66):
"""Yield `item` to 65, incrementing `item` after `stop-1`."""
yield from range(item, stop)
if item != stop:
yield from counter2(item+1)
def counter3(stop=2150-5):
"""Yield numbers 0 to `stop`."""
for item in range(stop):
yield item
cts = list(zip(counter1(), counter2(), counter3()))
Demo
# Sample results (see OP results)
counters = it.chain(cts[:5], cts[63:68], cts[128:132], cts[-3:])
for iteration in counters:
print("{:<10} {:<10} {:<10}".format(*iteration))
Sample Output
0 1 0
0 2 1
0 3 2
0 4 3
0 5 4
0 64 63
0 65 64
1 2 65
1 3 66
1 4 67
1 65 128
1 3 129
2 4 130
2 5 131
32 64 2142
32 65 2143
32 65 2144
Details
counter1: an infinite generator; yields a value for over a range of numbers. Repeat for incremented values recursively.
counter2: an infinite generator; for every iteration, yield a value from a range. Repeat for incremented counters recursively.
counter3: a finite generator; a simple iteration over a range().
The resulting counters are zipped together, exhausted after the termination of the finite counter3.
This example is Python 2 compatible after transforming yield from statements to for loops, e.g.
for i in range(x, stop):
yield i
I need to create a program that does a digital countdown from a set time. It needs to be printed so it reads Hours:minutes:seconds.
import time
count=int(input("Enter your start point"))
count2=int(input("Enter your start point"))
count3=int(input("Enter your start point"))
while count and count and count3 >0:
time.sleep(1)
print(count,+":",+":",+count3)
count -=1
count2 -=1
count3 -=1
import time
hours = 1
minutes = 0
seconds = 4
while not hours==minutes==seconds==0:
print str(hours)+":"+str(minutes)+":"+str(seconds)
time.sleep(1)
if minutes==seconds==0:
hours-=1
minutes=59
seconds=59
elif seconds==0:
minutes-=1
seconds=59
else:
seconds-=1
Try this. Can add padding to the numbers if required. Here is the POC.
>>1:0:4
>>1:0:3
>>1:0:2
>>1:0:1
>>1:0:0
>>0:59:59
>>0:59:58
>>0:59:57
>>0:59:56
I modified your code ,this will produce your required output.
Please let me know in terms of any query,
import time
count=int(input("Enter your start point"))
count2=int(input("Enter your start point"))
count3=int(input("Enter your start point"))
while count | count2 | count3 >0:
while(count>=0):
while(count2>=0):
while(count3>=0):
time.sleep(1)
print count,":",count2,":",+count3
count3 -= 1
count3 = 59
count2 -= 1
count2 = 59
count -= 1
In your old code AND operator is used , so it will terminate theexecution even if any variable is zero.
Output:
1 : 0 : 4
1 : 0 : 3
1 : 0 : 2
1 : 0 : 1
1 : 0 : 0
0 : 59 : 59
0 : 59 : 58
0 : 59 : 57
0 : 59 : 56
0 : 59 : 55
0 : 59 : 54
0 : 59 : 53
0 : 59 : 52
I have a complex group of a group problem I need help with.
I have names of drivers, each of who have driven several cars over time. Each time they turn on the car and drive, I capture cycles and hours, which are transmitted remotely.
What I am trying to do is use grouping to see when the driver gets a new car.
I'm using Car_Cycles and Car_Hours to monitor for a reset (new car). The hours and cycles are tabulated for each driver in ascending sequence until there's a new car and reset. I want to make each car a sequence, but logically can only recognize the car by a cycle/hour reset.
I used a for loop with if statements to do this on the dataframe, and the process time takes several hours. I have several hundred thousand rows with each containing about 20 columns.
My data comes from sensors over a moderately reliable connection, so I want to filter by using the following criteria: A new group is only valid when both Car_Hours and Car_Cycles are less the previous group's last row for 2 consecutive rows. Using both outputs and checking for two rows of change sufficiently filters all erroneous data.
If someone could show me how to quickly solve for Car_Group without using my cumbersome for loops and if statements, I would greatly appreciate it.
Also, for those how are very venturous, I added my original for loop below with if statements. Note I did some other data analysis/tracking within each group to look at other behavior of the car. If you dare look at that code and show me an efficient Pandas replacement, all the more kudos.
name Car_Hours Car_Cycles Car_Group DeltaH
jan 101 404 1 55
jan 102 405 1 55
jan 103 406 1 56
jan 104 410 1 55
jan 105 411 1 56
jan 0 10 2 55
jan 1 12 2 58
jan 2 14 2 57
jan 3 20 2 59
jan 4 26 2 55
jan 10 36 2 56
jan 15 42 2 57
jan 27 56 2 57
jan 100 61 2 58
jan 500 68 2 58
jan 2 4 3 56
jan 3 15 3 57
pete 190 21 1 54
pete 211 29 1 58
pete 212 38 1 55
pete 304 43 1 56
pete 14 20 2 57
pete 15 27 2 57
pete 36 38 2 58
pete 103 47 2 55
mike 1500 2001 1 55
mike 1512 2006 1 59
mike 1513 2012 1 58
mike 1515 2016 1 57
mike 1516 2020 1 55
mike 1517 2024 1 57
..............
for i in range(len(file)):
if i == 0:
DeltaH_limit = 57
car_thresholds = 0
car_threshold_counts = 0
car_threshold_counts = 0
car_change_true = 0
car_change_index_loc = i
total_person_thresholds = 0
person_alert_count = 0
person_car_count = 1
person_car_change_count = 0
total_fleet_thresholds = 0
fleet_alert_count = 0
fleet_car_count = 1
fleet_car_change_count = 0
if float(file['Delta_H'][i]) >= DeltaH_limit:
car_threshold_counts += 1
car_thresholds += 1
total_person_thresholds += 1
total_fleet_thresholds += 1
elif i == 1:
if float(file['Delta_H'][i]) >= DeltaH_limit:
car_threshold_counts += 1
car_thresholds += 1
total_person_thresholds += 1
total_fleet_thresholds += 1
elif i > 1:
if file['name'][i] == file['name'][i-1]: #is same person?
if float(file['Delta_H'][i]) >= DeltaH_limit:
car_threshold_counts += 1
car_thresholds += 1
total_person_thresholds += 1
total_fleet_thresholds += 1
else:
car_threshold_counts = 0
if car_threshold_counts == 3:
car_threshold_counts += 1
person_alert_count += 1
fleet_alert_count += 1
#Car Change?? Compare cycles and hours to look for reset
if i+1 < len(file):
if file['name'][i] == file['name'][i+1] == file['name'][i-1]:
if int(file['Car_Cycles'][i]) < int(file['Car_Cycles'][i-1]) and int(file['Car_Hours'][i]) < int(file['Car_Hours'][i-1]):
if int(file['Car_Cycles'][i+1]) < int(file['Car_Cycles'][i-1]) and int(file['Car_Hours'][i]) < int(file['Car_Hours'][i-1]):
car_thresholds = 0
car_change_true = 1
car_threshold_counts = 0
car_threshold_counts = 0
old_pump_first_flight = car_change_index_loc
car_change_index_loc = i
old_pump_last_flight = i-1
person_car_count += 1
person_car_change_count += 1
fleet_car_count += 1
fleet_car_change_count += 1
print(i, ' working hard!')
else:
car_change_true = 0
else:
car_change_true = 0
else:
car_change_true = 0
else:
car_change_true = 0
else: #new car
car_thresholds = 0
car_threshold_counts = 0
car_threshold_counts = 0
car_change_index_loc = i
car_change_true = 0
total_person_thresholds = 0
person_alert_count = 0
person_car_count = 1
person_car_change_count = 0
if float(file['Delta_H'][i]) >= DeltaH_limit:
car_threshold_counts += 1
car_thresholds += 1
total_person_thresholds += 1
total_fleet_thresholds += 1
file.loc[i, 'car_thresholds'] = car_thresholds
file.loc[i, 'car_threshold_counts'] = car_threshold_counts
file.loc[i, 'car_threshold_counts'] = car_threshold_counts
file.loc[i, 'car_change_true'] = car_change_true
file.loc[i, 'car_change_index_loc'] = car_change_index_loc
file.loc[i, 'total_person_thresholds'] = total_person_thresholds
file.loc[i, 'person_alert_count'] = person_alert_count
file.loc[i, 'person_car_count'] = person_car_count
file.loc[i, 'person_car_change_count'] = person_car_change_count
file.loc[i, 'Total_Fleet_Thresholds'] = total_fleet_thresholds
file.loc[i, 'Fleet_Alert_Count'] = fleet_alert_count
file.loc[i, 'fleet_car_count'] = fleet_car_count
file.loc[i, 'fleet_car_change_count'] = fleet_car_change_count
IIUC, and all we need to do is reproduce Car_Group, we can take advantage of a few tricks:
def twolow(s):
return (s < s.shift()) & (s.shift(-1) < s.shift())
new_hour = twolow(df["Car_Hours"])
new_cycle = twolow(df["Car_Cycles"])
new_name = df["name"] != df["name"].shift()
name_group = new_name.cumsum()
new_cargroup = new_name | (new_hour & new_cycle)
cargroup_without_reset = new_cargroup.cumsum()
cargroup = (cargroup_without_reset -
cargroup_without_reset.groupby(name_group).transform(min) + 1)
Trick #1: if you want to find out where a transition occurs, compare something to a shifted version of itself.
Trick #2: if you have a True where every new group begins, when you take the cumulative sum of that, you get a series where every group has an integer associated with it.
The above gives me
>>> cargroup.head(10)
0 1
1 1
2 1
3 1
4 1
5 2
6 2
7 2
8 2
9 2
dtype: int32
>>> (cargroup == df.Car_Group).all()
True