Prova 2 + 2 = 2 * 2 (e simili)


12

Produce una descrizione formale completa di tali dichiarazioni come 1+2=3, 2+2=2*(1+1)ecc.

Introuction

Se conosci l'aritmetica di Peano puoi probabilmente saltare questa sezione.

Ecco come definiamo i numeri naturali:

(Axiom 1) 0 is a number
(Axiom 2) If `x` is a number, the `S(x)`, the successor of `x`, is a number.

Quindi, ad esempio, S(S(S(0)))è un numero.

Puoi usare qualsiasi rappresentazione equivalente nel tuo codice. Ad esempio, tutti questi sono validi:

0    ""    0           ()       !
1    "#"   S(0)        (())     !'
2    "##"  S(S(0))     ((()))   !''
3    "###" S(S(S(0)))  (((()))) !'''
...
etc

Possiamo estendere le regole per definire l'addizione come segue.

(Rule 1) X+0 = X
(Rule 2) X+S(Y)=S(X)+Y

Con questo possiamo dimostrare 2 + 2 = 4 come segue

         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

Possiamo estendere queste regole per definire la moltiplicazione come segue

(Rule 3) X*0 = 0
(Rule 4) X*S(Y) = (X*Y) + X

Sebbene per consentire ciò, dobbiamo definire il ruolo strutturale delle parentesi.

(Axiom 3) If X is a number, (X) is the same number.

Gli operatori di addizione e moltiplicazione sono rigorosamente binari e le parentesi devono essere sempre esplicite. A+B+Cnon è ben definito, ma (A+B)+Ce lo A+(B+C)sono.

Esempio

Ora abbiamo abbastanza per dimostrare un teorema sulla moltiplicazione: 2 + 2 = 2 * 2

2 + 2
(2) + 2
(0 + 2) + 2
((0*2) + 2) + 2
(1*2) + 2
2*2

Requisiti

Una prova cheA=B è un elenco di espressioni tali che:

  • il primo è A,
  • l'ultimo è B, e
  • ogni espressione nella lista a parte la prima può essere ottenuta dalla precedente trasformandola in una delle regole.

Il tuo programma prenderà due espressioni valide come input , ogni espressione contiene numeri, addizioni, moltiplicazioni e parentesi come definito sopra.

Il tuo programma produrrà una prova, un elenco come sopra definito, che le due espressioni sono uguali, se tale prova esiste.

Se le due espressioni non sono uguali, il tuo programma non produrrà nulla.

Provare o confutare è sempre possibile in un numero finito di passaggi, perché ogni espressione può essere ridotta a un singolo numero e questi numeri possono essere banalmente testati per l'uguaglianza.

Se le espressioni di input non sono valide (ad esempio parentesi sbilanciate, contiene operatori non numeri o non binari), il programma dovrebbe uscire con errori, generare un'eccezione, stampare un errore o produrre in altro modo un comportamento osservabile che è distinto dal caso in cui gli input sono validi ma non uguali .

In sintesi, l'output normale per input ammissibili è un elenco di numeri uguali, inclusi gli input, che viene prodotto dalle seguenti regole.

(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.)

È consentita qualsiasi rappresentazione adeguata dei numeri in ingresso e in uscita, ad es 0=""=(). 3="###"=(((()))), Ecc. Gli spazi bianchi sono irrilevanti.

Le regole possono, ovviamente, essere applicate in entrambe le direzioni. Il tuo programma non deve produrre quale regola viene utilizzata, ma solo l'espressione prodotta dalla sua azione sull'espressione precedente.

Il codice più corto vince.


Risposte:


5

Perl, 166 + 1 byte

Esegui con -p(penalità di 1 byte).

$r='\((S*)';(@b,@a)=@a;push@a,$_ while+s/\+S/S+/||s/$r\+\)/$1/||s/$r\*\)//||s/$r\*S(S*)/(($1*$2)+$1/||s/$r\)/$1/;$\.=/[^S]./s;$_=$b[-1]eq$a[-1]?join'',@b,reverse@a:""

Più leggibile:

                           # implicito: leggi una riga di input in $ _
                           # lasciamo la nuova riga attiva
$ r = '\ ((S *)'; # usiamo molto questo frammento regex, lo fattorizziamo
(@b, @a) = @a; # imposta @b su @a, @a su vuoto
premi @a, $ _ mentre # ogni volta che fai il giro del ciclo, aggiungi $ _ a @a
+ S / \ + S / S + / || # regola 2: cambia "+ S" in "S +"
s / $ r \ + \) / $ 1 / || # regola 1: cambia "(X + 0)" in "X"
s / r $ \ * \) // || # regola 3: cambia "(X * 0)" in ""
s / $ r \ * S (S *) / (($ 1 * $ 2) + $ 1 / || # regola 4: cambia "(X * Y" in "((X * Y) + X"
s / $ r \) / $ 1 /; # regola 5: cambia "(X) in" X "
$ \ = / [^ S] ./ s.; # aggiungi un 1 al carattere di nuova riga se lo facciamo
                           # vedi eventuali non-S seguite da qualcosa
$ _ = $ B [-1] eq $ a [-1]? # se @b e @a terminano allo stesso modo
  unisci '', @ b, inverti @ a # quindi $ _ diventa @b seguito da (@a indietro)
  : "" # altrimenti vuoto $ _
                           # implicito: output $ _

Il formato di input esprime i numeri in unario come stringhe di Se richiede i due input su righe separate (ciascuna seguita da una nuova riga e un EOF dopo che entrambi sono stati visti). Ho interpretato la domanda come se le parentesi dovessero essere letteralmente ( )e l'addizione / moltiplicazione dovrebbe essere letteralmente + *; Posso salvare qualche byte con meno escape se mi è permesso fare diverse scelte.

L'algoritmo confronta effettivamente la prima riga di input con una riga vuota, la seconda con la prima, la terza con la seconda e così via. Questo soddisfa i requisiti della domanda. Ecco un esempio:

Il mio contributo:

(SS + SS)
(SS * SS)

Uscita del programma:

(SSS + S)
(SSSS +)
SSSS
SSSS
(SSSS +)
((SS +) SS +)
(((SS *) SS +) SS +)
(((SS *) S + S) SS +)
(((SS *) + SS) SS +)
((SS * S) SS +)
((SS * S) S + S)
((SS * S) + SS)

Il duplicato SSSSnel mezzo è fastidioso ma ho deciso che non violava le specifiche, ed è meno byte da lasciare.

In caso di input non valido, aggiungo 1al carattere di nuova riga, quindi 1alla fine dell'output vengono visualizzati dei randagi .


echo -e "((SS+)+(S+S))\nSS*SS" | perl -p /tmp/x.pluscite 1.
spruzzo il

Esatto, ti mancano le parentesi sulla seconda riga (che dovrebbe dire (SS*SS)). "Gli operatori di addizione e moltiplicazione sono rigorosamente binari e le parentesi devono essere sempre esplicite."
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.