ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# Selticq's solution

## to All Your Base in the Delphi Pascal Track

Published at Feb 07 2021 · 0 comments
Instructions
Test suite
Solution

Convert a number, represented as a sequence of digits in one base, to any other base.

Implement general base conversion. Given a number in base a, represented as a sequence of digits, convert it to base b.

## Note

• Try to implement the conversion yourself. Do not use something else to perform the conversion for you.

In positional notation, a number in base b can be understood as a linear combination of powers of b.

The number 42, in base 10, means:

(4 * 10^1) + (2 * 10^0)

The number 101010, in base 2, means:

(1 * 2^5) + (0 * 2^4) + (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0)

The number 1120, in base 3, means:

(1 * 3^3) + (1 * 3^2) + (2 * 3^1) + (0 * 3^0)

I think you got the idea!

Yes. Those three numbers above are exactly the same. Congratulations!

## Testing

In order to run the tests for this track, you will need to install DUnitX. Please see the installation instructions for more information.

If Delphi is properly installed, and `*.dpr` file types have been associated with Delphi, then double clicking the supplied `*.dpr` file will start Delphi and load the exercise/project. `control + F9` is the keyboard shortcut to compile the project or pressing `F9` will compile and run the project.

Alternatively you may opt to start Delphi and load your project via. the `File` drop down menu.

### When Questions Come Up

We monitor the Pascal-Delphi support room on gitter.im to help you with any questions that might arise.

### Submitting Exercises

Note that, when trying to submit an exercise, make sure the exercise file you're submitting is in the `exercism/delphi/<exerciseName>` directory.

For example, if you're submitting `ubob.pas` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/delphi/bob/ubob.pas`.

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you may request help from a mentor.

### uAllYourBaseTests.pas

``````unit uAllYourBaseTests;

interface
uses
DUnitX.TestFramework, System.SysUtils;

const
CanonicalVersion = '2.3.0.1';

type
[TestFixture]
TAllYourBaseTest = class(TObject)
private
procedure CompareArrays(Array1, Array2: TArray<integer>);
public
[Test]
//    [Ignore('Comment the "[Ignore]" statement to run the test')]
procedure single_bit_one_to_decimal;

[Test]
[Ignore]
procedure binary_to_single_decimal;

[Test]
[Ignore]
procedure single_decimal_to_binary;

[Test]
[Ignore]
procedure binary_to_multiple_decimal;

[Test]
[Ignore]
procedure decimal_to_binary;

[Test]
[Ignore]

[Test]
[Ignore]

[Test]
[Ignore]
procedure integer_15_bit;

[Test]
[Ignore]
procedure empty_list;

[Test]
[Ignore]
procedure single_zero;

[Test]
[Ignore]
procedure multiple_zeros;

[Test]
[Ignore]

[Test]
[Ignore]
procedure input_base_is_one;

[Test]
[Ignore]
procedure input_base_is_zero;

[Test]
[Ignore]
procedure input_base_is_negative;

[Test]
[Ignore]
procedure negative_digit;

[Test]
[Ignore]
procedure invalid_positive_digit;

[Test]
[Ignore]
procedure output_base_is_one;

[Test]
[Ignore]
procedure output_base_is_zero;

[Test]
[Ignore]
procedure output_base_is_negative;

[Test]
[Ignore]
procedure both_bases_are_negative;
end;

implementation
uses uAllYourBase;

procedure TAllYourBaseTest.binary_to_multiple_decimal;
begin
CompareArrays([4, 2], TBase.Rebase(2, [1, 0, 1, 0, 1, 0], 10));
end;

procedure TAllYourBaseTest.binary_to_single_decimal;
begin
CompareArrays([5], TBase.Rebase(2, [1, 0, 1], 10));
end;

procedure TAllYourBaseTest.both_bases_are_negative;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(-2, [1], -7);
end, EArgumentOutOfRangeException, 'input base must be >= 2');
end;

procedure TAllYourBaseTest.CompareArrays(Array1, Array2: TArray<integer>);
var
i: integer;
begin
Assert.AreEqual(Length(Array1), Length(Array2), ' - Array lengths must be equal');
for i := Low(Array1) to High(Array1) do
Assert.AreEqual(Array1[i], Array2[i], format('Expecting element %d to = %d, Actual = %d',
[i, Array1[i], Array2[i]]));
end;

procedure TAllYourBaseTest.decimal_to_binary;
begin
CompareArrays([1, 0, 1, 0, 1, 0], TBase.Rebase(10, [4, 2], 2));
end;

procedure TAllYourBaseTest.empty_list;
begin
CompareArrays([0], TBase.Rebase(2, [], 10));
end;

begin
CompareArrays([1, 1, 2, 0], TBase.Rebase(16, [2, 10], 3));
end;

procedure TAllYourBaseTest.input_base_is_negative;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(-2, [1], 10);
end, EArgumentOutOfRangeException, 'input base must be >= 2');
end;

procedure TAllYourBaseTest.input_base_is_one;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(1, [0], 10);
end, EArgumentOutOfRangeException, 'input base must be >= 2');
end;

procedure TAllYourBaseTest.input_base_is_zero;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(0, [0], 10);
end, EArgumentOutOfRangeException, 'input base must be >= 2');
end;

procedure TAllYourBaseTest.integer_15_bit;
begin
CompareArrays([6, 10, 45], TBase.Rebase(97, [3, 46, 60], 73));
end;

procedure TAllYourBaseTest.invalid_positive_digit;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(2, [1, 2, 1, 0, 1, 0], 10);
end, EArgumentOutOfRangeException, 'all digits must satisfy 0 <= d < input base');
end;

begin
CompareArrays([4, 2], TBase.Rebase(7, [0, 6, 0], 10));
end;

procedure TAllYourBaseTest.multiple_zeros;
begin
CompareArrays([0], TBase.Rebase(10, [0, 0, 0], 2));
end;

procedure TAllYourBaseTest.negative_digit;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(2, [1, -1, 1, 0, 1, 0], 10);
end, EArgumentOutOfRangeException, 'all digits must satisfy 0 <= d < input base');
end;

procedure TAllYourBaseTest.output_base_is_negative;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(2, [1], -7);
end, EArgumentOutOfRangeException, 'output base must be >= 2');
end;

procedure TAllYourBaseTest.output_base_is_one;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(2, [1, 0, 1, 0, 1, 0], 1);
end, EArgumentOutOfRangeException, 'output base must be >= 2');
end;

procedure TAllYourBaseTest.output_base_is_zero;
begin
Assert.WillRaise(procedure
begin
TBase.Rebase(10, [7], 0);
end, EArgumentOutOfRangeException, 'output base must be >= 2');
end;

procedure TAllYourBaseTest.single_bit_one_to_decimal;
begin
CompareArrays([1], TBase.Rebase(2, [1], 10));
end;

procedure TAllYourBaseTest.single_decimal_to_binary;
begin
CompareArrays([1, 0, 1], TBase.Rebase(10, [5], 2));
end;

procedure TAllYourBaseTest.single_zero;
begin
CompareArrays([0], TBase.Rebase(10, [0], 2));
end;

begin
CompareArrays([2, 10], TBase.Rebase(3, [1, 1, 2, 0], 16));
end;

initialization
TDUnitX.RegisterTestFixture(TAllYourBaseTest);
end.``````
``````unit uAllYourBase;

interface

type TBase = class
public
class function Rebase(BaseIn: Integer; Values: TArray<Integer>; BaseOut: Integer): TArray<Integer>;
private
class function GetHighestPower(Base, Number: Integer): Integer;
class function GetNumber(Base: Integer; Values: TArray<Integer>): Integer;
class procedure TestArguments(BaseIn, BaseOut: Integer; Values: TArray<Integer>);
end;

implementation

uses System.Math, System.SysUtils;

class function TBase.GetHighestPower(Base, Number: Integer): Integer;
begin
Result := 0;
while Power(Base, Result) < Number do
Inc(Result);
if (Power(Base, Result) > Number) then
Dec(Result);
end;

class function TBase.GetNumber(Base: Integer; Values: TArray<Integer>): Integer;
begin
Result := 0;
for var I := Low(Values) to High(Values) do
Inc(Result, Values[I] * Round(Power(Base, High(Values) - I)));
end;

class function TBase.Rebase(BaseIn: Integer; Values: TArray<Integer>; BaseOut: Integer): TArray<Integer>;
var
Number, HighestPower: Integer;
begin
TestArguments(BaseIn, BaseOut, Values);
Number := GetNumber(BaseIn, Values);
if Number = 0 then
begin
Result := [0];
Exit;
end;
HighestPower := GetHighestPower(BaseOut, Number);
for var I := HighestPower downto 0 do
begin
SetLength(Result, Length(Result) + 1);
Result[High(Result)] := 0;
while Number >= Power(BaseOut, I) do
begin
Inc(Result[High(Result)]);
Dec(Number, Round(Power(BaseOut, I)));
end;
end;
end;

class procedure TBase.TestArguments(BaseIn, BaseOut: Integer; Values: TArray<Integer>);
begin
if (BaseIn < 2) or (BaseOut < 2) then
raise EArgumentOutOfRangeException.Create('input base must be >= 2');
for var I := Low(Values) to High(Values) do
if (Values[I] < 0) or (Values[I] >= BaseIn) then
raise EArgumentOutOfRangeException.Create('all digits must satisfy 0 <= d < input base');
end;

end.``````