11
\$\begingroup\$

Task:

Return an array with all possible pairs between the elements of an array.

Example

From a=["a", "b", "c", "d"]; return b=[["a","b"],["a","c"],["a","d"],["b","c"],["b","d"],["c","d"]].

Pairs can be in any order as long as all possible combinations are included and obviously ["b","d"] is the same to ["d","b"].

Input

Array of unique string elements composed of chars from the class [a-z].

Output

2d array containing all the possible pairs of input array's elements.

Test Cases

input=["a","b","c"];
//output=[["a","b"],["a","c"],["b","c"]]

input=["a","b","c","d","e"];
//output=[["a","b"],["a","c"],["a","d"],["a","e"],["b","c"],["b","d"],["b","e"],["c","d"],["c","e"],["d","e"]]

Note: I could not find a duplicate to this challenge. If there is one, alert me with a comment to drop question.

\$\endgroup\$
  • 2
    \$\begingroup\$ I'm not clear on what happens when input values repeat or are not in sorted order. Some more general test cases would help there. \$\endgroup\$ – xnor Jun 19 '17 at 20:05
  • \$\begingroup\$ @Adám Not a dupe, that involves having 2 lists. \$\endgroup\$ – Mr. Xcoder Jun 19 '17 at 20:10
  • \$\begingroup\$ This problem excludes pairing an element with itself, soeven more nonduplicate. \$\endgroup\$ – CalculatorFeline Jun 19 '17 at 20:10
  • \$\begingroup\$ @xnor havent thought about repeating values because my original problem at work had to do with a unique set of individuals. I guess I should add uniqueness as a condition? \$\endgroup\$ – alexandros84 Jun 19 '17 at 20:57
  • \$\begingroup\$ @alexandros84 Uniqueness would be fine. What should ["c","b","a"] return? \$\endgroup\$ – xnor Jun 19 '17 at 21:00

27 Answers 27

5
\$\begingroup\$

Jelly, 2 bytes

Œc

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You ninja'd me - pretty print the output using something like ÇK€Y in the footer. \$\endgroup\$ – Jonathan Allan Jun 19 '17 at 20:10
  • \$\begingroup\$ @JonathanAllan Oh, thanks! \$\endgroup\$ – HyperNeutrino Jun 19 '17 at 20:12
8
\$\begingroup\$

Haskell, 29 bytes

f(a:b)=map((,)a)b++f b
f _=[]

Try it online! Example usage: f ["a","b","c"] yields [("a","b"),("a","c"),("b","c")].


With the flag -XTupleSections this can be shortened to 27 bytes, however the flag would need to be counted:

f(a:b)=map(a,)b++f b
f _=[]

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I think you can save one byte by modifying the be case to f l=l. \$\endgroup\$ – Kritzefitz Jun 19 '17 at 21:31
  • \$\begingroup\$ @Kritzefitz I'm afraid this won't work as the two empty lists have a different type, so Haskell's type checker will complain. \$\endgroup\$ – Laikoni Jun 19 '17 at 21:34
  • \$\begingroup\$ Good point. I Didn't think of that. \$\endgroup\$ – Kritzefitz Jun 19 '17 at 21:39
6
\$\begingroup\$

Mathematica, 14 bytes

#~Subsets~{2}&

input

[{"a", "b", "c"}]

\$\endgroup\$
  • \$\begingroup\$ I was going to do that :( \$\endgroup\$ – CalculatorFeline Jun 19 '17 at 20:10
6
\$\begingroup\$

Haskell, 25 bytes

f l=[(x,y)|x<-l,y<-l,x<y]

Try it online!

Outer (x) and inner (y) loop through the input list and keep the pair (x,y) only if x < y.

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

05AB1E, 3 bytes

Code:

æ2ù

Uses the 05AB1E encoding. Try it online!

Explanation:

æ      # Powerset of the input
 2ù    # Keep the items of length two
\$\endgroup\$
5
\$\begingroup\$

vim, 50 48

AX<esc>qqYplX@qq@qqrYpllDkxh@rq:g/./norm@r<cr>:g/X/d<cr>dG

Takes input in the form

abcd

and outputs as

ad
ac
ab
bd
bc
cd

Explanation

First, AX<esc> appends an X to the input in order to handle 2-length input, which is necessary for reasons that will become clear shortly.

Then comes the first recursive macro, of the form qq...@qq@q. (Record macro q, run itself again at the end, end the recording, then run itself once.) In the body of the macro, Yp duplicates the current line, l breaks out of the macro if the line is now one character long, and X deletes the first character in the line. This has the end result of producing

abcdX
abcX
abX
aX
X
X

Ignoring the Xs for now, all we have to do is turn abcdX, for example, into ab / ac / ad / aX. This is achieved with the second recursive macro, qr...@rq.

In this macro, we first duplicate the line (Yp), then delete everything but the first two characters by moving right two (ll) and deleting to the end of the line (D). Since the cursor is now on the second charcater of the line, kx will delete the second character from the previous line, which happens to be the one that was just paired with the first character on the line. This process is then repeated starting again from the beginning of the line (h) as many times as necessary due to the recursive nature of the macro.

It's now just a matter of running the macro on every line, which can be achieved with :g/./norm@r (I'm not sure why this behaves differently than :%norm@r, but suffice to say, the latter does not work as intended.) Lines with X are deleted with :g/X/d, and the blank lines at the end left as a result of the construction of the r macro are cleaned up with dG.

\$\endgroup\$
  • \$\begingroup\$ Great answer. Will take time for me to go through it. \$\endgroup\$ – alexandros84 Jun 19 '17 at 22:53
4
\$\begingroup\$

Octave, 23 bytes

@(s)[nchoosek(+s,2) '']

Try it online!

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

Python 3, 44 bytes

f=lambda k,*s:[*s]and[[k,x]for x in s]+f(*s)

Try it online!

Takes input as individual function parameters.

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

Brachylog, 5 bytes

{⊇Ċ}ᶠ

Try it online!

How it works

{⊇Ċ}ᶠ
    ᶠ   find all the possible outputs of the following predicate
 ⊇          the output is an ordered subset of the input
  Ċ         the output is a list with two elements
\$\endgroup\$
3
\$\begingroup\$

R, 18 bytes

combn(scan(,''),2)

reads the list from stdin, returns a matrix where the columns are pairs.

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Python, 53 bytes

2 bytes saved thanks to @CalculatorFeline

lambda a:[(x,y)for i,x in enumerate(a)for y in a[:i]]

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ a[i+1:] can be a[:i] \$\endgroup\$ – CalculatorFeline Jun 19 '17 at 20:21
  • \$\begingroup\$ Having a long username makes short comments easy by simply mentioning the aforementioned user. \$\endgroup\$ – CalculatorFeline Jun 19 '17 at 20:59
3
\$\begingroup\$

Octave, 49 48 bytes

@(x)[imag(y=(y=triu(x+j*x',1))(~~y)) real(y) '']

Anonymous function that avoids the built-in (nchoosek).

Try it online!

Explanation

x+j*x' uses broadcasting to build a matrix of complex numbers where the real and imaginary parts are all pairs of code points from the input x.

y=triu(...,1) keeps the upper triangular part excluding the diagonal, making the rest of elements zero. The result is assigned to variable y.

y=(...)(~~y) retains the nonzero elements in the form of a column vector, which is assigned to variable y.

imag(...) and real(...) extract the real and imaginary parts.

[... ... ''] converts back to char to build the output.

\$\endgroup\$
  • \$\begingroup\$ Nice! The whole challenge is really interesting. It took me about one hour and a half to come up with my es5 code (featured below). I am happy it generated so many interesting answers.. \$\endgroup\$ – alexandros84 Jun 19 '17 at 20:50
3
\$\begingroup\$

Pari/GP, 34 bytes

a->concat([[[x,y]|y<-a,x<y]|x<-a])

Try it online!

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

Python ≥ 2.7, 55 bytes

lambda l:list(combinations(l,2))
from itertools import*

repl.it!

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

Perl 6, 17 bytes

*.combinations(2)

Whew, that's a long method name.

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

Scala, 17 bytes

_.combinations(2)
\$\endgroup\$
2
\$\begingroup\$

Pyth, 7 4 bytes

-3 bytes thanks to Leaky Nun!

.cQ2

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ .cQ2? \$\endgroup\$ – Leaky Nun Jun 20 '17 at 4:16
  • \$\begingroup\$ @LeakyNun I could have sworn there was a function that did exactly what this challenge needed, but I only saw .C when looking through the list. Nice catch! \$\endgroup\$ – notjagan Jun 20 '17 at 15:35
2
\$\begingroup\$

Ruby, 38 34 24 bytes

->x{[*x.combination(2)]}

Thanks Seims for the idea that saved 10 bytes.

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ ->x{x.combination(2).to_a} saves some bytes :) \$\endgroup\$ – Seims Jun 22 '17 at 12:19
1
\$\begingroup\$

JavaScript ES6, 52 bytes

a=>a.map((x,i)=>a.slice(0,i).map(y=>[x,y])).slice(1)

If there was like a flatMap that would save a lot of bytes.

\$\endgroup\$
  • \$\begingroup\$ Hey nice answer! check out my es5 answer while I study yours if u want. any feedback will be appreciated (positive/constructive haha) \$\endgroup\$ – alexandros84 Jun 19 '17 at 20:45
  • 1
    \$\begingroup\$ Firefox 30's array comprehensions can simulate a flat map, e.g. a=>[for(x of[...a])for(y of(a.shift(),a))[x,y]]. \$\endgroup\$ – Neil Jun 19 '17 at 20:51
  • \$\begingroup\$ @Neil, some really advanced syntax there... I d have to google at least three things to start understanding your expression. Namely the spread operator, what is array comprehensions and what is the [x,y] in the end (still havent found answer to that). \$\endgroup\$ – alexandros84 Jun 19 '17 at 21:17
  • 1
    \$\begingroup\$ @alexandros84 The [x,y] at the end is the easy bit, it's just an array literal. \$\endgroup\$ – Neil Jun 19 '17 at 21:19
  • 1
    \$\begingroup\$ Also the spread operator is only there to copy the array, since I'm mutating it inside the loop. \$\endgroup\$ – Neil Jun 19 '17 at 21:20
1
\$\begingroup\$

Python, 55 bytes

f=lambda s:[(s[0],j)for j in s[1:]]+f(s[1:])if s else[]

Try it online!

Longer than other Python answers, but it uses a different technique so I think it's worth posting.

\$\endgroup\$
  • \$\begingroup\$ Dont have time to check, I hope is really different technique cause I ve upvoted. \$\endgroup\$ – alexandros84 Jun 20 '17 at 2:54
  • \$\begingroup\$ I think this is a very similar approach to @ovs's Python 3 answer. \$\endgroup\$ – Neil Jun 20 '17 at 7:39
1
\$\begingroup\$

Japt, 2 bytes

à2

Test it (-Q flag for visualisation purposes only)

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

Python, 64 bytes

f=lambda a:sum((list(zip(a, a[i:]))for i in range(1,len(a))),[])
\$\endgroup\$
1
\$\begingroup\$

Octave, 38 bytes

@(s)s([[x y]=find(s|s'),y](y<x,[2 1]))

Another answer to avoid nchoosek built-in.

Try it online!

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

Clojure, 42 bytes

#(set(for[i % j(remove #{i}%)](set[i j])))

Returns a set of sets :)

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

Python, 74 bytes

f=lambda a:[(c,d) for i,c in enumerate(a) for j,d in enumerate(a) if i<j]
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG! You can golf this: 1) replace 2-char variable names with 1-char 2) remove unnecessary whitespace 3) this is a snippet, you need to make it into a lambda, function or full program \$\endgroup\$ – Erik the Outgolfer Jun 20 '17 at 15:42
  • \$\begingroup\$ Golfing off 10 bytes: 64 bytes \$\endgroup\$ – Mr. Xcoder Jun 22 '17 at 11:48
1
\$\begingroup\$

Javascript (ES 5), from 108 to 78 bytes

I post my answer today but I obviously promise to not accept my own answer:

x=input;
a=[];

for(n=0;n<(x.length-1);n++){for(i=n+1;i<(x.length);i++){a.push([x[n],x[i]]);}}
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG; we expect submissions to be golfed, including removing unnecessary whitespace \$\endgroup\$ – HyperNeutrino Jun 20 '17 at 3:04
  • \$\begingroup\$ Ty. I was wondering also this: should I have included the x=input; a=[]; in my answer or not? I ll edit tomorrow. \$\endgroup\$ – alexandros84 Jun 20 '17 at 3:13
  • \$\begingroup\$ You can either just submit a function or do a full program. Since you use a, you need to define it, but you can make a function of x. \$\endgroup\$ – HyperNeutrino Jun 20 '17 at 3:14
  • \$\begingroup\$ much better now @HyperNeutrino. \$\endgroup\$ – alexandros84 Jun 25 '17 at 4:36
  • 1
    \$\begingroup\$ I think you can exclude some semicolons and the empty line to save some space. I also think you can change for(i=n+1;i<(x.length);i++) to for(i=n;++i<x.length;). Likewise, you can change n<(x.length-1);n++ to n++<x.length-1 \$\endgroup\$ – musicman523 Jun 25 '17 at 21:52
0
\$\begingroup\$

J, 17 bytes

({~$#:I.@,)#\</#\

Try it online!

Explanation

({~$#:I.@,)#\</#\  Input: string S
               #\  Get the length of each prefix of S
           #\      Get the length of each prefix of S again
             </    Test using greater than (<) between each
         ,         Flatten
      I.@          Find the indices where the value is 1
   $               Shape of that table
    #:             Convert the indices to the base represented by the shape
 {~                Index into S at those values
\$\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.