RosettaCodeData/Task/Hailstone-sequence/Modula-2/hailstone-sequence.mod2

74 lines
2.0 KiB
Plaintext

MODULE hailst;
IMPORT InOut;
CONST maxCard = MAX (CARDINAL) DIV 3;
TYPE action = (List, Count, Max);
VAR a : CARDINAL;
PROCEDURE HailStone (start : CARDINAL; type : action) : CARDINAL;
VAR n, max, count : CARDINAL;
BEGIN
count := 1;
n := start;
max := n;
LOOP
IF type = List THEN
InOut.WriteCard (n, 12);
IF count MOD 6 = 0 THEN InOut.WriteLn END
END;
IF n = 1 THEN EXIT END;
IF ODD (n) THEN
IF n < maxCard THEN
n := 3 * n + 1;
IF n > max THEN max := n END
ELSE
InOut.WriteString ("Exceeding max value for type CARDINAL at count = ");
InOut.WriteCard (count, 10);
InOut.WriteString (" for intermediate value ");
InOut.WriteCard (n, 10);
InOut.WriteString (". Aborting.");
HALT
END
ELSE
n := n DIV 2
END;
INC (count)
END;
IF type = Max THEN RETURN max ELSE RETURN count END
END HailStone;
PROCEDURE FindMax (num : CARDINAL);
VAR val, maxCount, maxVal, cnt : CARDINAL;
BEGIN
maxCount := 0;
maxVal := 0;
FOR val := 2 TO num DO
cnt := HailStone (val, Count);
IF cnt > maxCount THEN
maxVal := val;
maxCount := cnt
END
END;
InOut.WriteString ("Longest sequence below "); InOut.WriteCard (num, 1);
InOut.WriteString (" is "); InOut.WriteCard (HailStone (maxVal, Count), 1);
InOut.WriteString (" for n = "); InOut.WriteCard (maxVal, 1);
InOut.WriteString (" with an intermediate maximum of ");
InOut.WriteCard (HailStone (maxVal, Max), 1);
InOut.WriteLn
END FindMax;
BEGIN
a := HailStone (27, List);
InOut.WriteLn;
InOut.WriteString ("Iterations total = "); InOut.WriteCard (HailStone (27, Count), 12);
InOut.WriteString (" max value = "); InOut.WriteCard (HailStone (27, Max) , 12);
InOut.WriteLn;
FindMax (100000);
InOut.WriteString ("Done."); InOut.WriteLn
END hailst.