This documentation is automatically generated by online-judge-tools/verification-helper
require "spec"
require "../../src/collection/unique_permutation"
describe Array do
rng = Random.new(42)
arrays = [
[] of Int32,
[0],
[0, 0],
(0...8).to_a,
] + Array.new(100) {
Array.new(8) { rng.rand(3) }
}
it "#next_unique_permutation, #each_unique_permutation" do
arrays.each do |a|
perms = a.sort.permutations.uniq!.skip_while(&.!= a)
b, i = a.dup, 0
while i + 1 < perms.size
b.next_permutation!.should be_true
b.should eq perms[i += 1]
end
b.next_permutation!.should be_false
b.should eq perms.last
b, i = a.dup, 0
while i + 1 < perms.size
(b = b.next_permutation?.not_nil!).should eq perms[i += 1]
end
b.next_permutation?.should be_nil
a.unique_permutations.should eq perms
a.each_unique_permutation.to_a.should eq perms
i = 0
a.each_unique_permutation(true).each do |b|
b.should eq perms[i]
i += 1
end
i = 0
a.each_unique_permutation do |b|
b.should eq perms[i]
i += 1
end
i = 0
a.each_unique_permutation(reuse: true) do |b|
b.should eq perms[i]
i += 1
end
end
end
end
require "spec"
# require "../../src/collection/unique_permutation"
class Array(T)
def next_permutation! : Bool
i = (1...size).reverse_each.find { |i| self[i - 1] < self[i] } || return false
j = (0...size).reverse_each.find { |j| self[i - 1] < self[j] }.not_nil!
swap(i - 1, j)
Slice.new(to_unsafe + i, size - i).reverse!
true
end
def next_permutation? : Array(T)?
arr = dup
arr.next_permutation! ? arr : nil
end
def each_unique_permutation(reuse : Bool = false, &block) : Nil
pool = dup
loop do
yield reuse ? pool : pool.dup
break unless pool.next_permutation!
end
end
def each_unique_permutation(reuse : Bool = false)
UniquePermutationIterator.new(clone, reuse)
end
def unique_permutations : Array(Array(T))
permutations = [] of Array(T)
each_unique_permutation { |perm| permutations << perm.dup }
permutations
end
private class UniquePermutationIterator(T)
include Iterator(T)
@pool : T
def initialize(a : T, @reuse : Bool)
@pool = a.dup
@first = true
end
def next
if @first
@first = false
@reuse ? @pool : @pool.dup
elsif @pool.next_permutation!
@reuse ? @pool : @pool.dup
else
stop
end
end
end
end
describe Array do
rng = Random.new(42)
arrays = [
[] of Int32,
[0],
[0, 0],
(0...8).to_a,
] + Array.new(100) {
Array.new(8) { rng.rand(3) }
}
it "#next_unique_permutation, #each_unique_permutation" do
arrays.each do |a|
perms = a.sort.permutations.uniq!.skip_while(&.!= a)
b, i = a.dup, 0
while i + 1 < perms.size
b.next_permutation!.should be_true
b.should eq perms[i += 1]
end
b.next_permutation!.should be_false
b.should eq perms.last
b, i = a.dup, 0
while i + 1 < perms.size
(b = b.next_permutation?.not_nil!).should eq perms[i += 1]
end
b.next_permutation?.should be_nil
a.unique_permutations.should eq perms
a.each_unique_permutation.to_a.should eq perms
i = 0
a.each_unique_permutation(true).each do |b|
b.should eq perms[i]
i += 1
end
i = 0
a.each_unique_permutation do |b|
b.should eq perms[i]
i += 1
end
i = 0
a.each_unique_permutation(reuse: true) do |b|
b.should eq perms[i]
i += 1
end
end
end
end