Решение на Бонус задача: ArnoldC+- от Милен Дончев

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

Към профила на Милен Дончев

Резултати

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

Код

module EntryPoint
attr_accessor :variables
def its_showtime
@variables = {}
end
def you_have_been_terminated
@variables = {}
end
end
module VariableInitializer
attr_reader :current_variable
def get_to_the_chopper(variable)
@variables[variable] = nil
@current_variable = variable
end
def here_is_my_invitation(value)
@variables[@current_variable] = get_value_or_variable(value)
end
# operator +
def get_up(value)
previous = @variables[@current_variable]
@variables[@current_variable] = previous + get_value_or_variable(value)
end
# operator -
def get_down(value)
previous = @variables[@current_variable]
@variables[@current_variable] = previous - get_value_or_variable(value)
end
# operator *
def youre_fired(value)
previous = @variables[@current_variable]
@variables[@current_variable] = previous * get_value_or_variable(value)
end
# operator /
def he_had_to_split(value)
previous = @variables[@current_variable]
@variables[@current_variable] = previous / get_value_or_variable(value)
end
# operator %
def i_let_him_go(value)
previous = @variables[@current_variable]
@variables[@current_variable] = previous % get_value_or_variable(value)
end
def enough_talk
@current_variable = nil
end
end
module LogicalOperatorMethods
def i_lied
0
end
def no_problemo
1
end
def true?(value)
# everything different from 0
value != i_lied
end
# operator or
def consider_that_a_divorce(value)
# value could be variable
# that is the reason to use get_value_or_variable(value)
previous = @variables[@current_variable]
new_value = true?(previous) ? previous : get_value_or_variable(value)
@variables[@current_variable] = new_value
end
# operator and
def knock_knock(value)
# value could be variable
previous = @variables[@current_variable]
new_value = true?(previous) ? get_value_or_variable(value) : previous
@variables[@current_variable] = new_value
end
end
module ComparableOperators
# operator >
def let_off_some_steam_bennet(value)
# value could be variable
current_value = @variables[@current_variable]
@variables[@current_variable] = current_value > get_value_or_variable(value)
end
end
module FunctionDeclarations
attr_accessor :function_name
attr_accessor :parameters
attr_accessor :is_void_function
def listen_to_me_very_carefully(function_name)
@function_name = function_name
@parameters = {}
@is_void_function = true
end
def i_need_your_clothes_your_boots_and_your_motorcycle(parameter)
@parameters[parameter] = nil
end
def give_these_people_air
@is_void_function = false
end
def ill_be_back(return_value = nil)
# TODO: value could be variable
return_value.nil? ? 0 : return_value
end
def hasta_la_vista_baby
# TODO: create body for method
end
end
module ArnoldCPM
class << ArnoldCPM
include EntryPoint
include VariableInitializer
include LogicalOperatorMethods
include ComparableOperators
include FunctionDeclarations
attr_accessor :printer
def talk_to_the_hand(value)
to_print = get_value_or_variable(value)
ArnoldCPM.printer.print(to_print)
end
def get_value_or_variable(value)
# when variable -> it is symbol
# when number -> only value
@variables.key?(value) ? @variables[value] : value
end
def method_missing(name)
name
end
def totally_recall(&block)
instance_eval(&block)
end
end
end

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

Finished in 0.00091 seconds
2 examples, 1 failure
/data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/metadata.rb:200:in `flatten': can't convert Module to Array (Module#to_ary gives Symbol) (TypeError)
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/metadata.rb:200:in `full_description'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/metadata.rb:76:in `store_computed'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/metadata.rb:49:in `[]'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/metadata.rb:123:in `full_description'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/metadata.rb:76:in `store_computed'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/metadata.rb:49:in `[]'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example.rb:41:in `block (2 levels) in delegate_to_metadata'
	from /data/rails/evans-2016/releases/20161119130633/lib/language/ruby/json_formatter.rb:22:in `example_failed'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/reporter.rb:130:in `block in notify'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/reporter.rb:129:in `each'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/reporter.rb:129:in `notify'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/reporter.rb:92:in `example_failed'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example.rb:264:in `finish'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example.rb:231:in `fail_with_exception'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:523:in `block in fail_filtered_examples'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:523:in `each'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:523:in `fail_filtered_examples'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:501:in `rescue in run'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/example_group.rb:506:in `run'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:24:in `block (2 levels) in run'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:24:in `map'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:24:in `block in run'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/reporter.rb:58:in `report'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/command_line.rb:21:in `run'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/runner.rb:103:in `run'
	from /data/rails/evans-2016/shared/bundle/ruby/2.3.0/gems/rspec-core-2.99.2/lib/rspec/core/runner.rb:17:in `block in autorun'

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

Милен обнови решението на 29.12.2016 10:28 (преди почти 8 години)

+module EntryPoint
+ attr_accessor :variables
+
+ def its_showtime
+ @variables = {}
+ end
+
+ def you_have_been_terminated
+ @variables = {}
+ end
+end
+
+module VariableInitializer
+ attr_reader :current_variable
+
+ def get_to_the_chopper(variable)
+ @variables[variable] = nil
+ @current_variable = variable
+ end
+
+ def here_is_my_invitation(value)
+ @variables[@current_variable] = get_value_or_variable(value)
+ end
+
+ # operator +
+ def get_up(value)
+ previous = @variables[@current_variable]
+ @variables[@current_variable] = previous + get_value_or_variable(value)
+ end
+
+ # operator -
+ def get_down(value)
+ previous = @variables[@current_variable]
+ @variables[@current_variable] = previous - get_value_or_variable(value)
+ end
+
+ # operator *
+ def youre_fired(value)
+ previous = @variables[@current_variable]
+ @variables[@current_variable] = previous * get_value_or_variable(value)
+ end
+
+ # operator /
+ def he_had_to_split(value)
+ previous = @variables[@current_variable]
+ @variables[@current_variable] = previous / get_value_or_variable(value)
+ end
+
+ # operator %
+ def i_let_him_go(value)
+ previous = @variables[@current_variable]
+ @variables[@current_variable] = previous % get_value_or_variable(value)
+ end
+
+ def enough_talk
+ @current_variable = nil
+ end
+end
+
+module LogicalOperatorMethods
+ def i_lied
+ 0
+ end
+
+ def no_problemo
+ 1
+ end
+
+ def true?(value)
+ # everything different from 0
+ value != i_lied
+ end
+
+ # operator or
+ def consider_that_a_divorce(value)
+ # value could be variable
+ # that is the reason to use get_value_or_variable(value)
+
+ previous = @variables[@current_variable]
+ new_value = true?(previous) ? previous : get_value_or_variable(value)
+ @variables[@current_variable] = new_value
+ end
+
+ # operator and
+ def knock_knock(value)
+ # value could be variable
+
+ previous = @variables[@current_variable]
+ new_value = true?(previous) ? get_value_or_variable(value) : previous
+ @variables[@current_variable] = new_value
+ end
+end
+
+module ComparableOperators
+ # operator >
+ def let_off_some_steam_bennet(value)
+ # value could be variable
+
+ current_value = @variables[@current_variable]
+ @variables[@current_variable] = current_value > get_value_or_variable(value)
+ end
+end
+
+module FunctionDeclarations
+ attr_accessor :function_name
+ attr_accessor :parameters
+ attr_accessor :is_void_function
+
+ def listen_to_me_very_carefully(function_name)
+ @function_name = function_name
+ @parameters = {}
+ @is_void_function = true
+ end
+
+ def i_need_your_clothes_your_boots_and_your_motorcycle(parameter)
+ @parameters[parameter] = nil
+ end
+
+ def give_these_people_air
+ @is_void_function = false
+ end
+
+ def ill_be_back(return_value = nil)
+ # TODO: value could be variable
+ return_value.nil? ? 0 : return_value
+ end
+
+ def hasta_la_vista_baby
+ # TODO: create body for method
+ end
+end
+
+module ArnoldCPM
+ class << ArnoldCPM
+ include EntryPoint
+ include VariableInitializer
+ include LogicalOperatorMethods
+ include ComparableOperators
+ include FunctionDeclarations
+
+ attr_accessor :printer
+
+ def talk_to_the_hand(value)
+ to_print = get_value_or_variable(value)
+ ArnoldCPM.printer.print(to_print)
+ end
+
+ def get_value_or_variable(value)
+ # when variable -> it is symbol
+ # when number -> only value
+ @variables.key?(value) ? @variables[value] : value
+ end
+
+ def method_missing(name)
+ name
+ end
+
+ def totally_recall(&block)
+ instance_eval(&block)
+ end
+ end
+end

Лог от изпълнението при ръчна проверка:


...FFFFFFFFF.............FFFF

Failures:

  1) ArnoldCPM can define and call functions with arguments
     Failure/Error: talk_to_the_hand _n

       #<Double "printer"> received :print with unexpected arguments
         expected: (11)
              got: (:_n)
     # ./solution.rb:140:in `talk_to_the_hand'
     # ./spec.rb:478:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:475:in `block (2 levels) in <top (required)>'

  2) ArnoldCPM can define and call functions with return value
     Failure/Error: get_your_ass_to_mars _invocation_result

     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     # ./solution.rb:149:in `method_missing'
     # ./spec.rb:508:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:499:in `block (2 levels) in <top (required)>'

  3) ArnoldCPM returns 0 by default
     Failure/Error: get_your_ass_to_mars _invocation_result

     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     # ./solution.rb:149:in `method_missing'
     # ./spec.rb:532:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:525:in `block (2 levels) in <top (required)>'

  4) ArnoldCPM can take functions as arguments
     Failure/Error: talk_to_the_hand 6

       (Double "printer").print(6)
           expected: 0 times with arguments: (6)
           received: 1 time with arguments: (6)
     # ./solution.rb:140:in `talk_to_the_hand'
     # ./spec.rb:564:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:556:in `block (2 levels) in <top (required)>'

  5) ArnoldCPM can return functions
     Failure/Error: get_your_ass_to_mars _forty_two_printer

     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     # ./solution.rb:149:in `method_missing'
     # ./spec.rb:605:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:593:in `block (2 levels) in <top (required)>'

  6) ArnoldCPM defines new inner functions for each function invocation
     Failure/Error: get_your_ass_to_mars _first_invocation

     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     # ./solution.rb:149:in `method_missing'
     # ./spec.rb:635:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:625:in `block (2 levels) in <top (required)>'

  7) ArnoldCPM supports basic recursion
     Failure/Error: get_up 1

     NoMethodError:
       undefined method `+' for :_from:Symbol
     # ./solution.rb:27:in `get_up'
     # ./spec.rb:674:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:666:in `block (2 levels) in <top (required)>'

  8) ArnoldCPM can calculate fibonacci(20) recursively
     Failure/Error: let_off_some_steam_bennet _n

     ArgumentError:
       comparison of Fixnum with :_n failed
     # ./solution.rb:97:in `>'
     # ./solution.rb:97:in `let_off_some_steam_bennet'
     # ./spec.rb:720:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:714:in `block (2 levels) in <top (required)>'

  9) ArnoldCPM can use closures in very convoluted ways
     Failure/Error: get_your_ass_to_mars _result

     ArgumentError:
       wrong number of arguments (given 2, expected 1)
     # ./solution.rb:149:in `method_missing'
     # ./spec.rb:776:in `block (3 levels) in <top (required)>'
     # ./solution.rb:154:in `instance_eval'
     # ./solution.rb:154:in `totally_recall'
     # ./spec.rb:765:in `block (2 levels) in <top (required)>'

  10) ArnoldCPM has branching mechanism that can execute if statements
      Failure/Error: because_im_going_to_say_please no_problemo

      ArgumentError:
        wrong number of arguments (given 2, expected 1)
      # ./solution.rb:149:in `method_missing'
      # ./spec.rb:336:in `block (4 levels) in <top (required)>'
      # ./solution.rb:154:in `instance_eval'
      # ./solution.rb:154:in `totally_recall'
      # ./spec.rb:334:in `block (3 levels) in <top (required)>'

  11) ArnoldCPM has branching mechanism that can execute if-else statements
      Failure/Error: because_im_going_to_say_please no_problemo

      ArgumentError:
        wrong number of arguments (given 2, expected 1)
      # ./solution.rb:149:in `method_missing'
      # ./spec.rb:363:in `block (4 levels) in <top (required)>'
      # ./solution.rb:154:in `instance_eval'
      # ./solution.rb:154:in `totally_recall'
      # ./spec.rb:361:in `block (3 levels) in <top (required)>'

  12) ArnoldCPM has branching mechanism that can nest if-else statements
      Failure/Error: because_im_going_to_say_please no_problemo

      ArgumentError:
        wrong number of arguments (given 2, expected 1)
      # ./solution.rb:149:in `method_missing'
      # ./spec.rb:410:in `block (4 levels) in <top (required)>'
      # ./solution.rb:154:in `instance_eval'
      # ./solution.rb:154:in `totally_recall'
      # ./spec.rb:408:in `block (3 levels) in <top (required)>'

  13) ArnoldCPM has branching mechanism that considers functions truthy
      Failure/Error: because_im_going_to_say_please _function

      ArgumentError:
        wrong number of arguments (given 2, expected 1)
      # ./solution.rb:149:in `method_missing'
      # ./spec.rb:456:in `block (4 levels) in <top (required)>'
      # ./solution.rb:154:in `instance_eval'
      # ./solution.rb:154:in `totally_recall'
      # ./spec.rb:451:in `block (3 levels) in <top (required)>'

Finished in 0.0238 seconds (files took 0.10159 seconds to load)
29 examples, 13 failures

Failed examples:

rspec ./spec.rb:466 # ArnoldCPM can define and call functions with arguments
rspec ./spec.rb:489 # ArnoldCPM can define and call functions with return value
rspec ./spec.rb:517 # ArnoldCPM returns 0 by default
rspec ./spec.rb:540 # ArnoldCPM can take functions as arguments
rspec ./spec.rb:583 # ArnoldCPM can return functions
rspec ./spec.rb:613 # ArnoldCPM defines new inner functions for each function invocation
rspec ./spec.rb:651 # ArnoldCPM supports basic recursion
rspec ./spec.rb:695 # ArnoldCPM can calculate fibonacci(20) recursively
rspec ./spec.rb:760 # ArnoldCPM can use closures in very convoluted ways
rspec ./spec.rb:324 # ArnoldCPM has branching mechanism that can execute if statements
rspec ./spec.rb:347 # ArnoldCPM has branching mechanism that can execute if-else statements
rspec ./spec.rb:378 # ArnoldCPM has branching mechanism that can nest if-else statements
rspec ./spec.rb:441 # ArnoldCPM has branching mechanism that considers functions truthy

На пръв поглед изглежда чисто, но като цяло стратегията за отделяне на логика "събери кофа подобни методи в модул и го include-ни" единствено води до това да търсиш имплементацията на едно нещо на много места. Нещо, което може да ти подскаже, че многото неща всъщност са едно нещо, е използването на едно и също състояние - @variables. Може да погледнеш нашето решение относно как сме сметнали да разделим различните отговорности.

Самият ArnoldCPM не трябваше да пази друг контекст освен printer-a. Ако реша да пусна две програми една след друга, променливите от първата ще бъдат налични във втората.


Надявам се задачата да ти е била интересна и полезна.