N-Dimensional Cartesian Product

12

4

Introduction

The Cartesian product of two lists is calculated by iterating over every element in the first and second list and outputting points. This is not a very good definition, so here are some examples: the Cartesian product of [1, 2] and [3, 4] is [(1, 3), (1, 4), (2, 3), (2, 4)]. The product of [1] and [2] is [(1, 2)]. However, no one said you could only use two lists. The product of [1, 2], [3, 4], and [5, 6] is [(1, 3, 5), (1, 4, 5), (1, 3, 6), (1, 4, 6), (2, 3, 5), (2, 4, 5), (2, 3, 6), (2, 4, 6)].

Challenge

Given a number of lists, your program must output the Cartesian product of the lists given.

  • You can assume that there will always be more than 1 list, and that each list will have the same length. No list will ever be empty. If your language has no method of stdin, you may take input from command line arguments or a variable.
  • Your program must output the Cartesian product of all the input lists. If your language has no stdout, you may store output in a variable or as a return value. The output should be a list of lists, or any other iterable type.

Example I/O

Input: [1, 2] [3, 4]
Output: [(1, 3), (1, 4), (2, 3), (2, 4)]

Input: [1, 2] [3, 4] [5, 6]
Output: [(1, 3, 5), (1, 4, 5), (1, 3, 6), (1, 4, 6), (2, 3, 5), (2, 4, 5), (2, 3, 6), (2, 4, 6)]

Input: [1, 2, 3] [4, 5, 6]
Output: [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

Rules

This is so shortest answer in bytes wins!

sugarfi

Posted 2019-11-16T17:36:43.683

Reputation: 1 239

6boring answer: itertools.product in python – Quintec – 2019-11-16T17:54:50.827

Related, related. – Digital Trauma – 2019-11-16T23:13:10.073

2If your language has no method of stdin, you may take input from command line arguments or a variable I suggest you allow command-line inputs without any condition. See here – Luis Mendo – 2019-11-17T03:12:29.093

Does order matter among the output lists? – xnor – 2019-11-17T05:45:58.203

Order does not matter @xnor. – sugarfi – 2019-11-17T13:18:01.370

Is it mandatory to have an output in the format [[a,b,c],[a,c,b],...] (in any order), or are other formats also allowed? The two Japt answers output as [a,b,c,a,c,b,...] and [[[a,b],c], [[a,c],b], ...] instead for example (not sure if this is a valid output)? – Kevin Cruijssen – 2019-11-18T12:34:45.010

1No, the format described is not mandatory @KevinCruijssen – sugarfi – 2019-11-18T22:09:14.790

Answers

12

J, 1 byte

Courtesy of ngn

{

Try it online!

'tis called Catalogue

Adám

Posted 2019-11-16T17:36:43.683

Reputation: 37 779

You beat me to it :). I think ,@{ would be more fair though, since the output of naked { doesn't have a uniform structure (ie, it depends on the inputs). – Jonah – 2019-11-16T19:40:42.817

@Jonah Jelly gives the same structure.

– Adám – 2019-11-16T19:45:05.540

results not seem list deep 1 of element of input – RosLuP – 2019-11-17T07:04:10.117

@RosLuP It is. J's Try it online! L. is APL's .

– Adám – 2019-11-17T07:24:08.833

8

Haskell, 7 bytes

mapM id

Try it online!

Built-in, 8 bytes

sequence

Try it online!

Less boring, 33 bytes

Out-golfed by xnor's answer. Go upvote that instead!

f[]=[[]]
f(h:t)=[i:j|i<-h,j<-f t]

Try it online!

totallyhuman

Posted 2019-11-16T17:36:43.683

Reputation: 15 378

7

Haskell, 23 bytes

foldr((<*>).map(:))[[]]

Try it online!

Without using mapM or sequence or the like.

xnor

Posted 2019-11-16T17:36:43.683

Reputation: 115 687

6

Python 3, 56 bytes

def f(M,*l):M and[f(M[1:],*l,x)for x in M[0]]or print(l)

Try it online!

No itertools. This is one of those weird functions that prints. Thanks to Unrelated String for -2 bytes with def.

xnor

Posted 2019-11-16T17:36:43.683

Reputation: 115 687

Since the return value doesn't matter, you can shave two bytes off by using def: Try it online!

– Unrelated String – 2019-11-17T06:09:09.917

1@ChasBrown I don't think that's allowed, it nests the output a lot. And unfortunately Python doesn't do iterable unpacking in comprehensions. – xnor – 2019-11-17T09:11:17.463

1@xnor : quite right! Carry on... – Chas Brown – 2019-11-17T09:12:32.883

4

Japt -R, 2 bytes

A simple reduction by Cartesian product.

Try it

Shaggy

Posted 2019-11-16T17:36:43.683

Reputation: 24 623

Lol! Congrats! You preceded me by 12 minutes ! Anyway I'm really proud of .. I immediately thought about that solution – AZTECCO – 2019-11-16T21:34:50.247

Ha, I spent 15 minutes looking through Japt docs and couldn't find this again. Lol – Quintec – 2019-11-17T14:32:35.310

@KevinCruijssen, here it is "pretty printed": https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&code=cu8&input=W1sxLDJdLFszLDRdLFs1LDZdXQotUQ

– Shaggy – 2019-11-18T12:39:54.423

OP stated the output-format is indeed flexible, and those outputs are allowed. – Kevin Cruijssen – 2019-11-19T07:08:05.363

1Thanks, @KevinCruijssen. I've updated to Japt -R anyway. – Shaggy – 2019-11-19T10:43:09.607

4

Python 2, 60 59 bytes

f=lambda A,*x:[[v]+u for v in A for u in x and f(*x)or[[]]]

Try it online!

1 byte thx to ovs.

Look Ma! No itertools!

Chas Brown

Posted 2019-11-16T17:36:43.683

Reputation: 8 959

59 bytes – ovs – 2019-11-17T13:43:29.160

4

K (oK), 31 15 bytes

{x@'/:+!(#:)'x}

Try it online!

Galen Ivanov

Posted 2019-11-16T17:36:43.683

Reputation: 13 815

1How are you finding K compared with J? What have you been using to learn it? – Jonah – 2019-11-17T16:36:33.053

1

@Jonah I can't compare them directly. K lacks J's math capabilities, but works on heterogeneous lists. It is much more compact and I like it very much even I have only sctratched the surface. I started learning from the oK Manual. On several occasions ngn helped me in thr k tree. He also supplied almost all my previos k submissions with golfing tips.

– Galen Ivanov – 2019-11-17T19:31:48.883

3

Jelly, 4 2 bytes

Œp

Try it online!

Output is "pretty printed" in the TIO link

caird coinheringaahing

Posted 2019-11-16T17:36:43.683

Reputation: 13 702

3

Ruby, 20 bytes

->i,*j{i.product *j}

Try it online!

game0ver

Posted 2019-11-16T17:36:43.683

Reputation: 621

3

Brachylog, 1 byte

Try it online!

A slightly less boring generator solution:

Brachylog, 2 bytes

∋ᵐ

Try it online!

Unrelated String

Posted 2019-11-16T17:36:43.683

Reputation: 5 300

A careful reading of the rules suggests that function submissions are only allowed to output through return values if printing is impossible, so if that's actually enforced, +1 byte to the first for w, and +2 to the second for ẉ⊥. – Unrelated String – 2019-11-18T21:25:24.953

3

Retina, 54 39 32 bytes

This took really long to write (as I tried to golf it too) (unsurprisingly, all the golfing ideas only appeared after I finally posted this). Takes input as a list of strings of alphanumeric characters and underscores (whatever \w matches in your universe), each preceded by a semicolon (I assume characters are as acceptable in Retina as numbers are in everything else; in fact, the challenge never actually specified numbers). Outputs the list of the resulting strings, each preceded by a comma.

^
,
+w`,(\w*)[^;]*;\w*(\w)
,$1$2

Explanation:

^                       match the beginning of the string
,                       add a comma there
+w`,(\w*)[^;]*;\w*(\w)  solve the rest of the problem
,$1$2                   replace with a comma, group 1 and group 2

The third and fourth lines are in a convergence loop (run until no change) (declared by the +). The regular expression in the 3rd line works on lines like , ac, bc, ad, bd;ef;gh and matches all substrings starting at a comma and ending at a character after the first semicolon, where the group 1 is the string after the comma and group 2 is the last character.

Try it online!

my pronoun is monicareinstate

Posted 2019-11-16T17:36:43.683

Reputation: 3 111

3

Perl 6, 8 4 bytes

&[X]

Try it online!

Simple reduce by cross product. It would be nice if I could return the meta-operator by itself, but I've never figured out how to do that. Turns out it works for cross product?

Jo King

Posted 2019-11-16T17:36:43.683

Reputation: 38 234

&[X] seems to work in this case. – nwellnhof – 2019-11-17T16:52:27.997

@nwellnhof What? But &[+] doesn't work? I don't understand when it does and doesn't work – Jo King – 2019-11-17T20:43:46.350

2

Seems to be an implementation detail of the infix operators. Some infix operators accept more than two args but it's not a requirement.

– nwellnhof – 2019-11-17T22:03:31.627

2

Zsh, 30 bytes

for l;a=($^a\ ${^${=l}})
<<<$a

Try it online!

Split = and cartesian product ^ for each element. Our base case adds an extra space, which cleanly separates our output lists.

GammaFunction

Posted 2019-11-16T17:36:43.683

Reputation: 2 838

2

R, 54 47 bytes

f=function(x)split(j<-expand.grid(x),1:nrow(j))

Try it online!

If you consider data.frame rows iterable:

R, 27 bytes

f=function(x)expand.grid(x)

Try it online!

John

Posted 2019-11-16T17:36:43.683

Reputation: 171

1

You don't need to include the f= in the byte count here, and can include it in the header: Example

. Also, as expand.grid is a built-in, this is basically 11 bytes as expand.grid returns the function. I think we've scored them as such in the past, though am happy to be corrected by someone with more intimate knowledge of practice.

– CriminallyVulgar – 2019-11-18T11:57:28.173

2

Python 3 (Cython), 46 44 31 bytes

__import__('itertools').product

Try it online!

This doesn't need more explanation, right?

(-13 bytes thanks to Jo King; -2 bytes thanks to caird coinheringaahing)

L. F.

Posted 2019-11-16T17:36:43.683

Reputation: 147

Welcome to the site! Unnamed lambdas are perfectly acceptable here, so you can remove the f= to save two bytes. – caird coinheringaahing – 2019-11-18T13:58:34.063

@cairdcoinheringaahing Thank you! I have removed the f=. I'm not sure how to make TIO count this as 44 bytes though ... – L. F. – 2019-11-18T14:03:09.713

This should work – caird coinheringaahing – 2019-11-18T14:03:47.853

@cairdcoinheringaahing Thanks! Didn't know that the backslash works here. – L. F. – 2019-11-19T11:33:13.183

@JoKing Absolutely! Thank you! – L. F. – 2019-11-19T11:33:22.567

1

JavaScript (Node.js), 52 bytes

Returns a list of lists.

f=([a,...b],o=[])=>a?a.flatMap(x=>f(b,[...o,x])):[o]

Try it online!


JavaScript (V8), 52 bytes

Prints the results.

f=([a,...b],o)=>a?a.map(x=>f(b,o?o+[,x]:x)):print(o)

Try it online!

Arnauld

Posted 2019-11-16T17:36:43.683

Reputation: 111 334

1

Erlang, 57 bytes

c([]) -> [[]];
c([H|T]) -> [[X|Y] || X <- H, Y <- c(T)].

Yuri Ginsburg

Posted 2019-11-16T17:36:43.683

Reputation: 121

1

Julia 1.0, 34 bytes

No imports used, iterators in Base has this. It actually makes a lazy form of this, but to print them all it will collect each one.

println.(Iterators.product(l...))

where l is the list of lists.

caseyk

Posted 2019-11-16T17:36:43.683

Reputation: 167

1

Japt, 2 bytes

Try it

Reduces input by combination with initial value of 1st element

Duplicate of @Shaggy answer, I was solving this while he just posted the same solution. I hope I can leave my answer too because it's awesome

AZTECCO

Posted 2019-11-16T17:36:43.683

Reputation: 2 441

1

Charcoal, 22 bytes

IEΠEθLιEθ§λ÷ιΠ∨E…θμLν¹

Try it online! Link is to verbose version of code. Explanation:

    θ                   Input list
   E                    Map over elements
      ι                 Current element
     L                  Length
  Π                     Product
 E                      Map over implicit range
        θ               Input list
       E                Map over elements
          λ             Current element
         §              Cyclically indexed by
            ι           Outer index
           ÷            Integer divide
                 θ      Input list
                …       Truncated to length
                  μ     Inner index
               E        Map over elements
                    ν   Current element
                   L    Length
              ∨      ¹  Replace empty list with literal 1
             Π          Product
I                       Cast to string
                        Implicitly print double-spaced on separate lines

Neil

Posted 2019-11-16T17:36:43.683

Reputation: 95 035

1

APL(NARS), chars 11, bytes 22

{,↑(∘.,)/⍵}

test for product of sets:

  f←{,↑(∘.,)/⍵}
  ⎕fmt (1 2)(3 4)
┌2────────────┐
│┌2───┐ ┌2───┐│
││ 1 2│ │ 3 4││
│└~───┘ └~───┘2
└∊────────────┘
  ⎕fmt f (1 2)(3 4)
┌4──────────────────────────┐
│┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐│
││ 1 3│ │ 1 4│ │ 2 3│ │ 2 4││
│└~───┘ └~───┘ └~───┘ └~───┘2
└∊──────────────────────────┘
  ⎕fmt f (1 2)(3 4)(5 6)
┌8──────────────────────────────────────────────────────────────────────┐
│┌3─────┐ ┌3─────┐ ┌3─────┐ ┌3─────┐ ┌3─────┐ ┌3─────┐ ┌3─────┐ ┌3─────┐│
││ 1 3 5│ │ 1 3 6│ │ 1 4 5│ │ 1 4 6│ │ 2 3 5│ │ 2 3 6│ │ 2 4 5│ │ 2 4 6││
│└~─────┘ └~─────┘ └~─────┘ └~─────┘ └~─────┘ └~─────┘ └~─────┘ └~─────┘2
└∊──────────────────────────────────────────────────────────────────────┘
  ≢f (1 2)(3 4)(5 6)
8
  f (⍳3)(4 5 6)
 1 4  1 5  1 6  2 4  2 5  2 6  3 4  3 5  3 6 

  ⎕fmt f (4 5 6)
┌1───────┐
│┌3─────┐│
││ 4 5 6││
│└~─────┘2
└∊───────┘

RosLuP

Posted 2019-11-16T17:36:43.683

Reputation: 3 036

1

05AB1E, 3 bytes

.ȉ

Outputs [[a,b],[c,d],[d,e]] in the format [[[a,c],d], [[a,c],e], ...]. To output in the format [[a,[c,d]], [a,[c,e]], ...], replace the » with «.

Try it online or try it online with right- instead of left-reduce.

Explanation:

.»   # (Left-)reduce by (or right-reduce with `.«`):
  â  #  Taking the cartesian product of the two lists
     # (after which the resulting list is output implicitly)

Kevin Cruijssen

Posted 2019-11-16T17:36:43.683

Reputation: 67 575

0

Python 3.8, 136 bytes

import re
from itertools import*
print(list(product(*[[int(i) for i in i.split(', ')] for i in re.findall(r'\[([0-9, ]+)\]',input())])))

Try it online!

Alexey Burdin

Posted 2019-11-16T17:36:43.683

Reputation: 844

5You don't have to do any of the string processing. You could just take input as a list of lists: "Given a number of lists" – caird coinheringaahing – 2019-11-16T18:03:57.950

1The heart of this answer is just itertools.product too. – qwr – 2019-11-17T06:13:49.127