Выведите полный формальный пух таких утверждений, как 1+2=3
, 2+2=2*(1+1)
и т. Д.
Introuction
Если вы знаете арифметику Пеано, вы можете пропустить этот раздел.
Вот как мы определяем натуральные числа:
(Axiom 1) 0 is a number
(Axiom 2) If `x` is a number, the `S(x)`, the successor of `x`, is a number.
Следовательно, например, S(S(S(0)))
число.
Вы можете использовать любое эквивалентное представление в вашем коде. Например, все они действительны:
0 "" 0 () !
1 "#" S(0) (()) !'
2 "##" S(S(0)) ((())) !''
3 "###" S(S(S(0))) (((()))) !'''
...
etc
Мы можем расширить правила, чтобы определить сложение следующим образом.
(Rule 1) X+0 = X
(Rule 2) X+S(Y)=S(X)+Y
При этом мы можем доказать 2 + 2 = 4 следующим образом
S(S(0)) + S(S(0)) = 2 + 2
[Rule 2 with X=S(S(0)), Y=S(0)]
S(S(S(0))) + S(0) = 3 + 1
[Rule 2 with X=S(S(S(0))), Y=0]
S(S(S(S(0)))) + 0 = 4 + 0
[Rule 1 with X=S(S(S(S(0))))
S(S(S(S(0)))) = 4
Мы можем расширить эти правила, чтобы определить умножение следующим образом
(Rule 3) X*0 = 0
(Rule 4) X*S(Y) = (X*Y) + X
Хотя для этого нам нужно определить структурную роль скобок.
(Axiom 3) If X is a number, (X) is the same number.
Операторы сложения и умножения строго двоичны, а круглые скобки всегда должны быть явными. A+B+C
не четко определены, но (A+B)+C
и A+(B+C)
есть.
пример
Теперь нам достаточно доказать теорему о умножении: 2 + 2 = 2 * 2
2 + 2
(2) + 2
(0 + 2) + 2
((0*2) + 2) + 2
(1*2) + 2
2*2
Требования
Доказательство того, чтоA=B
это список выражений , таких , что:
- во-первых
A
, - последний
B
и - каждое выражение в списке, кроме первого, может быть получено из предыдущего путем преобразования его по одному из правил.
Ваша программа примет два допустимых выражения в качестве входных данных , каждое выражение содержит числа, сложение, умножение и круглые скобки, как определено выше.
Ваша программа выведет доказательство, список, как определено выше, что два выражения равны, если такое доказательство существует.
Если два выражения не равны, ваша программа ничего не выведет.
Доказательство или опровержение всегда возможно за конечное число шагов, потому что каждое выражение может быть сведено к одному числу, и эти числа могут быть тривиально проверены на равенство.
Если входные выражения недопустимы (например, несбалансированные круглые скобки, содержат не числа или недвоичные операторы), тогда ваша программа должна завершиться с ошибкой, выдать исключение, вывести ошибку или иным образом произвести некоторое наблюдаемое поведение, отличное от случай, когда входные данные действительны, но не равны .
Таким образом, нормальный вывод для допустимых входных данных представляет собой список равных чисел, включая входные данные, который создается по следующим правилам.
(Axiom 1) 0 is a number
(Axiom 2) If `x` is a number, the `S(x)`, the successor of `x`, is a number.
(Axiom 3) If X is a number, (X) is the same number
(Rule 1) X+0 = X
(Rule 2) X+S(Y)=S(X)+Y
(Rule 3) X*0 = 0
(Rule 4) X*S(Y) = (X*Y) + X
(Rule 5) X = (X) (Axiom 3 expressed as a transformation rule.)
Допускается любое подходящее представление чисел на входе и выходе, например 0=""=()
, 3="###"=(((())))
и т. Д. Пробельные символы не имеют значения.
Правила могут, конечно, применяться в любом направлении. Ваша программа не должна выводить, какое правило используется, только выражение, созданное ее действием над предыдущим выражением.
Самый короткий код выигрывает.
Ответы:
Perl, 166 + 1 байт
Запустить с
-p
(штраф 1 байт).Более читабельно:
Формат ввода выражает числа в унарном виде в виде строк
S
и требует двух входных данных в отдельных строках (за каждой следует новая строка, и EOF после того, как видны оба). Я интерпретировал вопрос как требующий, чтобы круглые скобки были буквально,(
)
а сложение / умножение - буквально+
*
; Я могу сэкономить несколько байтов за счет меньшего количества экранирования, если мне будет позволено сделать другой выбор.Алгоритм фактически сравнивает первую строку ввода с пустой строкой, вторую - с первой, третью - со второй и т. Д. Это отвечает требованиям вопроса. Вот пример запуска:
Мой вклад:
Выход программы:
Дублированный
SSSS
в середине раздражает, но я решил, что это не нарушает спецификации, и меньше байтов, чтобы оставить его.При неправильном вводе я добавляю
1
символ новой строки, так что1
в конце вывода добавляются случайные числа.источник
echo -e "((SS+)+(S+S))\nSS*SS" | perl -p /tmp/x.pl
выходы1
.(SS*SS)
). «Операторы сложения и умножения строго двоичны, а круглые скобки всегда должны быть явными».