ref: 012c761ef5952366fe4c9be95ad8aa250afe6154
parent: 8aef13f0d3a760760a3843245f6d5b1f62c2a142
author: Quentin Carbonneaux <quentin@c9x.me>
date: Mon Jan 15 16:11:02 EST 2018
Fix iter.byperm when there are duplicates. Eh, I'm trying to get back in business. Cheers.
--- a/lib/iter/perm.myr
+++ b/lib/iter/perm.myr
@@ -47,12 +47,12 @@
if j == 0
-> false
;;
- match itp.cmp(seq[j - 1], seq[j])
- | `std.After: j--
- | _: break
+ j--
+ match itp.cmp(seq[j], seq[j + 1])
+ | `std.Before: break
+ | _:
;;
;;
- j--
/*
Find highest i s.t. seq[j] < seq[i]. This
@@ -62,9 +62,12 @@
*/
i = seq.len - 1
while true
- if i <= j
- -> false
- ;;
+ /*
+ By the previous loop, we know that
+ seq[j] < seg[j + 1], thus, in this loop,
+ we always have j + 1 <= i, and the array
+ accesses are always in bounds.
+ */
match itp.cmp(seq[j], seq[i])
| `std.Before: break
| _: i--
--- a/lib/iter/test/perm.myr
+++ b/lib/iter/test/perm.myr
@@ -8,6 +8,7 @@
[.name = "byperm-01", .fn = byperm01],
[.name = "byperm-02", .fn = byperm02],
[.name = "byperm-03", .fn = byperm03],
+ [.name = "byperm-04", .fn = byperm04],
][:])
}
@@ -51,4 +52,20 @@
var expected : byte[:] = " [1, 1, 3] [1, 3, 1] [3, 1, 1] "
var actual : byte[:] = std.sbfin(sb)
testr.check(c, std.eq(expected, actual), "expected “{}”, got “{}”", expected, actual)
+}
+
+const byperm04 = {c
+ var v : int[:] = [ 0, 3, 1, 1 ][:]
+ var nperm = 0
+
+ for w : iter.byperm(v, std.numcmp)
+ nperm++
+ ;;
+
+ /*
+ There are 24 permutations for 4 elements, but we get only
+ half because two elements are equal.
+ */
+ const expected = 12
+ testr.check(c, std.eq(expected, nperm), "expected “{}”, got “{}”", expected, nperm)
}