# Objective

• Learn the consequence of not cleaning up in the refactor phase.

# Prerequisites

• Read the article on GCD if you want to refresh your memory on reduction

• Read these articles to learn about terminating condition:

# Problem Statement

Convert a decimal integer to octal representation.

# Problem Domain Analysis

``````(891) in base 10 = ? in base 8
`````` # Solution Domain Analysis

## Step 1 ## Step 2 ## Step 3 ## Step 4 ## Step 5 ## Step 6 # Algorithm

This will use the concept of reduction to reach the terminating condition. The terminating condition is reached when the remainder becomes less than 8.

1) Find the remainder of the given number by using mod 8. This is first digit of the new base.
2) Divide the given number by 8, the reduced number becomes the new quotient.
3) The two steps are repeated until the reduced quotient becomes < 8.

Step 2 is the reduction step.

# Code

The implementation is trivial until we hit the number 8.

``````describe OctalConverter do
it 'should return 1 for 1' do
converter = OctalConverter.new(1)

expect(converter.result).to eq(1)
end

it 'should return 2 for 2' do
converter = OctalConverter.new(2)

expect(converter.result).to eq(2)
end

it 'should return 10 for 8' do
converter = OctalConverter.new(8)

expect(converter.result).to eq(10)
end
end
``````

The current implementation that fails :

``````class OctalConverter
def initialize(number)
@number = number
end

def result
if @number < 8
@number
else
remainder = @number % 8
@number = @number / 8
end
end
end
``````

This brings up a question. The converter takes a decimal number as it's argument so the what is the base of the converted number? It should be 8. How do you return a value that is octal base? Let's store the digits of the octal number in an array and return that as the result. Here is the implementation that works for the third test case:

``````class OctalConverter
def initialize(number)
@number = number
end

def result
if @number < 8
[@number]
else
remainder = @number % 8
@number = @number / 8
octal = [@number, remainder]
end
end
end

describe OctalConverter do
it 'should return 1 for 1' do
converter = OctalConverter.new(1)

expect(converter.result).to eq()
end

it 'should return 2 for 2' do
converter = OctalConverter.new(2)

expect(converter.result).to eq()
end

it 'should return 10 for 8' do
converter = OctalConverter.new(8)

expect(converter.result).to eq([1,0])
end
end
``````

The current logic works until we hit a number that needs to generate three digits for the octal number.

``````  it 'should return 137 for 95' do
converter = OctalConverter.new(95)

expect(converter.result).to eq([1,3, 7])
end
``````

The failure message is :

``````expected: [1, 3, 7]
got: [11, 7]
``````

After some print statements and thinking through the logic, here is the solution that works for the fifth test case:

``````class OctalConverter
def initialize(number)
@number = number
end

def result
octal = []
if @number < 8
octal << @number
else

if (@number % 8) == 0
remainder = @number % 8
@number = @number / 8

octal << @number
octal << remainder
end

until remainder == 0
remainder = @number % 8
@number = @number / 8
octal << remainder unless remainder == 0

octal.sort!
end
octal
end
end
end

describe OctalConverter do
it 'should return 1 for 1' do
converter = OctalConverter.new(1)

expect(converter.result).to eq()
end

it 'should return 2 for 2' do
converter = OctalConverter.new(2)

expect(converter.result).to eq()
end

it 'should return 10 for 8' do
converter = OctalConverter.new(8)

expect(converter.result).to eq([1,0])
end

it 'should return 20 for 16' do
converter = OctalConverter.new(16)

expect(converter.result).to eq([2,0])
end

it 'should return 137 for 95' do
converter = OctalConverter.new(95)

expect(converter.result).to eq([1, 3, 7])
end

end
``````

Once I got the right terminating condition, the ugliness in the solution was reduced by the following solution:

``````class OctalConverter
def initialize(number)
@number = number
end

def result
octal = []
if @number < 8
octal << @number
else

until @number == 0
remainder = @number % 8
@number = @number / 8
octal.unshift(remainder)
end

octal
end
end

end

describe OctalConverter do
it 'should return 1 for 1' do
converter = OctalConverter.new(1)

expect(converter.result).to eq()
end

it 'should return 2 for 2' do
converter = OctalConverter.new(2)

expect(converter.result).to eq()
end

it 'should return 10 for 8' do
converter = OctalConverter.new(8)

expect(converter.result).to eq([1,0])
end

it 'should return 20 for 16' do
converter = OctalConverter.new(16)

expect(converter.result).to eq([2,0])
end

it 'should return 137 for 95' do
converter = OctalConverter.new(95)

expect(converter.result).to eq([1, 3, 7])
end

it 'should return 4000 for 2048' do
converter = OctalConverter.new(2048)

expect(converter.result).to eq([4, 0, 0, 0])
end

end
``````

Surprisingly the last test (an acceptance test) also passes when it is uncommented. This is a very good example how cleaning up the code in refactoring stage allows us to handle more complicated test cases. Here is the final refactored solution:

``````class OctalConverter
def initialize(number)
@number = number
end

def result
octal = []
until finished?
digit = extract_octal_digit
reduce

octal.unshift(digit)
end

octal
end

private

def extract_octal_digit
@number % 8
end

def reduce
@number = @number / 8
end

def finished?
@number == 0
end
end
``````

# References

1. How to Solve it Using Computer by R.G. Dromney
2. Decimal to Octal Converter

# Ace the Technical Interview

• Easily find the gaps in your knowledge
• Get customized lessons based on where you are
• Take consistent action everyday
• Builtin accountability to keep you on track
• You will solve bigger problems over time
• Get the job of your dreams

#### Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.