20
\$\begingroup\$

Challenge

Given an arbitrary list of 2-tuples, and a single element in one of those tuples, output its "partner", i.e. given a and [(i,j),...,(a,b),...,(l,m)], output b. You can assume all tuples are unique, and that all elements in tuples are strings. Further assume you do not have both (x,y) and (y,x).

Test cases

Input                                                           Output

[("(", ")"), ("{", "}"), ("[", "]")], "}"                       "{"
[("I'm", "So"), ("Meta", "Even"), ("This", "Acronym")], "Even"  "Meta"
[("I", "S"), ("M", "E"), ("T", "A")], "A"                       "T"
[("test", "cases"), ("are", "fun")], "test"                     "cases"
[("sad", "beep"), ("boop", "boop")], "boop"                     "boop"

Fewest bytes wins!

\$\endgroup\$
6
  • \$\begingroup\$ Also, what to do if the input appears several times, or doesn't appear \$\endgroup\$ – Luis Mendo Aug 15 '17 at 19:16
  • \$\begingroup\$ I don't suppose we can take input as a flat list, right? For example, [a, b, c, d] instead of [(a, b), (c, d)]. It would shave a ton of bytes off my answer. :P \$\endgroup\$ – totallyhuman Aug 15 '17 at 21:54
  • \$\begingroup\$ I have edited to hopefully clear some stuff up and have added test cases. Feel free to roll back if anything is wrong. \$\endgroup\$ – totallyhuman Aug 15 '17 at 23:46
  • \$\begingroup\$ @totallyhuman I specifically asked about (a,a) and was told it would not happen. Nate then even edited the question to specify this fact. However you've added a test case with such an entry and also edited the specification reversing this decision - why? It's broken a bunch of answers. \$\endgroup\$ – Jonathan Allan Aug 16 '17 at 20:46
  • 1
    \$\begingroup\$ @totallyhuman I took it to mean "return anything, crash, whatever" especially since the post was then revised to say everything would be unique. \$\endgroup\$ – Jonathan Allan Aug 16 '17 at 20:56

28 Answers 28

8
\$\begingroup\$

Japt, 6 bytes

Works with strings or integers.

æøV kV

Test it


Explanation

Implicit input of array U and string/integer V.

æ

Get the first element (subarray) in U that ...

øV

Contains V.

kV

Remove V and implicitly return the resulting single-element array.

\$\endgroup\$
2
  • \$\begingroup\$ That's... I literally tried that exact scenario, same input and all. I must have missed something... EDIT: Oh right, I was using f instead of æ at the time. Duh :P \$\endgroup\$ – ETHproductions Aug 15 '17 at 19:05
  • \$\begingroup\$ @ETHproductions: Makes a nice change - usually I'm the one who forgets about æ and tries to muddle through with f! :D \$\endgroup\$ – Shaggy Aug 16 '17 at 8:35
8
\$\begingroup\$

Haskell, 33 bytes

x!((a,b):c)|x==a=b|x==b=a|1<2=x!c

Try it online!

Defines a binary operator !, which takes as its left argument a value x of type τ and as its right argument a list of tuples (τ, τ). The definition pattern matches on the head (a,b) and tail c of the given list; if x==a then b is returned; if x==b then a is returned, and otherwise we go on looking in the rest of the list by recursing.

  'f' ! [('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h')]
≡ 'f' ! [('c', 'd'), ('e', 'f'), ('g', 'h')]
≡ 'f' ! [('e', 'f'), ('g', 'h')]
≡ 'e'

(If there’s no “partner” in the list, this will crash, because we didn’t define what x![] should be.)

\$\endgroup\$
0
5
\$\begingroup\$

JavaScript (ES6), 39 bytes

e=>g=([[b,c],...a])=>e==b?c:e==c?b:g(a)

Takes the entry and array of arrays as curried arguments. Best non-recursive version I could do was 44 bytes:

e=>a=>a.find(a=>a.includes(e)).find(b=>b!=e)
\$\endgroup\$
3
  • \$\begingroup\$ Here's a 41-byte non-recursive solution: a=>b=>a.map(e=>b=e[1-e.indexOf(b)]||b)&&b \$\endgroup\$ – Rick Hitchcock Aug 15 '17 at 21:56
  • \$\begingroup\$ You ... You finally gave in to currying?! :o \$\endgroup\$ – Shaggy Aug 17 '17 at 8:40
  • \$\begingroup\$ @Shaggy Normally I don't bother for the (a,b)=> => a=>b=> type of currying, but the non-recursive version started out from the recursive version, which was curried because I was able to save 2 bytes on the recursive call (the currying itself actually costs a byte). \$\endgroup\$ – Neil Aug 17 '17 at 10:55
5
\$\begingroup\$

MATL, 4 14 5 6 bytes

yY=P)u

Try it online!

Input is an array as [{a;b},{c;d}]. Bytecount fluctuates heavily while the OP figures out what's actually allowed.

y     % Implicitly input tuples T and 'lonely element' E, duplicate from below to get [T E T] on the stack
 Y=   % String comparison, element wise, between T and E. Yields a boolean array with a 1 at the correct location.
   P  % Flip this array vertically, to put the 1 at the 'partner' of E.
    ) % Select this partner from the bottom T.

I started off with a 4-byte version that could only handle single-character strings, which was the only testcase in the original challenge. When this turned out to be invalid, I made a very long 14-byte version, which was nice and hacky (check the revision history!), made me discover a bug, and then turned out to be completely unnecessary as Y=, with suitable input, worked just as well as my original 4-byte y=P).

\$\endgroup\$
4
\$\begingroup\$

Python 2, 37 bytes

lambda x,y:dict(x+map(reversed,x))[y]

Try it online!

Proton, 31 bytes

a,b=>dict(a+map(reversed,a))[b]

Try it online!

(These two answers are so similar that I'm posting them together to avoid repfarming)

\$\endgroup\$
4
  • \$\begingroup\$ Rename reversed to reverse in Proton for -1 byte. \s :P More seriously, reverse is a much better name, no? :P \$\endgroup\$ – totallyhuman Aug 15 '17 at 19:32
  • \$\begingroup\$ @totallyafloppydisk maybe /shrug but I didn't rename most of the Python builtins that get carried over to Proton \$\endgroup\$ – hyper-neutrino Aug 15 '17 at 19:33
  • \$\begingroup\$ @Sanchises I don't see what's wrong? \$\endgroup\$ – hyper-neutrino Aug 17 '17 at 15:06
  • \$\begingroup\$ Sorry my bad, disregard that comment. \$\endgroup\$ – Sanchises Aug 17 '17 at 21:22
2
\$\begingroup\$

Perl 5, 30 + 1 (-p) = 31 bytes

$_={@f=eval$_,reverse@f}->{<>}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 2, 59 45 42 bytes

-14 bytes thanks to Emigna. -3 bytes thanks to Maltysen.

lambda l,v:sum(l,())[sum(l,()).index(v)^1]

Try it online!

Still wanna use currying though. ;-;

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 45 bytes \$\endgroup\$ – Emigna Aug 15 '17 at 21:12
  • \$\begingroup\$ Aha, knew there was a shorter way of doing y+[1,-1][y%2]. Just didn't think it was bitwise... Thanks! \$\endgroup\$ – totallyhuman Aug 15 '17 at 21:29
2
\$\begingroup\$

C++, 179 bytes

#include<vector>
#include<string>
#define S std::string
S f(std::vector<std::pair<S,S>>s,S t){for(auto&a:s){if(a.first==t)return a.second;if(a.second==t)return a.first;}return"";}

C++ w/ map data type, 162 bytes

#include<map>
#include<string>
#define S std::string
S f(std::map<S,S>s,S t){for(auto&a:s){if(a.first==t)return a.second;if(a.second==t)return a.first;}return"";}

With MSVC, the code compiles even if the last return statement ( return""; ) is omitted. It makes the code 9 bytes lighter, BUT exiting by the function end ( i.e. not exiting by a return statement in the loop ) with no return statements will cause undefined behavior, and not work if the tuple array does not contains the "key" element

\$\endgroup\$
2
\$\begingroup\$

PowerShell, 36 Bytes

param($a,$c)$a|?{$c-in$_}|%{$_-ne$c}

finds the element containing the intput, then gets the 'other' element by excluding the input from it, PowerShell doesn't have the most amazing array management but there might be a built-in for this i'm not aware of.

.\Partner.ps1 (("I'm","So"),("Meta","Even"),("This","Acronym")) "Even"
Meta
\$\endgroup\$
1
  • \$\begingroup\$ This approach doesn't work for the ("boop", "boop") test case. \$\endgroup\$ – AdmBorkBork Aug 17 '17 at 12:57
2
\$\begingroup\$

Röda, 30 bytes

f a{[(_+"")[1-indexOf(a,_1)]]}

Try it online!

Explanation:

f a{[(_+"")[1-indexOf(a,_1)]]}
f a{                         } /* Function f(a)                         */
                               /* For each pair _1 in the stream:       */
              indexOf(a,_1)    /*   Index of a in _1 or -1 if not found */
            1-                 /*   Subtract from 1 to get the index of
                                     the other value in the pair or 2 if
                                     a is not in the pair               */
     (_+"")                    /*   Append "" to _1                     */
           [               ]   /*   Get element the other element or "" */
    [                       ]  /*   Push it to the straem               */
                               /* All values in the stream are printed  */
\$\endgroup\$
2
\$\begingroup\$

Mathematica 27 24 Bytes

Cases picks out elements of a list that match a pattern. When used with an arrow, elements matching patterns can be transformed.

Cases[{#,x_}|{x_,#}:>x]&

Usage:

%[3][{{1, 2}, {3, 4}}]

Explanation: In this example, after encountering the first argument, 3, the function becomes Cases[{3,x_}|{x_,3}:>x] which is an operator form of Cases that is then applied to the 2nd argument, {{1, 2}, {3, 4}}, thus selecting the companion of 3, whether it be in the abscissa or ordinate position. Notably, this function will list out all of the companions if in fact the 1st argument appears more than once within the 2nd argument, in other words, this goes a little beyond the assumptions of the stated question.

Enclosing glyphs must be squiggly braces. Saved 3 bytes with "Currying" suggestion from @Notatree

\$\endgroup\$
2
  • 1
    \$\begingroup\$ If you have version 10 and you take input by currying, you can save 3 bytes: Cases[{#,x_}|{x_,#}:>x]&, used like %[3][{{1,2},{3,4}}] \$\endgroup\$ – Not a tree Aug 15 '17 at 23:58
  • \$\begingroup\$ Can you explain this one a bit? \$\endgroup\$ – Nate Stemen Aug 16 '17 at 7:15
2
\$\begingroup\$

R, 47 42 bytes

function(v,a)a[(i=min(which(v==a)))+(i%%2*2-1)]

Try it online!

Works on either a matrix or a straight vector. v = the search value, a = tuple array.

\$\endgroup\$
1
  • \$\begingroup\$ @Sanchises Thanks, all fixed up now. \$\endgroup\$ – MickyT Aug 16 '17 at 20:36
2
\$\begingroup\$

Jelly, 6 bytes

ċÞṪ⁻ÞṪ

A dyadic link taking the list partners on the left and the lost-partner on the right and returning the partner.

Try it online!

How?

ċÞṪ⁻ÞṪ - Link: list, partners; item, lost-partner
 Þ     - sort (the tuples) by:
ċ      -   count occurrence of lost-partner
  Ṫ    - tail (gets the tuple containing the lost-partner)
    Þ  - sort (that tuple's items) by:
   ⁻   -   not equals (non-vectorising version)
     Ṫ - tail (get the other one, or the rightmost one if they were equla)
\$\endgroup\$
5
  • \$\begingroup\$ This is invalid since the new testcases have been added. \$\endgroup\$ – Sanchises Aug 16 '17 at 20:25
  • 1
    \$\begingroup\$ Thanks for pointing that out - I've commented under the question to the editor (I had specifically asked the OP about (a,a) and was told we did not need to handle it). I'm sure I could fix it, but am unsure if the specification is as it was intended now. \$\endgroup\$ – Jonathan Allan Aug 16 '17 at 20:49
  • \$\begingroup\$ Hmm, although looking at the revision history it seems we need to support strings not just characters so this wont work anyway... \$\endgroup\$ – Jonathan Allan Aug 16 '17 at 20:52
  • \$\begingroup\$ Works with the new spec now. \$\endgroup\$ – Jonathan Allan Aug 16 '17 at 21:31
  • \$\begingroup\$ That was my interpretation too of the "oh well" comment, but evidently this was not the case. \$\endgroup\$ – Sanchises Aug 17 '17 at 6:08
1
\$\begingroup\$

Pyth - 11 9 8 bytes

h-hf}QTE

Try it online here.

\$\endgroup\$
1
\$\begingroup\$

Haskell, 65 62 bytes

c#(a,b)|a==c=b|1>0=a
x%l=x#(snd(span(\(a,b)->a/=x&&b/=x)l)!!0)

Try it online!

Explanation

This uses span to find the first instance where x is contained by the tuple. It then grabs the first element of the tuple if its not equal and the second otherwise.

Haskell Lambdabot, 59 56 bytes

c#Just(a,b)|a==c=b|1>0=a
x%l=x#find(\(a,b)->a==x||b==x)l

Try it online!

Explanation

This uses Data.Lists first function to cut down on the bytes used by (!!0).snd.span, however because first returns a Maybe we need to add Just to our pattern match in #.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Don’t overthink it… x!((a,b):c)|x==a=b|x==b=a|1<2=x!c is 33 bytes. \$\endgroup\$ – Lynn Aug 15 '17 at 19:50
  • 1
    \$\begingroup\$ @Lynn Go ahead and post it. I feel a bit foolish for not thinking of that, but its really your answer. \$\endgroup\$ – Wheat Wizard Aug 15 '17 at 19:51
  • \$\begingroup\$ Fair, posted ^^ \$\endgroup\$ – Lynn Aug 15 '17 at 19:52
1
\$\begingroup\$

05AB1E, 7 bytes

.åÏ`¹K`
  Ï      # keep only pairs that contain the first input
   `     # flatten
    ¹K   # remove the first input
      `  # flatten

Try it online!

Alternative 7 byte solution

˜DIkX~è
˜        # deep flatten
 D       # duplicate
  Ik     # get the index of the second input in this list
    X^   # XOR with 1
      è  # get the element at this index

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ ˜D²k>è for 6, unless there's a specific reason for XOR'ing with 1? \$\endgroup\$ – Magic Octopus Urn Aug 16 '17 at 1:52
  • \$\begingroup\$ @MagicOctopusUrn: The reason is that even indices should decrement and odd indices increment. \$\endgroup\$ – Emigna Aug 16 '17 at 6:05
  • \$\begingroup\$ Except the reverse of what I wrote there... \$\endgroup\$ – Emigna Aug 16 '17 at 8:25
1
\$\begingroup\$

Common Lisp, 74 bytes

(lambda(a x)(or(cdr(assoc x a :test'equal))(car(rassoc x a :test'equal))))

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Java 8, 78 bytes

A lambda (curried) from Stream<List<String>> to a lambda from String to String (although implicit typing happens to allow this to work for arbitrary lists). The language has no dedicated tuple classes, and I'm not aware of any in the standard library, so input pairs are represented as lists. Can be assigned to Function<Stream<List<String>>, Function<String, String>>.

l->s->l.filter(p->p.contains(s)).map(p->p.get(1-p.indexOf(s))).findAny().get()

Try It Online

I'll credit the saving of the last 6 bytes to anyone who can convince me that returning an Optional is valid. I haven't been able to convince myself.

One of the interesting parts of this solution for me was determining the cheapest way to get the output from the stream. I considered reduce, findFirst, and min/max, but none was shorter than the intuitive findAny.

\$\endgroup\$
1
\$\begingroup\$

Ruby, 31 bytes

->a,e{e=*e;a.find{|p|p!=p-e}-e}

Returns a singleton array.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 45 bytes

Came up with this last night then noticed Neil had beaten me to a better JS solution; figured I may as well post it anyway.

Works with strings and integers.

a=>n=>a.reduce((x,y)=>y[1-y.indexOf(n)]||x,0)
\$\endgroup\$
1
\$\begingroup\$

Prolog (SWI), 43 bytes

f([[A,B]|T],X,R):-A=X,R=B;B=X,R=A;f(T,X,R).

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C# (.NET Core), 101 100 + 18 bytes

thank you to Grzegorz Puławski helping reducing a couple of bytes.

x=>y=>x.Where(z=>z.Item1==y).FirstOrDefault()?.Item2??x.Where(z=>z.Item2==y).FirstOrDefault()?.Item1

Try it online!

C# (.NET Core), 122 121 120 bytes

x=>y=>{for(int i=0;i<x.Length;i++){if(x[i].Item1==y){return x[i].Item2;}if(x[i].Item2==y){return x[i].Item1;}}return"";}

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ x=>y=> is shorter than (x,y)=> (Func<a, b, c> becomes Func<a, Func<b, c>> and function call f(a, b) becomes f(a)(b)) - Great answer btw! \$\endgroup\$ – Grzegorz Puławski Aug 16 '17 at 10:29
  • \$\begingroup\$ Also for first answer, the function itself doesn't use anything but System.Linq, so you can add only 18 bytes to answer (using System.Linq; versus namespace System.Linq{}) \$\endgroup\$ – Grzegorz Puławski Aug 16 '17 at 10:34
  • \$\begingroup\$ @GrzegorzPuławski thank you for the help and the compliment, hopefully i fixed the answers up to snuff \$\endgroup\$ – Dennis.Verweij Aug 16 '17 at 12:43
1
\$\begingroup\$

Husk, 10 bytes

→ḟo=⁰←S+m↔

Try it online!

Ungolfed/Explanation

            -- example input:                         4 [(1,2),(3,4)]
      S+    -- concatenate list with                -
        m↔  --   itself but all pairs flipped       -   [(1,2),(3,4),(2,1),(4,3)]
 ḟo         -- find first occurence where           -
   =⁰←      --   the left element is equal to input -   (4,3)
→           -- get the right element                -   3

Note: The above example works on integers just for the sake of readability, the type itself doesn't matter (as long as you can compare it).

\$\endgroup\$
0
1
\$\begingroup\$

Swift 4, 43 bytes

{a,m in a.flatMap{$0==m ?$1:$1==m ?$0:nil}}

The output is an array, which is either empty (no partner found), or has a single element (the partner).

Test cases:

let testcases: [(pairs: [(String, String)], match: String, expected: String)] = [
    (
        pairs: [("(", ")"), ("{", "}"), ("[", "]")],
        match: "}", expected: "{"
    ),
    (
        pairs: [("I'm", "So"), ("Meta", "Even"), ("This", "Acronym")],
        match: "Even", expected: "Meta"
    ),
    (
        pairs: [("I", "S"), ("M", "E"), ("T", "A")],
        match: "A", expected: "T"
    ),
    (
        pairs: [("test", "cases"), ("are", "fun")],
        match: "test", expected: "cases"
    ),
    (
        pairs: [("sad", "beep"), ("boop", "boop")],
        match: "boop", expected: "boop"
    ),
]

for (caseNumber, testcase) in testcases.enumerated() {
    let actual = f(testcase.pairs, testcase.match).first

    assert(actual == testcase.expected,
        "Testcase #\(caseNumber) \((testcase.pairs, testcase.match)) failed. Got \(String(reflecting: actual)), but expected \(testcase.expected)!")
    print("Testcase #\(caseNumber) passed!")
}
\$\endgroup\$
1
\$\begingroup\$

QBIC, 30 bytes

{_?~A=G|_X]_?~A=;|Z=B]~B=C|Z=A

QBIC isn't strong on lists and tuples. The above code takes a as a command line parameter, then asks for user input in pairs for the tuples. When an empty element is given, it outputs b.

Sample run

Command line: Even
I'm
So
Meta
Even
This
Acronym

Meta

Explanation

{           DO infinitely
_?          Ask for part 1 of tuple, A$
~A=G|  ]    IF A$ is empty (equal to G$, which is undefined and therefore "") THEN
     _X         Quit
_?          Ask for part 2 of tuple, B$
~A=;|       IF part 1 of the tuple equals teh cmd line param (loaded in as C$) THEN
    Z=B]        set Z$ to part 2 of the tuple (Z$ gets printed when QBIC quits)
~B=C|Z=A    IF part 2 of the tuple matches input, set Z$ to part 1
            The final IF and the DO loop are closed implicitly

Alternative version, 22 bytes

{_?_?~A=;|_XB]~B=C|_XA

This basically does the same as the longer version, but immediately quits when it finds a match. I've listed this as the alternative, because you can't input all tuples into this program given that it quits early.

\$\endgroup\$
0
\$\begingroup\$

Mathematica, 50 bytes

(t={#2};Select[Complement[#,t]&/@#,Length@#==1&])&

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ This doesn't work for the {'boop','boop'} testcase. \$\endgroup\$ – Sanchises Aug 17 '17 at 9:03
  • \$\begingroup\$ @Sanchises"boop" wasn't there when I answered and the question was not about [a,a] tuples.I believe answers before boop-edit are valid \$\endgroup\$ – ZaMoC Aug 17 '17 at 11:29
  • \$\begingroup\$ I don't know the policy on clarifications of the OP invalidating existing answers; it was just a heads-up about the edit. \$\endgroup\$ – Sanchises Aug 17 '17 at 11:43
0
\$\begingroup\$

Stacked, 21 bytes

[:$revmap,KeyArray\#]

Try it online! This takes input from the the stack and leaves output on the stack. Expanded, this looks like:

[ : $rev map , KeyArray \ # ]

Explanation

Let's take (('sad' 'beep') ('boop' 'boop')) and 'boop' as the input. Then, an array like so is constructed by :$revmap,:

(( 'sad' 'beep')
 ('boop' 'boop')
 ('beep'  'sad')
 ('boop' 'boop'))

That is, a copy of the array is map, each member is reversed, and the two are concatenated together. KeyArray in turn makes a hash out of the values given, like so:

KeyArray [ sad => beep, boop => boop, beep => sad, boop => boop ]

Then, \ brings the search string to the top of the stack, and obtains the key from the KeyArray that matches with #. This returns only one value, so the duplicate key in the KeyArray does not need to be worried about.

Other approaches

32 bytes: (input from stack, output to STDOUT) [@x:$revmap,uniq[...x=$out*]map]

36 bytes: {%x[y index#+]YES 0# :y neq keep 0#}

38 bytes: [@x:$revmap#,[KeyArray x#]map:keep 0#]

46 bytes: [@x:KeyArray\$revmap KeyArray,[x#]map:keep 0#]

\$\endgroup\$
0
\$\begingroup\$

Excel, 18 Bytes

Anonymous Excel Workbook Formula that takes input as <Lookup Value> from range A1, <Key Array> from range B:B and <Def Array> from range C:C, and outputs the value of the definition associated with the lookup value to the calling cell

=VLOOKUP(A1,B:C,2)

Sample I/O shall be included when possible

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.