Решение на Четвърта задача от Давид Петров

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

Към профила на Давид Петров

Резултати

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

Код

module Asm
class Evaluator
def initialize
@operations=[]
end
def method_missing(name,*args)
if args.empty?
name
else
@operations<<[name,*args]
end
end
end
class Helper
attr_accessor :ax,:bx,:cx,:dx,:flag,:current
def initialize(labels)
@ax,@bx,@cx,@dx,@flag,@current,@labels=0,0,0,0,0,0,labels
end
@flag=0
jumps={:jmp=>proc{true},:je => proc {@flag==0},:jne => proc {@flag!=0},
:jl=>proc {@flag < 0},:jle => proc {@flag<=0},
:jg=>proc {@flag>0},:jge=> proc {@flag>=0}
}
jumps.each do |name,operation|
define_method name do |argument|
g = operation.call
if g and argument.class==Symbol
@current = @labels[argument]
elsif g
@current = argument
else
@current+=1
end
end
end
def mov(from,to)
@current+=1
if to.class==Fixnum
public_send(from.to_s+"=",to)
else
public_send(from.to_s+"=",public_send(to))
end
end
def inc(destination,value=1)
@current+=1
if value.class==Fixnum
public_send(destination.to_s+"=",public_send(destination)+ value)
else
public_send(destination.to_s+"=",public_send(destination)+public_send(value))
end
end
def dec(destination,value=1)
@current+=1
if value.class==Fixnum
public_send(destination.to_s+"=",public_send(destination) - value)
else
public_send(destination.to_s+"=",public_send(destination) - public_send(value))
end
end
def cmp(register,value)
@current+=1
value = value.class==Fixnum ? value : public_send(value)
if public_send(register)==value
@flag=0
elsif public_send(register)<value
@flag=-1
else
@flag=1
end
end
end
def self.asm(&block)
a=Evaluator.new.instance_eval &block
labels={}
a.each_with_index{|x,i| labels[x[1]]=i-labels.size if x[0]==:label }
h=Helper.new(labels)
a1=a.select {|x| x[0]!=:label}
#p a1
#p [h.current]
while h.current!=a1.length do
#p "curr#{h.current}"
h.send(a1[h.current][0],*a1[h.current][1..a1[h.current].size-1])
end
[h.ax,h.bx,h.cx,h.dx]
end
end

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

F...F..F

Failures:

  1) Asm.asm works with empty programs
     Failure/Error: Asm.asm {}.should eq [0, 0, 0, 0]
     NoMethodError:
       undefined method `each_with_index' for nil:NilClass
     # /tmp/d20140115-8451-1p776ci/solution.rb:86:in `asm'
     # /tmp/d20140115-8451-1p776ci/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 CMP
     Failure/Error: Asm.asm do
       
       expected: [0, 4, 0, 1]
            got: [0, 4, 1, 1]
       
       (compared using ==)
     # /tmp/d20140115-8451-1p776ci/spec.rb:57: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 can be used to find GCD of two numbers
     Failure/Error: Asm.asm do
       
       expected: [8, 8, 0, 0]
            got: [40, 32, 0, 0]
       
       (compared using ==)
     # /tmp/d20140115-8451-1p776ci/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.008 seconds
8 examples, 3 failures

Failed examples:

rspec /tmp/d20140115-8451-1p776ci/spec.rb:2 # Asm.asm works with empty programs
rspec /tmp/d20140115-8451-1p776ci/spec.rb:33 # Asm.asm implements CMP
rspec /tmp/d20140115-8451-1p776ci/spec.rb:88 # Asm.asm can be used to find GCD of two numbers

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

Давид обнови решението на 15.01.2014 17:28 (преди почти 11 години)

+module Asm
+ class Evaluator
+ def initialize
+ @operations=[]
+ end
+
+ def method_missing(name,*args)
+ if args.empty?
+ name
+ else
+ @operations<<[name,*args]
+ end
+ end
+ end
+ class Helper
+ attr_accessor :ax,:bx,:cx,:dx,:flag,:current
+ def initialize(labels)
+ @ax,@bx,@cx,@dx,@flag,@current,@labels=0,0,0,0,0,0,labels
+ end
+ @flag=0
+ jumps={:jmp=>proc{true},:je => proc {@flag==0},:jne => proc {@flag!=0},
+ :jl=>proc {@flag < 0},:jle => proc {@flag<=0},
+ :jg=>proc {@flag>0},:jge=> proc {@flag>=0}
+ }
+
+
+ jumps.each do |name,operation|
+ define_method name do |argument|
+ g = operation.call
+ if g and argument.class==Symbol
+ @current = @labels[argument]
+ elsif g
+ @current = argument
+ else
+ @current+=1
+ end
+ end
+ end
+
+ def mov(from,to)
+ @current+=1
+ if to.class==Fixnum
+ public_send(from.to_s+"=",to)
+ else
+ public_send(from.to_s+"=",public_send(to))
+ end
+ end
+
+ def inc(destination,value=1)
+ @current+=1
+ if value.class==Fixnum
+ public_send(destination.to_s+"=",public_send(destination)+ value)
+ else
+ public_send(destination.to_s+"=",public_send(destination)+public_send(value))
+ end
+ end
+
+ def dec(destination,value=1)
+ @current+=1
+ if value.class==Fixnum
+ public_send(destination.to_s+"=",public_send(destination) - value)
+ else
+ public_send(destination.to_s+"=",public_send(destination) - public_send(value))
+ end
+ end
+
+ def cmp(register,value)
+ @current+=1
+ value = value.class==Fixnum ? value : public_send(value)
+ if public_send(register)==value
+ @flag=0
+ elsif public_send(register)<value
+ @flag=-1
+ else
+ @flag=1
+ end
+ end
+
+
+ end
+
+
+ def self.asm(&block)
+ a=Evaluator.new.instance_eval &block
+ labels={}
+ a.each_with_index{|x,i| labels[x[1]]=i-labels.size if x[0]==:label }
+ h=Helper.new(labels)
+ a1=a.select {|x| x[0]!=:label}
+ #p a1
+ #p [h.current]
+ while h.current!=a1.length do
+ #p "curr#{h.current}"
+ h.send(a1[h.current][0],*a1[h.current][1..a1[h.current].size-1])
+ end
+ [h.ax,h.bx,h.cx,h.dx]
+ end
+end

Имаш множество нарушения на конвенциите за стил – изпуснати интервали, лошо именувани променливи, лош стил, много повторения, странна подредба на кода на места, лош дизайн. Това ще ти струва наказателни точки.

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

Може би си бил прав, все пак хващаш две точки :)

Оставяйки настрана темата за предаването на домашни в последния момент, спазавнето на конвенциите е нещо, което трябва да стане втора природа и навик, тоест, кодът, който продуцираш, да спазва конвенциите изначало, а не да трябва да минаваш впоследствие и да си оправяш нещата така, че да спазват някакви правила. Същото важи и за писането на чист, ясен и качествен код – стремиш се да го превърнеш в своя природа, а не да кръщаваш променливи "tmp", "a", "a1", "h" и прочее и после да минаваш и да ги оправяш. Това трявба да ти е целта. Навик не се създава много лесно, но ще е една от най-ценните ти придобивки.

Затова, старай се да си налагаш определени правила и ограничения дори когато единственият, пред когото отговаряш, си ти самият :)