IMPLEMENTATION MODULE TQuant;

FROM Streams IMPORT StdOut, InputStream;
FROM List IMPORT StringElement, List;
IMPORT String;
IMPORT SYSTEM;

  CLASS Tq;
  
    REDEFINE METHOD CREATE;
      VAR
        k, Seed: INTEGER;
        Arr: ARRAY OF INTEGER;
      BEGIN
      Arr.CREATE (128);
      Seed := 97;
      FOR i := 0 TO Arr.SIZE - 1 BY 1 DO
        Arr[i] := Seed;
        StdOut.WriteInt (Seed, 0);
        StdOut.WriteString (" ");
        Seed := ((Seed + 1) * 17) MOD 1024;
        END;
      StdOut.WriteLn;  
      
      StdOut.WriteInt (
        FIRST Val IN Arr :- Val > 700, 
        5);
    
      StdOut.WriteInt (
        FIRST Val IN Arr | Val MOD 10 = 0 :- Val > 700, 
        5);
        
      ASSERT NOT THERE_IS x IN Arr :- x > 1024 ;
      ASSERT THERE_IS x IN Arr     :- x = 500;
      ASSERT THERE_IS x IN Arr     :- x = 500;
      ASSERT FOR_ALL x IN Arr      :- x >= 0;
      ASSERT FOR_ALL x IN 0 TO 1024 |
        THERE_IS y IN Arr :- x = y :-
          THERE_IS Index IN 0 TO Arr.SIZE - 1 :-
            Arr[Index] = x;
        
      
      StdOut.WriteLn;  
      k := FIRST Index IN 0 TO Arr.SIZE -1 :- Arr[Index] = 500;
      ASSERT Arr[k] = 500;
      
      StdOut.WriteLn;                 
      k := FIRST Index IN 0 TO Arr.SIZE - 1 :- 
             FOR_ALL OtherIndex IN 0 TO Arr.SIZE - 1 | 
               Index <> OtherIndex :-
                   Arr[Index] > Arr[OtherIndex];
      ASSERT THERE_IS Index IN 0 TO Arr.SIZE - 1 :- Arr[Index] = Arr[k];
      StdOut.WriteString ("Second test:");         
      StdOut.WriteInt (k, 4);
      StdOut.WriteInt (Arr[k], 6);
      StdOut.WriteLn;
      END CREATE;
      
  END Tq;
  
  CLASS Tq2;
  
    REDEFINE METHOD CREATE;
      VAR
        El: StringElement;
        Arr: ARRAY OF StringElement;
        Input: InputStream;
        Index: INTEGER;
      BEGIN
      Arr.CREATE (128);
      Input.CREATE;
      Input.Open (SYSTEM.Argument(0), Input.ReadAccess);
      ASSERT Input.ErrorCode = Input.NoError;
      WHILE NOT Input.Eof AND (Index < Arr.SIZE) DO
        Arr[Index].CREATE (Input.ReadLine);
        Index := Index + 1;
        END;
      IF THERE_IS El1 IN Arr | El1 <> VOID :-
        THERE_IS El2 IN Arr | El2 <> VOID, El1 <> El2 :-
          String.Equals (El1.Get, El2.Get) THEN
        StdOut.WriteLine ("Duplicates found");
       ELSE
        StdOut.WriteLine ("No duplicates");
        END;
      El := FIRST El IN Arr | El <> VOID :-
        FOR_ALL El1 IN Arr | El1 <> VOID, El <> El1 :-
          El.Get.SIZE >= El1.Get.SIZE;
      StdOut.WriteLine ("Longest: " + El.Get);  
      El := FIRST El IN Arr | El <> VOID, El.Get.SIZE >= 10 :-
        FOR_ALL El1 IN Arr | El1 <> VOID, El1.Get.SIZE >= 10,
                             El <> El1 :-
          El.Get.SIZE <= El1.Get.SIZE;
      
      StdOut.WriteLine ("Shortest: (" + El.Get + ")");  
      END CREATE;
      
  END Tq2;
-----------------------------------------------  
  CLASS Tq3;
  
    REDEFINE METHOD CREATE;
      VAR
        El: StringElement;
        l: List(StringElement);
        l2: List(List);
        Input: InputStream;
        r, Index: INTEGER;
      BEGIN
      l.CREATE;
      Input.CREATE;
      Input.Open (SYSTEM.Argument(0), Input.ReadAccess);
      ASSERT Input.ErrorCode = Input.NoError;
      WHILE NOT Input.Eof DO
        El.CREATE(Input.ReadLine);
        l.Append (El);
        END;
        
      ASSERT FOR_ALL El IN l :- El <> VOID;
      
      IF THERE_IS El1 IN l :-
        THERE_IS El2 IN l | El1 <> El2 :-
          String.Equals (El1.Get, El2.Get) THEN
        StdOut.WriteLine ("Duplicates found");
       ELSE
        StdOut.WriteLine ("No duplicates");
        END;
      r := l.Size;  
      l2.CREATE;
      l2.Append (l);  
      l2.Append (l);  
      l2.Append (l);  
      l2.Append (l);
      ASSERT FOR_ALL AList IN l2 :- AList.Size = r;  
      END CREATE;
      
  END Tq3;
-----------------------------------------------  
  CLASS Tq4;
  
    REDEFINE METHOD CREATE;
      VAR
        El: StringElement;
        l, LNot: List(StringElement);
        l2: List(List);
        Input: InputStream;
        r, Index: INTEGER;
      BEGIN
      l.CREATE;
      Input.CREATE;
      Input.Open (SYSTEM.Argument(0), Input.ReadAccess);
      ASSERT Input.ErrorCode = Input.NoError;
      WHILE NOT Input.Eof DO
        El.CREATE(Input.ReadLine);
        l.Append (El);
        END;
        
      ASSERT FOR_ALL El IN l :- El <> VOID;
      -- FOR e IN l | e.Get.SIZE > 15  DO
      --  StdOut.WriteLine (e.Get);
      --  END;
      IF FOR_ALL e IN LNot :- FALSE THEN
        StdOut.WriteLine ("Ok");
        END;
      IF THERE_IS e IN LNot :- TRUE THEN
        StdOut.WriteLine ("Not Ok");
       ELSE 
        StdOut.WriteLine ("Ok, again");
        END;
      l.CREATE;
      FOR e IN l DO
        StdOut.WriteLine ("Problem: should not appear");
        END;
        
      StdOut.WriteLine ("1 + 3x: ");
      FOR i IN 1 TO 10 | i MOD 3 = 1 DO
        StdOut.WriteInt (i, 0);
        StdOut.WriteString (" ");
        END;
      StdOut.WriteLn;
      StdOut.WriteLn;
      StdOut.WriteLine ("Nothing ");
      FOR i IN 10 TO 1 | i MOD 3 = 1 DO
        StdOut.WriteInt (i, 0);
        StdOut.WriteString (" ");
        END;
      StdOut.WriteLn;
      StdOut.WriteLn;
      StdOut.WriteLine ("1 + 3x, reversed ");
      FOR i IN 10 TO 1 BY -1 | i MOD 3 = 1 DO
        StdOut.WriteInt (i, 0);
        StdOut.WriteString (" ");
        END;
      StdOut.WriteLn;
      StdOut.WriteLn;
      StdOut.WriteLine ("Nothing again ");
      FOR i IN 1 TO 10 BY -1 | i MOD 3 = 1 DO
        StdOut.WriteInt (i, 0);
        StdOut.WriteString (" ");
        END;
      StdOut.WriteLn;
      StdOut.WriteLn;
        
      StdOut.WriteInt (
         FIRST i IN 1 TO 10 :- i > 20,
         5);
      StdOut.WriteLine (" 0 expected");
         
      StdOut.WriteInt (
         LAST i IN 1 TO 10 :- i > 20,
         5);
      StdOut.WriteLine (" 11 expected");
      
      StdOut.WriteInt (
         FIRST i IN 10 TO 1 BY -1 :- i > 20,
         5);
      StdOut.WriteLine (" 11 expected");
      
      StdOut.WriteInt (
         LAST i IN 10 TO 1 BY -1 :- i > 20,
         5);
      StdOut.WriteLine (" 0 expected");
      
      StdOut.WriteInt (
         FIRST i IN 10 TO 1 BY -1 :- i = 5,
         5);
      StdOut.WriteLine (" 5 expected");
      
      StdOut.WriteInt (
         LAST i IN 10 TO 1 BY -1 :- i = 6,
         5);
      StdOut.WriteLine (" 6 expected");
      
      StdOut.WriteInt (
         FIRST i IN 1 TO 10 :- i = 5,
         5);
      StdOut.WriteLine (" 5 expected");
      
      StdOut.WriteInt (
         LAST i IN 1 TO 10 :- i = 6,
         5);
      StdOut.WriteLine (" 6 expected");
      
      StdOut.WriteLn;   
      END CREATE;
      
  END Tq4;
  
-----------------------------------------------  
  CLASS Tq5;
  
    REDEFINE METHOD CREATE;
      VAR
        El: StringElement;
        l, LNot: List(StringElement);
        l2: List(List);
        Input: InputStream;
        r, Index: INTEGER;
        Arr: ARRAY OF StringElement;
      BEGIN
      l.CREATE;
      Input.CREATE;
      Input.Open (SYSTEM.Argument(0), Input.ReadAccess);
      ASSERT Input.ErrorCode = Input.NoError;
      WHILE NOT Input.Eof DO
        El.CREATE(Input.ReadLine);
        l.Append (El);
        END;
      Arr := ALL El IN l :- El.Get.SIZE > 5;
      ASSERT FOR_ALL El IN Arr :- El <> VOID;
      ASSERT FOR_ALL El IN Arr :- El.Get.SIZE > 5;
      ASSERT FOR_ALL El IN l | El.Get.SIZE > 5 :-
        THERE_IS El2 IN Arr :- El = El2;
      FOR e IN Arr DO
        StdOut.WriteLine (e.Get);
        END;
      ASSERT l <> VOID;  
      Arr := ALL El IN l :- El.Get.SIZE = 9999;
      IF Arr = VOID THEN
        StdOut.WriteLine ("OK...");
       ELSE
        StdOut.WriteLine ("Problem, apparent...");
        END;
      END CREATE;
      
  END Tq5;
  
  
END TQuant;