I'm trying to compare the position and elements of 3 different lists, to then save them in a new list, if at least 2 of the elements at the same position matched.
For Example:
a = [FF2, FF6, FC4]
b = [FB5, FB3, FC4]
c = [FF2, FB3, FM8]
Result = [FF2, FB3, FC4]
At the beginning I used the following code to compare 2 lists, and tried to adapt it for 3 lists, by adding an extra for loop after the for i1 and also adding an or to my if, but went horribly wrong (almost 10 times more values as expected as output).
for i, v in enumerate(a):
for i1, v1 in enumerate(b):
if (i==i1) & (v==v1):
Result.append(v)
This is my current approach, it's working fine, but I have no idea how can I append the matched value to my Result list.
Result = list(x for x, (xa, xb, xc) in enumerate(zip(a, b, c))
if xa == xb or xb == xc or xa == xc)
al = ['FF2', 'FF6', 'FC4']
bl = ['FB5', 'FB3', 'FC4']
cl = ['FF2', 'FB3', 'FM8']
res = []
for a,b,c in zip(al, bl, cl):
if a == b or b == c or c == a:
if a == b:
res.append(a)
elif b == c:
res.append(b)
elif c == a:
res.append(c)
print(res)
You can iterate through the 3 lists at the same time & append to the resulting list. Use zip()
You could avoid the issues you're having by eliminating the use of enumerate() and just using zip. We then check each unique element in each tuple created by zip and see if the count of that element is greater than 1. If so, we append this to our return list. The use of t.count() resolves the need for the untidy xa == xb or xb == xc or xa == xc condition & makes it easily extendable to n lists.
Code:
a = ['FF2', 'FF6', 'FC4']
b = ['FB5', 'FB3', 'FC4']
c = ['FF2', 'FB3', 'FM8']
r = [x for t in zip(a, b, c) for x in set(t) if t.count(x) > 1]
Output:
>>> r
['FF2', 'FB3', 'FC4']
You could do something like this,
a = ["FF2", "FF6", "FC4"]
b = ["FB5", "FB3", "FC4"]
c = ["FF2", "FB3", "FM8"]
result = []
for idx in range(len(a)):
if a[idx] == b[idx] or a[idx] == c[idx]:
result.append(a[idx])
elif b[idx] == c[idx]:
result.append(b[idx])
else:
pass
print(result)
the output will be,
['FF2', 'FB3', 'FC4']
Related
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.
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.
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 want to make a function that will remove '-' from two sequences of char if both contain it. This is my code.
def normalized(seq1, seq2):
x = ''
y = ''
for a, b in zip(seq1, seq2):
if a != '-' and b != '-':
print a,b, 'add'
x += a
y += b
else:
print a, b, 'remove'
return x,y
x = 'ab--dfd--df'
y = 'rt-bfdsu-vf'
print normalized(x, y)
and this is the result.
a r add
b t add
- - remove
- b remove
d f add
f d add
d s add
**- u remove**
- - remove
d v add
f f add
('abdfddf', 'rtfdsvf')
You can see that - and u should not be removed. What's wrong with my code?
You want to use or, not and ...
Another clever way that you could do this is to use operator chaining:
if a == b == '-':
print a,b, 'remove'
else:
print a,b, 'add'
x += a
y += b
This is extremely succint and clear that you want to remove the dashes only if they appear in both strings.
If you only want to remove if both are -, then test for that:
if not (a == '-' and b == '-'):
which can be shortened to:
if not (a == b == '-'):
or use or instead of and to remove the not:
if a != '-' or b != '-':
but that is not as readable.
Perhaps no more readable, but the list comprehension would be:
def normalized(seq1, seq2):
return [''.join(v) for v in zip(*[(a, b)
for a, b in zip(seq1, seq2) if not (a == b == '-')])]
or using map(), sufficient for Python 2:
def normalized(seq1, seq2):
return map(''.join, zip(*[(a, b) for a, b in zip(seq1, seq2) if not (a == b == '-')]))
The condition should be not (a =='-' and b == '-'):
def normalized(seq1, seq2):
x = ''
y = ''
for a, b in zip(seq1, seq2):
if not (a =='-' and b == '-'): # you need `not` here
print a,b, 'add'
x += a
y += b
else:
print a, b, 'remove'
return x,y
x = 'ab--dfd--df'
y = 'rt-bfdsu-vf'
print normalized(x, y)
According to your code, - u shoud be removed.
In fact,
a != '-' and b != '-' is False
the first part is false and the second is true. False and True is False. (Boolean Algebra 101, see http://en.wikipedia.org/wiki/Boolean_algebra#Basic_operations for details)
You are currently asking for the program to match when a and b are not "-". This means that unless both are not equal to "-" then it will go to your else. The code you want is:
def normalized(seq1, seq2):
x = ''
y = ''
for a, b in zip(seq1, seq2):
if a == '-' and b == '-':
print a,b, 'remove'
else:
print a, b, 'add'
x += a
y += b
return x,y
x = 'ab--dfd--df'
y = 'rt-bfdsu-vf'
print normalized(x, y)
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)