14
\$\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\$
7
  • 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, 2017 at 20:05
  • \$\begingroup\$ @Adám Not a dupe, that involves having 2 lists. \$\endgroup\$
    – Mr. Xcoder
    Jun 19, 2017 at 20:10
  • \$\begingroup\$ This problem excludes pairing an element with itself, soeven more nonduplicate. \$\endgroup\$ Jun 19, 2017 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\$ Jun 19, 2017 at 20:57
  • \$\begingroup\$ @alexandros84 Uniqueness would be fine. What should ["c","b","a"] return? \$\endgroup\$
    – xnor
    Jun 19, 2017 at 21:00

35 Answers 35

9
\$\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\$
3
  • \$\begingroup\$ I think you can save one byte by modifying the be case to f l=l. \$\endgroup\$
    – Kritzefitz
    Jun 19, 2017 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, 2017 at 21:34
  • \$\begingroup\$ Good point. I Didn't think of that. \$\endgroup\$
    – Kritzefitz
    Jun 19, 2017 at 21:39
6
\$\begingroup\$

Mathematica, 14 bytes

#~Subsets~{2}&

input

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

\$\endgroup\$
1
  • \$\begingroup\$ I was going to do that :( \$\endgroup\$ Jun 19, 2017 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\$
6
\$\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\$
1
  • \$\begingroup\$ Great answer. Will take time for me to go through it. \$\endgroup\$ Jun 19, 2017 at 22:53
6
\$\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\$
5
\$\begingroup\$

Jelly, 2 bytes

Œc

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You ninja'd me - pretty print the output using something like ÇK€Y in the footer. \$\endgroup\$ Jun 19, 2017 at 20:10
  • \$\begingroup\$ @JonathanAllan Oh, thanks! \$\endgroup\$
    – hyper-neutrino
    Jun 19, 2017 at 20:12
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\$
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\$

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\$
1
  • \$\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\$ Jun 19, 2017 at 20:50
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\$
2
  • 1
    \$\begingroup\$ a[i+1:] can be a[:i] \$\endgroup\$ Jun 19, 2017 at 20:21
  • \$\begingroup\$ Having a long username makes short comments easy by simply mentioning the aforementioned user. \$\endgroup\$ Jun 19, 2017 at 20:59
3
\$\begingroup\$

Perl 6, 17 bytes

*.combinations(2)

Whew, that's a long method name.

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

Pari/GP, 34 bytes

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

Try it online!

\$\endgroup\$
3
\$\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\$
3
\$\begingroup\$

Arturo, 18 bytes

$=>[combine.by:2&]

Try it

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

Python ≥ 2.7, 55 bytes

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

repl.it!

\$\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\$
2
  • 1
    \$\begingroup\$ .cQ2? \$\endgroup\$
    – Leaky Nun
    Jun 20, 2017 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, 2017 at 15:35
2
\$\begingroup\$

Japt, 2 bytes

à2

Test it (-Q flag for visualisation purposes only)

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

Python, 64 bytes

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

Clojure, 42 bytes

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

Returns a set of sets :)

\$\endgroup\$
2
\$\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\$
2
  • 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\$ Jun 20, 2017 at 15:42
  • \$\begingroup\$ Golfing off 10 bytes: 64 bytes \$\endgroup\$
    – Mr. Xcoder
    Jun 22, 2017 at 11:48
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
  • 1
    \$\begingroup\$ ->x{x.combination(2).to_a} saves some bytes :) \$\endgroup\$
    – Seims
    Jun 22, 2017 at 12:19
2
\$\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\$
5
  • 1
    \$\begingroup\$ Welcome to PPCG; we expect submissions to be golfed, including removing unnecessary whitespace \$\endgroup\$
    – hyper-neutrino
    Jun 20, 2017 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\$ Jun 20, 2017 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\$
    – hyper-neutrino
    Jun 20, 2017 at 3:14
  • \$\begingroup\$ much better now @HyperNeutrino. \$\endgroup\$ Jun 25, 2017 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\$ Jun 25, 2017 at 21:52
2
\$\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\$
2
\$\begingroup\$

Pip, -p 4 bytes

aCB2

CB is the operator for combinations, not much explanation needed

Try It Online!

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

Go, 132 bytes

func f[T any](S[]T)(O[][]T){if len(S)<3{O=append(O,S)}else{for a,i:=range(S){for _,j:=range(S[a+1:]){O=append(O,[]T{i,j})}}}
return}

Attempt This Online!

A generic function that takes in a slice of type T and outputs a slice of slices of type T.

A solution that does only []string -> [][]string is 8 bytes longer.

Explanation

func f[T any](S[]T)(O[][]T){  // boilerplate
if len(S)<3{                  // if the input length < 3,
  O=append(O,S)               // just return the input
}else{                        // otherwise,
  for a,i:=range(S){          // for each 1st element,
    for _,j:=range(S[a+1:]){  // and each 2nd element,
      O=append(O,[]T{i,j})}}} // add the pair
return}                       // return the result
\$\endgroup\$
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\$
8
  • \$\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\$ Jun 19, 2017 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, 2017 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\$ Jun 19, 2017 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, 2017 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, 2017 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\$
2
  • \$\begingroup\$ Dont have time to check, I hope is really different technique cause I ve upvoted. \$\endgroup\$ Jun 20, 2017 at 2:54
  • \$\begingroup\$ I think this is a very similar approach to @ovs's Python 3 answer. \$\endgroup\$
    – Neil
    Jun 20, 2017 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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