Published at Nov 04 2018
·
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**.

- 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!*

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

```
module Test.Main where
import Prelude
import Effect (Effect)
import Data.Maybe (Maybe(..))
import Test.Unit.Assert as Assert
import Test.Unit (TestSuite, suite, test)
import Test.Unit.Main (runTest)
import AllYourBase (rebase)
main :: Effect Unit
main = runTest suites
suites :: TestSuite
suites = do
suite "AllYourBase.rebase" do
test "single bit one to decimal" $
Assert.equal (Just [1])
(rebase 2 10 [1])
test "binary to single decimal" $
Assert.equal (Just [5])
(rebase 2 10 [1,0,1])
test "single decimal to binary" $
Assert.equal (Just [1,0,1])
(rebase 10 2 [5])
test "binary to multiple decimal" $
Assert.equal (Just [4,2])
(rebase 2 10 [1,0,1,0,1,0])
test "decimal to binary" $
Assert.equal (Just [1,0,1,0,1,0])
(rebase 10 2 [4,2])
test "trinary to hexadecimal" $
Assert.equal (Just [2,10])
(rebase 3 16 [1,1,2,0])
test "hexadecimal to trinary" $
Assert.equal (Just [1,1,2,0])
(rebase 16 3 [2,10])
test "15-bit integer" $
Assert.equal (Just [6,10,45])
(rebase 97 73 [3,46,60])
test "empty list" $
Assert.equal Nothing
(rebase 2 10 [])
test "single zero" $
Assert.equal Nothing
(rebase 10 2 [0])
test "multiple zeros" $
Assert.equal Nothing
(rebase 10 2 [0,0,0])
test "leading zeros" $
Assert.equal Nothing
(rebase 7 10 [0,6,0])
test "negative digit" $
Assert.equal Nothing
(rebase 2 10 [1,-1,1,0,1,0])
test "invalid positive digit" $
Assert.equal Nothing
(rebase 2 10 [1,2,1,0,1,0])
test "first base is one" $
Assert.equal Nothing
(rebase 1 10 [])
test "second base is one" $
Assert.equal Nothing
(rebase 2 1 [1,0,1,0,1,0])
test "first base is zero" $
Assert.equal Nothing
(rebase 0 10 [])
test "second base is zero" $
Assert.equal Nothing
(rebase 10 0 [7])
test "first base is negative" $
Assert.equal Nothing
(rebase (-2) 10 [1])
test "second base is negative" $
Assert.equal Nothing
(rebase 2 (-7) [1])
test "both bases are negative" $
Assert.equal Nothing
(rebase (-2) (-7) [1])
```

```
module AllYourBase
( rebase
, toNumber
) where
import Prelude
import Data.Array (any, head, mapWithIndex, reverse, snoc)
import Data.Foldable (sum)
import Data.Int (pow, quot, rem)
import Data.Maybe (Maybe(..))
rebase :: Int -> Int -> Array Int -> Maybe (Array Int)
rebase curr goal numbers
| curr <= 1 || goal <= 1 = Nothing
| numbers == [] = Nothing
| head numbers == Just 0 = Nothing
| any (_ < 0) numbers = Nothing
| any (_ >= curr) numbers = Nothing
| otherwise = pure $ fromNumber goal $ toNumber curr numbers
-- | Converts an integer value into the specific numeral system
fromNumber :: Int -> Int -> Array Int
fromNumber system number = let init = quot number system in if init == 0
then [number]
else snoc (fromNumber system init) $ rem number system
-- | Converts a numeral system pair into an integer
toNumber :: Int -> Array Int -> Int
toNumber system =
reverse >>>
mapWithIndex (\index num -> num * (pow system index)) >>>
sum
```

This exercise was very fun but not very hard once you understand the maths underneath. Converting it first to integer and then to then target system makes things a lot easier. I am sure there is a solution where you would convert the systems directly. I don't think it will be easier to build and understand though. The verification part is very annoying. Is there a better way to do this?

Level up your programming skills with 3,092 exercises across 52 languages, and insightful discussion with our volunteer team of welcoming mentors.
Exercism is
**100% free forever**.

## Community comments