Skip to content

Instantly share code, notes, and snippets.

@tomphp
Last active November 13, 2017 21:45
Show Gist options
  • Save tomphp/3d6e5ab5b5ee9db9f1f4b560e3a0b2bd to your computer and use it in GitHub Desktop.
Save tomphp/3d6e5ab5b5ee9db9f1f4b560e3a0b2bd to your computer and use it in GitHub Desktop.
RSpec.describe 'acceptance test' do
xit 'works' do
runner = CommandRunner.new(Tokenizer.new)
expect(runner.run(
'I 5 5',
'C 1',
'V 2 5 3 4',
'H 5 1 4 3',
'P 4 2 2',
'S'
)).to eq([
'11111',
'11421',
'11411',
'11411',
'33331'
])
end
end
class Tokenizer
INITIALIZE_REGEX = /^I (\d+) (\d+)$/
CLEAR_REGEX = /^C(?: (\d+))?$/
SET_PIXEL_REGEX = /^P (\d+) (\d+) (\d+)$/
VLINE_REGEX = /^V (\d+) (\d+) (\d+) (\d+)$/
SHOW = /^S$/
def tokenize(commands)
case commands
when INITIALIZE_REGEX
(width, height) = commands.match(INITIALIZE_REGEX).captures
{ type: :initialize, width: width.to_i, height: height.to_i }
when CLEAR_REGEX
colour = commands.match(CLEAR_REGEX).captures[0]
{ type: :clear, value: colour.to_i || 0 }
when SET_PIXEL_REGEX
(x, y, colour) = commands.match(SET_PIXEL_REGEX).captures
{ type: :set_pixel, x: x.to_i, y: y.to_i, colour: colour.to_i }
when VLINE_REGEX
(x, y, l, colour) = commands.match(SET_PIXEL_REGEX).captures
{ type: :vline, x: x.to_i, y: y.to_i, colour: colour.to_i }
when SHOW
{ type: :show }
end
end
end
RSpec.describe Tokenizer do
describe '#tokenize' do
it 'tokenizes initialize' do
expect(subject.tokenize('I 2 4')).to eq(type: :initialize, width: 2, height: 4)
expect(subject.tokenize('I 3 7')).to eq(type: :initialize, width: 3, height: 7)
end
it 'tokenizes clear with value' do
expect(subject.tokenize('C 11')).to eq(type: :clear, value: 11)
expect(subject.tokenize('C 101')).to eq(type: :clear, value: 101)
end
it 'tokenizes clear without value' do
expect(subject.tokenize('C')).to eq(type: :clear, value: 0)
end
it 'tokenizes set pixed' do
expect(subject.tokenize('P 5 3 9')).to eq(type: :set_pixel, x: 5, y: 3, colour: 9)
expect(subject.tokenize('P 6 4 10')).to eq(type: :set_pixel, x: 6, y: 4, colour: 10)
end
it 'tokenize show' do
expect(subject.tokenize('S')).to eq(type: :show)
end
end
end
class CommandRunner
def run(*commands)
tokenizer = Tokenizer.new
image = nil
commands.each do |cmd|
token = tokenizer.tokenize(cmd)
case token[:type]
when :initialize
image = Image.new(token[:width], token[:height])
when :clear
image.clear(token[:value])
when :set_pixel
image.set_pixel(token[:x], token[:y], token[:colour])
end
end
image.show
end
end
RSpec.describe CommandRunner do
subject { described_class.new }
let(:result) { 'rendered' }
let(:image) { spy('image', show: result) }
describe '#run' do
before do
allow(Image).to receive(:new).and_return(image)
end
it 'creates an image' do
subject.run('I 1 4')
expect(Image).to have_received(:new).with(1, 4)
end
it 'clears the image' do
subject.run('I 1 4', 'C', 'S')
expect(image).to have_received(:clear).with(0)
end
it 'clears the image with colour' do
subject.run('I 1 4', 'C 4', 'S')
expect(image).to have_received(:clear).with(4)
end
it 'sets a pixel ' do
subject.run('I 1 4', 'P 1 2 3', 'S')
expect(image).to have_received(:set_pixel).with(1, 2, 3)
end
it 'sets a different pixel ' do
subject.run('I 1 4', 'P 2 3 4', 'S')
expect(image).to have_received(:set_pixel).with(2, 3, 4)
end
it 'returns shows the image' do
expect(subject.run('I 1 4', 'S')).to eq(result)
end
end
end
class Image
def initialize(width, height)
@width = width
@height = height
@image = @height.times.map { @width.times.map { 0 } }
end
def clear(colour)
@image = @height.times.map { @width.times.map { colour } }
end
def set_pixel(x, y, colour)
@image[x-1][y-1] = colour
end
def show
@image
end
end
RSpec.describe Image do
it 'shows an empty image' do
expect(described_class.new(1, 2).show).to eq([[0], [0]])
expect(described_class.new(2, 1).show).to eq([[0, 0]])
end
context 'with 2 x 3 image' do
subject { Image.new(2, 3) }
it 'sets a pixel' do
subject.set_pixel(1, 2, 3)
expect(subject.show).to eq([
[0, 3],
[0, 0],
[0, 0]
])
end
it 'clears' do
subject.clear(5)
expect(subject.show).to eq([
[5, 5],
[5, 5],
[5, 5]
])
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment