I'm trying to write an if else statement in shorthand.
An if else to check a value and increment if it has not reached a value, otherwise minus a set number.
As an if else this works, but trying to do this as a shorthand version and am stuck.
Is the issue you cant use -= or += in this context? Any help to understand would be appreciated.
Have tried day-=7 if day == 7 else day+=1 - but know this is wrong as the var is already referenced on the left.
If else works fine
day = 5
if day == 7:
day-=7
else:
day+=1
Trying to write this in shorthand and I get an error on the right day+=1 as this is clearly incorrect. Looking for some advice on how to increment the day value if day != 7
day = 5
day-=7 if day == 7 else +=1
The +=1 throws an error.
Expect day to be 6
day += -7 if day == 7 else 1
The way you read this is "Add negative 7 to day if day == 7, otherwise, add 1 to day"
Dagorodir's original answer does not work, because it will subtract (day + 1) from the current value of day if day != 7. So using your example with the the starting value of 5 for day, the result of running the code from the other answer is -1.
You are right in saying that you cannot use the assignment operators -= or += in some places in the context of a "conditional expression" in Python. My understanding is that the shorthand if-else is an expression, not a statement, as seen in your initial example. You cannot make assignments on the right hand side but instead specify the return value if false, and the return value (or assignment to the variable) if true on the left.
In your second attempt, on the right hand side, you have used the assignment operator without a variable. If you wanted the evaluation of the condition to take more complex values, you could assign to variables:
day = 5
ret_false = day + 1
ret_true = day - 7
ret_true if day == 7 else ret_false
Refer to Samantha's answer for more elegant solution: the += increment assignment operator is used for evaluation of either True or False in the expression - so -7 is necessary on the left, while += 1 is assigned otherwise. I repeat the inverse of the solution in her answer to illustrate the mechanics of the syntax; using the decremental -= operator on the left enforces its use on the right -
day -= 7 if day == 7 else -1
Following the above logic, my original suggestion below uses the decremental -= assignment operator on the left; day-7 is returned if true, while day-(day+1) is returned if false. Thanks to Samantha for pointing this out.
Original
Try:
day -= 7 if day == 7 else day + 1
There are many questions regarding this: here and here, for example.
To me this is the most readable, using modulo arithmetic
day = 5
day = (day + 1) % 7
print(day)
# result 6
day = 6
day = (day + 1) % 7
print(day)
# result 0
I have two option for you:
day = day + (-7 if day == 7 else 1)
OR
day = day -7 if day == 7 else day + 1
Related
I understand using relativedelta for exact month calculation taking into account the number of days in each month.
Are there any streamlined libraries for adding just month ints together?
ie. December is 12. Adding 2 months is 14 which is 2 == February?
I am hoping to solve all edge cases surrounding the problem with a tested library.
I have thought of doing a modulo calculation along the following:
curr_month = 12 - 1 (-1 for 0 indexing) = 11
if we do divmod(curr_month, 11) , we get (0,0) but the result in reality should be 11. If I just handled that with an if result[0] == 0: curr_month = 11, then whenever result[1] we will get the wrong answer
This formula should work for you
>>> current_month = 12
>>> delta = 2
>>> (((current_month - 1) + delta) % 12) + 1
2
I came across the LeetCode problem 2100. Find Good Days to Rob the Bank:
You and a gang of thieves are planning on robbing a bank. You are given a 0-indexed integer array security, where security[i] is the number of guards on duty on the ith day. The days are numbered starting from 0. You are also given an integer time.
The ith day is a good day to rob the bank if:
There are at least time days before and after the ith day,
The number of guards at the bank for the time days before i are non-increasing, and
The number of guards at the bank for the time days after i are non-decreasing.
More formally, this means day i is a good day to rob the bank if and only if security[i - time] >= security[i - time + 1] >= ... >= security[i] <= ... <= security[i + time - 1] <= security[i + time].
Return a list of all days (0-indexed) that are good days to rob the bank. The order that the days are returned in does not matter.
The solution, that I created seems fine to me. Not sure, where I am going wrong with some test cases failing.
class Solution(object):
def goodDaysToRobBank(self, security, time):
"""
:type security: List[int]
:type time: int
:rtype: List[int]
"""
total_guards = len(security)
if time == 0:
return [i for i in range(total_guards)]
left = [1]*total_guards
right = [1]*total_guards
l_pattern_found = False
r_pattern_found = False
for i in range(1, total_guards):
if security[i-1] >= security[i]:
left[i] = left[i-1] + 1
l_pattern_found = True
for i in range(total_guards-2, -1, -1):
if security[i+1] >= security[i]:
right[i] = right[i+1] + 1
r_pattern_found = True
if not l_pattern_found or not r_pattern_found:
return []
days = []
for i in range(time, total_guards-time):
if left[i-1] >= time and right[i+1] >= time:
days.append(i)
return days
Here is what I have done:
Compute the left prefix for the condition mentioned
Compute the right prefix for the condition mentioned
Find the days in the range [time, n-time]
This is failing for the test case as follows:
security = [1,2,5,4,1,0,2,4,5,3,1,2,4,3,2,4,8]
time = 2
The expected output is: [5,10,14] and my output is [4,5,6,10,14]
What is it that I am doing wrong?
The main issue is in this line:
if left[i-1] >= time and right[i+1] >= time:
Here the value of left[i-1] does not guarantee that the current value at security[i] is not greater than security[i-1]. To ensure that, you would need to look at left[i] instead of left[i-1]. For the same reason you should be looking at right[i] instead of right[i+1]. But that means you need to reduce all counts by 1, and initialise your left and right lists with zeroes:
left = [0]*total_guards
right = [0]*total_guards
With those corrections it will work.
The problem:
There are 3 paths where only one leads home.
The first path gets you lost for 3 days, then you're back to the beginning where you have to pick another path.
The second path gets you lost for 2 days, then you're back at the beginning and you have to pick another path.
The last door leads you home in 1 day.
Basically you keep going until you pick the last path. I'm trying to find the average time it takes to get home by simulating 1000 tries.
Here is what I have thus far:
days=0
for i in range(1000):
door=["a","b","c"]
numpy.random.choice(path)
if numpy.random.choice(path)=="a":
days=+2
if numpy.random.choice(path)=="b":
days=+3
if numpy.random.choice(path)=="c":
days=+1
print(steps)
As is, my code will just print out a value from 1-3 as the days.
I'm having trouble figuring out how to pick one and then accumulate it into the days and then restarting the loop until it picks path C.
I've done research and think a while loop might work but I don't know how to apply that.
You can use a while loop that keeps iterating while you are stuck and then when door 'a' is selected it adds the 1 to get home but then the person is no longer stuck so it drops out of the while loop. Then before entering the while loop again, just set stuck = True and the process continues always adding to the total number of days, then at the end just take the average.
import numpy
days=0
door=["a","b","c"]
N = 1000
for i in range(N):
stuck = True
while stuck:
if numpy.random.choice(door)=="a":
days += 2
if numpy.random.choice(door)=="b":
days += 3
if numpy.random.choice(door)=="c":
days += 1
stuck = False
print('Average number of days taken to get home: ', days / N)
I hope this helps!
Here's the code you're looking for:
import numpy
def runOnce():
days = 0
door=["a","b","c"]
while(True):
path = numpy.random.choice(door)
if path=="a":
days+=2
if path=="b":
days+=3
if path=="c":
days+=1
return days
total = 0
for i in range(1000):
total += runOnce()
print(total / 1000.0)
This code must solve your problem:
import random
doors = ['a', 'b', 'c']
total_days = 0
runs = 1000
for i in range(runs):
days = 0
choice = None
while choice != 'c':
choice = random.choice(doors)
if choice == 'a':
days += 2
if choice == 'b':
days += 3
if choice == 'c':
days += 1
total_days += days
avg_days = total_days / runs
print(avg_days)
I'm not quite sure on your rules, but this is my attempt
import numpy as np
def choose_path():
p =np.random.randint(3)
#print("Path = {}".format(p))
return p
N = 100000
days=0.0
for i in range(N):
#make sure you don't take the wrong path twice
taken = [False, False, False]
path = choose_path()
while(path != 2):
if(path==0):
if(not(taken[path])):
taken[path] = True
days += 2.0
if(path==1):
if(not(taken[path])):
taken[path] = True
days += 3.0
path = choose_path()
days += 1.0
# print("Days = {}".format(days))
print("Average for {} iterations = {}".format(N, days/N))
In contrast to the some of the other codes my guy doesn't take the same route twice. I'm not sure how you problem is defined. My solution seems to be 3.5.
Some of the mistakes you made are:
=+ is an assignment of a positive number a = +3 or a = -3
+= is an increment a = a + 3 <=> a += 3
you define door, but never use it
you never define steps but you use it
I think you should come up with an algorithm first and then implement it.
There are a few problems with your code. For example, you define a door list of possible choices, but then you pass path to the choice function. At the end of your program you print steps, but that's not defined anywhere. Instead, you should be printing days, or days / 1000. You need to pay attention to things like that when you're programming!
As others have shown, you need to do this with two loops. Each iteration of the outer loop performs a trial. The inner loop chooses paths until you get home and adds the day counts to the current total.
In your code, each if test generates a fresh random choice on top of the one you make at the start of the loop. That's not right. Just make the choice at the top of the loop, determine how many days to add to the count, and if you're home, break out of the loop.
We can do this in a simpler way. Rather than choosing from 'a', 'b', or 'c', just choose from 1, 2, or 3, the number of days each path takes. And as I said earlier, there's no need to use Numpy for this, we can just call the random module functions directly instead of letting Numpy do it on our behalf.
Here's a short demo.
from random import randint
trials = 10000
days = 0
for n in range(trials):
while True:
path = randint(1, 3)
days += path
if path == 1:
break
print(days, days / trials)
typical output
59996 5.9996
We can get a more accurate estimate to the true expected time by performing multiple runs and averaging the results. We could do that by wrapping the previous code in an extra loop, but it makes the code more readable if instead we wrap the old code in a function, and call that function in a loop. Like this:
from random import randint
def sim(trials):
days = 0
for n in range(trials):
while True:
path = randint(1, 3)
days += path
if path == 1:
break
return days
num = 10
trials = 10000
total = 0
for i in range(num):
days = sim(trials)
x = days / trials
print(i, x)
total += x
print('Final', total / num)
typical output
0 5.9732
1 6.007
2 6.0555
3 5.9943
4 5.9964
5 5.9514
6 6.0689
7 6.0457
8 5.9859
9 5.9685
Final 6.00468
It looks like the true expected value is 6 days. Actually, it's not hard to show that mathematically.
Let d equal the expected number of days to get home. 1/3 of the time we get home in 1 day, 1/3 of the time we get back to the start in 2 days and so we still have d days before we get home, and 1/3 of the time we get back to the start in 3 days and so, once again we still have d days before we get home.
We can put that into an equation:
d = (1/3)*1 + (1/3)*(2 + d) + (1/3)*(3 + d)
3*d = 1 + 2 + d + 3 + d
3*d = 6 + 2*d
d = 6
I was wondering how I could change the following lines of codes to use a while loop instead of a for loop.
for num in range(10):
print(num+1)
It currently prints out the following:
1
2
3
4
5
6
7
8
9
10
Thanks!
start = 0
while start != 10:
start = start + 1
print(start)
hope this hepls
number = 1
while (number <=10):
print 'The number is:', number
number = number + 1
The for loop runs over an iterable, while a while loop runs while a condition is true, so you just need to think of the right condition.
Here, something counting up to 10 will work:
>>> number = 0
>>> while number < 10:
... print(number + 1)
... number += 1
...
1
2
3
4
5
6
7
8
9
10
Writing code that has the same output is not the same as rewriting code to do the same thing. Other answers simply do the former, so this solves the latter:
numbers = range(10)
while numbers:
numbers.pop(0) + 1
The original code iterates over a list that does not exist outside of the loop - it could work with a list of something other than range(10), but it's not necessarily just a '+ 1' operation.
The conditional statement for a while loop, however, needs to be true for the loop to begin so the list should already exist. To keep true to the spirit of the original code, we use range() to create the list, and use pop() to iteratively remove the first element from it.
The differences here are that a variable (numbers) gets used, but is empty after the loop, and we don't rely on list comprehension to iterate, but explicitly remove the first element until 'numbers', being empty, results in a false condition.
well..... a while statement operates UNTIL a certain condition is met, as the for operates for a set of given iterations.
in your case you want to print stuff until num reaches 10, so
while num <= 10 :
print num
num = num + 1
would do
def show_time(hour,min):
hour = int(input())
min = ''
for hour in (hour,min):
while 24 >= hour > 12:
hour -= 12
min == min
return hour, ":" min,'pm'
if hour < 12:
if 0 <= min <= 59
hour == hour
min == min
return hour, ":" min,'am'
So this is my code so far.^^
When I run this code, i keep getting an infinite loop for one... another thing is.. I feel like i am totally off. Btw.. I am trying to do this without importing anything and using the string formatting method. Please HELP!
Here were my instructions...
def show_time(hour,min): Accept integers for the hour (values from 0 to 23) and the minute
(values from 0 to 59). Construct the correct clock representation, such as the examples below.
o you must use the format method.
o Examples:
! show_time(9,15) → "9:15am"
! show_time(0,0) → "12:00am"
! show_time(12,0) → "12:00pm"
! show_time(22,5) → "10:05pm"
I can't get what you're trying to achieve using loops, but here's a simple solution.
def show_time(hour, minutes):
if hour >= 12:
suffix = "pm"
if hour != 12:
hour -= 12
else:
suffix = "am"
if hour == 0:
hour = 12
return "{0}:{1:02}{2}".format(hour, minutes, suffix)
Hope it helps.
Correct code should be like this:
def show_time(hour,min):
hour = int(hour)
min = int(min)
if hour > 12:
hour -= 12
return str(hour) + ":" + str(min) + 'pm'
else:
return str(hour) + ":" + str(min) + 'am'
print show_time(9,15)
You should think on simple level. For and while loops are unnecessary.
How about this:
def show_time(hour, min):
if hour > 24 or min > 59 or hour < 0 or min < 0:
raise ValueError("Invalid input")
# which half of day is this?
is_pm = (hour / 12.0) > 1
# normalize time in 0 to 11
hour = hour % 12
# get the correct half of day readable form
half_day = "pm" if is_pm else "am"
# print it out
print "%02d:%02d%s" % (hour, min, half_day)
Always try too keep things simple when possible, loops are useful but try to question whether they are really necessary.