RosettaCodeData/Task/Cistercian-numerals/Modula-2/cistercian-numerals.mod2
2025-08-11 18:05:26 -07:00

132 lines
3 KiB
Text

MODULE CistercianNumerals;
FROM STextIO IMPORT
WriteLn, WriteString;
FROM SWholeIO IMPORT
WriteInt;
CONST
MaxCoord = 14;
TYPE
TCanvas = ARRAY [0 .. MaxCoord], [0 .. MaxCoord] OF CHAR;
TSignVals = [-1 .. 1];
(* BEGIN. Operations on the TCanvas ADT. *)
PROCEDURE ClearCanvas(VAR Canvas: TCanvas);
VAR
I, J: CARDINAL;
BEGIN
FOR I := 0 TO MaxCoord DO
FOR J := 0 TO MaxCoord DO
Canvas[I, J] := ' '
END
END
END ClearCanvas;
PROCEDURE DrawLine(VAR Canvas: TCanvas; R0, C0: CARDINAL;
Dist: CARDINAL; DR, DC: TSignVals);
(* Draws a straight (vertical, horizontal, or diagonal) line
from Canvas[R0, C0] to Canvas[R0 + DR * Dist, C0 + DC * Dist]. *)
VAR
C, R, I: CARDINAL;
BEGIN
R := R0; C := C0;
FOR I := 0 TO Dist DO
Canvas[R, C] := '*';
R := INT(R) + DR; C := INT(C) + DC;
END
END DrawLine;
PROCEDURE ShowCanvas(VAR Canvas: TCanvas);
VAR
I, J: CARDINAL;
Row: ARRAY [0 .. MaxCoord + 1] OF CHAR;
BEGIN
FOR I := 0 TO MaxCoord DO
FOR J := 0 TO MaxCoord DO
Row[J] := Canvas[I, J]
END;
Row[MaxCoord + 1] := CHR(0);
WriteString(Row);
WriteLn
END
END ShowCanvas;
(* END Operations on the TCanvas ADT. *)
PROCEDURE DrawNumber(VAR Canvas: TCanvas; V: CARDINAL);
(* DrawDigit is part of the algorithm, so it is nested in DrawNumber. *)
TYPE
TDigits = [0 .. 9];
VAR
Thousands, Hundreds, Tens, Ones: CARDINAL;
RAxis, CAxis: CARDINAL;
PROCEDURE DrawDigit(V: TDigits; RS, CS: TSignVals);
(* RS, CS are signs of rows and cols in in relation to the axis.
They decide in which quadrant a digit is located. *)
VAR
IRS, ICS: CARDINAL;
BEGIN
IRS := INT(RS);
ICS := INT(CS);
CASE V OF
| 1: DrawLine(Canvas, RAxis + IRS * 7, CAxis + ICS, 4, 0, CS)
| 2: DrawLine(Canvas, RAxis + IRS * 3, CAxis + ICS, 4, 0, CS)
| 3: DrawLine(Canvas, RAxis + IRS * 7, CAxis + ICS, 4, -RS, CS)
| 4: DrawLine(Canvas, RAxis + IRS * 3, CAxis + ICS, 4, RS, CS)
| 5: DrawDigit(1, RS, CS); DrawDigit(4, RS, CS)
| 6: DrawLine(Canvas, RAxis + IRS * 3, CAxis + ICS * 5, 4, RS, 0)
| 7: DrawDigit(1, RS, CS); DrawDigit(6, RS, CS)
| 8: DrawDigit(2, RS, CS); DrawDigit(6, RS, CS)
| 9: DrawDigit(1, RS, CS); DrawDigit(8, RS, CS)
ELSE
END;
END DrawDigit;
BEGIN (*DrawNumber *)
RAxis := MaxCoord DIV 2;
CAxis := 5;
DrawLine(Canvas, 0, CAxis, MaxCoord, 1, 0); (* Draw 0 (or vertical axis) *)
Thousands := V DIV 1000;
V := V MOD 1000;
Hundreds := V DIV 100;
V := V MOD 100;
Tens := V DIV 10;
Ones := V MOD 10;
IF Thousands > 0 THEN
DrawDigit(Thousands, 1, -1)
END;
IF Hundreds > 0 THEN
DrawDigit(Hundreds, 1, 1)
END;
IF Tens > 0 THEN
DrawDigit(Tens, -1, -1)
END;
IF Ones > 0 THEN
DrawDigit(Ones, -1, 1)
END;
END DrawNumber;
PROCEDURE Test(N: CARDINAL);
VAR
Canvas: TCanvas;
BEGIN
WriteInt(N, 1);
WriteString(':');
WriteLn;
ClearCanvas(Canvas);
DrawNumber(Canvas, N);
ShowCanvas(Canvas);
WriteLn;
END Test;
BEGIN
Test(0);
Test(1);
Test(20);
Test(300);
Test(4000);
Test(5555);
Test(6789);
Test(9999);
END CistercianNumerals.