Task: Negative base numbers



C#: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NegativeBaseNumbers {
    class Program {
        const string DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

        static string EncodeNegativeBase(long n, int b) {
            if (b < -62 || b > -1) {
                throw new ArgumentOutOfRangeException("b");
            }
            if (n == 0) {
                return "0";
            }
            StringBuilder output = new StringBuilder();
            long nn = n;
            while (nn != 0) {
                int rem = (int)(nn % b);
                nn /= b;
                if (rem < 0) {
                    nn++;
                    rem -= b;
                }
                output.Append(DIGITS[rem]);
            }
            return new string(output.ToString().Reverse().ToArray());
        }

        static long DecodeNegativeBase(string ns, int b) {
            if (b < -62 || b > -1) {
                throw new ArgumentOutOfRangeException("b");
            }
            if (ns == "0") {
                return 0;
            }
            long total = 0;
            long bb = 1;
            for (int i = ns.Length - 1; i >= 0; i--) {
                char c = ns[i];
                total += DIGITS.IndexOf(c) * bb;
                bb *= b;
            }
            return total;
        }

        static void Main(string[] args) {
            List<Tuple<long, int>> nbl = new List<Tuple<long, int>>() {
                new Tuple<long, int>(10,-2),
                new Tuple<long, int>(146,-3),
                new Tuple<long, int>(15,-10),
                new Tuple<long, int>(-34025238427,-62),
            };
            foreach (var p in nbl) {
                string ns = EncodeNegativeBase(p.Item1, p.Item2);
                Console.WriteLine("{0,12} encoded in base {1,-3} = {2}", p.Item1, p.Item2, ns);
                long n = DecodeNegativeBase(ns, p.Item2);
                Console.WriteLine("{0,12} decoded in base {1,-3} = {2}", ns, p.Item2, n);
                Console.WriteLine();
            }
        }
    }
}









Ada: with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

package Negative_Base_Numbers is

   subtype base_t is Long_Long_Integer range -62 .. -1;

   function Encode_Negative_Base
     (N : in Long_Long_Integer; Base : in base_t) return Unbounded_String;
   function Decode_Negative_Base
     (N : in Unbounded_String; Base : in base_t) return Long_Long_Integer;

end Negative_Base_Numbers;

with Ada.Text_IO;
package body Negative_Base_Numbers is

   Digit_Chars : constant String :=
     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

   
   
   

   function Encode_Negative_Base
     (N : in Long_Long_Integer; Base : in base_t) return Unbounded_String
   is
      procedure swap (a, b : in out Character) is
         temp : Character := a;
      begin
         a := b;
         b := temp;
      end swap;

      Result    : Unbounded_String  := Null_Unbounded_String;
      Local_N   : Long_Long_Integer := N;
      Remainder : Long_Long_Integer;

   begin
      if Local_N = 0 then
         Result := To_Unbounded_String ("0");
      else
         while Local_N /= 0 loop
            Remainder := Local_N rem Base;
            Local_N   := Local_N / Base;
            if Remainder < 0 then
               Local_N   := Local_N + 1;
               Remainder := Remainder - Base;
            end if;
            Append (Result, Digit_Chars (Integer (Remainder + 1)));
         end loop;
      end if;

      declare
         Temp_Result : String   := To_String (Result);
         Low         : Positive := Temp_Result'First;
         High        : Positive := Temp_Result'Last;
      begin
         while Low < High loop
            swap (Temp_Result (Low), Temp_Result (High));
            Low  := Low + 1;
            High := High - 1;
         end loop;
         Result := To_Unbounded_String (Temp_Result);
      end;

      return Result;
   end Encode_Negative_Base;

   
   
   

   function Decode_Negative_Base
     (N : in Unbounded_String; Base : in base_t) return Long_Long_Integer
   is
      Total : Long_Long_Integer := 0;
      bb    : Long_Long_Integer := 1;
      Temp  : String            := To_String (N);
   begin
      if Length (N) = 0 or else (Length (N) = 1 and Element (N, 1) = '0') then
         return 0;
      end if;

      for char of reverse Temp loop
         for J in Digit_Chars'Range loop
            if char = Digit_Chars (J) then
               Total := Total + Long_Long_Integer (J - 1) * bb;
               bb    := bb * Base;
            end if;
         end loop;
      end loop;

      return Total;
   end Decode_Negative_Base;

end Negative_Base_Numbers;

with Ada.Text_IO;           use Ada.Text_IO;
with Negative_Base_Numbers; use Negative_Base_Numbers;
with Ada.Strings.Fixed;     use Ada.Strings.Fixed;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Main is

   procedure driver (N : in Long_Long_Integer; B : in base_t) is
      package long_IO is new Integer_IO (Long_Long_Integer);
      use long_IO;

      ns     : Unbounded_String := Encode_Negative_Base (N, B);
      P      : Long_Long_Integer;
      Output : String (1 .. 12);

   begin
      Put (Item => N, Width => 12);
      Put (" encoded in base ");
      Put (Item => B, Width => 3);
      Put_Line (" = " & To_String (ns));

      Move
        (Source  => To_String (ns), Target => Output,
         Justify => Ada.Strings.Right);
      P := Decode_Negative_Base (ns, B);
      Put (Output & " decoded in base ");
      Put (Item => B, Width => 3);
      Put (" = ");
      Put (Item => P, Width => 1);
      New_Line (2);
   end driver;

begin
   driver (10, -2);
   driver (146, -3);
   driver (15, -10);
   driver (36_058, -62);
end Main;