Python sum of non duplicate int - python

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))

Related

How can I avoid getting Index error in the question sorting the output from a quadratic equation if the input is already sorted?

So I was trying this question on g4g:
https://practice.geeksforgeeks.org/problems/sort-the-given-array-after-applying-the-given-equation0304/1#
Here I am using the idea to get the minima/maxima of the quadratic
equation so that I can apply the merge process(which is using two
sorted arrays to make a single sorted array containing both the
elements) Here A0 and A<=0 is used to get the nature of the parabola,
opening upward or downward
I am facing error at out.append(A*arr[i]arr[i]+Barr[i]+C) as
indexerror, list out of range. I am sure if x = 0 or x = len(nums),
then I'll get into trouble, but I am not able to think anything
otherwise:
Some of the test cases are:
A = 1, B = 1, C = 1. N = 3 Arr[] = {1, 2, 3}
A = -1, B = 2, C = -1. N = 6 Arr[] = {-1, 0, 1, 2, 3, 4}
Here is my code for the same:
class Solution:
def sortArray(self, arr, n, A, B, C):
# Code here
#nums = arr[:]
#print(nums)
out = []
nums = []
for i in range(len(arr)):
nums.append(A*arr[i]*arr[i]+B*arr[i]+C)
x = -((B)//2*A)
#print(x)
i = x
j = x-1
#out = []
if i == 0:
return arr
if A>0:
while j>=0 and i<len(nums):
if A*arr[i]*arr[i]+B*arr[i]+C<=A*arr[j]*arr[j]+B*arr[j]+C:
out.append(A*arr[i]*arr[i]+B*arr[i]+C)
i+=1
else:
out.append(A*arr[j]*arr[j]+B*arr[j]+C)
j-=1
while i<len(nums):
#print(i)
out.append(A*arr[i]*arr[i]+B*arr[i]+C)
i+=1
while j>=0:
out.append(A*arr[j]*arr[j]+B*arr[j]+C)
j-=1
return out
elif A<=0:
i = 0
j = len(nums)-1
while j>=x and i<x:
if A*arr[i]*arr[i]+B*arr[i]+C<=A*arr[j]*arr[j]+B*arr[j]+C:
out.append(A*arr[i]*arr[i]+B*arr[i]+C)
i+=1
else:
out.append(A*arr[j]*arr[j]+B*arr[j]+C)
j-=1
while j>=x:
out.append(A*arr[j]*arr[j]+B*arr[j]+C)
j-=1
while i<x:
out.append(A*arr[i]*arr[i]+B*arr[i]+C)
i+=1
return out
#{
# Driver Code Starts
#Initial Template for Python 3
if __name__ == '__main__':
T=int(input())
for i in range(T):
a, b, c = input().split()
a = int(a)
b = int(b)
c = int(c)
n = int(input())
arr = list(map(int, input().split()))
ob = Solution()
ans = ob.sortArray(arr, n, a, b, c)
for each in ans:
print(each,end=" ")
print()
#} Driver Code Ends
Thanks in advance!
Always try to break such a problem down into small junks that makes it way easier for you to understand what is happening and find errors. Also, you don't need to define a class for this problem, when you can just use simple functions.
I don't want to give a finished code sample, because I guess you like to solve the problem yourself, so here is a boilerplate that may help you to solve it. The body of the two functions should not be longer than maybe 10 lines of code, so if you end up with more lines, you should reconsider. Good luck :)
def calculate_new_array(arr, a, b, c):
# calculate the resulting array out of the input values
# ...
# return resulting array
return result
def sort_array(arr):
# sort the array somehow
# ...
# return the sorted array
return sorted_arr
if __name__ == '__main__':
a, b, c = input().split()
a = int(a)
b = int(b)
c = int(c)
arr = list(map(int, input().split()))
new_array = calculate_new_array(arr, a, b, c)
sorted_array = sort_array(new_array)
print(sorted_array)
Small little spoiler: With python N is not that important.

Nested if ... else (Python exercise)

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)

Longest Common Subsequence of Three Sequences

I've implemented my version of Longest Common Subsequence of Three Sequences and cannot find a mistake. But Coursera grader says that I fail last test case.
It means that the algorithm is almost corrects but outputs a wrong answer in a specific case. But what case is it?
Constraints: length of the list is not less than one and not bigger than 100. Numbers in the lists are integers from -10^9 to 10^9.
import sys
def lcs3(a, b, c):
start_b = 0
start_c = 0
result = []
for i in range(len(a)):
for j in range(start_b, len(b)):
if a[i] == b[j]:
for k in range(start_c, len(c)):
if b[j] == c[k]:
start_b = j+1
start_c = k+1
result.append(a[i])
break
if b[j] == c[k]:
break
return len(result)
def lcs3_reversed(a,b, c):
# check reversed sequence which can be with different order
a_rev = a[::-1]
b_rev = b[::-1]
c_rev = c[::-1]
result = lcs3(a, b, c)
result_reversed = lcs3(a_rev, b_rev, c_rev)
if result == result_reversed:
return result
else:
return result_reversed
if __name__ == '__main__':
input = sys.stdin.read()
data = list(map(int, input.split()))
an = data[0]
data = data[1:]
a = data[:an]
data = data[an:]
bn = data[0]
data = data[1:]
b = data[:bn]
data = data[bn:]
cn = data[0]
data = data[1:]
c = data[:cn]
print(lcs3_reversed(a, b, c))
Update: added the function lcs3_reversed to solve the cases described by you. Anyway cannot pass the test case.
Output should contain the length of common subsequence. For example, for input:
3
1 2 3
3
2 1 3
3
1 3 5
output is 2 because the common part is (1, 3) for these 3 lists.
Runtime for failed case is 0.04 seconds and it looks like that the lists are rather long since most of my own tests worked much faster.
Thanks for your help!
Update2: I've tried another version. First we find the Longest Common Subsequence of 2 lists and then use it again on our result and the 3-rd list.
def lcs2(a, b):
start_b = 0
result = []
for i in range(len(a)):
for j in range(start_b, len(b)):
if a[i] == b[j]:
start_b = j+1
result.append(a[i])
break
return result
def lcs2_reversed(a, b):
# check reversed sequence which can be with different order
a_rev = a[::-1]
b_rev = b[::-1]
result_reversed = lcs2(a_rev, b_rev)[::-1]
return result_reversed
def lcs3_reversed(a, b, c):
lcs2_str = lcs2(a, b)
lcs2_rev = lcs2_reversed(a, b)
lcs3_str_str = lcs2(lcs2_str, c)
lcs3_rev_rev = lcs2_reversed(lcs2_rev, c)
lenghts = [len(lcs3_str_str), len(lcs3_rev_rev)]
return max(lenghts)
if __name__ == '__main__':
an = input()
a = input().split()
bn = input()
b = input().split()
cn = input()
c = input().split()
print(max(lcs3_reversed(a, b, c), lcs3_reversed(a, c, b), lcs3_reversed(b, a, c),
lcs3_reversed(b, c, a), lcs3_reversed(c, a, b), lcs3_reversed(c, b, a)))
Moreover, I tried all the combinations of orders but it did not help... Again I cannot pass this last test case.
Your example breaks with something like:
a = [1,2,7,3,7]
b = [2,1,2,3,7]
c = [1,2,3,1,7]
The sequence should be [1,2,3,7] (if I understand the exercise correctly), but the problem is that the last element of a gets matched to the last elements of b and c, which means that start_b and start_c are set to the last elements and therefore the loops are over.

Looking for a more pythonic logical solution

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)

Python Fibonacci Generator

I need to make a program that asks for the amount of Fibonacci numbers printed and then prints them like 0, 1, 1, 2... but I can't get it to work. My code looks the following:
a = int(raw_input('Give amount: '))
def fib():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
a = fib()
a.next()
0
for i in range(a):
print a.next(),
I would use this method:
Python 2
a = int(raw_input('Give amount: '))
def fib(n):
a, b = 0, 1
for _ in xrange(n):
yield a
a, b = b, a + b
print list(fib(a))
Python 3
a = int(input('Give amount: '))
def fib(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
print(list(fib(a)))
You are giving a too many meanings:
a = int(raw_input('Give amount: '))
vs.
a = fib()
You won't run into the problem (as often) if you give your variables more descriptive names (3 different uses of the name a in 10 lines of code!):
amount = int(raw_input('Give amount: '))
and change range(a) to range(amount).
Since you are writing a generator, why not use two yields, to save doing the extra shuffle?
import itertools as it
num_iterations = int(raw_input('How many? '))
def fib():
a,b = 0,1
while True:
yield a
b = a+b
yield b
a = a+b
for x in it.islice(fib(), num_iterations):
print x
.....
Really simple with generator:
def fin(n):
a, b = 0, 1
for i in range(n):
yield a
a, b = b, a + b
ln = int(input('How long? '))
print(list(fin(ln))) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]
Python is a dynamically typed language. the type of a variable is determined at runtime and it can vary as the execution is in progress.
Here at first, you have declared a to hold an integer type and later you have assigned a function to it and so its type now became a function.
you are trying to apply 'a' as an argument to range() function which expects an int arg but you have in effect provided a function variable as argument.
the corrected code should be
a = int(raw_input('Give amount: '))
def fib():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
b = fib()
b.next()
for i in range(a):
print b.next(),
this will work
def fibonacci(n):
fn = [0, 1,]
for i in range(2, n):
fn.append(fn[i-1] + fn[i-2])
return fn
To get the fibonacci numbers till any number (100 in this case) with generator, you can do this.
def getFibonacci():
a, b = 0, 1
while True:
yield b
b = a + b
a = b - a
for num in getFibonacci():
if num > 100:
break
print(num)
def genFibanocciSeries():
a=0
b=1
for x in range(1,10):
yield a
a,b = b, a+b
for fib_series in genFibanocciSeries():
print(fib_series)
Your a is a global name so-to-say.
a = int(raw_input('Give amount: '))
Whenever Python sees an a, it thinks you are talking about the above one. Calling it something else (elsewhere or here) should help.
Also you can use enumerate infinite generator:
for i,f in enumerate(fib()):
print i, f
if i>=n: break
Also you can try the closed form solution (no guarantees for very large values of n due to rounding/overflow errors):
root5 = pow(5, 0.5)
ratio = (1 + root5)/2
def fib(n):
return int((pow(ratio, n) - pow(1 - ratio, n))/root5)
You had the right idea and a very elegant solution, all you need to do fix is your swapping and adding statement of a and b. Your yield statement should go after your swap as well
a, b = b, a + b #### should be a,b = a+b,a #####
`###yield a`
Simple way to print Fibonacci series till n number
def Fib(n):
i=a=0
b=1
while i<n:
print (a)
i=i+1
c=a+b
a=b
b=c
Fib(input("Please Enter the number to get fibonacci series of the Number : "))
a = 3 #raw_input
def fib_gen():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
fs = fib_gen()
next(fs)
for i in range(a):
print (next(fs))
I've build this a while ago:
a = int(raw_input('Give amount: '))
fab = [0, 1, 1]
def fab_gen():
while True:
fab.append(fab[-1] + fab[-2])
yield fab[-4]
fg = fab_gen()
for i in range(a): print(fg.next())
No that fab will grow over time, so it isn't a perfect solution.
It looks like you are using the a twice. Try changing that to a different variable name.
The following seems to be working great for me.
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
f = fib()
for x in range(100):
print(f.next())
i like this version:
array = [0,1]
for i in range(20):
x = array[0]+array[1]
print(x)
array[0] = array[1]
array[1] = x
Below are two solution for fiboncci generation:
def fib_generator(num):
'''
this will works as generator function and take yield into account.
'''
assert num > 0
a, b = 1, 1
while num > 0:
yield a
a, b = b, a+b
num -= 1
times = int(input('Enter the number for fib generaton: '))
fib_gen = fib_generator(times)
while(times > 0):
print(next(fib_gen))
times = times - 1
def fib_series(num):
'''
it collects entires series and then print it.
'''
assert num > 0
series = []
a, b = 1, 1
while num > 0:
series.append(a)
a, b = b, a+b
num -= 1
print(series)
times = int(input('Enter the number for fib generaton: '))
fib_series(times)
Why do you go for complex here is one of my snippet to work on!!
n = int(input('Enter your number..: '))
a = 0
b = 1
c = 0
print(a)
print(b)
for i in range(3, n+1):
c = a+b
print(c)
a,b=b,c
check out my git - rohith-sreedharan
We can use it in a short way without through 'yield and 'next' statements
def fib(n):
return n if n <= 1 else fib(n - 1) + fib(n - 2)

Categories