Cartesian product of two lists

14

2

Task

Given two lists of characters, output their Cartesian product, i.e. the list of pairings of each letter from the first list with each letter from the second list.

Example

"123456" and "abcd" give:

[["1","a"],["1","b"],["1","c"],["1","d"],["2","a"],["2","b"],["2","c"],["2","d"],["3","a"],["3","b"],["3","c"],["3","d"],["4","a"],["4","b"],["4","c"],["4","d"],["5","a"],["5","b"],["5","c"],["5","d"],["6","a"],["6","b"],["6","c"],["6","d"]]

Input

Two lists of characters or strings. The characters used will be alphanumeric a-z, A-Z, 0-9 and a character can occur both multiple times and in both inputs at the same time.

Output

The Cartesian product of the input lists. That is, a list of each possible ordered pair of a character from the first list and a character from the second list. Each pair is a list or string or similar of two characters, or of two length-one strings. The output's length will be equal to the product of the lengths of the inputs.

The pairs must be listed in order; first listing the first character of the first list with the first of the second list, followed by all the pairings of the first character of the first list. The last pair consists of the last character of the first list together with the last character of the second list.

The output must be a flat list of pairs; not a 2D matrix where pairs are grouped by their first or second element.

Test cases

inputs               output

"123456", "abcd"     [["1","a"],["1","b"],["1","c"],["1","d"],["2","a"],["2","b"],["2","c"],["2","d"],["3","a"],["3","b"],["3","c"],["3","d"],["4","a"],["4","b"],["4","c"],["4","d"],["5","a"],["5","b"],["5","c"],["5","d"],["6","a"],["6","b"],["6","c"],["6","d"]]
"abc", "123"         [["a","1"],["a","2"],["a","3"],["b","1"],["b","2"],["b","3"],["c","1"],["c","2"],["c","3"]]
"aa", "aba"          [["a","a"],["a","b"],["a","a"],["a","a"],["a","b"],["a","a"]]

alexandros84

Posted 2017-06-07T22:58:49.577

Reputation: 365

@Adám Changed. I'm having trouble though wording that repeated characters in an input string can and should cause repeated pairs in the output (assuming that's how interpret it). – xnor – 2017-06-08T00:25:56.327

@xnor maybe easier if the order of pairs is fixed? – Adám – 2017-06-08T00:28:18.923

Why does the title say "list" yet the body say "list of characters"? – Leaky Nun – 2017-06-08T07:56:06.720

Just to be sure: is ["1a", "1b", "1c", "2a", "2b", "2c", "3a", "3b", "3c"] a valid output format? – Shaggy – 2017-06-08T16:22:37.167

wow. lots of amazing answers. what are the criteria for chosing an accepted answer? And should I give my own answer on es5 (the code that inspired the question in the first place?) – alexandros84 – 2017-06-09T03:22:42.347

1

You tagged this as code-golf therefore shortest answer wins. In the event of a tie, the first answer to reach that score is usually the winner (currently this one). Give it another few days, at least, before accepting an answer, though, if at all. And see here for guidelines on answering your own question.

– Shaggy – 2017-06-09T10:52:56.703

@Adám ty for editing. – alexandros84 – 2017-06-11T03:17:16.790

@Adám I assume taking the input as boxed in J allowed? – Jonah – 2017-09-22T05:43:28.957

@Jonah I'd think so. That's natural for J. – Adám – 2017-09-23T20:19:58.483

@Adám, Sorry I thought you were the OP and not just the editor. But thanks. – Jonah – 2017-09-23T20:40:49.977

Answers

7

Neil A.

Posted 2017-06-07T22:58:49.577

Reputation: 2 038

17

Haskell, 12 bytes

(<*>).map(,)

Try it online!

Anders Kaseorg

Posted 2017-06-07T22:58:49.577

Reputation: 29 242

7

Mathematica, 12 bytes

Tuples@{##}&

Takes two lists of characters as input.

alephalpha

Posted 2017-06-07T22:58:49.577

Reputation: 23 988

1Same length: Tuples@*List Alternatively, if arbitrary heads are allowed: Tuples@*f – CalculatorFeline – 2017-06-09T16:40:31.950

5

APL (Dyalog), 4 bytes

,∘.,

Try it online!

, flatten

∘. the Cartesian

, concatenation

Adám

Posted 2017-06-07T22:58:49.577

Reputation: 37 779

I don't think flatten is a good description here, since flattening would produce the incorrect result, I think "tighten" or "reduce rank" or something similar should work. (Flattened [1,2]x[1,2] is [1,1,1,2,2,1,2,2]) – Zacharý – 2017-09-24T14:03:01.697

4

Ruby, 30 18 bytes

-12 bytes from Jordan reminding me of a way to use the spec to my advantage!

Takes lists of characters as input.

->a,b{a.product b}

Try it online!

Value Ink

Posted 2017-06-07T22:58:49.577

Reputation: 10 608

1The specification says the input is "Two lists of characters or strings," so I don't think you need .chars. – Jordan – 2017-06-08T04:09:12.250

1It is a shame browsers dont speak ruby. Such a friendly language.. – alexandros84 – 2017-06-11T02:33:21.363

4

Perl 6, 4 bytes

&[X]

This is just a reference to the built-in cross product operator X. It works on lists of any sort, not just characters.

Sean

Posted 2017-06-07T22:58:49.577

Reputation: 4 136

3

Dennis

Posted 2017-06-07T22:58:49.577

Reputation: 196 637

3

JavaScript (ES6), 45 36 34 33 bytes

Requires Firefox. Takes both inputs as strings or as arrays of individual characters.

a=>b=>[for(x of a)for(y of b)x+y]

Try It

f=
a=>b=>[for(x of a)for(y of b)x+y]
oninput=_=>console.clear()&console.log(f(i.value)(j.value))
console.log(f(i.value="123456")(j.value="abcd"))
<input id=i><input id=j>

Shaggy

Posted 2017-06-07T22:58:49.577

Reputation: 24 623

Destructuring works on strings too. – Neil – 2017-06-08T15:33:11.910

Thanks, @Neil; forgot to update that after I changed the method I was using. – Shaggy – 2017-06-08T15:35:56.410

Is x+y a valid output format? – Neil – 2017-06-08T16:12:07.587

@Neil: That's what I was originally going to go with but, from the test cases, it appears that wouldn't be valid; rereading the output requirements, though, they seem to indicate that it might be. I'll ask for clarification to be sure. – Shaggy – 2017-06-08T16:21:12.483

for ( Why is there a space? – CalculatorFeline – 2017-06-09T16:40:56.137

D'oh! Don't know how that slipped past me @CalculatorFeline! – Shaggy – 2017-06-09T16:43:52.097

It seems you have really taken the hang of es6! I invite you to check out my es5 "answer" on my own challenge (the code that inspired my question). Pls feel free to provide improvement suggestions on it. – alexandros84 – 2017-06-11T03:04:51.207

1@alexandros84: Yeah, ES6(+) is essential if you're to stand even a remote chance of being competitive in golf - by the time you've typed function, you've already lost! I'll throw a few pointers on your answer later but, in the meantime, have a look at my original array mapping solution in the edit history; you should be able to just rip that off and replace the arrow functions with "real" functions. – Shaggy – 2017-06-11T09:15:47.017

3

Octave, 32 bytes

@(a,b)[(a+~b')(:) (b'+~a)(:) '']

Try it online!

rahnema1

Posted 2017-06-07T22:58:49.577

Reputation: 5 435

3

Tcl, 60 bytes

proc p x\ y {lmap X $x {lmap Y $y {lappend l $X\ $Y}};set l}

Use:

% p {1 2 3} {a 2 2}
{1 a} {1 2} {1 2} {2 a} {2 2} {2 2} {3 a} {3 2} {3 2}

avl42

Posted 2017-06-07T22:58:49.577

Reputation: 111

3

Bash, 18

This can be done with brace expansions:

eval echo {$1}{$2}

Try it online.

Digital Trauma

Posted 2017-06-07T22:58:49.577

Reputation: 64 644

2

Brachylog, 5 bytes

{∋ᵐ}ᶠ

Try it online!

Explanation

Pretty self-explanatory

{  }ᶠ       Find all:
  ᵐ           Map:
 ∋              In

Fatalize

Posted 2017-06-07T22:58:49.577

Reputation: 32 976

2

QBIC, 29 bytes

[_l;||[_l;||?_sA,a,1|+_sB,b,1

This prints 2-char strings with all combinations on one line each.

Explanation

   ;      Read in string A$
 _l |     Get its length as b
[    |    and kick off a FOR-loop from 1 to that
[_l;||    Do the same for B$
          Note that, while the FOR-loop may pass this code several times, the
          'read-from cmd line' is done only once.
?_sA,a,1| PRINT the character from A$ at the position of the 'a' loop counter
+_sB,a,1   concatenated with the char from B$ at the pos of the 'b' loop counter

steenbergh

Posted 2017-06-07T22:58:49.577

Reputation: 7 772

2

Pyth, 3 bytes

*ww

Multiplying two strings just acts as the cartesian product.

Test it online!

Jim

Posted 2017-06-07T22:58:49.577

Reputation: 1 442

The 2 Bytes solution *E would require to swap the order of the input strings :( https://pyth.herokuapp.com/?code=%2aE&input=%22cd%22%0A%22ab%22&debug=0

– KarlKastor – 2017-06-08T15:44:29.893

2

MATL, 2 bytes

Z*

* is the general operator for products and the prefix Z makes it the cartesian product and can take two strings as arguments.

Try it online!

flawr

Posted 2017-06-07T22:58:49.577

Reputation: 40 560

2

Actually, 1 byte

Try it online!

is the Cartesian product command.

Mego

Posted 2017-06-07T22:58:49.577

Reputation: 32 998

2

Ohm, 1 byte

Try it online!

Literally only the built-in

Datboi

Posted 2017-06-07T22:58:49.577

Reputation: 1 213

2

J, 3 bytes

,@{

This is the Catalogue verb in J. We need to Ravel (,) the result to make it 1 dimensional.

Try it online!

Jonah

Posted 2017-06-07T22:58:49.577

Reputation: 8 729

2

Common Lisp, 63 bytes

(lambda(a b)(mapcan(lambda(x)(mapcar(lambda(y)(list x y))b))a))

Try it online!

Renzo

Posted 2017-06-07T22:58:49.577

Reputation: 2 260

1

Python 2, 39 bytes

lambda x,y:[[i,j]for i in x for j in y]

Try it online!

Alternate solution, 34 30 bytes

-4 bytes thanks to Anders Kaseorg.

There is a built-in for this...

from itertools import*
product

totallyhuman

Posted 2017-06-07T22:58:49.577

Reputation: 15 378

30 bytes: from itertools import*;product – Anders Kaseorg – 2017-06-08T02:30:31.393

1

Clojure, 21 bytes

#(for[i % j %2][i j])

NikoNyrh

Posted 2017-06-07T22:58:49.577

Reputation: 2 361

1

C# 7, 78 63 bytes

(a,b)=>$"({string.Join(",",a.SelectMany(x=>b,(x,y)=>(x,y)))})";

Dennis_E

Posted 2017-06-07T22:58:49.577

Reputation: 119

this isn't a full program nor a function – ASCII-only – 2018-06-01T12:12:25.540

You are supposed to write a full program or a function and not snippet. – Muhammad Salman – 2018-06-04T19:08:17.243

I just changed it. But many answers on this page aren't full programs or functions. Not sure why this one is singled out. – Dennis_E – 2018-06-04T19:17:55.887

btw, this is why I don't like code golf. – Dennis_E – 2018-06-04T19:23:41.083

Since this is a function, you can directly return the output string instead of writing it to the screen, I think that saves you ~20 bytes. – sundar - Reinstate Monica – 2018-07-12T05:46:36.430

@sundar I suppose so. Thnx. – Dennis_E – 2018-07-12T08:34:59.193

Note that some languages used here have pretty compact notation for functions. I see only one answer on this page that clearly isn't a full program or function. It seems to be getting complained about now. I've flagged it too. And yes, PPCG's rules can take a while to get used to. I'm probably still missing some.

– Ørjan Johansen – 2018-07-12T09:53:52.653

1

PHP, 69 bytes

<?foreach($_GET[0]as$x)foreach($_GET[1]as$y)$r[]=[$x,$y];print_r($r);

Try it online!

Jörg Hülsermann

Posted 2017-06-07T22:58:49.577

Reputation: 13 026

1

Cheddar, 52 bytes

a->b->a.chars.map(i->b.chars.map(i&(+))).reduce((+))

Try it online!

Leaky Nun

Posted 2017-06-07T22:58:49.577

Reputation: 45 011

1

05AB1E, 10 bytes

v²NFÀ}¹ø)˜

Try it online!

This is without the built-in, and undoubtedly won't be competitive.

Magic Octopus Urn

Posted 2017-06-07T22:58:49.577

Reputation: 19 422

The output For input "aba" "aa" it seems wrong – RosLuP – 2017-11-11T06:51:39.547

1

Retina, 49 bytes

.(?=.*¶(.+))
$1$&¶
¶¶.+
¶
.(?=.*(.)¶)
$1$&¶
¶.¶
¶

Try it online! Takes input on separate lines. Explanation:

.(?=.*¶(.+))
$1$&¶

Each character in the first string generates a separate line prefixed by the second string.

¶¶.+
¶

The original second string is deleted.

.(?=.*(.)¶)
$1$&¶

For each character in the first string, each character in the second string generates a separate line prefixed with the first character.

¶.¶
¶

The left-over characters from the first string are deleted.

Neil

Posted 2017-06-07T22:58:49.577

Reputation: 95 035

1

Charcoal, 8 7 bytes

FθEη⁺ικ

Try it online! Link is to verbose version of code. Explanation: The variables θ and η implicitly refer to the two input strings. The command loops over each character of the first input, while the command maps over each character of the second input concatenating the loop variable ι and the map variable κ, the result of which is implicitly printed on separate lines.

Neil

Posted 2017-06-07T22:58:49.577

Reputation: 95 035

This seems to be 19 bytes. – CalculatorFeline – 2017-06-09T16:44:13.650

@CalculatorFeline Charcoal has its own code page.

– Neil – 2017-06-09T17:03:49.947

1

q/kdb+, 5 bytes

Solution:

cross           / yup, there's a built-in to do exactly this

Example:

q)"123456"cross"abcd"
"1a"
"1b"
"1c"
"1d"
"2a"
"2b"
"2c"
"2d"
"3a"
"3b"
"3c"
"3d"
"4a"
"4b"
...etc

streetster

Posted 2017-06-07T22:58:49.577

Reputation: 3 635

1

Japt, 5 2 bytes

Japt now has a method for the Cartesian product.

Takes input as 2 arrays of character strings.

ïV

Try it

Shaggy

Posted 2017-06-07T22:58:49.577

Reputation: 24 623

1

R, 29 bytes

function(x,y)outer(x,y,paste)

Try it online!

Note that R matrix are filled by column, so the result is in the order dictated by the spec.

If allowed to have factors for input and output, there is a built-in... but one needs to extract the resulting levels from the factor so in the end it would be more than 29 bytes.

R, 11 bytes

interaction

Try it online!

JayCe

Posted 2017-06-07T22:58:49.577

Reputation: 2 655

0

Jq 1.5, 29 bytes

map(split(""))|[combinations]

Uses combinations builtin.

Sample Run

$ jq -Mc  'map(split(""))|[combinations]' <<< '["123456","abcd"]'
[["1","a"],["1","b"],["1","c"],["1","d"],["2","a"],["2","b"],["2","c"],["2","d"],["3","a"],["3","b"],["3","c"],["3","d"],["4","a"],["4","b"],["4","c"],["4","d"],["5","a"],["5","b"],["5","c"],["5","d"],["6","a"],["6","b"],["6","c"],["6","d"]]

$ echo -n 'map(split(""))|[combinations]' | wc -c
  29

jq170727

Posted 2017-06-07T22:58:49.577

Reputation: 411

0

Axiom, 55 bytes

f(a,b)==concat[[[a.x,b.y]for y in 1..#b]for x in 1..#a]

some results

(15) -> f("123456","abcd")
   (15)
   [[1,a], [1,b], [1,c], [1,d], [2,a], [2,b], [2,c], [2,d], [3,a], [3,b],
    [3,c], [3,d], [4,a], [4,b], [4,c], [4,d], [5,a], [5,b], [5,c], [5,d],
    [6,a], [6,b], [6,c], [6,d]]
                                                Type: List List Character
(16) -> f("abc","123")
   (16)  [[a,1],[a,2],[a,3],[b,1],[b,2],[b,3],[c,1],[c,2],[c,3]]
                                                Type: List List Character
(17) -> f("aa","aba")
   (17)  [[a,a],[a,b],[a,a],[a,a],[a,b],[a,a]]
                                                Type: List List Character

RosLuP

Posted 2017-06-07T22:58:49.577

Reputation: 3 036

0

APL NARS 8 chars

{,⍺∘.,⍵}

Copy from https://codegolf.stackexchange.com/a/125115/58988 test

f←{,⍺∘.,⍵}
'123456' f 'abcd'
 1a 1b 1c 1d 2a 2b 2c 2d 3a 3b 3c 3d 4a 4b 4c 4d 5a 5b 5c 5d 6a 6b 6c 6d 

RosLuP

Posted 2017-06-07T22:58:49.577

Reputation: 3 036

0

Prolog (SWI), 48 bytes

L-R:-findall([A,B],(member(A,L),member(B,L)),R).

Try it online!

ASCII-only

Posted 2017-06-07T22:58:49.577

Reputation: 4 687

0

GolfScript, 21 bytes

~\:a;{a{[.;1$]}%\;}%`

Try it online!

user85052

Posted 2017-06-07T22:58:49.577

Reputation: