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

# Greycoat21's solution

## to All Your Base in the Delphi Pascal Track

Published at Oct 23 2019 · 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.

## About Positional Notation

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
TDigit  = Integer;
TNumber = TArray<Integer>;

TBase = class
private
class procedure ValidateArguments(
SrcBase: Integer;
Number:  TNumber;
DstBase: Integer);
public
class function Rebase(
SrcBase: Integer;
Number:  TNumber;
DstBase: Integer): TNumber;
end;

implementation

uses
SysUtils, Math;

{ TBase }

//------------------------------------------------------------------------------
class function TBase.Rebase(
SrcBase: Integer;
Number:  TNumber;
DstBase: Integer): TNumber;
var
Digit: TDigit;
Value, Multiplicand, i: Integer;
begin
ValidateArguments(SrcBase, Number, DstBase);

// Convert from SrcBase to base 10
Value := 0;
for i := Low(Number) to High(Number) do begin
Multiplicand := Trunc(Power(SrcBase, i));
Digit := Number[High(Number) - i];
Value := Value + (Digit * Multiplicand);
end;

// Convert from base 10 to DstBase
Result := [];
repeat
Digit  := Value mod DstBase;
Result := [Digit] + Result;
Value  := Value div DstBase;
until Value = 0;
end;
//------------------------------------------------------------------------------
class procedure TBase.ValidateArguments(

SrcBase: Integer;

Number: TNumber;

DstBase: Integer);

procedure ValidateBase(Base: Integer; BaseCode: string);
begin
if Base < 2 then
raise EArgumentOutOfRangeException.Create(
BaseCode + ' base must be >= 2');
end;

procedure ValidateNumber(SrcBase: Integer; Number:  TNumber);

procedure ValidateDigit(SrcBase: Integer; Digit: TDigit);
begin
if (0 > Digit) or (Digit >= SrcBase) then
raise EArgumentOutOfRangeException.Create(
'all digits must satisfy 0 <= d < input base');
end;

var
Digit: TDigit;
begin
for Digit in Number do
ValidateDigit(SrcBase, Digit);
end;

const
sSrc = 'input';
sDst = 'output';
begin
ValidateBase(SrcBase, sSrc);
ValidateBase(DstBase, sDst);
ValidateNumber(SrcBase, Number);
end;
//------------------------------------------------------------------------------
end.``````