I was doing some practice problems in Coding Bat, and came across this one..
Given 3 int values, a b c, return their sum. However, if one of the values is the same as another of the values, it does not count towards the sum.
lone_sum(1, 2, 3) → 6
lone_sum(3, 2, 3) → 2
lone_sum(3, 3, 3) → 0
My solution was the following.
def lone_sum(a, b, c):
sum = a+b+c
if a == b:
if a == c:
sum -= 3 * a
else:
sum -= 2 * a
elif b == c:
sum -= 2 * b
elif a == c:
sum -= 2 * a
return sum
Is there a more pythonic way of doing this?
Another possibility that works for an arbitrary number of arguments:
from collections import Counter
def lone_sum(*args):
return sum(x for x, c in Counter(args).items() if c == 1)
Note that in Python 2, you should use iteritems to avoid building a temporary list.
How about:
def lone_sum(*args):
return sum(v for v in args if args.count(v) == 1)
A more general solution for any number of arguments is
def lone_sum(*args):
seen = set()
summands = set()
for x in args:
if x not in seen:
summands.add(x)
seen.add(x)
else:
summands.discard(x)
return sum(summands)
Could use a defaultdict to screen out any elements appearing more than once.
from collections import defaultdict
def lone_sum(*args):
d = defaultdict(int)
for x in args:
d[x] += 1
return sum( val for val, apps in d.iteritems() if apps == 1 )
def lone_sum(a, b, c):
z = (a,b,c)
x = []
for item in z:
if z.count(item)==1:
x.append(item)
return sum(x)
Had a very similar approach to what you had:
def lone_sum(a, b, c):
if a != b and b != c and c != a:
return a + b + c
elif a == b == c:
return 0
elif a == b:
return c
elif b == c:
return a
elif c == a:
return b
Since if 2 values are the same the code will automatically return the
remaining value.
I tried this on Codingbat but it doesn`t work, although it does on the code editor.
def lone_sum(a, b, c):
s = set([a,b,c])
return sum(s)
Related
I'm trying to make a number based Mastermind game. Trying to figure out a function that takes two lists as paramenters and if indexes in the lists are the same it should return the amount of indexes that are the same.
PS. hope you understand what i mean ;P
generated_number_as_list = [1,1,1,1]
guess_as_list = [1,2,1,2]
correct = right_inrightplace(guess_as_list, generated_number_as_list)
print(correct)
output >> 2
You can use zip to compare values with corresponding indexes and then sum True which will be cast to 1
print(sum(x==y for x,y in zip(generated_number_as_list, guess_as_list))) #2
I wrote it outside of a function. Just copy the for loop in your function and return the ans value as the output.
generated_number_as_list = [1,1,1,1]
guess_as_list = [1,2,1,2]
ans = 0
for i in range(len(generated_number_as_list)):
if guess_as_list[i] == generated_number_as_list[i]:
ans = ans + 1
print(ans)
You can try this also:
a=[1,1,1,1]
b=[1,2,1,2]
print(min(len([x for x in a if x in b]),len([x for x in b if x in a])))
You can use the sum and map with operator.eq:
def right_inrightplace(a, b):
return sum(map(eq, a, b))
Or without using additional libraries:
def right_inrightplace(a, b):
return sum(x == y for x, y in zip(a, b))
Just for fun here's a solution using recursion:
def right_inrightplace(a, b):
if len(a) == 0 or len(b) == 0:
return 0
current = 0
if a[0] == b[0]:
current = 1
return current+right_inrightplace(a[1:],b[1:])
I have a function that returns a list of the factors of a number "n":
def factors(n):
i = 2
factlist = []
while i <= n:
if n% i == 0:
factlist.append(i)
i = i + 1
return factlist
Now I'm trying to create a function that counts how many times a factor is a factor of n. I have a function called "howManyTimesDivides" that returns this:
def howManyTimesDivides(n, d):
i = 0
while n%d==0:
n /= 2
i += 1
return i
Now, I'm trying to combine these two, but I cannot seem to apply the howManyTimesDivides function to a list "a = factors(n)". Here's what I have:
from collections import Counter
def factorCounts(n):
a = factors(n)
map(howManyTimesDivides(n,a), a)
return dict(Counter(divides))
Any insights?
You could use a list comprehension:
def factorCounts(n):
a = factors(n)
b = [howManyTimesDivides(n, i) for i in a]
return b
print(factorCounts(20))
Output:
[2, 1, 3, 2, 1]
I'm trying to build a function that checks which of a,b,c is less then returns the lesser value.
def minimal_three(a,b,c):
if a < b:
if a < c:
return (a)
elif b < a:
if b < c:
return (b)
elif c < a:
if c < b:
return (c)
else:
return 'none'
So far the code runs fine until it gets to check 'c', then it doesnt return anything, nested if else statements already get really confusing to me.
You shouldn't use if-else as the 3 conditions are not exclusive.
For example, [3, 4, 1] should return in the 3rd condition but is also suitable in the 1st condition, so it returns nothing.
If you don't want to change your code a lot. You can use:
def minimal_three(a,b,c):
if a < b:
if a < c:
return (a)
if b < a:
if b < c:
return (b)
if c < a:
if c < b:
return (c)
return 'none'
For simple, you can try:
def minimal_three(a,b,c):
return min(a, b, c)
why that code doesn't work:
def minimal_three(a,b,c):
if a < b:
if a < c:
return (a)
else:
# what if a >= c and a < b ?
return "i returned nothing"
elif b < a:
if b < c:
return (b)
else:
# what if b >= c and a > b ?
return "i returned nothing"
elif c < a:
if c < b:
return (c)
else:
# what if b <= c and a < c ?
return "i returned nothing"
else:
return 'none'
Alternative:
def min_of_two(a, b):
if a > b:
return b
return a
def min_of_three(a, b, c):
min_ab = min_of_two(a, b)
min_abc = min_of_two(min_ab, c)
return min_abc
def min_of_three_v2(a, b, c):
min_ab = a
if a > b:
min_ab = b
min_abc = min_ab
if min_ab > c:
min_abc = c
return min_abc
def min_of_three_v3(a, b, c):
min_abc = a
if min_abc > b:
min_abc = b
if min_abc > c:
min_abc = c
return min_abc
if you really want to use nested if/else (this code is so long):
# if-elif-else is ok.
# nested if is hard to read
# if-elif-elif-elif-elif...-else is hard to read.
# hard to read == easy to have bugs, which is bad.
def min_abc_slower(a, b, c):
if a > b:
# a > b. This means min(a, b) == b
if b > c:
# b > c. This means min(c, min(a, b)) == c
return c
else:
# b > c is False. This means b <= c.
# So, min(c, min(a, b)) == b
return b
else:
# a > b is False. This means a <= b.
# So, min(a, b) = a
if a > c:
# a > c. This means min(c, min(a, b)) == c
return c
else:
# a > c is False. This means a <= c
# So, min(c, min(a, b)) == a
return a
Use the power of if...elif...else over if...if...if or if...else...if...else. The way you have written your code, depreciates the power of elif. The correct way should be as this:
def minimal_three(a,b,c):
if a < b and a < c:
return (a)
elif b < c:
return (b)
else
return (c)
This code will always return the min no matter what numbers you give.
Explaination:
In your code, the line if a < b already tells you the comparison between a and b that which one is greater. So checking for this condition again in the second if if b < a is useless. if a is not lesser than b, then obviously it is either greater than b or equal to b. So now you must just check if b is lesser than c to prove that b is smallest or even a or b both but the returned value is always minimum. I hope you get that.
Also I don't understand whyt do you want to return None. If you provide three numbers to a function to find the minimum number, it should always and always return a number. Tell me a case where you can expect a None.
Easily be done using min inbuilt function:
def min_value(a,b,c):
return (min(a,min(b,c)))
also the number of steps in your code can be reduced with some tweaking.
It works - Finding two greatest in three int:
def Biggest(a, b, c):
if a >= b >= c:
print a, b, 'are the biggest two'
elif b >= c >= a:
print b, c, 'are the biggest two'
else:
print c, a, 'are the biggest two'
Find greatest in three integer:
def Biggest(a, y, z):
Max = a
if y > Max:
Max = y
if z > Max:
Max = z
if y > z:
Max = y
return Max
You could probably get away with using a for loop to minimise lines of code!
It would look something like this:
c = 3
b = 2
a = 1
list = [a,b,c]
def minimal_three(a,b,c):
for y in list:
n = y
for x in list:
if x < n:
print(n)
I am given 3 int, a, b, c. I would like to find the sum of all three int provided that they are unique. If a, b, or c has the same values as any of the other values, then they don't count towards the sum.
Example 1:
a = 3, b = 3, c =3
sum = 0
Example 2
a = 1, b = 3, c =3
sum = 1
This is what I have done. Is there a more pythonic way of doing this without so many if else statements?
def lone_sum(a, b, c):
if a != b and b != c and a != c:
return a + b + c
elif a == b == c:
return 0
elif a == b:
return c
elif b == c:
return a
elif a == c:
return b
from collections import Counter
def lone_sum(a, b, c):
d = Counter([a, b, c])
return sum(k for k in d if d[k]==1)
Add any number of numbers:
def lone_sum(*L):
d = Counter(L)
return sum(k for k in d if d[k]==1)
Add numbers repeated exactly c times:
def rep_sum(c, *L):
d = Counter(L)
return sum(k for k in d if d[k]==c)
Add numbers repeated at most c times:
def rep_sum(c, *L):
d = Counter(L)
return sum(k for k in d if d[k]<=c)
... or if you're bored and want to get really creative:
def lone_sum(*L):
nums = set()
all_nums = set()
for num in L:
if num in nums:
nums.remove(num)
elif num not in all_nums:
all_nums.add(num)
nums.add(num)
return sum(nums)
Here is a good beginners way to solve it
def lone_sum(*args):
return sum(x for x in args if args.count(x) == 1)
The issue with this is that args.count is a hidden loop, so the calculation becomes O(n2)
This doesn't matter much if there are only ever 3 arguments - ie n == 3.
A longhand way to write the same thing is
def lone_sum(a, b, c):
args = (a, b, c)
s = 0
for x in args:
if args.count(x) == 1:
s += x
return s
Here I take a list of your numbers, call it x, and then select only those x[i] which are not present in a list which is x without x[i]. That is, it removes all numbers which have a duplicate.
def lone_sum(a, b, c):
x = [a,b,c]
x = [x[i] for i in range(len(x)) if x[i] not in [x[j] for j in range(len(x)) if j!=i]]
return sum(x)
So,
[x[j] for j in range(len(x)) if j!=i]
is basically a list of elements excluding x[i]. It takes all elements apart from ith. If x[i] is in this list, it means it is a duplicate and we need to remove it. That is,
x[i] not in [x[j] for j in range(len(x)) if j!=i]
I think a lot has already been said and done on this topic and there is not much that can be added. But I too have written a program that uses sets to go about this task which is a little different from the top answer. So if you still wish to see all possible programs then here you go. Hope it helps!
def lone_sum(x):
c = set(x)
for b in c:
x.remove(b)
for a in set(x):
if a in c:
c.remove(a)
return(sum(c))
I'm having some trouble with the itertools.count function, and I don't quite understand what it does. I expect the code below to accomplish Project Euler problem 2.
I know that I could write this with a simple while loop, but is there a way to do it with a list comprehension? This code just freezes as I guess it's going to go infinity with count(). I would have hoped it would stop after x > MAX, but I know that won't happen. Is there a way to stop count in a generator expression like below?
def fib(n):
if (n <= 1): return 1
else: return fib(n-1) + fib(n-2)
MAX = 4000000
infiniteFib = (fib(x) for x in count())
s = (x for x in infiniteFib if x < MAX and x % 2 == 0)
print sum(s)
You could use takewhile:
>>> from itertools import count, takewhile, imap
>>> sum(x for x in takewhile(lambda x: x < 4000000, imap(fib, count())) if x % 2 == 0)
4613732
We just need to tell the infiniteFib generator when to stop yielding elements. itertools provides a number of useful methods to help with this:
less_than_max = itertools.takewhile(lambda x: x<MAX, infiniteFib))
even = itertools.ifilter(lambda x: x%2==0, less_than_max)
print sum(even)
We get a generator for all the numbers yielded by infiniteFib, until one returned is greater than MAX. Then we filter that generator, choosing only the even numbers. And finally we can sum the result.
How about:
def fib():
a, b = 1, 1
while True:
yield b
a, b = b, a+b
sum(f for f in itertools.takewhile(functools.partial(operator.ge, 4000000), fib()) if f % 2 == 0)
Or, pushing the parity check into the generator:
def even_fib():
a, b = 1, 1
while True:
if b % 2 == 0: yield b
a, b = b, a+b
sum(itertools.takewhile(functools.partial(operator.ge, 4000000), even_fib()))
Yeah, count() just keeps going, which isn't what you want. List comprehensions / iterator expressions don't have flexible exit conditions (but see #DSM's solution using takewhile).
I prefer just using while.
Here's my old answer to Euler 2:
def SumEvenFibonacci(limit):
x = y = 1
sum = 0
while (sum <= limit):
sum += (x + y)
x, y = x + 2 * y, 2 * x + 3 * y
return sum
ce = SumEvenFibonacci(4000000)
print ce
Here's another solution using takewhile, but non-recursively. Since the recursive solution requires calculating all the fibs less than n for each n, it's horrible slow.
def fib_gen(only_even=False):
one = 1
if not only_even:
yield one
two = 1
if not only_even:
yield two
while True:
next = one + two
one = two
two = next
if only_even:
if next % 2 == 0:
yield next
else:
yield next
list(itertools.takewhile(lambda x: x < 4000000, fib_gen()))