Task: Negative base numbers





Java: import java.util.List;
import java.util.Map;
import java.util.Objects;

public class NegativeBaseNumbers {
    private static final String DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    private static String encodeNegBase(long n, int b) {
        if (b < -62 || b > -1) throw new IllegalArgumentException("Parameter b is out of bounds");
        if (n == 0) return "0";
        StringBuilder out = new StringBuilder();
        long nn = n;
        while (nn != 0) {
            int rem = (int) (nn % b);
            nn /= b;
            if (rem < 0) {
                nn++;
                rem -= b;
            }
            out.append(DIGITS.charAt(rem));
        }
        out.reverse();
        return out.toString();
    }

    private static long decodeNegBase(String ns, int b) {
        if (b < -62 || b > -1) throw new IllegalArgumentException("Parameter b is out of bounds");
        if (Objects.equals(ns, "0")) return 0;
        long total = 0;
        long bb = 1;
        for (int i = ns.length() - 1; i >= 0; i--) {
            char c = ns.charAt(i);
            total += DIGITS.indexOf(c) * bb;
            bb *= b;
        }
        return total;
    }

    public static void main(String[] args) {
        List<Map.Entry<Long, Integer>> nbl = List.of(
                Map.entry(10L, -2),
                Map.entry(146L, -3),
                Map.entry(15L, -10),
                Map.entry(-4393346L, -62)
        );
        for (Map.Entry<Long, Integer> p : nbl) {
            String ns = encodeNegBase(p.getKey(), p.getValue());
            System.out.printf("%12d encoded in base %-3d = %s\n", p.getKey(), p.getValue(), ns);
            long n = decodeNegBase(ns, p.getValue());
            System.out.printf("%12s decoded in base %-3d = %d\n\n", ns, p.getValue(), n);
        }
    }
}







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;