! anaguniv V0.0
! Sort letters within a word
!
%external %predicate Exists(%string (255) File, %integer %name len)
  %constant %integer os length index = 2
  %record %format osfile array fm (%integer %array element (0:3))
  %record (osfile array fm) osfile array
  %record %format Time stamp fm (%integer low, high)
  %record (time stamp fm) time stamp
  %external %integer %fn %spec Get file information(%c
    %record (osfile array fm) %name osfile array, 
    %record (time stamp fm) %name time stamp,
    %string (255) file name)

  %integer success = Get file information(osfile array,
                                          time stamp,
                                          File)
  %false %if success # 1
  len = osfile array_element(os length index)
  %true
%end

%external %routine loadup(%string (255) file name,
                          %integer address, actual length, max length)
  %external %routine %spec  X Load File (%string (255) file name,
                                         %integer      buffer size,
                                         %integer      address)
  %if max length < actual length %then %start
    print string("File ".file name." of ".itos(actual length,0). %c
                 " bytes is too big for buffer of ". %c
                 itos(max length,0)." bytes".nl)
    %stop
  %finish
  X Load file(file name, max length, address)
%end

%external %routine writeout(%string (255) file name, %integer address, len)
%external %integer %fn %spec Save File (%integer straddr,strlen,
                                     %integer     buffer size,
                                                  address)
%integer cc
  cc = Save file(ADDR(file name)+1, LENGTH(file name), len, address)
  %if cc < 0 %then printstring ("Failed to write out file ".file name.nl) %c
    %and %stop
%end

%begin
%constant %integer max dict = 120 000*2

%byte %array dict(0:max dict)
%integer step factor, word length

%string (63) %fn str(%integer idx)
%string(63) s
  s = ""
  s = s.dict(idx) %for idx = idx, 1, idx+word length-1
  %result = s
%end

%routine hquicksort(%integer a, b)
%integer l,r
%byte dump
  %return %if a>=b
  l=a;r=b; dump=dict(b)
  %while l<r %cycle
    %while l<r %cycle
      %if dict(l)>dump %then dict(r)=dict(l) %and r=r-1 %and %exit
      l=l+1
    %repeat
    %while l<r %cycle
      %if dict(r)<dump %then dict(l)=dict(r) %and l=l+1 %and %exit
      r=r-1
    %repeat
  %repeat
  dict(l)=dump
  hquicksort(a,l-1)
  hquicksort(r+1,b)
%end

%routine shuffle dict(%integer low index, high index)
%integer wp
%for wp = low index, step factor, high index %cycle
!  index(wp//step factor)=wp
  hquicksort(wp, wp+word length-1)
%repeat
%end

%routine sortdict(%integer a,b)
%integer l,r,i
%byte test
%byte %array dump(0:word length)
%integer dump index
%const %integer true=0,false=1
  %return %if a>=b
  l=a;r=b
  ! dump=dict(b)...
!  dump index=index(b//step factor)
  %for i = 0, 1, wordlength %cycle
    dump(i)=dict(b+i)
  %repeat
  %while l<r %cycle
    %while l<r %cycle
      ! test = dict(l)>dump
      test = false
      %for i=0,1,word length %cycle
        %if dict(l+i)>dump(i) %then test=true %and %exit
      %repeat
      %if test=true %then %start
        ! dict(r)=dict(l) ...
!        index(r//step factor)=index(l//step factor)
        %for i=0,1,word length %cycle
          dict(r+i)=dict(l+i)
        %repeat
        r=r-step factor
        %exit
      %finish
      l=l+step factor
    %repeat
    %while l<r %cycle
      ! test = dict(r)<dump
      test = false
      %for i=0,1,word length %cycle
        %if dict(r+i)<dump(i) %then test=true %and %exit
      %repeat
      %if test=true %then %start
        ! dict(l)=dict(r) ...
!        index(l//step factor)=index(r//step factor)
        %for i=0,1,word length %cycle
          dict(l+i)=dict(r+i)
        %repeat
        l=l+step factor
        %exit
      %finish
      r=r-step factor
    %repeat
  %repeat
  ! dict(l)=dump ...
!  index(l//step factor)=dump index
  %for i = 0,1,word length %cycle
    dict(l+i)=dump(i)
  %repeat
  sortdict(a,l-step factor)
  sortdict(r+step factor,b)
%end

%routine vsort(%integer l,r)
%constinteger true=0,false=1
%byte test
%integer i,j,ix
%byte %array v(0:word length+9),t(0:word length+9)
%unless r>l %then %return
%for ix=0,1,word length*2+1 %cycle
  v(ix)=dict(r+ix)
%repeat
i = l-step factor
j = r
%cycle
  test=false
  %cycle
    i=i+step factor
    ! test = dict(i+ix)>=v
    %for ix=0,1,word length*2+1 %cycle
      %if dict(i+ix)<v(ix) %then %exit
      %if dict(i+ix)>v(ix) %then test=true
      %if ix=word length*2+1 %then test=true
    %repeat
  %repeat %until test=true
  test=false
  %cycle
    j=j-step factor
    ! test = dict(j+ix)<=v
    %for ix=0,1,word length*2+1 %cycle
      %if dict(j+ix)>v(ix) %then %exit
      %if dict(j+ix)<v(ix) %then test=true
      %if ix=word length*2+1 %then test=true
    %repeat
  %repeat %until test=true
  ! t = dict(i)
  t(ix)=dict(i+ix) %for ix=0,1,word length*2+1
  ! dict(i) = dict(j)
  dict(i+ix)=dict(j+ix) %for ix=0,1,word length*2+1
  ! dict(j) = t
  dict(j+ix)=t(ix) %for ix=0,1,word length*2+1
%repeat %until j<=i
! dict(j)=dict(i)
dict(j+ix)=dict(i+ix) %for ix=0,1,word length*2+1
! dict(i)=dict(r)
dict(i+ix)=dict(r+ix) %for ix=0,1,word length*2+1
! dict(r)=t
dict(r+ix)=t(ix) %for ix=0,1,word length*2+1
vsort(l,i-step factor)
vsort(i+step factor,r)
%end

%routine printdict(%integer low index, high index)
%integer cp, wp
  %for wp = low index, step factor, high index %cycle
    ! wp is index of word
    Write(wp,6);space
    %for cp = wp, 1, wp+word length*2+1 %cycle
      ! cp is index of char {inc. NL}
      print symbol(dict(cp))
    %repeat
  %repeat %until wp = high index
%end

%routine duplicate(%integer low index, high index)
%integer i, j, k
%for i = high index, -step factor, low index %cycle
  ! Move <word length> bytes at i to i*2, i*2+step factor
  j=i*2
  %for k=0,1,word length %cycle
    dict(j+k+step factor)=dict(i+k)
    dict(j+k)=dict(i+k)
  %repeat
%repeat
%end

%routine pogle(%integer low index, high index)
%integer i
%for i = low index, step factor, high index %cycle
  dict(i+word length)=' '
%repeat
%end

%const %string (*) ordinary dict dir = "adfs::0.$.words.longmans."
%const %string (*) anagram dict dir = "adfs::0.$.words.longanag."
%string (255) file name
%integer i, dict length
%for word length = 1, 1, 32 %cycle
  file name = ordinary dict dir.itos(word length,0)
  %if exists(file name, dict length) %start
    printstring("********* ".file name." **********".nl)
    step factor = word length+1 { 1 is for NL }
    loadup(file name, ADDR(dict(step factor)), dict length, max dict)
    dict(i) = '#' %for i = 0, 1, word length-1
    dict(word length)=NL                         {Start sentinel}
    dict(i) = '~' %c
      %for i = dict length+step factor,1,dict length+step factor+word length-1
    dict(dict length+step factor+word length)=NL {End sentinel}
    printstring("Duplicating...".nl)
    duplicate(0,dict length+step factor)
    printstring("shuffling...".nl)
    step factor=step factor*2
    dict length=dict length*2
    shuffle dict(0, dict length+step factor)
    printstring("sorting...".nl)
    vsort(step factor, dict length)
    pogle(0,dict length+step factor)
    ! printdict(0, dict length+step factor)
    writeout( %c
     anagram dict dir.itos(word length,0), %c
     ADDR(dict(0)), %c
     dict length+step factor*2)
  %finish
%repeat
%endofprogram
