Собрать беспорядочный метод - PullRequest
1 голос
/ 18 марта 2019

Вчера парень по соседству, Джек, подошел, чтобы рассказать о неудачном опыте, который у него был, и подумал, могу ли я помочь ему с его проблемой.Он изучал Ruby самостоятельно (с небольшой помощью от меня) и только что получил программу для работы после нескольких дней тяжелой работы.Перед сохранением источника он случайно стер его.

К счастью, у него была распечатка.К сожалению, когда он был в школе, его младшая сестра взяла ножницы для распечатки.Вот фотография, которую Джек снял с ее рукоделия (после того, как он склеил несколько черенков вместе).

enter image description here

Джек хочет, чтобы я помог ему поставить программуВернуться вместе.Я попросил его описать проблему, над которой он работал, но он был настолько расстроен, что его ответ был полным путаницей.

Я организовал информацию из черенков следующим образом.

code = [
  ["def doit *args"],             # position fixed
  ["y = [a,c,d].reduce", :block],
  [:left, :right],
  [:left, :right],
  ["args.rotate!"],  
  ["z = yield(a,b)"],
  ["args.reverse!"],  
  ["a-2*b+7*c-3*d+30*e-2*y+6*z"], # position fixed
  ["end"],                        # position fixed
  ["doit(1,21,13,4,55)", :block]  # position fixed
]

Порядок первой строки и последних трех строк довольно очевиден, но я не знаю порядок других строк.Два выреза должны быть левой стороной задания, два - правой стороной задания, а два - блоками.

Шесть вырезов, представленных в массиве :left, :right и :blockвыше приведены в этом хэше:

pos = {
  left:  ["a,b,*_,c =", "d,e ="],
  right: ["args", "args.reverse"],
  block: ["{ |x,y| x+y }", "{ |x,y| x-y }"]  
} 

Джек сказал, что единственным другим вырезом, #=> 275, было возвращаемое значение, когда он выполнял метод, поэтому мы можем написать

rv = 275

Я подумывал попробовать разные комбинации, но это кажется безнадежной задачей.Наверняка должен быть способ каким-то образом автоматизировать восстановление кода.

Кто-нибудь может мне помочь с этим?Предложения будут в порядке, но я бы очень хотел увидеть код.

1 Ответ

2 голосов
/ 18 марта 2019

Поскольку вы настаиваете на том, что это служба написания кода, и вы хотели бы увидеть какой-то код, и у меня есть время убить, и мне нравится код, который генерирует код, и никому из нас больше не важен счет репутации,Вот моя попытка восстановить тяжелую работу маленького Джека:

# jack_gen.rb
["a,b,*_,c =", "d,e ="].permutation do |l1, l2|
  ["args", "args.reverse"].permutation do |r1, r2|
    ["{ |x,y| x+y }", "{ |x,y| x-y }"].permutation do |b1, b2|
      [
        "  y = [a,c,d].reduce #{b1}",
        "  #{l1} #{r1}",
        "  #{l2} #{r2}",
        "  args.rotate!",
        "  z = yield(a,b)",
        "  args.reverse!"
      ].permutation do |lines|
        source = [
          "def doit *args",
          *lines,
          "  a-2*b+7*c-3*d+30*e-2*y+6*z",
          "end",
          "doit(1,21,13,4,55) #{b2}"
        ].join("\n")

        rv = Object.new.instance_eval(source) rescue nil
        puts "\n#{source}\n#=> #{rv}" if rv == 275
      end
    end
  end
end

Программа создает permutation с 2 левых сторон, 2 правых сторон, 2 блоков и 6нефиксированные линии (2! × 2! × 2! × 6! = 5760 возможностей).Затем он объединяет их в исходную строку (вместе с фиксированными строками), состоящую из определения метода и вызова метода.Создается новый объект, и строка оценивается в контексте этого объекта, используя instance_eval, спасая исключения, которые могут возникнуть из-за неопределенных переменных (около 80% сгенерированных методов ошибочны).

Если результат (вызова метода) равен 275, печатается соответствующий исходный код (вместе с результатом).

Мы получаем 8 таких программ:

$ ruby jack_gen.rb

def doit *args
  args.reverse!
  a,b,*_,c = args
  args.rotate!
  d,e = args.reverse
  y = [a,c,d].reduce { |x,y| x-y }
  z = yield(a,b)
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

def doit *args
  args.reverse!
  a,b,*_,c = args
  args.rotate!
  d,e = args.reverse
  z = yield(a,b)
  y = [a,c,d].reduce { |x,y| x-y }
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

def doit *args
  args.reverse!
  a,b,*_,c = args
  args.rotate!
  z = yield(a,b)
  d,e = args.reverse
  y = [a,c,d].reduce { |x,y| x-y }
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

def doit *args
  args.reverse!
  a,b,*_,c = args
  z = yield(a,b)
  args.rotate!
  d,e = args.reverse
  y = [a,c,d].reduce { |x,y| x-y }
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

def doit *args
  args.reverse!
  a,b,*_,c = args
  args.rotate!
  d,e = args.reverse
  y = [a,c,d].reduce { |x,y| x-y }
  z = yield(a,b)
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

def doit *args
  args.reverse!
  a,b,*_,c = args
  args.rotate!
  d,e = args.reverse
  z = yield(a,b)
  y = [a,c,d].reduce { |x,y| x-y }
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

def doit *args
  args.reverse!
  a,b,*_,c = args
  args.rotate!
  z = yield(a,b)
  d,e = args.reverse
  y = [a,c,d].reduce { |x,y| x-y }
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

def doit *args
  args.reverse!
  a,b,*_,c = args
  z = yield(a,b)
  args.rotate!
  d,e = args.reverse
  y = [a,c,d].reduce { |x,y| x-y }
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275

4 из этих программ на самом деле являются дубликатами из-за #{l1} #{r1} / #{l2} #{r2} (подсказка к Register Sole ) - этого было бы достаточно, чтобы сделать правую переменную, т.е. " a,b,*_,c = #{r1}" / " d,e = #{r2}".

Остальные 4 программы отличаются только положением z = yield(a, b).Предполагая, что Джек назначает свои переменные в алфавитном порядке, мы можем выбрать ту, которая имеет z = после y =:

def doit *args
  args.reverse!
  a,b,*_,c = args
  args.rotate!
  d,e = args.reverse
  y = [a,c,d].reduce { |x,y| x-y }
  z = yield(a,b)
  a-2*b+7*c-3*d+30*e-2*y+6*z
end
doit(1,21,13,4,55) { |x,y| x+y }
#=> 275
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...