Task

Show one or more idiomatic ways of generating the Cartesian product of two arbitrary lists in your language.

Demonstrate that your function/method correctly returns:

{1, 2} × {3, 4} = {(1, 3), (1, 4), (2, 3), (2, 4)}
and, in contrast:

{3, 4} × {1, 2} = {(3, 1), (3, 2), (4, 1), (4, 2)}
Also demonstrate, using your function/method, that the product of an empty list with any other list is empty.

 {1, 2} × {} = {}
 {} × {1, 2} = {}
For extra credit, show or write a function returning the n-ary product of an arbitrary number of lists, each of arbitrary length. Your function might, for example, accept a single argument which is itself a list of lists, and return the n-ary product of those lists.

Use your n-ary Cartesian product function to show the following products:

 {1776, 1789} × {7, 12} × {4, 14, 23} × {0, 1}
 {1, 2, 3} × {30} × {500, 100}
 {1, 2, 3} × {} × {500, 100}


DEFINE MAX_COUNT="10"
DEFINE MAX_RESULT="100"
 
DEFINE PTR="CARD"
 
PROC PrintInput(PTR ARRAY a INT count)
  INT i,j,n
  INT ARRAY tmp
 
  FOR i=0 TO count-1
  DO
    tmp=a(i) n=tmp(0)
    Put('[)
    FOR j=1 TO n
    DO
      PrintI(tmp(j))
      IF j<n THEN Put(',) FI
    OD
    Put('])
    IF i<count-1 THEN Put('x) FI
  OD
RETURN
 
PROC PrintOutput(INT ARRAY a INT groups,count)
  INT i,j,k
 
  Put('[)
  k=0
  FOR i=0 TO groups-1
  DO
    Put('()
    FOR j=0 TO count-1
    DO
      PrintI(a(k)) k==+1
      IF j<count-1 THEN Put(',) FI
    OD
    Put('))
    IF i<groups-1 THEN Put(',) FI
  OD
  Put('])
RETURN
 
PROC Product(PTR ARRAY a INT count
  INT ARRAY r INT POINTER groups)
  INT ARRAY ind(MAX_COUNT),tmp
  INT i,j,k
 
  IF count>MAX_COUNT THEN Break() FI
  groups^=1
  FOR i=0 TO count-1
  DO
    ind(i)=1 tmp=a(i)
    groups^==*tmp(0)
  OD
  IF groups^=0 THEN RETURN FI
 
  j=count-1 k=0
  DO
    FOR i=0 TO count-1
    DO
      tmp=a(i)
      r(k)=tmp(ind(i)) k==+1
    OD
 
    DO
      tmp=a(j)
      IF ind(j)<tmp(0) THEN
        ind(j)==+1
        FOR i=j+1 TO count-1
        DO
          ind(i)=1
        OD
        j=count-1
        EXIT
      ELSE
        IF j=0 THEN RETURN FI
        j==-1
      FI
    OD
  OD
RETURN
 
PROC Test(PTR ARRAY a INT count)
  INT ARRAY r(MAX_RESULT)
  INT groups
 
  IF count<2 THEN Break() FI
  Product(a,count,r,@groups)
  PrintInput(a,count)
  Put('=)
  PrintOutput(r,groups,count)
  PutE()
RETURN
 
PROC Main()
  INT ARRAY
    a1=[2 1 2],a2=[2 3 4],a3=[0],
    a4=[2 1776 1789],a5=[2 7 12],
    a6=[3 4 14 23],a7=[2 0 1],
    a8=[3 1 2 3],a9=[1 30],a10=[2 500 100]
  PTR ARRAY a(4)
 
  a(0)=a1 a(1)=a2 Test(a,2)
  a(0)=a2 a(1)=a1 Test(a,2)
  a(0)=a1 a(1)=a3 Test(a,2)
  a(0)=a3 a(1)=a1 Test(a,2) PutE()
  a(0)=a4 a(1)=a5 a(2)=a6 a(3)=a7 Test(a,4) PutE()
  a(0)=a8 a(1)=a9 a(2)=a10 Test(a,3) PutE()
  a(0)=a8 a(1)=a3 a(2)=a10 Test(a,3)
RETURN