aboutsummaryrefslogtreecommitdiff
path: root/challenge-281/deadmarshal/modula-3/ch2/src/Ch2.m3
blob: a011c979ee635832ea1bae0b9031efe15fd7c0d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
MODULE Ch2 EXPORTS Main;

IMPORT SIO,Text,ASCII,Cell,CellSeq;

PROCEDURE IsInside(READONLY X,Y,N:INTEGER):BOOLEAN =
  BEGIN
    RETURN X >= 0 AND X <= N AND Y >= 0 AND Y <= N
  END IsInside;

PROCEDURE MinSteps(READONLY K1,K2,T1,T2,N:INTEGER):CARDINAL =
  VAR
    Dirs := ARRAY[0..7] OF Cell.T{
    Cell.T{-2,1},Cell.T{-1,2},
    Cell.T{1,2},Cell.T{2,1},
    Cell.T{2,-1},Cell.T{1,-2},
    Cell.T{-1,-2},Cell.T{-2,-1}};
    Q:CellSeq.T := NEW(CellSeq.T).init(NUMBER(Dirs)+1);
    Visited: REF ARRAY OF ARRAY OF BOOLEAN :=
        NEW(REF ARRAY OF ARRAY OF BOOLEAN,N+1,N+1);
    Temp:Cell.T;
    X,Y:INTEGER;
  BEGIN
    Q.addhi(Cell.T{K1,K2,0});
    WHILE Q.size() # 0 DO
      Temp := Q.remlo();
      IF Temp.X = T1 AND Temp.Y = T2 THEN RETURN Temp.D END;
      FOR I := FIRST(Dirs) TO LAST(Dirs) DO
        X := Temp.X + Dirs[I].X;
        Y := Temp.Y + Dirs[I].Y;
        IF IsInside(X,Y,N) AND NOT Visited[X,Y] THEN
          Visited[X][Y] := TRUE;
          Q.addhi(Cell.T{X,Y,Temp.D+1})
        END
      END
    END;
    RETURN LAST(INTEGER);
  END MinSteps;

PROCEDURE KnightsMoves(READONLY Start,End:TEXT):CARDINAL =
  BEGIN
    <* ASSERT Text.Length(Start) = 2 AND Text.Length(End) = 2
    AND Text.GetChar(Start,0) IN ASCII.Letters AND
    Text.GetChar(Start,1) IN ASCII.Digits AND
    Text.GetChar(End,0) IN ASCII.Letters AND
    Text.GetChar(End,1) IN ASCII.Digits *>
    RETURN MinSteps(ORD(Text.GetChar(Start,0)) - ORD('a'),
                    ORD(Text.GetChar(Start,1)) - ORD('0'),
                    ORD(Text.GetChar(End,0)) - ORD('a'),
                    ORD(Text.GetChar(End,1)) - ORD('0'),
                    8)
  END KnightsMoves;
  
BEGIN
  SIO.PutInt(KnightsMoves("g2","a8")); SIO.Nl();
  SIO.PutInt(KnightsMoves("g2","h2")); SIO.Nl()
END Ch2.