RosettaCodeData/Task/Negative-base-numbers/Seed7/negative-base-numbers.seed7

72 lines
1.9 KiB
Plaintext

$ include "seed7_05.s7i";
const string: DIGITS is "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const func string: encodeNegativeBase (in var integer: number, in integer: base) is func
result
var string: encoded is "";
local
var integer: remainder is 0;
begin
if base < -62 or base > -1 then
raise RANGE_ERROR;
elsif number = 0 then
encoded := "0";
else
while number <> 0 do
remainder := number rem base;
number := number div base;
if remainder < 0 then
incr(number);
remainder -:= base;
end if;
encoded &:= DIGITS[succ(remainder)];
end while;
encoded := reverse(encoded);
end if;
end func;
const func integer: decodeNegativeBase (in string: encoded, in integer: base) is func
result
var integer: decoded is 0;
local
var integer: factor is 1;
var integer: index is 0;
var integer: digit is 0;
begin
if base < -62 or base > -1 then
raise RANGE_ERROR;
elsif encoded = "0" then
decoded := 0;
else
for index range length(encoded) downto 1 do
digit := pred(pos(DIGITS, encoded[index]));
if digit = -1 then
raise RANGE_ERROR;
else
decoded +:= digit * factor;
factor *:= base;
end if;
end for;
end if;
end func;
const proc: doCheck (in integer: number, in integer: base) is func
local
var string: encoded is "";
var integer: decoded is 0;
begin
encoded := encodeNegativeBase(number, base);
writeln(number lpad 10 <& " encoded in base " <& base lpad 3 <& " = " <& encoded);
decoded := decodeNegativeBase(encoded, base);
writeln(encoded lpad 10 <& " decoded in base " <& base lpad 3 <& " = " <& decoded);
end func;
const proc: main is func
begin
doCheck(10, -2);
doCheck(146, -3);
doCheck(15, -10);
doCheck(404355637, -62);
end func;