Решение на Четвърта задача от Александър Тахчиев

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

Към профила на Александър Тахчиев

Резултати

  • 3 точки от тестове
  • 1 отнета точка
  • 2 точки общо
  • 4 успешни тест(а)
  • 4 неуспешни тест(а)

Код

module Asm
def self.asm (&block)
Evaluator.new.instance_eval &block
Evaluator.class_variable_get('@@registers').values
end
def method_missing(name, *args)
name.to_s
end
def execute_instruction (where)
if (where)
original_queue = @operations_queue
method(@operations_queue[where][0]).call(*@operations_queue[where].drop(1))
else
end
end
def execute_instruction_queue (where)
original_queue = @operations_queue.dup
@operations_queue.drop(@operations_queue.keys.index(where)).
map{|i| i.drop(1).flatten}.select{|i| i.length != 1}.
each{|i| execute_instruction (where)}
@operations_queue = original_queue
end
end
class Evaluator
attr_accessor :ax, :bx, :cx, :dx
def initialize()
@@registers = {'ax' => 0, 'bx' => 0, 'cx' => 0, 'dx' => 0}
@ax, @bx ,@cx, @dx = 'ax', 'bx', 'cx', 'dx'
@operations_queue = {}
@instruction_number = 0
@last_compare = -1
@jump_key = 0
end
def mov (destination_register, source)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :mov , destination_register, source ]
if source.class == String
@@registers[destination_register] = @@registers[source]
else
@@registers[destination_register] = source
end
end
end
def inc (destination_register, value = 1)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :inc, destination_register, value ]
if value.class == String
@@registers[destination_register] += @@registers[value]
else
@@registers[destination_register] = @@registers[destination_register] + value
end
end
end
def dec (destination_register, value = 1)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :dec, destination_register, value ]
if value.class == String
@@registers[destination_register] -= @@registers[value]
else
@@registers[destination_register] = @@registers[destination_register] - value
end
end
end
def cmp (register, value)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@last_compare = @instruction_number
@operations_queue[@instruction_number] = [ :cmp, register, value ]
if value.class == String
@@registers[register] <=> @@registers[value]
else
@@registers[register] <=> value
end
end
end
def label (label_name)
label_name = label_name
@operations_queue[label_name] = @instruction_number + 1
if (@jump_key == label_name)
execute_instruction_queue(label_name)
end
end
def jmp (where)
where = where
if (where.class == String and @operations_queue[where])
@jump_key = where
execute_instruction_queue (@operations_queue[where])
elsif (where.class == Fixnum)
@jump_key = where
execute_instruction_queue (where)
else
@jump_key = where
end
end
[:==, :"!=", :>, :<, :<=, :>=].
zip([:je, :jne, :jg, :jl, :jle, :jge]).
each do |operation, name|
define_method(name) do |where|
where = where
if execute_instruction (@last_compare).send(operation, 0)
jmp(where)
else
false
end
end
end
end

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

....FFFF

Failures:

  1) Asm.asm implements CMP
     Failure/Error: je 5
     NoMethodError:
       undefined method `execute_instruction' for #<Evaluator:0xb98f8f40>
     # /tmp/d20140115-8451-52v7pg/solution.rb:118:in `block (2 levels) in <class:Evaluator>'
     # /tmp/d20140115-8451-52v7pg/spec.rb:38:in `block (3 levels) in <top (required)>'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `instance_eval'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `asm'
     # /tmp/d20140115-8451-52v7pg/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)>'

  2) Asm.asm implements JMP
     Failure/Error: jmp l1
     NameError:
       undefined local variable or method `l1' for #<Evaluator:0xb98f71b8>
     # /tmp/d20140115-8451-52v7pg/spec.rb:70:in `block (3 levels) in <top (required)>'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `instance_eval'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `asm'
     # /tmp/d20140115-8451-52v7pg/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)>'

  3) Asm.asm implements LABEL
     Failure/Error: je l1
     NameError:
       undefined local variable or method `l1' for #<Evaluator:0xb98f4850>
     # /tmp/d20140115-8451-52v7pg/spec.rb:81:in `block (3 levels) in <top (required)>'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `instance_eval'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `asm'
     # /tmp/d20140115-8451-52v7pg/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)>'

  4) Asm.asm can be used to find GCD of two numbers
     Failure/Error: label cycle
     NameError:
       undefined local variable or method `cycle' for #<Evaluator:0xb98f2f28>
     # /tmp/d20140115-8451-52v7pg/spec.rb:92:in `block (3 levels) in <top (required)>'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `instance_eval'
     # /tmp/d20140115-8451-52v7pg/solution.rb:3:in `asm'
     # /tmp/d20140115-8451-52v7pg/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.00738 seconds
8 examples, 4 failures

Failed examples:

rspec /tmp/d20140115-8451-52v7pg/spec.rb:33 # Asm.asm implements CMP
rspec /tmp/d20140115-8451-52v7pg/spec.rb:67 # Asm.asm implements JMP
rspec /tmp/d20140115-8451-52v7pg/spec.rb:77 # Asm.asm implements LABEL
rspec /tmp/d20140115-8451-52v7pg/spec.rb:88 # Asm.asm can be used to find GCD of two numbers

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

Александър обнови решението на 15.01.2014 17:25 (преди почти 11 години)

+module Asm
+ def self.asm (&block)
+ Evaluator.new.instance_eval &block
+ Evaluator.class_variable_get('@@registers').values
+ end
+
+ def method_missing(name, *args)
+ name.to_s
+ # @operations_queue[name.to_s] = @instruction_number + 1
+ end
+
+ def execute_instruction (where)
+
+ if (where)
+ original_queue = @operations_queue
+ method(@operations_queue[where][0]).call(*@operations_queue[where].drop(1))
+ else
+
+ end
+ end
+
+ def execute_instruction_queue (where)
+ original_queue = @operations_queue.dup
+ @operations_queue.drop(@operations_queue.keys.index(where)).
+ map{|i| i.drop(1).flatten}.select{|i| i.length != 1}.
+ each{|i| execute_instruction (where)}
+ @operations_queue = original_queue
+ end
+
+end
+
+class Evaluator
+
+
+ attr_accessor :ax, :bx, :cx, :dx
+ # attr_accessor :registers
+ def initialize()
+
+ @@registers = {'ax' => 0, 'bx' => 0, 'cx' => 0, 'dx' => 0}
+ @ax, @bx ,@cx, @dx = 'ax', 'bx', 'cx', 'dx'
+ @operations_queue = {}
+ @instruction_number = 0
+ @last_compare = -1
+ @jump_key = 0
+ end
+
+ def mov (destination_register, source)
+ if (@jump_key == @instruction_number)
+ @instruction_number += 1
+ @jump_key += 1
+ @operations_queue[@instruction_number] = [ :mov , destination_register, source ]
+ if source.class == String
+ @@registers[destination_register] = @@registers[source]
+ else
+ @@registers[destination_register] = source
+ end
+ end
+
+ end
+
+ def inc (destination_register, value = 1)
+ if (@jump_key == @instruction_number)
+ @instruction_number += 1
+ @jump_key += 1
+ @operations_queue[@instruction_number] = [ :inc, destination_register, value ]
+ if value.class == String
+ @@registers[destination_register] += @@registers[value]
+ else
+ @@registers[destination_register] = @@registers[destination_register] + value
+ end
+ end
+
+ end
+
+ def dec (destination_register, value = 1)
+ if (@jump_key == @instruction_number)
+ @instruction_number += 1
+ @jump_key += 1
+ @operations_queue[@instruction_number] = [ :dec, destination_register, value ]
+ if value.class == String
+ @@registers[destination_register] -= @@registers[value]
+ else
+ @@registers[destination_register] = @@registers[destination_register] - value
+ end
+ end
+ end
+
+ def cmp (register, value)
+ if (@jump_key == @instruction_number)
+ @instruction_number += 1
+ @jump_key += 1
+ @last_compare = @instruction_number
+ @operations_queue[@instruction_number] = [ :cmp, register, value ]
+ if value.class == String
+ @@registers[register] <=> @@registers[value]
+ else
+ @@registers[register] <=> value
+ end
+ end
+ end
+
+ def label (label_name)
+ label_name = label_name
+ @operations_queue[label_name] = @instruction_number + 1
+ if (@jump_key == label_name)
+ execute_instruction_queue(label_name)
+ end
+
+ end
+
+
+
+
+ def jmp (where)
+ where = where
+ if (where.class == String and @operations_queue[where])
+ @jump_key = where
+ execute_instruction_queue (@operations_queue[where])
+ elsif (where.class == Fixnum)
+ @jump_key = where
+ execute_instruction_queue (where)
+ else
+ @jump_key = where
+ end
+ end
+
+ [:==, :"!=", :>, :<, :<=, :>=].
+ zip([:je, :jne, :jg, :jl, :jle, :jge]).
+ each do |operation, name|
+ define_method(name) do |where|
+ #where = where
+ if execute_instruction (@last_compare).send(operation, 0)
+ jmp(where)
+ else
+ false
+ end
+ end
+ end
+end

Александър обнови решението на 15.01.2014 17:26 (преди почти 11 години)

module Asm
def self.asm (&block)
Evaluator.new.instance_eval &block
Evaluator.class_variable_get('@@registers').values
end
def method_missing(name, *args)
name.to_s
# @operations_queue[name.to_s] = @instruction_number + 1
end
def execute_instruction (where)
if (where)
original_queue = @operations_queue
method(@operations_queue[where][0]).call(*@operations_queue[where].drop(1))
else
end
end
def execute_instruction_queue (where)
original_queue = @operations_queue.dup
@operations_queue.drop(@operations_queue.keys.index(where)).
map{|i| i.drop(1).flatten}.select{|i| i.length != 1}.
each{|i| execute_instruction (where)}
@operations_queue = original_queue
end
end
class Evaluator
attr_accessor :ax, :bx, :cx, :dx
# attr_accessor :registers
def initialize()
@@registers = {'ax' => 0, 'bx' => 0, 'cx' => 0, 'dx' => 0}
@ax, @bx ,@cx, @dx = 'ax', 'bx', 'cx', 'dx'
@operations_queue = {}
@instruction_number = 0
@last_compare = -1
@jump_key = 0
end
def mov (destination_register, source)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :mov , destination_register, source ]
if source.class == String
@@registers[destination_register] = @@registers[source]
else
@@registers[destination_register] = source
end
end
end
def inc (destination_register, value = 1)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :inc, destination_register, value ]
if value.class == String
@@registers[destination_register] += @@registers[value]
else
@@registers[destination_register] = @@registers[destination_register] + value
end
end
end
def dec (destination_register, value = 1)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :dec, destination_register, value ]
if value.class == String
@@registers[destination_register] -= @@registers[value]
else
@@registers[destination_register] = @@registers[destination_register] - value
end
end
end
def cmp (register, value)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@last_compare = @instruction_number
@operations_queue[@instruction_number] = [ :cmp, register, value ]
if value.class == String
@@registers[register] <=> @@registers[value]
else
@@registers[register] <=> value
end
end
end
def label (label_name)
label_name = label_name
@operations_queue[label_name] = @instruction_number + 1
if (@jump_key == label_name)
execute_instruction_queue(label_name)
end
end
def jmp (where)
where = where
if (where.class == String and @operations_queue[where])
@jump_key = where
execute_instruction_queue (@operations_queue[where])
elsif (where.class == Fixnum)
@jump_key = where
execute_instruction_queue (where)
else
@jump_key = where
end
end
[:==, :"!=", :>, :<, :<=, :>=].
zip([:je, :jne, :jg, :jl, :jle, :jge]).
each do |operation, name|
define_method(name) do |where|
- #where = where
+ where = where
if execute_instruction (@last_compare).send(operation, 0)
jmp(where)
else
false
end
end
end
end

Александър обнови решението на 15.01.2014 17:28 (преди почти 11 години)

module Asm
def self.asm (&block)
Evaluator.new.instance_eval &block
Evaluator.class_variable_get('@@registers').values
end
def method_missing(name, *args)
name.to_s
- # @operations_queue[name.to_s] = @instruction_number + 1
end
def execute_instruction (where)
-
if (where)
original_queue = @operations_queue
method(@operations_queue[where][0]).call(*@operations_queue[where].drop(1))
else
-
end
end
def execute_instruction_queue (where)
original_queue = @operations_queue.dup
@operations_queue.drop(@operations_queue.keys.index(where)).
map{|i| i.drop(1).flatten}.select{|i| i.length != 1}.
each{|i| execute_instruction (where)}
@operations_queue = original_queue
end
-
end
class Evaluator
-
-
attr_accessor :ax, :bx, :cx, :dx
- # attr_accessor :registers
def initialize()
-
@@registers = {'ax' => 0, 'bx' => 0, 'cx' => 0, 'dx' => 0}
@ax, @bx ,@cx, @dx = 'ax', 'bx', 'cx', 'dx'
@operations_queue = {}
@instruction_number = 0
@last_compare = -1
@jump_key = 0
end
def mov (destination_register, source)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :mov , destination_register, source ]
if source.class == String
@@registers[destination_register] = @@registers[source]
else
@@registers[destination_register] = source
end
end
-
end
def inc (destination_register, value = 1)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :inc, destination_register, value ]
if value.class == String
@@registers[destination_register] += @@registers[value]
else
@@registers[destination_register] = @@registers[destination_register] + value
end
end
-
end
def dec (destination_register, value = 1)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@operations_queue[@instruction_number] = [ :dec, destination_register, value ]
if value.class == String
@@registers[destination_register] -= @@registers[value]
else
@@registers[destination_register] = @@registers[destination_register] - value
end
end
end
def cmp (register, value)
if (@jump_key == @instruction_number)
@instruction_number += 1
@jump_key += 1
@last_compare = @instruction_number
@operations_queue[@instruction_number] = [ :cmp, register, value ]
if value.class == String
@@registers[register] <=> @@registers[value]
else
@@registers[register] <=> value
end
end
end
def label (label_name)
label_name = label_name
@operations_queue[label_name] = @instruction_number + 1
if (@jump_key == label_name)
execute_instruction_queue(label_name)
end
-
end
-
-
-
def jmp (where)
where = where
if (where.class == String and @operations_queue[where])
@jump_key = where
execute_instruction_queue (@operations_queue[where])
elsif (where.class == Fixnum)
@jump_key = where
execute_instruction_queue (where)
else
@jump_key = where
end
end
[:==, :"!=", :>, :<, :<=, :>=].
zip([:je, :jne, :jg, :jl, :jle, :jge]).
each do |operation, name|
define_method(name) do |where|
where = where
if execute_instruction (@last_compare).send(operation, 0)
jmp(where)
else
false
end
end
end
end

Ползваш клас-променливи, което е лоша идея. Казвали сме го много пъти на лекции, включително и на последната сбирка.

Освен това, имаш проблеми с прилагането на конвенцията – слагаш интервали където не трябва, а където трябва – пропускаш. Имаш странно идентиране на места (например метода jmp), излишни скоби (пак там), празни else клаузи (ред 15), доста повторения и проблеми с дизайна.

Не трябва да има интервал преди скобата тук: execute_instruction (where). Оставял си го неконсистентно, само при някои дефиниции на методи.

Щеше да е по-удачно да ползваш символи за имената на регистрите.

Нарушенията ще ти струват наказателни точки.

Виж решенията на колегите, както и нашето (качено е в GitHub), за идеи как може да стане по-добре.