0

I am using the following script to compare the elements in two separate lists in Python3. If an element matches e.g. element [0] from list one matches element [0] from list two then the variable c is incremented by one. If the element does not match but the value is in the list then a different variable d is incremented.

I have put the code together but it is rather long and wanted to know if it could be condensed in some way.

a = [1,2,3,4]
b = [2,1,3,4]
c = 0
d = 0

if a[0] == b[0]:
    c += 1
elif a[0] == b[1] or a[0] == b[2] or a[0] == b[3]:
    d += 1

if a[1] == b[1]:
    c += 1
elif a[1] == b[0] or a[1] == b[2] or a[1] == b[3]:
    d += 1

if a[2] == b[2]:
    c += 1
elif a[2] == b[0] or a[2] == b[1] or a[2] == b[3]:
    d += 1

if a[3] == b[3]:
    c += 1
elif a[3] == b[0] or a[3] == b[1] or a[3] == b[2]:
    d += 1
MSeifert
  • 145,886
  • 38
  • 333
  • 352
zeeman
  • 185
  • 1
  • 1
  • 12
  • Show your desired output, there is no doubt it can be condensed, it's `elif` or `else`, there's probably a dupe somewhere... – Chris_Rands Aug 14 '17 at 10:16
  • what's the desired results in case of reprtition? – Mehdi Aug 14 '17 at 10:21
  • the desired output is to compare each element for exact matches in value or if the same value is in the other list – zeeman Aug 14 '17 at 10:28
  • so if `a=[1,2,3,4]` and `b=[1,1,2,1]`, the output must be `c=1` and `d=3`? – Mehdi Aug 14 '17 at 10:39
  • Yes that is correct Mehdi. The numbers in list a will change and the second list is a users input. The c and d variables are used to indicate the correct guesses made. – zeeman Aug 14 '17 at 11:47
  • But usually in mastermind game when you are allowed to have repetition and if the correct answer is `1234` but you guess `1111` the indicators must be: `1/1`. – Mehdi Aug 14 '17 at 14:14

4 Answers4

1
a = [1,2,3,4]
b = [2,1,3,4]

match = [a[i] == b[i] for i in range(len(a)) if a[i] in b]
c = sum(match)
d = len(match)-c

In this code match consists of boolean values, for matchings locations per members in the intersection of a and b.

This code will perform similarly to what was asked in the question. However, if the intention is to use it like mastermind game, this won't work. For example, if a=[1,2,3,4] and b=[4,4,4,4] the matching indicator must be: 1/1. The following code would do:

a = [1,2,3,4]
b = [4,4,4,4]

c = sum([a[i] == b[i] for i in range(len(a)) if a[i] in b])
d = sum([min(b.count(item), a.count(item)) for item in set(a)]) - c

Similar to the first guess in following game screenshot:

masetermind example

Mehdi
  • 4,202
  • 5
  • 20
  • 36
0

Instead of the elif statement you can use in. Let's look an example:

I have this list: a = [1, 2, 3]. 0 in areturns False but 1 in a returns True.

So, your code will look like this:

a = [1,2,3,4]
b = [2,1,3,4]
c = 0
d = 0

if a[0] == b[0]:
    c += 1
elif a[0] in b:
    d += 1

if a[1] == b[1]:
    c += 1
elif a[1] in b:
    d += 1

if a[2] == b[2]:
    c += 1
elif a[2] in b:
    d += 1

if a[3] == b[3]:
    c += 1
elif a[3] in b:
    d += 1
Néstor
  • 351
  • 1
  • 5
  • 20
0

You can just do this.

c = [e[0]==e[1] for e in [*zip(a,b)]].count(True)
d = [e in b for e in a].count(True) - c
N M
  • 596
  • 4
  • 18
0

Yes, it can be condensed by using a for-loop and you can also make it more performant by doing the elseif (in Python this is called elif) check on a set.

a = [1,2,3,4]
b = [2,1,3,4]
c = 0
d = 0

b_set = set(b)
for item_from_a, item_from_b in zip(a, b):
    if item_from_a == item_from_b:
        c += 1
    elif item_from_a in b_set:
        d += 1

With zip one iterates over both lists at once, so it will in the first iteration access the first element from a and b (i.e. 1 and 2) in the second iteration it will access the second element from both lists (2 and 1) and so on. You could also write it as loop over the indices (it's not as "clean" as using zip but maybe easier to understand):

for idx in range(len(a)):
    item_from_a = a[idx]
    item_from_b = b[idx]
    if item_from_a == item_from_b:
        c += 1
    elif item_from_a in b_set:
        d += 1

The loop body itself should be fairly straightforward but please leave a comment if some part needs more explanation.

MSeifert
  • 145,886
  • 38
  • 333
  • 352
  • I havent used the zip function before. if you could please provide more info or an example it would be mucha appreciatted, – zeeman Aug 14 '17 at 10:30
  • @zeeman Look here: https://docs.python.org/2/library/functions.html#zip. Zip is defintely one of the functions mostly used in Python. – Anton vBR Aug 14 '17 at 10:36
  • @zeeman `zip` is just a tool to iterate over multiple containers at once. It avoids having to loop over indices or calling `next` manually. There's a great answer (including examples) in this [Q+A on "How can I iterate through two lists in parallel?"](https://stackoverflow.com/questions/1663807/how-can-i-iterate-through-two-lists-in-parallel) – MSeifert Aug 14 '17 at 10:36