gsort.red 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. %===================================================================
  2. % Simple sorting functions for PSL strings and Ids
  3. % use with FindPrefix and FindSuffix
  4. % MLG, 8:16pm Monday, 14 December 1981
  5. %===================================================================
  6. % Revision History
  7. %
  8. % Edit by Cris Perdue, 26 Jan 1983 1343-PST
  9. % Fixed the order of arguments in one call to make GMergeSort stable.
  10. % MLG, 2 Jan 1983
  11. % Changed IDSORT form Macro to procedure, so that
  12. % it could be redefined for experiments with alternate GSORT
  13. % Affected RCREF and FIND
  14. lisp procedure StringCompare(S1,S2);
  15. % Returns 1,0,-1 for S1<S2,S1=S2,S1>S2
  16. % String Comparison
  17. Begin scalar L1,L2,I,L;
  18. L1:=Size(S1); L2:=Size(S2);
  19. L:=MIN2(L1,L2);
  20. I:=0;
  21. loop: If I>L then return(If L1 <L2 then 1
  22. else if L1 > L2 then -1
  23. else 0);
  24. if S1[I] < S2[I] then return 1;
  25. if S1[I] > S2[I] then return (-1);
  26. I:=I+1;
  27. goto loop;
  28. End;
  29. lisp procedure IdCompare(D1,D2);
  30. % Compare IDs via print names
  31. %/ What of case
  32. StringCompare(Id2String D1,Id2String D2);
  33. lisp procedure SlowIdSort DList;
  34. % Worst Possible Sort;
  35. If Null DList then NIL
  36. else InsertId(car Dlist, SlowIdSort Cdr Dlist);
  37. lisp procedure InsertId(D,DL);
  38. If Null DL then D . Nil
  39. else if IdCompare(D,Car DL)>=0 then D . DL
  40. else Car Dl . InsertId(D,Cdr Dl);
  41. % ======= Tree based ALPHA-SORT package, derived from CREF
  42. % routines modified from FUNSTR for alphabetic sorting
  43. %
  44. % Tree Sort of list of ELEM
  45. %
  46. % Tree is NIL or STRUCT(VAL:value,SONS:Node-pair)
  47. % Node-pair=STRUCT(LNode:tree,RNode:tree);
  48. lisp smacro procedure NewNode(Elem); %/ use A vector?
  49. LIST(Elem,NIL);
  50. lisp smacro procedure VAL Node;
  51. % Access the VAL in node
  52. CAR Node;
  53. lisp smacro procedure LNode Node;
  54. CADR Node;
  55. lisp smacro procedure RNode Node;
  56. CDDR Node;
  57. lisp smacro procedure NewLeftNode(Node,Elem);
  58. RPLACA(CDR Node,NewNode Elem);
  59. lisp smacro procedure NewRightNode(Node,Elem);
  60. RPLACD(CDR Node,NewNode Elem);
  61. lisp procedure IdSort LST;
  62. % Sort a LIST of ID's. Do not remove Dups
  63. % Build Tree then collapse;
  64. Tree2LST(IdTreeSort(LST),NIL);
  65. lisp procedure IdTreeSort LST;
  66. % Uses insert of Element to Tree;
  67. Begin scalar Tree;
  68. If NULL LST then Return NIL;
  69. Tree:=NewNode CAR LST; % First Element
  70. While PAIRP(LST:=CDR LST) DO IdPutTree(CAR LST,Tree);
  71. Return Tree;
  72. END;
  73. lisp smacro procedure IdPlaceToLeft (Elem1,Elem2);
  74. % ReturnS T If Elem to go to left of Node
  75. IdCompare(Elem1,Elem2)>=0;
  76. lisp procedure IdPutTree(Elem,Node);
  77. % Insert Elements into Tree
  78. Begin
  79. DWN: If Not IdPlaceToLeft(Elem,VAL Node) then GOTO RGT;
  80. If LNode Node then <<Node:=LNode Node;GO TO DWN>>;
  81. NewLeftNode(Node,Elem);
  82. Return;
  83. RGT: If RNode Node then <<Node:=RNode Node;GO TO DWN>>;
  84. NewRightNode(Node,Elem);
  85. Return;
  86. END;
  87. lisp procedure Tree2LST(Tree,LST);
  88. % Collapse Tree to LIST
  89. Begin
  90. While Tree DO
  91. <<LST:=VAL(Tree) .Tree2LST(RNode Tree,LST);
  92. Tree:=LNode Tree>>;
  93. Return LST;
  94. END;
  95. % More General Sorting, given Fn=PlaceToRight(a,b);
  96. lisp procedure GenSort(LST,Fn);
  97. % Sort a LIST of elems
  98. % Build Tree then collapse;
  99. Tree2LST(GenTreeSort(LST,Fn),NIL);
  100. lisp procedure GenTreeSort(LST,Fn);
  101. % Uses insert of Element to Tree;
  102. Begin scalar Tree;
  103. If NULL LST then Return NIL;
  104. Tree:=NewNode CAR LST; % First Element
  105. While PAIRP(LST:=CDR LST) DO GenPutTree(CAR LST,Tree,Fn);
  106. Return Tree;
  107. END;
  108. lisp procedure GenPutTree(Elem,Node,SortFn);
  109. % Insert Elements into Tree
  110. Begin
  111. DWN: If Not Apply(SortFn,list(Elem,VAL Node)) then GOTO RGT;
  112. If LNode Node then <<Node:=LNode Node;GO TO DWN>>;
  113. NewLeftNode(Node,Elem);
  114. Return;
  115. RGT: If RNode Node then <<Node:=RNode Node;GO TO DWN>>;
  116. NewRightNode(Node,Elem);
  117. Return;
  118. END;
  119. % More General Sorting, given SortFn=PlaceToLeft(a,b);
  120. lisp procedure GSort(LST,SortFn);
  121. % Sort a LIST of elems
  122. % Build Tree then collapse;
  123. Begin
  124. CopyD('GsortFn!*,SortFn);
  125. LST:= Tree2LST(GTreeSort LST,NIL);
  126. RemD('GsortFn!*);
  127. Return LST;
  128. End;
  129. lisp procedure GTreeSort LST;
  130. % Uses insert of Element to Tree;
  131. Begin scalar Tree;
  132. If NULL LST then Return NIL;
  133. Tree:=NewNode CAR LST; % First Element
  134. While PAIRP(LST:=CDR LST) DO GPutTree(CAR LST,Tree);
  135. Return Tree;
  136. END;
  137. lisp procedure GPutTree(Elem,Node);
  138. % Insert Elements into Tree
  139. Begin
  140. DWN: If Not GSortFn!*(Elem,VAL Node) then GOTO RGT;
  141. If LNode Node then <<Node:=LNode Node;GO TO DWN>>;
  142. NewLeftNode(Node,Elem);
  143. Return;
  144. RGT: If RNode Node then <<Node:=RNode Node;GO TO DWN>>;
  145. NewRightNode(Node,Elem);
  146. Return;
  147. END;
  148. % Standard Comparison Functions:
  149. lisp procedure IdSortFn(Elem1,Elem2);
  150. % ReturnS T If Elem1 to go to right of Elem 2;
  151. IdCompare(Elem1,Elem2)>=0;
  152. lisp procedure NumberSortFn(Elem1,Elem2);
  153. Elem1 <= Elem2;
  154. lisp procedure NumberSort Lst;
  155. Gsort(Lst,'NumberSortFn);
  156. lisp procedure StringSortFn(Elem1,Elem2);
  157. StringCompare(Elem1,Elem2)>=0;
  158. lisp procedure StringSort Lst;
  159. Gsort(Lst,'StringSortFn);
  160. lisp procedure NoSortFn(Elem1,Elem2);
  161. NIL;
  162. lisp procedure AtomSortFn(E1,E2);
  163. % Ids, Numbers, then strings;
  164. If IdP E1 then
  165. If IdP E2 then IdSortFn(E1,E2)
  166. else NIL
  167. else if Numberp E1
  168. then if IdP E2 then T
  169. else if NumberP E2 then NumberSortFn (E1,E2)
  170. else NIL
  171. else if StringP(E1)
  172. then if IDP(E2) then T
  173. else if Numberp E2 then T
  174. else StringSortFn(E1,E2)
  175. else NIL;
  176. lisp procedure AtomSort Lst;
  177. Gsort(Lst,'AtomSortFn);
  178. lisp procedure StringLengthFn(S1,S2);
  179. % For string length
  180. % String Length Comparison
  181. Size(S1)<=Size(S2);
  182. procedure IdLengthFn(e1,e2);
  183. StringLengthFn(Id2string e1,Id2string e2);
  184. On syslisp;
  185. syslsp procedure SC1(S1,S2);
  186. % Returns T if S1<=S2
  187. % String Comparison
  188. Begin scalar L1,L2,I,L;
  189. S1:=Strinf s1; S2:=Strinf S2;
  190. L1:=StrLen(S1); L2:=StrLen(S2);
  191. If L1>L2 then L:=L2 else L:=L1;
  192. I:=0;
  193. loop: If I>L then return(If L1 <=L2 then T else NIL);
  194. if StrByt(S1,I) < StrByt(S2,I) then return T;
  195. if StrByt(S1,I) > StrByt(S2,I) then return NIL;
  196. I:=I+1;
  197. goto loop;
  198. End;
  199. syslsp procedure IdC1(e1,e2);
  200. Sc1(ID2String e1, ID2String e2);
  201. syslsp procedure SC2(S1,S2);
  202. % Returns T if S1<=S2
  203. % String Comparison done via packed word compare, may glitch
  204. Begin scalar L1,L2,I,L;
  205. S1:=Strinf s1; S2:=Strinf S2;
  206. L1:=Strpack StrLen(S1); L2:=strpack StrLen(S2);
  207. S1:=S1+1; S2:=S2+1;
  208. If L1>L2 then L:=L2 else L:=L1;
  209. I:=0; %/ May be off by one?
  210. loop: If I>L then return(If L1 <=L2 then T else NIL);
  211. if S1[I] < S2[I] then return T;
  212. if S1[I] > S2[I] then return NIL;
  213. I:=I+1;
  214. goto loop;
  215. End;
  216. syslsp procedure IdC2(e1,e2);
  217. Sc2(ID2String e1,ID2String e2);
  218. Off syslisp;
  219. Lisp procedure GsortP(Lst,SortFn);
  220. Begin
  221. If Not PairP Lst then return T;
  222. L: If Not PairP Cdr Lst then Return T;
  223. If Not Apply(SortFn,list(Car Lst, Cadr Lst)) then return NIL;
  224. Lst :=Cdr Lst;
  225. goto L;
  226. END;
  227. Lisp procedure GMergeLists(L1,L2,SortFn);
  228. If Not PairP L1 then L2
  229. else if Not PairP L2 then L1
  230. else if Apply(SortFn,list(Car L1, Car L2))
  231. then Car(L1) . GMergeLists(cdr L1, L2,SortFn)
  232. else car(L2) . GmergeLists(L1, cdr L2,SortFn);
  233. Lisp procedure MidPoint(Lst1,Lst2,M); % Set MidPointer List at M
  234. Begin
  235. While Not (Lst1 eq Lst2) and M>0 do
  236. <<Lst1 := cdr Lst1;
  237. M:=M-1>>;
  238. return Lst1;
  239. End;
  240. Lisp procedure GMergeSort(Lst,SortFn);
  241. GMergeSort1(Lst,NIL,Length Lst,SortFn);
  242. Lisp procedure GMergeSort1(Lst1,Lst2,M,SortFn);
  243. If M<=0 then NIL
  244. else if M =1 then if null cdr Lst1 then Lst1 else List Car lst1
  245. else if M=2 then
  246. (if Apply(SortFn,list(Car Lst1,Cadr Lst1)) then List(Car Lst1, Cadr Lst1)
  247. else List(Cadr Lst1,Car lst1))
  248. else begin scalar Mid,M1;
  249. M1:=M/2;
  250. Mid :=MidPoint(Lst1,Lst2,M1);
  251. Lst1 :=GMergeSort1(Lst1,Mid, M1,SortFn);
  252. Lst2 :=GmergeSort1(Mid,Lst2, M-M1,SortFn);
  253. Return GmergeLists(Lst1,Lst2,SortFn);
  254. end;
  255. end;