perm.mws


FELADAT:

Írjunk egy olyan eljárást, melynek argumentumába egy
N pozitív egész számot, vagy egy listát megadva egy olyan eljárást kapunk vissza, amely minden meghívásakor az N szám vagy a lista elemeinek egy újabb permutációját adja.

> restart;


Először megírjuk a KNUTH-könyvben (http://www-cs-faculty.stanford.edu/~knuth/news.html) szereplő algoritmust. Csak két dolgon változtatunk:

1. a legvégén szereplő goto 1 helyett a programrészlet elejére egy do, végére egy end do parancsot írunk;

2. a könyvben szerplő algoritmus azt feltételezi, hogy az 'a' vektor 'a[0]' eleme határozottan kisebb 'a' legnagyobb eleménél. Ezt nehéz teljesíteni, ha minden elem egyforma, és nem kötjük, hogy a lista elemei csak számok lehetnek, ezért beszúrtunk egy vizsgálatot, mely megadkadályozza, hogy az 'a[0]' elemet összehasonlítsuk bármivel is, vagyis 'a' indexe így csak 1-től fut n-ig.

Itt követhetjük KNUTH algoritmusát is, ha pl. kikötjük, hogy ha az algoritmus listaként van megadva, akkor az csak számok listája lehet, és ekkor kiadjuk pl. a

a[0] := a[1]-1

utasítást az inicializációs részben.

A programban megjegyzésként szerepelnek KNUTH sorszámai is:

> perms := proc(N::{integer,list})

> local a, j, k, l, n;

>

> if type(args,integer) then n:=N; a:=array([$1..n])

> elif type(args,list) then n:=nops(N); a:=array(N)

> else error "wrong type of args"

> end if;

>

> do

> #1:

> print(a);

> #2:

> j:=n-1;

> while j>0 and a[j] >= a[j+1] do

> j:=j-1;

> od;

> if j=0 then break end if;

> #3:

> l:=n;

> while a[j] >= a[l] do

> l:=l-1

> od;

> (a[j],a[l]) := (a[l],a[j]);

> #4:

> k:=j+1; l:=n;

> while k<l do

> (a[k],a[l]) := (a[l],a[k]);

> k:=k+1;

> l:=l-1;

> od;

> od;

>

> print("vége");

>

> end proc:

> perms(3);

vector([1, 2, 3])

vector([1, 3, 2])

vector([2, 1, 3])

vector([2, 3, 1])

vector([3, 1, 2])

vector([3, 2, 1])

> perms([1,2,2]);

vector([1, 2, 2])

vector([2, 1, 2])

vector([2, 2, 1])

>


A következő lépésben minimális változtatást végzünk e kódon, hogy beilleszthessük perms-et egy olyan perm nevű eljárásba, mely egy olyan függvényt ad vissza, mely minden meghívásakor csak egyetlen permutációt ad vissza:

1. A j változót mindig FAIL-re állítjuk, ha előlről kezdődik a felsorolás;

2. Az 1-es pontot, vagyis a kiíratást az elejéről a végére tesszük, és beszúrunk az elejére egy olyan inicializáló utasítást, mely a legelső nyomtatást is elvégzi.

> perm := proc(N::{integer,list})

> local perms, a, j, k, l, n;

>

> j:=FAIL;

>

> perms := proc()

>

> if j=FAIL then

> if type(N,integer) then n := N; a := array([$1..n])

> else a := array(N); n := nops(N)

> end if;

> print(a); j:=0; return NULL

> end if;

>

> #2:

> j:=n-1;

> while j>0 and a[j] >= a[j+1] do

> j:=j-1;

> od;

> if j=0 then

> j:=FAIL; return j

> end if;

>

> #3:

> l:=n;

> while a[j] >= a[l] do

> l:=l-1

> od;

> (a[j],a[l]) := (a[l],a[j]);

> #4:

> k:=j+1; l:=n;

> while k<l do

> (a[k],a[l]) := (a[l],a[k]);

> k:=k+1:

> l:=l-1:

> od:

>

> #1:

> return evalm(a);

>

> end proc;

>

> proc()

> perms()

> end proc;

>

> end proc;

perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...
perm := proc (N::{integer, list}) local perms, a, j...

> f:=perm([1,2,2]);

f := proc () perms() end proc

> to 6 do f() end do;

vector([1, 2, 2])

vector([2, 1, 2])

vector([2, 2, 1])

FAIL

vector([1, 2, 2])

vector([2, 1, 2])

> f();

vector([2, 2, 1])

> f:=perm(4);

f := proc () perms() end proc

> to 25 do f() end do;

vector([1, 2, 3, 4])

vector([1, 2, 4, 3])

vector([1, 3, 2, 4])

vector([1, 3, 4, 2])

vector([1, 4, 2, 3])

vector([1, 4, 3, 2])

vector([2, 1, 3, 4])

vector([2, 1, 4, 3])

vector([2, 3, 1, 4])

vector([2, 3, 4, 1])

vector([2, 4, 1, 3])

vector([2, 4, 3, 1])

vector([3, 1, 2, 4])

vector([3, 1, 4, 2])

vector([3, 2, 1, 4])

vector([3, 2, 4, 1])

vector([3, 4, 1, 2])

vector([3, 4, 2, 1])

vector([4, 1, 2, 3])

vector([4, 1, 3, 2])

vector([4, 2, 1, 3])

vector([4, 2, 3, 1])

vector([4, 3, 1, 2])

vector([4, 3, 2, 1])

FAIL

> f();

vector([1, 2, 3, 4])

>