Решение на Четвърта задача от Христо Аврамов

Обратно към всички решения

Към профила на Христо Аврамов

Резултати

  • 0 точки от тестове
  • 0 бонус точки
  • 0 точки общо
  • 0 успешни тест(а)
  • 8 неуспешни тест(а)

Код

module JumpInterface
def jmp where
jump_to_instruction_int where if where.is_a? Integer
jump_to_label where if where.is_a? String
end
def je where
if @last_cmp_result == 0
jmp where
else
nil
end
end
end
module JumpInterfaceHelper
def jmp where
@instructions_evaluator.operations_queue.push([@instruction_number, __method__,
[where]])
end
def je where
@instructions_evaluator.operations_queue.push([@instruction_number, __method__,
[where]])
end
end
module Asm
class InstructionsQueueCreater
include JumpInterfaceHelper
attr_accessor :instruction_number
attr_accessor :instructions_evaluator
def initialize
@instructions_evaluator = Instructions.new
@instruction_number = 0
end
def mov (destination_register, source)
@instructions_evaluator.operations_queue.push([@instruction_number, __method__,
[destination_register, source]])
@instruction_number += 1
end
def inc (destination_register, value = 1)
@instructions_evaluator.operations_queue.push([@instruction_number, __method__,
[destination_register, value]])
@instruction_number += 1
end
def dec (destination_register, value = 1)
@instructions_evaluator.operations_queue.push([@instruction_number, __method__,
[destination_register, value]])
@instruction_number += 1
end
def cmp (register, value)
@instructions_evaluator.operations_queue.push([@instruction_number, __method__,
[register, value]])
@instruction_number += 1
end
def label (label_name)
@instructions_evaluator.operations_queue.push(label_name)
end
def method_missing(name, *args, &block)
name
end
end
class Instructions
# attr_writer :ax
# attr_writer :bx
# attr_writer :cx
include JumpInterface
attr_accessor :last_cmp_result
attr_accessor :operations_queue
def initialize
@ax,@bx,@cx,@dx = 0, 0, 0, 0
@operations_queue = []
@instruction_number = 0
end
def mov (destination_register, source)
destination_register, source_value = '@'+ destination_register.to_s, 0
if source.is_a? String or source.is_a? Symbol
source_value = self.instance_variable_get('@'+source.to_s)
else
source_value = source
end
self.instance_variable_set destination_register, source_value
end
def inc (destination_register, value = 1)
destination_register, source_value = '@'+ destination_register.to_s, 1
if value.is_a? String or value.is_a? Symbol
source_value = self.instance_variable_get('@'+value.to_s)
else
source_value = value
end
destination_value = self.instance_variable_get destination_register
self.instance_variable_set destination_register , destination_value + source_value
end
def dec (destination_register, value = 1)
destination_register, source_value = '@'+ destination_register.to_s, 1
if value.is_a? String or value.is_a? Symbol
source_value = self.instance_variable_get('@'+value.to_s)
else
source_value = value
end
destination_value = self.instance_variable_get destination_register
self.instance_variable_set destination_register , destination_value - source_value
end
def cmp (register, value)
register,source_value = '@'+ register.to_s
if value.is_a? String or value.is_a? Symbol
source_value = self.instance_variable_get('@'+value.to_s)
else
source_value = value
end
register_value = self.instance_variable_get register
@last_cmp_result = register_value <=> source_value
end
def method_missing(name, *args, &block)
name
end
private
def jump_to_instruction_int(instruction_number)
instruction_place = @operations_queue.index{|x| x[0]==instruction_number}
next_first_instruction = @operations_queue
.values_at(instruction_place..@operations_queue.size-1).index{|x| x[0] == 0}
next_first_instruction = @operations_queue.size-1 if next_first_instruction.nil?
@operations_queue.values_at(instruction_place..@operations_queue.size-1)
.map{ |x| self.send(x[1],*x[2]) if (!x[1].nil? and !x[2].nil?)}
end
def jump_to_label(label_name)
instruction_place = @operations_queue.index{|x| x == label_name}
next_first_instruction = @operations_queue
.values_at(instruction_place..@operations_queue.size-1).index{|x| x[0] == 0}
next_first_instruction = @operations_queue.size-1 if next_first_instruction.nil?
@operations_queue.values_at(instruction_place+1..next_first_instruction)
.map{ |x| self.send(x[1],*x[2]) if (!x[1].nil? and !x[2].nil?) }
end
end
def self.asm(&block)
evaluator = InstructionsQueueCreater.new
evaluator.instance_eval &block
evaluator.instructions_evaluator.instance_eval &block
end
end

Лог от изпълнението

FFFFFFFF

Failures:

  1) Asm.asm works with empty programs
     Failure/Error: Asm.asm {}.should eq [0, 0, 0, 0]
       
       expected: [0, 0, 0, 0]
            got: nil
       
       (compared using ==)
     # /tmp/d20140115-8451-hmeyod/spec.rb:3:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Asm.asm implements MOV
     Failure/Error: Asm.asm do
       
       expected: [3, 4, 3, 0]
            got: 3
       
       (compared using ==)
     # /tmp/d20140115-8451-hmeyod/spec.rb:7:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Asm.asm implements INC
     Failure/Error: Asm.asm do
       
       expected: [1, 3, 3, 0]
            got: 3
       
       (compared using ==)
     # /tmp/d20140115-8451-hmeyod/spec.rb:15:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Asm.asm implements DEC
     Failure/Error: Asm.asm do
       
       expected: [2, 2, 5, 0]
            got: 5
       
       (compared using ==)
     # /tmp/d20140115-8451-hmeyod/spec.rb:23:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Asm.asm implements CMP
     Failure/Error: je 5
     ArgumentError:
       bad value for range
     # /tmp/d20140115-8451-hmeyod/solution.rb:128:in `jump_to_instruction_int'
     # /tmp/d20140115-8451-hmeyod/solution.rb:3:in `jmp'
     # /tmp/d20140115-8451-hmeyod/solution.rb:8:in `je'
     # /tmp/d20140115-8451-hmeyod/spec.rb:38:in `block (3 levels) in <top (required)>'
     # /tmp/d20140115-8451-hmeyod/solution.rb:146:in `instance_eval'
     # /tmp/d20140115-8451-hmeyod/solution.rb:146:in `asm'
     # /tmp/d20140115-8451-hmeyod/spec.rb:34:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Asm.asm implements JMP
     Failure/Error: Asm.asm do
       
       expected: [0, 0, 1, 1]
            got: 1
       
       (compared using ==)
     # /tmp/d20140115-8451-hmeyod/spec.rb:68:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Asm.asm implements LABEL
     Failure/Error: Asm.asm do
       
       expected: [1, 1, 0, 0]
            got: 1
       
       (compared using ==)
     # /tmp/d20140115-8451-hmeyod/spec.rb:78:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) Asm.asm can be used to find GCD of two numbers
     Failure/Error: Asm.asm do
       
       expected: [8, 8, 0, 0]
            got: :label
       
       (compared using ==)
     # /tmp/d20140115-8451-hmeyod/spec.rb:89:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.00806 seconds
8 examples, 8 failures

Failed examples:

rspec /tmp/d20140115-8451-hmeyod/spec.rb:2 # Asm.asm works with empty programs
rspec /tmp/d20140115-8451-hmeyod/spec.rb:6 # Asm.asm implements MOV
rspec /tmp/d20140115-8451-hmeyod/spec.rb:14 # Asm.asm implements INC
rspec /tmp/d20140115-8451-hmeyod/spec.rb:22 # Asm.asm implements DEC
rspec /tmp/d20140115-8451-hmeyod/spec.rb:33 # Asm.asm implements CMP
rspec /tmp/d20140115-8451-hmeyod/spec.rb:67 # Asm.asm implements JMP
rspec /tmp/d20140115-8451-hmeyod/spec.rb:77 # Asm.asm implements LABEL
rspec /tmp/d20140115-8451-hmeyod/spec.rb:88 # Asm.asm can be used to find GCD of two numbers

История (1 версия и 2 коментара)

Христо обнови решението на 15.01.2014 00:25 (преди почти 11 години)

+module JumpInterface
+ def jmp where
+ jump_to_instruction_int where if where.is_a? Integer
+ jump_to_label where if where.is_a? String
+ end
+ def je where
+ if @last_cmp_result == 0
+ jmp where
+ else
+ nil
+ end
+ end
+end
+module JumpInterfaceHelper
+ def jmp where
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [where]])
+ end
+ def je where
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [where]])
+ end
+end
+
+module Asm
+ class InstructionsQueueCreater
+ include JumpInterfaceHelper
+ attr_accessor :instruction_number
+ attr_accessor :instructions_evaluator
+ def initialize
+ @instructions_evaluator = Instructions.new
+ @instruction_number = 0
+ end
+ def mov (destination_register, source)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [destination_register, source]])
+ @instruction_number += 1
+ end
+
+ def inc (destination_register, value = 1)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [destination_register, value]])
+ @instruction_number += 1
+ end
+
+ def dec (destination_register, value = 1)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [destination_register, value]])
+ @instruction_number += 1
+ end
+
+ def cmp (register, value)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [register, value]])
+ @instruction_number += 1
+ end
+
+ def label (label_name)
+ @instructions_evaluator.operations_queue.push(label_name)
+ end
+ def method_missing(name, *args, &block)
+ name
+ end
+ end
+
+ class Instructions
+ # attr_writer :ax
+ # attr_writer :bx
+ # attr_writer :cx
+ include JumpInterface
+ attr_accessor :last_cmp_result
+ attr_accessor :operations_queue
+ def initialize
+ @ax,@bx,@cx,@dx = 0, 0, 0, 0
+ @operations_queue = []
+ @instruction_number = 0
+ end
+
+ def mov (destination_register, source)
+ destination_register, source_value = '@'+ destination_register.to_s, 0
+ if source.is_a? String or source.is_a? Symbol
+ source_value = self.instance_variable_get('@'+source.to_s)
+ else
+ source_value = source
+ end
+ self.instance_variable_set destination_register, source_value
+ end
+
+ def inc (destination_register, value = 1)
+ destination_register, source_value = '@'+ destination_register.to_s, 1
+ if value.is_a? String or value.is_a? Symbol
+ source_value = self.instance_variable_get('@'+value.to_s)
+ else
+ source_value = value
+ end
+ destination_value = self.instance_variable_get destination_register
+ self.instance_variable_set destination_register , destination_value + source_value
+ end
+
+ def dec (destination_register, value = 1)
+ destination_register, source_value = '@'+ destination_register.to_s, 1
+ if value.is_a? String or value.is_a? Symbol
+ source_value = self.instance_variable_get('@'+value.to_s)
+ else
+ source_value = value
+ end
+ destination_value = self.instance_variable_get destination_register
+ self.instance_variable_set destination_register , destination_value - source_value
+ end
+
+ def cmp (register, value)
+ register,source_value = '@'+ register.to_s
+ if value.is_a? String or value.is_a? Symbol
+ source_value = self.instance_variable_get('@'+value.to_s)
+ else
+ source_value = value
+ end
+ register_value = self.instance_variable_get register
+ @last_cmp_result = register_value <=> source_value
+ end
+ def method_missing(name, *args, &block)
+ name
+ end
+ private
+ def jump_to_instruction_int(instruction_number)
+ instruction_place = @operations_queue.index{|x| x[0]==instruction_number}
+ next_first_instruction = @operations_queue
+ .values_at(instruction_place..@operations_queue.size-1).index{|x| x[0] == 0}
+ next_first_instruction = @operations_queue.size-1 if next_first_instruction.nil?
+ @operations_queue.values_at(instruction_place..@operations_queue.size-1)
+ .map{ |x| self.send(x[1],*x[2]) if (!x[1].nil? and !x[2].nil?)}
+ end
+
+ def jump_to_label(label_name)
+ instruction_place = @operations_queue.index{|x| x == label_name}
+ next_first_instruction = @operations_queue
+ .values_at(instruction_place..@operations_queue.size-1).index{|x| x[0] == 0}
+ next_first_instruction = @operations_queue.size-1 if next_first_instruction.nil?
+ @operations_queue.values_at(instruction_place+1..next_first_instruction)
+ .map{ |x| self.send(x[1],*x[2]) if (!x[1].nil? and !x[2].nil?) }
+ end
+ end
+ def self.asm(&block)
+ evaluator = InstructionsQueueCreater.new
+ evaluator.instance_eval &block
+ evaluator.instructions_evaluator.instance_eval &block
+ end
+end

Whitespace-а ще ти коства поне 1 точка, ако го запазиш както е в момента. Отделно е добре JumpInterface и JumpInterfaceHelper да бъдат преместени в Asm. Няма ли да имплементираш всички jump-ове, също така?

В кода има голямо количество повторения, което ще затрудни евентуален refactoring, или промяна/добавяне на функционалност. Погледни DRY принципа и виж какво можеш да направиш по въпроса.

Нямаше кога да го направя, за съжаление съм доста зает напоследък. Иначе не виждам Whitespace ,нито на скептик нито на око.а за JumpInterface и JumpInterfaceHelper немогат да са в асм заради най-много 9те метода на клас. П.с Благодаря за фийдбека :)