Classic Proof Fallacy [chiuso]


18

Lo sfondo

Quindi, conosciamo tutti la prova classica che va così:

a = b
a² = ab
a² - b² = ab - b²
(ab) (a + b) = b (ab)
(a + b) = b
b + b = b
2b = b
2 = 1 (Ah ah!)
Di naturalmente, l'errore è che non puoi dividere per 0. Dato che a = b, a - b = 0, quindi c'era una divisione nascosta per 0.

La sfida

Devi replicare questa prova. Prima di tutto, dichiara due numeri interi aeb (non importa come li chiami) uguale. Quindi dichiarare aMod e bMod come versioni modificabili di a e b e inizialmente pari a a e b, rispettivamente. Devi moltiplicarli entrambi per a, quindi sottrarre b * b da entrambi. È quindi necessario dividere per a - b e quindi dividerli per b (o a) per ottenere. Quindi, stampa aMod e bMod con un segno uguale tra loro.

The Underhanded

Naturalmente, poiché hai dichiarato aeb uguale, a - b = 0 e la divisione per 0 provoca un errore. Quindi devi falsificarlo in modo creativo. Inoltre, poiché si sta tentando di replicare la prova, il risultato di tutte le operazioni su aMod e bMod non deve essere uguale quando viene stampato. Non devono eguagliare esattamente 2 e 1, solo due numeri che non sono uguali.

Ecco un esempio:

#include <iostream>
#define subtract(a, b) a - b

using namespace std;
int main()
{
    int a = 4, b = 4;
    int a_2 = a, b_2 = b;

    a_2 *= a;
    b_2 *= b;

    a_2 -= b * b;
    b_2 -= b * b;

    a_2 = a_2 / subtract(a, b);
    b_2 = b_2 / subtract(-b, -a); // a - b == (-b) - (-a)

    a_2 /= a;
    b_2 /= a;

    cout << a_2 << " = " << b_2 << " because I did the same operations on both of them.";

    return 0;
}

Forse non il migliore, ma illustra il punto.

Bonus Underhanded

Invece di stampare il segno di uguale, puoi stampare solo le due variabili (aMod e bMod) e quindi avere un codice che sembra confrontare le due variabili per uguaglianza ma in realtà risiede che sono uguali (e stampa una forma di true ).

Ricorda, questo è un concorso di popolarità, quindi vince il maggior numero di voti.
Inoltre, una nuova versione della matematica chiamata Mathematics 2.0 ha fatto uso di scappatoie standard invalidando automaticamente una prova.


Ecco un link Wikipedia

3
Sto votando per chiudere questa domanda come fuori tema perché le sfide subdole non sono più in argomento su questo sito. meta.codegolf.stackexchange.com/a/8326/20469
cat

Risposte:


17

JavaScript

var a=3,b=3,a2=3,b2=3
[a2,b2]=[a2*a,b2*a]
[a2,b2]=[a2-b*b,b2-b*b]
[a2,b2]=[a2/(a-b),b2/(a-b)]
console.log([a2/a,b2/a])

Produzione:

[1, NaN]

Si noti che 0/0 = NaN

Suggerimento

Prova ad aggiungere alcuni punti e virgola.
Questo programma è in realtà var a=3,b=3,a2=3,b2=3[a2,b2]=...=[a2/(a-b),b2/(a-b)];console.log([a2/a,b2/a]).
E la NaN lo è [3/0,undefined/0]/3.


Wow. È stato molto intelligente, dimenticando "per sbaglio" di aggiungere punti e virgola rendendo (quasi) l'intero programma una frase di esecuzione.
user155698

3

Python 2

Sono abbastanza sicuro che sia ovvio poiché tutti conoscono Python, ma ecco il mio tentativo:

a=b=1
x,y=a*a,a*b
x,y=x-b*b,y-b*b
x,y=a+b/a-b,b
x,y=x/a,y/a
print(x==y)

Emette True .

Suggerimento:

Controlla la mia divisione.


poiché tutti usano Python . Conosco Python, ma lo uso raramente
rpax il

@rpax Questo è ciò che intendevo.
mbomb007,

Spiacenti, non ho letto correttamente la tua risposta.
rpax,

2

Rubino

def calculate a,
  b = a
  left, right = a, b
  left, right = [left, right].map { |x| x * a     }
  left, right = [left, right].map { |x| x - b*b   }
  left, right = [left, right].map { |x| x / a - b }
  left, right = [left, right].map { |x| x / b     }
  puts $/=[left, right].join(' = ')
end

calculate 3,
STDOUT.write($/)

Ideone

Suggerimento:

,

Spiegazione:

Le due righe che finiscono in virgole fanno sì che il programma si comporti in modo diverso rispetto a quanto farebbe. Senza le virgole, il metodo accetta un singolo argomento a, imposta buguale a a, esegue le trasformazioni dalla prova su ognuna (tranne per alcune parentesi mancanti, non si divide per 0) e genera il risultato (Con input di 3 , genererebbe "-1 = -1". Con la virgola finale, tuttavia, la b = alinea diventa parte della firma del metodo, il che significa che sta dichiarando un secondo argomento con un valore predefinito. L'invocazione del metodo alla fine passa nel risultato di STDOUT.write($/), che è 1 (il numero di byte che ha scritto su STDOUT, poiché $/è predefinito a un carattere di nuova riga.) Quindi a è 3 e b è 1, con il risultato che l'equazione inizia come "3 = 1". Garbage in, spazzatura fuori.


Bel trucco lì con le tue nuove linee.
LegionMammal978,

Potresti aggiungere una spiegazione per i non rubyisti?
kirbyfan64sos,

@ kirbyfan64sos Certo, fatto.
istocrato

2

GolfScript

Attenzione: questo programma tradisce un po ', in quanto non stampa aMod e bMod

1nt main(){
  int a = 2, b = 2;
  int aMod,bMod;
//The next line should throw and error, but why doesn't it??/
  aMod = (a*a - b*b) / (a-b);
//The next line should throw and error, but why doesn't it??/
  bMod = (b*a - b*b) / (a-b);
//The if should fail, but it works??/
  if(aMod == bMod)
    printf("1");
  return 0;
};

Provalo qui !

Quindi cosa sta succedendo?

La prima cosa che potresti aver notato sono le "trigrafi proibite". Ma ricorda, questo è GolfScript, non C! Inoltre, probabilmente notato che in realtà non dice "int main ()", dice "1nt main ()". In GolfScript, "1" significa spingere 1 nello stack e "nt main" viene elaborato come due variabili non inizializzate, che non fanno nulla. Le due parentesi prima aggiungono 1 al numero più alto della pila, quindi sottraggono una, essenzialmente annullandosi. Le parentesi indicano un blocco che viene inserito nello stack, quindi il punto e virgola lo rimuove immediatamente. Quindi, alla fine, abbiamo solo l'originale "1" che è stato inserito, e alla fine di un programma GolfScript, lo stack viene stampato. Questa risposta è stata ispirata da questa .


Trigrafi rilevati. Attivazione del sistema -1 automatico. Errore: -1 non riuscito (4792, RPLS)
CalculatorFeline

Questo è subdolo, perché ti inganna pensando di non averti ingannato. +1
Rɪᴋᴇʀ

1

Prolog

areEqual(A, B) :-
    Amod = A,
    Bmod = B,

    Amod = Amod * A,
    Bmod = Bmod * B,

    Amod = Amod - B*B,
    Bmod = Bmod - B*B,

    Amod = Amod / (A-B),
    Bmod = Bmod / (A-B),

    Amod = Amod / A,
    Bmod = Bmod / A,

    Amod == Bmod.

L'output quando areEqual(4,4)viene chiamato (o qualsiasi altra coppia di numeri in realtà):

false

Perché?

In Prolog, l'operatore "=" non è affetto; è "Unificazione". Pertanto Amod = Amod * Afallisce perché Amodè già stato unificato Ae quindi non può essere unificato Amod * A. Prolog quindi interrompe immediatamente l'esecuzione della regola corrente e ritorna false.


2
Penso che dovrebbe essere il contrario, devi produrre "vero" quando i due valori sono diversi, non "falso" quando sono uguali ^^ '
Katenkyo,

1

JavaScript

//Very badly written code!
//No! It is "poetic" code!
while(true){break;}{ 
let scrollMaxX = 3, screenX = 3;
var scrollBarWithBeerMax = scrollMaxX, Yscroll = screenX; for(var i = 0; i<1; i++){}}

scrollBarWithBeerMax *= scrollMaxX;
Yscroll *= screenX;

scrollBarWithBeerMax -= screenX * screenX;
Yscroll -= screenX * screenX;

scrollBarWithBeerMax /= (scrollMaxX - screenX);
Yscroll /= (scrollMaxX - screenX);

alert(scrollBarWithBeerMax + ' = ' + Yscroll);

Uscita: http://jsbin.com/furino/2/edit?js, output
JsBin non sembra essere in grado di eseguire questo codice. Utilizzare invece la console del browser.

Perché?

scrollMaxX e screenX sono già variabili esistenti. Sono integrati nel browser. Pertanto, il risultato può variare. La parola chiave let modifica solo temporaneamente il loro valore.

Un altro JavaScript: non segue esattamente le regole, emette solo se le variabili sono uguali o meno.

var a = 2;
var b = 2;

var a_duplicate = a;
var b_duplicate = b;

a_duplicate*=a
b_duplicate*=b;

a_duplicate-=b*b;
b_duplicate-=b*b;

a_duplicate/=(a-b);
b_duplicate/=(a-b);

alert(a_duplicate==b_duplicate);

Perché?

NaN non è uguale a NaN dalle specifiche del galleggiante IEEE. Grazie ad Alex Van Liew per aver sottolineato che questo non si applica solo a Javascript.


NaNnon è uguale alle NaNspecifiche del galleggiante IEEE. In effetti, un modo rapido per testare se hai un NaNin C è quello di confrontarlo con se stesso. Quindi questo vale per tutte le lingue, non solo per JS.
Alex Van Liew,

1
@AlexVanLiew Interessante. Non lo sapevo! Ok, cambiando leggermente la mia risposta e aggiungendo credito dove è dovuto.
Stefnotch,

0

Fantom

a := 3
b := 3
duplicates := [a:b]
duplicates = duplicates.map {it * a}
duplicates = duplicates.map {it - b*b}
duplicates = duplicates.map {it / a-b}
echo(duplicates.join("") |Int a_2, Int b_2 ->Str| {"" +  a_2 + " = " + b_2})

Produzione:

-3 = 3

Perché?

[a: b] è una mappa, non un elenco. Non così subdolo, lo so :(


Dovresti avere a uguale alla b fine.
mbomb007,

La fine dell'errore originale è 2 = 1, quindi la fine di qualsiasi risposta qui non dovrebbe essere "vera"
Caino

Stavo pensando al BONUS subdolo. Non importa. "Invece di stampare il segno di uguale, puoi stampare solo le due variabili (aMod e bMod), e quindi avere un codice che sembra confrontare le due variabili per uguaglianza ma in realtà si trova che sono uguali (e stampa una forma di vero) ".
mbomb007,

0

C

L'errore fallace classico richiede un malinteso sulla sintassi C classica. Purtroppo ho incontrato alcuni sviluppatori "di alto livello" che sono convinti che C sia rotto a causa di risultati simili a questo codice. Se sai come funziona C diventa abbastanza ovvio, ma se hai visto il codice e hai pensato che fosse una lingua diversa, potrebbe non esserlo.

a,b,LHS,RHS;
main(){
    a=2; b=2;
    LHS=a; RHS=b;

    //multiply both sides by a
    LHS,RHS *= a; 
    //subtract b squared from both sides
    LHS,RHS -= b*b; 
    //assert that it factors correctly
    if (LHS,RHS != (a+b)*(a-b), b*(a-b)) printf("ERROR!\n");
    //'hard' division, just to be sure the compiler doesn't remove it
    LHS,RHS /=! (a-b);
    //assert that a+a really is b+b
    if (a+a != b+b) printf("ERROR!\n");
    //now just divide them by b
    printf("%d = %d ? ", LHS/b, RHS/b);
    if (RHS = LHS) 
        printf("true!");
    else
        printf("false!");
}

Ovviamente non funziona altrettanto bene se scritto in modo più idiomatico con #include <stdio.h>e int viene lanciato di fronte alle dichiarazioni.


Come funziona però?
CalculatorFeline

Prima nota che in c se 'dimentichi' l'int in una dichiarazione, assume il tipo int per essere retrocompatibile con k & r c. Quindi cercare l'operatore, in ce prestare attenzione alla sua precedenza. Quindi nota il = invece di == nell'ultima istruzione if.
LambdaBeta,
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.