3

Possible Duplicate:
How can I find the missing value more concisely?

Is there a nice way of expressing the commutative operator T on the alphabet a b c using the language of Python, where

  • a T b == c
  • b T c == a
  • c T a == b

My best attempt is to hardcode things:

def T(first, second):
    if first is 'a' and second is 'b':
        return 'c'
    if first is 'a' and second is 'c':
        return 'c'
    if first is 'b' and second is 'c':
        return 'a'
    if first is 'b' and second is 'a':
        return 'c'
    if first is 'c' and second is 'a':
        return 'b'
    if first is 'c' and second is 'b':
        return 'a'
Community
  • 1
  • 1
Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • Please define the requirements for "commutative ternary operator T". What's it do? – Steven Rumbalski Feb 15 '12 at 15:23
  • commutative: `i T j == j T i` for any `i, j`. ternary: "on the alphabet `a, b, c`" – Randomblue Feb 15 '12 at 15:25
  • 2
    http://stackoverflow.com/questions/8792440/how-can-i-find-the-missing-value-more-concisely/ is this what you want? – ChessMaster Feb 15 '12 at 15:26
  • 4
    Don't use `is` for comparing strings. Use `==`. –  Feb 15 '12 at 15:30
  • 2
    what values do you want "a T a", "b T b", and "c T c" to have? – Edward Loper Feb 15 '12 at 15:32
  • @Randomblue: Because it does not work, at least not reliably. See http://stackoverflow.com/questions/2988017/string-comparison-in-python-is-vs (and note that the same is true for integer, small ones may be cached but in general you can have multiple integer objects with equal value). –  Feb 15 '12 at 15:35

5 Answers5

10

How about this:

alphabet = set(['a', 'b', 'c'])
def T(x, y):
    return (alphabet - set([x, y])).pop()

Using it like this:

T('a', 'b')
> 'c'
eumiro
  • 207,213
  • 34
  • 299
  • 261
Óscar López
  • 232,561
  • 37
  • 312
  • 386
3
l = ['a', 'b', 'c']
return list(set(l) - set((first, second)))[0]
eumiro
  • 207,213
  • 34
  • 299
  • 261
3

Here is a Python class that defines operator '|' such that you can write 'a' |T| 'b' and get your resulting 'c':

class Ternary(object):
    def __init__(self, *items):
        if len(items) != 3:
            raise ValueError("must initialize with exactly 3 items")

        self.items = set(items)
        self.left = None

    def __ror__(self, other):
        ret = Ternary(*list(self.items))
        ret.left = other
        return ret

    def __or__(self, other):
        if self.left is not None:
            ret = (self.items-set([self.left,other])).pop()
            return ret
        else:
            raise ValueError("cannot process right side without left side")

T = Ternary('a', 'b', 'c')
for test in """'a' |T| 'c'
               'a' |T| 'b'
               'c' |T| 'b'""".splitlines():
    test = test.strip()
    print test, '->', eval(test)

Prints:

'a' |T| 'c' -> b
'a' |T| 'b' -> c
'c' |T| 'b' -> a
PaulMcG
  • 62,419
  • 16
  • 94
  • 130
1
>>> def T(first, second):
...     s = ord('a') + ord('b') + ord('c')
...     return chr(s - ord(first) - ord(second))
... 
>>> T('a', 'b')
'c'
Mariy
  • 5,746
  • 4
  • 40
  • 57
1

How about a look-up table:

def T(first, second):
   d={'ab':'c',
      'ac':'c',
      'bc':'a',
      'ba':'c',
      'ca':'b',
      'cb':'a'}

      st=''.join([first,second])
      if d[st]: return d[st]
      else: return None
the wolf
  • 34,510
  • 13
  • 53
  • 71