-- RandomizeWords.mesa -- Edited by Sweet, 22-Jan-81 15:48:41 DIRECTORY Ascii, IODefs, OutputDefs, Random, Segments, Storage, StreamDefs, Streams, String; RandomizeWords: PROGRAM IMPORTS IODefs, OutputDefs, Random, Segments, Storage, StreamDefs, Streams, String = BEGIN Sort: PUBLIC PROCEDURE [ a: DESCRIPTOR FOR ARRAY OF UNSPECIFIED, Greater: PROC[UNSPECIFIED, UNSPECIFIED] RETURNS [BOOLEAN]] = BEGIN n: CARDINAL = LENGTH[a]; i: CARDINAL; temp: CARDINAL; SiftUp: PROC [l, u: CARDINAL] = BEGIN s: CARDINAL; key: CARDINAL ← a[l-1]; DO s ← l*2; IF s > u THEN EXIT; IF s < u AND Greater[a[s+1-1], a[s-1]] THEN s ← s+1; IF Greater[key, a[s-1]] THEN EXIT; a[l-1] ← a[s-1]; l ← s; ENDLOOP; a[l-1] ← key; END; FOR i DECREASING IN [2..n/2] DO SiftUp[i, n]; ENDLOOP; FOR i DECREASING IN [2..n] DO SiftUp[1, i]; temp ← a[1-1]; a[1-1] ← a[i-1]; a[i-1] ← temp; ENDLOOP; END; Randomize: PROC [rand: DESCRIPTOR FOR ARRAY OF UNSPECIFIED] = BEGIN r: DESCRIPTOR FOR ARRAY OF CARDINAL; rGreater: PROC [x, y: CARDINAL] RETURNS [BOOLEAN] = {RETURN [r[x] > r[y]]}; i: CARDINAL; r ← DESCRIPTOR[Storage.Node[LENGTH[rand]], LENGTH[rand]]; FOR i IN [0..LENGTH[rand]) DO r[i] ← Random.InRange[0, 1000]; ENDLOOP; Sort[rand, rGreater]; Storage.Free[BASE[r]]; END; ReadDataFile: PROC [file: STRING, Add: PROC [STRING]] = BEGIN in: Streams.Handle ← NIL; streamEnd: BOOLEAN ← FALSE; name: STRING = [40]; number: STRING = [20]; ch: CHARACTER; GetToken: PROC [token: STRING] = BEGIN ENABLE Streams.End[] => {streamEnd ← TRUE; GO TO done}; token.length ← 0; IF streamEnd THEN RETURN; WHILE ch = Ascii.SP OR ch = Ascii.CR DO ch ← Streams.GetChar[in]; ENDLOOP; WHILE (ch IN ['A..'Z]) OR (ch IN ['a..'z]) OR (ch IN ['0..'9]) DO String.AppendChar[token, ch]; ch ← Streams.GetChar[in]; ENDLOOP; IF token.length = 0 AND ~streamEnd THEN ERROR; EXITS done => RETURN; END; BEGIN ENABLE { String.StringBoundsFault => GO TO tooLong; String.InvalidNumber => GO TO badNumber}; in ← Streams.NewStream [file, Streams.Read ! Segments.FileNameProblem[] => GO TO notFound]; ch ← Streams.GetChar[in ! Streams.End[] => GO TO badFormat]; WHILE ~streamEnd DO GetToken[name]; Add[name]; ENDLOOP; EXITS notFound => { IODefs.WriteString[file]; IODefs.WriteLine[" not found."L]}; tooLong => { IODefs.WriteString["token too long at "L]; WriteLongNumber[Streams.GetIndex[in]]}; badNumber => { IODefs.WriteString["invalid number at "L]; WriteLongNumber[Streams.GetIndex[in]]}; badFormat => { IODefs.WriteString["invalid format at "L]; WriteLongNumber[Streams.GetIndex[in]]}; END; IF in # NIL THEN Streams.Destroy[in]; END; input: DESCRIPTOR FOR ARRAY OF STRING; WriteLongNumber: PROC [ln: LONG CARDINAL] = BEGIN ls: STRING = [20]; String.AppendLongNumber[ls, ln, 10]; IODefs.WriteString[ls]; END; Driver: PROC = BEGIN OPEN IODefs, StreamDefs, OutputDefs; nS: CARDINAL ← 0; Count: PROC [s: STRING] = {nS ← nS + 1}; Insert: PROC [s: STRING] = {input[nS] ← Storage.CopyString[s]; nS ← nS + 1}; inputFile: STRING ← [40]; WriteString["Input data: "L]; ReadID[inputFile]; WriteChar[CR]; ReadDataFile[inputFile, Count]; input ← DESCRIPTOR[Storage.Node[nS], nS]; nS ← 0; ReadDataFile[inputFile, Insert]; Randomize[input]; OpenOutput[inputFile, ".rand"]; FOR i: CARDINAL IN [0..nS) DO PutString[input[i]]; PutCR[]; ENDLOOP; CloseOutput[]; Storage.FreeWords[BASE[input]]; END; Driver[]; END.