Finding your partner

20

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!

Nate Stemen

Posted 2017-08-15T18:53:45.613

Reputation: 325

Also, what to do if the input appears several times, or doesn't appear – Luis Mendo – 2017-08-15T19:16:42.330

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 – totallyhuman – 2017-08-15T21:54:20.310

I have edited to hopefully clear some stuff up and have added test cases. Feel free to roll back if anything is wrong. – totallyhuman – 2017-08-15T23:46:43.993

@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.

– Jonathan Allan – 2017-08-16T20:46:58.600

It seems I misunderstood this comment. What does "oh well" mean?

– totallyhuman – 2017-08-16T20:50:35.777

1@totallyhuman I took it to mean "return anything, crash, whatever" especially since the post was then revised to say everything would be unique. – Jonathan Allan – 2017-08-16T20:56:14.457

Answers

8

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.

Shaggy

Posted 2017-08-15T18:53:45.613

Reputation: 24 623

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 – ETHproductions – 2017-08-15T19:05:11.143

@ETHproductions: Makes a nice change - usually I'm the one who forgets about æ and tries to muddle through with f! :D – Shaggy – 2017-08-16T08:35:13.963

8

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

Lynn

Posted 2017-08-15T18:53:45.613

Reputation: 55 648

5

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

Sanchises

Posted 2017-08-15T18:53:45.613

Reputation: 8 530

5

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)

Neil

Posted 2017-08-15T18:53:45.613

Reputation: 95 035

Here's a 41-byte non-recursive solution: a=>b=>a.map(e=>b=e[1-e.indexOf(b)]||b)&&b – Rick Hitchcock – 2017-08-15T21:56:24.427

You ... You finally gave in to currying?! :o – Shaggy – 2017-08-17T08:40:10.080

@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). – Neil – 2017-08-17T10:55:38.140

4

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)

HyperNeutrino

Posted 2017-08-15T18:53:45.613

Reputation: 26 575

Rename reversed to reverse in Proton for -1 byte. \s :P More seriously, reverse is a much better name, no? :P – totallyhuman – 2017-08-15T19:32:10.387

@totallyafloppydisk maybe /shrug but I didn't rename most of the Python builtins that get carried over to Proton – HyperNeutrino – 2017-08-15T19:33:09.973

@Sanchises I don't see what's wrong?

– HyperNeutrino – 2017-08-17T15:06:07.567

Sorry my bad, disregard that comment. – Sanchises – 2017-08-17T21:22:12.847

2

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)

Jonathan Allan

Posted 2017-08-15T18:53:45.613

Reputation: 67 804

This is invalid since the new testcases have been added. – Sanchises – 2017-08-16T20:25:26.750

1Thanks 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. – Jonathan Allan – 2017-08-16T20:49:40.300

Hmm, although looking at the revision history it seems we need to support strings not just characters so this wont work anyway... – Jonathan Allan – 2017-08-16T20:52:58.443

Works with the new spec now. – Jonathan Allan – 2017-08-16T21:31:58.620

That was my interpretation too of the "oh well" comment, but evidently this was not the case. – Sanchises – 2017-08-17T06:08:53.050

2

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. ;-;

totallyhuman

Posted 2017-08-15T18:53:45.613

Reputation: 15 378

145 bytes – Emigna – 2017-08-15T21:12:33.817

Aha, knew there was a shorter way of doing y+[1,-1][y%2]. Just didn't think it was bitwise... Thanks! – totallyhuman – 2017-08-15T21:29:15.540

2

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

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

Try it online!

Xcali

Posted 2017-08-15T18:53:45.613

Reputation: 7 671

2

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

Kelly Lowder

Posted 2017-08-15T18:53:45.613

Reputation: 3 225

1

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}}]

– Not a tree – 2017-08-15T23:58:38.503

Can you explain this one a bit? – Nate Stemen – 2017-08-16T07:15:49.923

2

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.

MickyT

Posted 2017-08-15T18:53:45.613

Reputation: 11 735

@Sanchises Thanks, all fixed up now. – MickyT – 2017-08-16T20:36:27.003

2

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

HatsuPointerKun

Posted 2017-08-15T18:53:45.613

Reputation: 1 891

2

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

colsw

Posted 2017-08-15T18:53:45.613

Reputation: 3 195

This approach doesn't work for the ("boop", "boop") test case. – AdmBorkBork – 2017-08-17T12:57:10.773

2

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  */

fergusq

Posted 2017-08-15T18:53:45.613

Reputation: 4 867

1

Pyth - 11 9 8 bytes

h-hf}QTE

Try it online here.

Maltysen

Posted 2017-08-15T18:53:45.613

Reputation: 25 023

1

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 #.

Post Rock Garf Hunter

Posted 2017-08-15T18:53:45.613

Reputation: 55 382

2Don’t overthink it… x!((a,b):c)|x==a=b|x==b=a|1<2=x!c is 33 bytes. – Lynn – 2017-08-15T19:50:05.393

1@Lynn Go ahead and post it. I feel a bit foolish for not thinking of that, but its really your answer. – Post Rock Garf Hunter – 2017-08-15T19:51:04.950

Fair, posted ^^ – Lynn – 2017-08-15T19:52:27.320

1

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

ბიმო

Posted 2017-08-15T18:53:45.613

Reputation: 15 345

1

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!

Emigna

Posted 2017-08-15T18:53:45.613

Reputation: 50 798

˜D²k>è for 6, unless there's a specific reason for XOR'ing with 1? – Magic Octopus Urn – 2017-08-16T01:52:36.790

@MagicOctopusUrn: The reason is that even indices should decrement and odd indices increment. – Emigna – 2017-08-16T06:05:04.683

Except the reverse of what I wrote there... – Emigna – 2017-08-16T08:25:54.200

1

Common Lisp, 74 bytes

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

Try it online!

Renzo

Posted 2017-08-15T18:53:45.613

Reputation: 2 260

1

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.

Jakob

Posted 2017-08-15T18:53:45.613

Reputation: 2 428

1

Ruby, 31 bytes

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

Returns a singleton array.

m-chrzan

Posted 2017-08-15T18:53:45.613

Reputation: 1 390

1

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!

Dennis.Verweij

Posted 2017-08-15T18:53:45.613

Reputation: 101

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! – Grzegorz Puławski – 2017-08-16T10:29:15.777

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{}) – Grzegorz Puławski – 2017-08-16T10:34:05.480

@GrzegorzPuławski thank you for the help and the compliment, hopefully i fixed the answers up to snuff – Dennis.Verweij – 2017-08-16T12:43:32.367

1

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)

Shaggy

Posted 2017-08-15T18:53:45.613

Reputation: 24 623

1

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!

Emigna

Posted 2017-08-15T18:53:45.613

Reputation: 50 798

1

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.

steenbergh

Posted 2017-08-15T18:53:45.613

Reputation: 7 772

1

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!")
}

Alexander - Reinstate Monica

Posted 2017-08-15T18:53:45.613

Reputation: 481

0

Mathematica, 50 bytes

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

Try it online!

J42161217

Posted 2017-08-15T18:53:45.613

Reputation: 15 931

This doesn't work for the {'boop','boop'} testcase. – Sanchises – 2017-08-17T09:03:32.730

@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 – J42161217 – 2017-08-17T11:29:24.350

I don't know the policy on clarifications of the OP invalidating existing answers; it was just a heads-up about the edit. – Sanchises – 2017-08-17T11:43:22.437

0

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#]

Conor O'Brien

Posted 2017-08-15T18:53:45.613

Reputation: 36 228

0

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

Taylor Scott

Posted 2017-08-15T18:53:45.613

Reputation: 6 709