RosettaCodeData/Task/Permutations/Lobster/permutations.lobster

133 lines
3.2 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Lobster implementation of the (very fast) Go example
// http://rosettacode.org/wiki/Permutations#Go
// implementing the plain changes (bell ringers) algorithm, using a recursive function
// https://en.wikipedia.org/wiki/SteinhausJohnsonTrotter_algorithm
def permr(s, f):
if s.length == 0:
f(s)
return
def rc(np: int):
if np == 1:
f(s)
return
let np1 = np - 1
let pp = s.length - np1
rc(np1) // recurs prior swaps
var i = pp
while i > 0:
// swap s[i], s[i-1]
let t = s[i]
s[i] = s[i-1]
s[i-1] = t
rc(np1) // recurs swap
i -= 1
let w = s[0]
for(pp): s[_] = s[_+1]
s[pp] = w
rc(s.length)
// Heap's recursive method https://en.wikipedia.org/wiki/Heap%27s_algorithm
def permh(s, f):
def rc(k: int):
if k <= 1:
f(s)
else:
// Generate permutations with kth unaltered
// Initially k == length(s)
rc(k-1)
// Generate permutations for kth swapped with each k-1 initial
for(k-1) i:
// Swap choice dependent on parity of k (even or odd)
// zero-indexed, the kth is at k-1
if (k & 1) == 0:
let t = s[i]
s[i] = s[k-1]
s[k-1] = t
else:
let t = s[0]
s[0] = s[k-1]
s[k-1] = t
rc(k-1)
rc(s.length)
// iterative Boothroyd method
import std
def permi(xs, f):
var d = 1
let c = map(xs.length): 0
f(xs)
while true:
while d > 1:
d -= 1
c[d] = 0
while c[d] >= d:
d += 1
if d >= xs.length:
return
let i = if (d & 1) == 1: c[d] else: 0
let t = xs[i]
xs[i] = xs[d]
xs[d] = t
f(xs)
c[d] = c[d] + 1
// next lexicographical permutation
// to get all permutations the initial input `a` must be in sorted order
// returns false when input `a` is in reverse sorted order
def next_lex_perm(a):
def swap(i, j):
let t = a[i]
a[i] = a[j]
a[j] = t
let n = a.length
/* 1. Find the largest index k such that a[k] < a[k + 1]. If no such
index exists, the permutation is the last permutation. */
var k = n - 1
while k > 0 and a[k-1] >= a[k]: k--
if k == 0: return false
k -= 1
/* 2. Find the largest index l such that a[k] < a[l]. Since k + 1 is
such an index, l is well defined */
var l = n - 1
while a[l] <= a[k]: l--
/* 3. Swap a[k] with a[l] */
swap(k, l)
/* 4. Reverse the sequence from a[k + 1] to the end */
k += 1
l = n - 1
while l > k:
swap(k, l)
l -= 1
k += 1
return true
var se = [0, 1, 2, 3] //, 4, 5, 6, 7, 8, 9, 10]
print "Iterative lexicographical permuter"
print se
while next_lex_perm(se): print se
print "Recursive plain changes iterator"
se = [0, 1, 2, 3]
permr(se): print(_)
print "Recursive Heap\'s iterator"
se = [0, 1, 2, 3]
permh(se): print(_)
print "Iterative Boothroyd iterator"
se = [0, 1, 2, 3]
permi(se): print(_)