summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSimon Hafner <hafnersimon@gmail.com>2014-01-30 02:07:21 -0600
committerSimon Hafner <hafnersimon@gmail.com>2014-01-30 02:07:55 -0600
commitac0f15379cb0409e47512bcd40af28d1e7816337 (patch)
treed78b5c82ce7bf55c3b9308f6e4d33958ff52b19d
parent47e2999fec48d05943d9d2162cee446586d261b5 (diff)
downloadNim-ac0f15379cb0409e47512bcd40af28d1e7816337.tar.gz
added Cartesian product
-rw-r--r--lib/pure/algorithm.nim32
-rw-r--r--tests/stdlib/talgorithm.nim9
2 files changed, 41 insertions, 0 deletions
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index df7ae6d17..2620f7c90 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -131,3 +131,35 @@ proc sort*[T](a: var openArray[T],
       dec(m, s*2)
     s = s*2
 
+proc product[T](x: openarray[seq[T]]): seq[seq[T]] =
+  ## produces the Cartesian product of the array. Warning: complexity
+  ## may explode.
+  result = @[]
+  if x.len == 0:
+    return
+  if x.len == 1:
+    result = @x
+    return
+  var
+    indexes = newSeq[int](x.len)
+    initial = newSeq[int](x.len)
+    index = 0
+  # replace with newSeq as soon as #853 is fixed
+  var next: seq[T] = @[]
+  next.setLen(x.len)
+  for i in 0..(x.len-1):
+    initial[i] = len(x[i])-1
+  indexes = initial
+  while true:
+    while indexes[index] == -1:
+      indexes[index] = initial[index]
+      index +=1
+      if index == x.len: return
+      indexes[index] -=1
+    for ni, i in indexes:
+      next[ni] = x[ni][i]
+    var res: seq[T]
+    shallowCopy(res, next)
+    result.add(res)
+    index = 0
+    indexes[index] -=1
diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim
new file mode 100644
index 000000000..ea57883b0
--- /dev/null
+++ b/tests/stdlib/talgorithm.nim
@@ -0,0 +1,9 @@
+import unittest
+
+suite "product":
+  test "a simple case of one element":
+    check product(@[@[1,2]]) == @[@[1,2]]
+  test "two elements":
+    check product(@[@[1,2], @[3,4]]) == @[@[2,4],@[1,4],@[2,3],@[1,3]]
+  test "three elements":
+    check product(@[@[1,2], @[3,4], @[5,6]]) == @[@[2,4,6],@[1,4,6],@[2,3,6],@[1,3,6], @[2,4,5],@[1,4,5],@[2,3,5],@[1,3,5]]