import { Sequence } from '../../core';
import { compose } from '../../../../helper/compose';
compose(Sequence, class extends Sequence {
public override permutations(): Sequence>, Sequence.Iterator]> {
return Sequence.from([0])
.bind(() => {
const xs = this.extract();
return xs.length === 0
? Sequence.mempty
: Sequence.from([xs]);
})
.bind(xs =>
Sequence.mappend(
Sequence.from([xs]),
perms(Sequence.from(xs), Sequence.mempty)));
}
});
function perms(ts: Sequence, is: Sequence): Sequence>, Sequence.Iterator]> {
return Sequence.Iterator.when>, Sequence.Iterator]>>(
ts.iterate(),
() => Sequence.mempty,
tt =>
new Sequence>, Sequence.Iterator]>, unknown>((_, cons) =>
Sequence.Iterator.when(
tt,
() => cons(),
tt => {
const t = Sequence.Thunk.value(tt);
const ts = Sequence.resume(Sequence.Thunk.iterator(tt)).memoize();
return cons(
is.permutations()
.foldr((ys, r) =>
interleave(Sequence.from(ys), r)
, perms(
ts,
Sequence.mappend(Sequence.from([t]), is))));
function interleave(
xs: Sequence,
r: Sequence
): Sequence, Sequence.Iterator]> {
return interleave_(as => as, xs, r)[1];
}
function interleave_(
f: (as: Sequence) => Sequence,
ys: Sequence,
r: Sequence
): [Sequence, Sequence.Iterator]>, Sequence, Sequence.Iterator]>] {
return Sequence.Iterator.when, Sequence]>(
ys.iterate(),
() => [ts, r],
yt => {
const y = Sequence.Thunk.value(yt);
const { 0: us, 1: zs } = interleave_(
as => f(Sequence.mappend(Sequence.from([y]), as)),
Sequence.resume(Sequence.Thunk.iterator(yt)),
r);
return [
Sequence.mappend(Sequence.from([y]), us),
Sequence.mappend(
Sequence.from([f(Sequence.mappend(Sequence.from([t]), Sequence.mappend(Sequence.from([y]), us))).extract()]),
zs)
];
});
}
}))
.bind(xs => xs));
}