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