This is the code about to find out dice gamble's prize amount:
a, b, c = map(int, input().split())
if a == b and b == c: #same all of dice numbers
print(10000 + (a * 1000))
elif a == b or b == c: #same two of dice numbers
print(1000 + (b * 100))
elif a == c: #same two of dice numbers
print(1000 + (a * 100))
else: #no same number
print(max(a, b, c)*100)
This is equivalent:
*_, a, b, c=sorted(input())
print(['1'+b, c][a < b < c]+'000'[a < c:])
But i can't understanding about what does
['1'+b, c][a < b < c]
and
'000'[a < c:]
do.
So, I had tried to find out the meaning of
`['1'+b, c][a < b < c]`
I found this is similar with
`c if a<b<c else '1'+b`
but i can't be sure about that.
anyway, about
`'000'[a < c:]`
I tried input a=c to
`print('000'[a < c:])`
It shows 000.
I tried else that input a<c, it shows 00
Anyone can tell me about this expression?
The original is unnecessarily cryptic. It uses the fact that:
int(False) == 0
int(True) == 1
For instance,
'000'[False:] == '000'[0:] == '000'
'000'[True:] == '000'[1:] == '00'
Similarly,
['1' + b, c][False] == ['1' + b, c][0] == '1' + b
['1' + b, c][True] == ['1' + b, c][1] == c
Here's an equivalent rewrite:
prefix = c if a < b < c else '1' + b
suffix = '00' if a < c else '000'
print(prefix + suffix)
a < c will evaluate to either True or False. So you are effectively getting either print('000'[True:]) or print('000'[False:]).
When you have the [] after a string, those will perform a slice on the string. You'd see this in actually practice as something like the following (here's a link for more info:
'abcde'[2] # returns 'c', which, starting from zero, is 2nd item
'abcde'[0] # returns 'a', which is the zero-th item
'abcde'[1:3] # returns 'bc', starting from the 1st item and going to the 3rd, not inclusive of the third
It looks like if you use booleans in such a slice, the False acts as a 0 and True acts as a 1
"abcde"[True] == "abcde"[1] # evaluates to true, these are the same
'abcde'[True] # evaluates to 'b'
"abcde"[False] == "abcde"[2] # evaluates to `False`
"abcde"[True] == "abcde"[2] # evaluates to `False`
"abcde"[False] == "abcde"[0] # evaluates to True, because False is effectively 0 here
So, having a [True:] or [False:] in that string-slice is the same as having [1:] or '[0:]`, which is saying to "give all characters starting with the second (for True/1:) or first (for False/0:) in this string".
The string '000' has length 3. The boolean a < c has value False or True. The operation s[i] for a string s and integer i refers to the i'th element of s, and the operation s[i:] takes the substring of s from index i through the end of s. A boolean value will be converted to an integer in Python as follows: False becomes 0 and True becomes 1.
So, '000'[a < c:] is the same as '000'[0:] if a < c is False, and this is the same as '000'. If a < c is True, then '000'[a < c:] is the same as '000'[1:] which is '00'.
Related
I was wondering if someone would be able to help me regarding my coding problem. I'm still a beginner and I may have missed something here.
Basically, the instruction says that I need to arrange 3 integers in ascending order.
e.g Input : 5 2 4 ------> Output : 2 4 5
I need to utilize the conditional statements for this. Here is what I've done so far.
a, b, c = input().split()
a = int (a)
b = int (b)
c = int (c)
if a < b and a < c:
smallest = a
elif b < a and b < c:
smallest = b
else:
smallest = c
if a > b and a < c:
middle = a
elif a < b and a > c:
middle = a
elif b > a and b < c:
middle = b
elif b < a and b > c:
middle = b
else:
middle = c
if a > b and a > c:
largest = a
elif b > a and b > c:
largest = b
else:
largest = c
print(smallest, middle, largest)
This is on CodeChum btw, I'm stuck in this because I can't figure out why it doesn't accept the code I did. Basically there are 5 tests that the code needs in order to submit the whole activity. I managed to do test 1-4 but for some reason it fails on test 5.
The problem is that your code does not react well if two numbers are identical. You should replace your strict inequalities with non-strict ones.
a = 3
b = 3
c = 1
if a > b and a < c:
middle = a
elif a < b and a > c:
middle = a
elif b > a and b < c:
middle = b
elif b < a and b > c:
middle = b
else:
middle = c
print(middle) # 1 when it should be 3
As a == b, none of the 4 conditions can be True, and therefore the middle number will always be c.
In order to support the case where a == b, we can add another condition:
elif a == b:
middle = a
else:
middle = c
we can simplify this code by replacing the strict inequalities with non-strict ones (⩽ , <= in Python):
if b <= a < c:
middle = a
elif b >= a > c:
middle = a
elif a < b < c:
middle = b
elif a > b > c:
middle = b
else:
middle = c
We simply said that if a == b, the middle is always a. I also simplified the structure for better readability.
Why don't you simply use sorted function?
This one results in the exact thing you are looking for.
smallest, middle, largest = sorted(map(int, input().split()))
print(smallest, middle, largest)
Note that you don't need the map to int function for this. But you if don't do that, the smallest, middle, largest variables will remain str objects.
As the input is guaranteed to contain exactly 3 numbers (separated by whitespace) you can just do this:
if (inval := input()):
if len(nums := inval.split()) == 3:
try:
lo, mid, hi = sorted(map(int, nums))
print(lo, mid, hi)
except ValueError:
pass
Pretty much have to print 'a'&'b' of amount of integer from parameter.
def function(A,B):
pass
A or B is integer amount, function(3,5) gonna print 3 a's, and 5 b's like these combinations:
'baabbabb'
'babababb'
'bbabbaab'
but it never print three consecutive alphabet in their combination like this one:
'bbaaabbb'
more examples:
function(5,3): 'aabbaaba'
function(1,4): 'bbabb'
function(3,3): 'aabbab'
Tried using if else and while>=3 but it looks horrendous. Any pointer would be appreciated
def solution(A,B):
text = ""
if A > B:
while (A >= 3 or B >= 3) and A != 0 and B != 0:
text += 'a' * 1
A-=1
text += 'b' * 1
B-=1
if text[-1] == 'a':
text += 'b' * B
text += 'a' * A
else:
text += 'a' * A
text += 'b' * B
elif A < B:
while (A >= 3 or B >= 3) and A != 0 and B != 0:
text += 'b' * 1
B-=1
text += 'a' * 1
A-=1
if text[-1] == 'a':
text += 'b' * B
text += 'a' * A
else:
text += 'a' * A
text += 'b' * B
else:
while (A >= 3 or B >= 3) and A != 0 and B != 0:
text+='a' * 1
A-=1
text+='b' * 1
B-=1
if text[-1] == 'a':
text += 'b' * B
text += 'a' * A
else:
text += 'a' * A
text += 'b' * B
return text
pass
I want to show you another way to think about your problem. What you have there is essentially a binary number, where the digits are 'a' and 'b' instead of 0 and 1. So, here I run through all of the numbers up to length A+B, then reject any where a run of 3 occur. I then convert 0/1 to a/b and print.
The z = bin(i+top)[3:] is a bit of trickery. The bin function converts a number to binary, and adds the prefix 0b. For numbers less than the full length, it does not pad zeros on the left, so 3 comes out 0b11 even if we want 7 digits. So, I 0b10000000 to the number, and throw out the top three characters. That leave a 0-padded string.
def solution(A,B):
a3 = '0'*3
b3 = '1'*3
top = 1 << (A+B)
for i in range(top):
z = bin(i+top)[3:]
if a3 in z or b3 in z:
continue
z = z.replace('0','a').replace('1','b')
print( z )
solution(5,3)
My solution:
def solve(a, b, previous):
if a == 0 and b == 0:
return ""
if a > b:
if previous == "a":
return "b" + solve(a, b - 1, "b")
else:
count = min(2, a)
return "a" * count + solve(a - count, b, "a")
else:
if previous == "b":
return "a" + solve(a - 1, b, "a")
else:
count = min(2, b)
return "b" * count + solve(a, b - count, "b")
def solution(a, b):
if max(a, b) > (min(a, b) + 1) * 2:
return "Impossible"
return solve(a, b, None)
print(solution(5, 3))
If you only need an answer (as opposed to all answers), you can do it iteratively in a while loop:
While there are letters to add, select 'a' and/or 'b' depending on which one has more to place and also avoid repetitions of 3. If you end up using more that the allocated count of a given letter, this will mean that there is no solution.
def alternate(A,B):
result = ""
while A or B:
if A<0 or B<0: return "impossible"
useA = A >= B # use an 'a' ?
useB = B >= A # use a 'b' ?
if result[-2:] == "aa": useA,useB = 0,1 # next must be 'b'
if result[-2:] == "bb": useA,useB = 1,0 # next must be 'a'
result += "a"*useA + "b"*useB # append letter(s)
A,B = A-useA, B-useB # decrement used
return result
print(alternate(3,5)) # bbababab
print(alternate(8,3)) # aabaabaabaa
print(alternate(3,8)) # bbabbabbabb
print(alternate(2,7)) # impossible
I just started doing some leetcode questions, and quite not sure why in this problem, we considering a case when 2 words are equal. This is a problem statement:
Given two strings A and B of lowercase letters, return true if you can swap two letters in A so the result is equal to B, otherwise, return false.
Swapping letters is defined as taking two indices i and j (0-indexed) such that i != j and swapping the characters at A[i] and A[j]. For example, swapping at indices 0 and 2 in "abcd" results in "cbad"
And this is a solution
def buddyStrings(self, A, B):
if len(A) != len(B): return False
if A == B and len(set(A)) < len(A): return True
dif = [(a, b) for a, b in zip(A, B) if a != b]
return len(dif) == 2 and dif[0] == dif[1][::-1]
I cant why we consider second if condition and how this list comprehension workd in 3 if. I will appreciate any help.
I guess maybe this would be a bit simplified version:
class Solution:
def buddyStrings(self, A, B):
if len(A) != len(B):
return False
if A == B and len(set(A)) < len(A):
return True
diff = []
for i in list(zip(A, B)):
if i[0] != i[1]:
diff.append(i)
return len(diff) == 2 and diff[0] == diff[1][::-1]
for i in list(zip(A, B)) means for a pair in A and B.
Here are the checks:
def buddyStrings(self, A, B):
if len(A) != len(B): return False # can't be true if lengths not equal
if A == B and len(set(A)) < len(A): return True # if same letter appears twice in word
dif = [(a, b) for a, b in zip(A, B) if a != b] # get letters that don't match
return len(dif) == 2 and dif[0] == dif[1][::-1] # if mismatch length is 2 and mismatch of first letter is reverse of mismatch of second letter
dif = [(a, b) for a, b in zip(A, B) if a != b]
it finds all charachters that are not equal to each other in the same position.
for ABCDE and FGCDE
dif = [('A','F'), ('B','G')]
I'm trying to optimize my code by using dictionaries instead of if-elif statements.
I've read that you can optimize code by using dictionaries instead of if-elif statements, but I don't know how to do that. I'd like to use the logical expressions below somehow in the dictionary. (The code iterates through a and b)
def e_ha(n, t, a, b, E):
if a == b:
return 6
elif (a%n == 0, a != n**2, b == a + 1) == (True, True, True):
return 0
elif ((a-1)%n == 0, (a-1) != n**2, b == a - 1) == (True, True, True):
return 0
elif (a%n == 0, b == a-(n-1)) == (True, True):
return 1
elif (b%n == 0, a == b-(n-1)) == (True, True):
return 1
elif abs(a-b) == 1:
return 1
elif abs(a-b) == n:
return 1
else:
return 0
One naive approach to achieve the best performance is to build a big table storing the results for all possible (a, b) pairs. However, this could consume lots of memory and becomes inpractical for large ns.
Here is how the code can be optimized using a normal approach, as explained in the following step-by-step.
1. Using Explicit and for Logical Expressions
As suggested in the comments, this is much more readable and also more efficient because of the short circuiting behavior of and. This change alone reduces the runtime by 60% in my tests.
2. Remove Redundant Conditions
Since both a and b range from 1 to n**2, if a == n**2, then b == a + 1 can never be fulfilled. Therefore the a != n**2 check in the condition a%n == 0 and a != n**2 and b == a + 1 is redundant. The same applies to the third condition. Eliminating them simplifies these conditions to:
...
elif a % n == 0 and b == a + 1:
elif (a - 1) % n == 0 and b == a - 1:
...
3. Avoid Repeated Computations in Conditions
Note that the above-improved conditions
a % n == 0 and b == a + 1 and (a - 1) % n == 0 and b == a - 1 are special cases of abs(a - b) == 1. Therefore these conditions can be rewritten using nested if-else as follows.
if abs(a - b) == 1:
if a % n == 0 and b > a: return 0
elif b % n == 0 and a > b: return 0 # a - 1 equals to b here so it is replaced to save one computation
else return 1
Also note that the value abs(a - b) is related to all the conditions. Therefore it can be computed before all conditions are checked. With this change, the code becomes
d = abs(a - b)
if d == 0: return 6
elif d == 1:
if a % n == 0 and b > a: return 0
elif b % n == 0 and a > b: return 0
else return 1
elif d == n - 1:
if a % n == 0 and a > b: return 1
elif b % n == 0 and b > a: return 1
else return 0
elif d == n: return 1
else: return 0
4. Simplify Logic
For example, the first nested if-else above can be simplified to
if min(a, b) % n == 0: return 0
else return 1
A more compact syntax is:
return 1 if min(a, b) % n == 0 else 0
5. Apply Python-specific Optimizations
In Python, the number 0 is regarded as having a falsy value. So for numbers if d != 0: and if d == 0: are equivalent to if d: and if not d: respectively. The latter is a bit faster. Applying this change results in the following optimized code (here a more compact syntax is used to shorten the answer).
d = abs(b - a)
if not d: return 6
elif d == 1: return 1 if min(a, b) % n else 0
elif d == n - 1: return 0 if max(a, b) % n else 1
else: return 1 if d == n else 0
Applying steps 2 to 5 above reduces the runtime by another 50%.
6. Adjust Order of Conditions based on Input Distribution
This change relies on the knowledge of the actual input distribution in the application. The target is to make the more frequently seen inputs return faster. In this example, assume the inputs a and b are uniformly distributed within [1, n**2] and n >= 10. In this case, the most frequent scenario is that the value d does not match any of the if conditions and 0 is returned at the end after all conditions are checked. In order to speedup, we can make it fail faster by first checking whether d can possibly lead to a non-zero return value.
d = abs(a - b)
if 1 < d < n - 1 or d > n: return 0 # Return 0 if d is not in [0, 1, n - 1, n]
elif d == 1: return 1 if min(a, b) % n else 0
elif d == n - 1: return 0 if max(a, b) % n else 1
else: return 1 if d == n else 6 # d == 0 case is moved to the last "else" since it is least frequently seen
7. Using Lookup Tables
Further speedup can be achieved by using lookup tables. Here, the values [0, 1, n - 1, n] for the first conditional check can be stored to speedup the check. In this case, there are two primary options for this: a set or a length-n+1 list of boolean values. The former uses less memory while the latter has better performance. Note that the lookup table should be constructed once outside the function and passed into it. The code using a boolean list as a lookup is as follows:
def func(n, a, b, lookup):
d = abs(a - b)
if not (d <= n and lookup[d]): return 0
...
Applying steps 6 and 7 (with boolean list lookup) reduces the runtime by another 15%.
Note that in this example a 2D lookup table (implemented as nested lists or dictionaries) can also be applied using (min(a, b) % n, d) as indices. However, under the same assumption of input distribution in step 6, this is slightly slower than a 1D lookup because of the overhead of one extra level of indexing.
The runtime above is the total time of applying the function to all possible (a, b) values within [1, n**2] for n=20.
Using a dictionary, where the keys are boolean expressions is not going to work the way you hope it does. There is no such thing as a boolean-expression-object that could take the place of the key, only booleans. In the end, boolean expressions evaluate to either True or False, so at most you could only have two key-value pairs.
I would suggest, however, you make things a bit more readable/pythonic:
if a%n == 0 and a != n**2 and b == a + 1:
or
if all((a%n == 0, a != n**2, b == a + 1)):
You can just use a list of tuples and loop through it:
def e_ha(n, t, a, b, E):
checks = [
(a == b, 6),
(all(a%n == 0, a != n**2, b == a + 1), 0 ),
(all((a-1)%n == 0, (a-1) != n**2, b == a - 1), 0),
(all(a%n == 0, b == a-(n-1)), 1),
(all(b%n == 0, a == b-(n-1)), 1 ),
(abs(a-b) == 1, 1),
(abs(a-b) == n, 1),
(true, 0)
]
for valid, return_value in checks:
if valid:
return return_value
Caveat:
This is most certainly not faster in any way. Timed it multiple times and it was always slower.
It is less readable than the alternative
I'm new to programming and this is my first time asking a question, so apologies in advance if I'm breaking any protocols. I tried searching for an answer before posting, but I didn't find any matching results.
I'm working my way through Think Python 2, and here is my solution to exercise 5.3, the triangle exercise.
def is_tri():
print('Give me 3 lengths')
a = int(input('first?\n'))
b = int(input('second?\n'))
c = int(input('third?\n'))
if a > b + c or b > a + c or c > a + b:
print('Not a triangle')
else:
print("Yes, it's a triangle")
is_tri()
What I noticed is that if I give 3 answers wherein 2 of the lengths equal the third when added together, i.e. (1,1,2), the program returns Yes. But 2 is not greater than 2. I even added a series of 'and' statements requiring that the sum of any two sides must not equal the third, and it still returns Yes:
if (a > b + c or b > a + c or c > a + b) and (a != b + c and b != a + c and c != a + b):
The author mentions that the sum of two sides equaling the third is a 'degenerate triangle', perhaps anticipating this outcome. But why? Don't the '>' and '>=' operators provide different functions? Am I missing something? How can I constrain the operator to exclude degenerate triangles?
If you need to declare that triangles that have the largest side equal to the sum of the others are invalid you are using the wrong operator, you should use == in conjunction to >, so your condition would look like:
if (a > b + c or a == b + c) or (b > a + c or b == a + c ) or (c > a + b or c == a + b):
Which is exactly the same as to making it like this:
if a >= b + c or b >= a + c or c >= a + b:
One nice way of doing it is sorting the list to get the largest element and then comparing to the sum of the others using slices, for this you would need the inputs to be in a list:
triangle_sides = [int(input('first?\n')), int(input('second?\n')), int(input('third?\n'))]
triangle_sides = sorted(triangle_sides, reverse=True)
if triangle_sides[0] >= sum(triangle_sides[1:]):
print("Absolutelly not a triangle")
else:
print("Congratulations, its a triangle")
I would also recommend you to get your inputs from outside the function, separating the "user interface" from the logic, your script would look like:
def is_valid_triangle(triangle_sides):
triangle_sides = sorted(triangle_sides, reverse=True)
if triangle_sides[0] >= sum(triangle_sides[1:]):
return False
return True
def triangle_validator():
print('Give me 3 lengths')
triangle_sides = [
int(input('first?\n')),
int(input('second?\n')),
int(input('third?\n'))
]
if is_valid_triangle(triangle_sides):
print('Yes, it\'s a triangle')
else:
print('Not a triangle')
if __name__ == '__main__':
triangle_validator()
Your condition clearly states that the line lengths do not form a triangle only if one length is strictly greater than the sum of the other two. That's not the condition you're looking for. You want to disqualify the input if one is greater or equal to the sum of the other two.
This would work:
if a >= b + c or b >= a + c or c >= a + b: