Classic Proof Fallacy

18

0

The Background

So, we all know the classic proof that goes like this:

a = b
a² = ab
a² - b² = ab - b²
(a-b)(a+b) = b(a-b)
(a+b) = b
b+b = b
2b = b
2 = 1 (Ha ha!)
Of course, the mistake is that you can't divide by 0. Since a = b, a - b = 0, so there was a hidden division by 0.

The Challenge

You have to replicate this proof. First, declare two integers a and b (it doesn't matter what you call them) that equal. Then declare aMod and bMod to be modifiable versions of a and b and initially equal to a and b, respectively. You must multiply them both by a, then subtract b*b from both of them. You must then divide by a - b and then divide them by b (or a) to get. Then, print out aMod and bMod with an equal sign between them.

The Underhanded

Of course, since you declared a and b to equal, a - b = 0, and dividing by 0 causes an error. So you must creatively fake it. Also, because you are trying to replicate the proof, the result on all the operations on aMod and bMod must not equal when printed. They don't have to equal exactly 2 and 1, just two numbers that don't equal.

Here is an example:

#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;
}

Maybe not the best one, but it illustrates the point.

Bonus Underhanded

Instead of printing the equals sign, you can print out just the two variables (aMod and bMod), and then have code that appears to compare the two variables for equality but in actuality lies that they equal (and prints some form of true).

Remember, this is a popularity contest, so highest number of upvotes wins.
Also, a new version of mathematics called Mathematics 2.0 has made use of standard loopholes automatically invalidate a proof.

user155698

Posted 2015-04-03T22:02:04.493

Reputation: 189

Question was closed 2016-04-18T18:52:10.250

Here is a Wikipedia link of the mathematical fallacy so people can better understand – None – 2015-04-04T13:03:09.257

3

I'm voting to close this question as off-topic because underhanded challenges are no longer on-topic on this site. http://meta.codegolf.stackexchange.com/a/8326/20469

– cat – 2016-04-18T14:48:16.410

Answers

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])

Output:

[1, NaN]

Note that 0/0 = NaN

Hint

Try add some semicolons.
This program is actually var a=3,b=3,a2=3,b2=3[a2,b2]=...=[a2/(a-b),b2/(a-b)];console.log([a2/a,b2/a]).
And the NaN is [3/0,undefined/0]/3.

jimmy23013

Posted 2015-04-03T22:02:04.493

Reputation: 34 042

Wow. That was very clever, "accidentally" forgeting to add semicolons making (almost) the whole program a run-on sentence. – user155698 – 2015-04-04T16:10:12.487

3

Python 2

I'm pretty sure it's obvious since everyone knows Python, but here's my attempt:

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)

It outputs True.

Hint:

Check my division.

mbomb007

Posted 2015-04-03T22:02:04.493

Reputation: 21 944

since everyone uses Python . I know python, but I rarely use it – rpax – 2015-07-30T01:14:17.600

@rpax That's what I meant. – mbomb007 – 2015-07-30T14:05:51.610

Sorry, I didn't read properly your answer. – rpax – 2015-07-30T15:53:38.530

2

Ruby

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

Hint:

,

Explanation:

The two lines that end in commas cause the program to behave differently than it would. Without the commas, the method takes a single argument a, sets b equal to a, performs the transformations from the proof on each one (except due to some missing parentheses, it doesn't divide by 0), and outputs the result (With input of 3, it'd output "-1 = -1". With the trailing comma, however, the b = a line becomes part of the method signature, meaning that it's declaring a second argument with a default value. The method invocation at the end passes in the result of STDOUT.write($/), which is 1 (the number of bytes it wrote to STDOUT, since $/ is predefined to a newline character.) So a is 3 and b is 1, resulting in the equation starting off as "3 = 1". Garbage in, garbage out.

histocrat

Posted 2015-04-03T22:02:04.493

Reputation: 20 600

Nice trick there with your newlines. – LegionMammal978 – 2015-04-05T00:57:15.377

Could you add an explanation for non-Rubyists? – kirbyfan64sos – 2015-07-30T16:26:22.000

@kirbyfan64sos Sure, done. – histocrat – 2015-07-30T18:18:55.137

2

GolfScript

Warning: this program is cheating a bit, in that it doesn't print aMod and 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;
};

Try it here!

So what's going on?

The first thing you may have noticed are the "forbidden trigraphs". But remember, this is GolfScript, not C! Also, probably noticed that it doesn't actually say "int main()", it says "1nt main()". In GolfScript, the "1" means push 1 onto the stack, and the "nt main" gets processed as two uninitialized variables, which do nothing. The two parentheses first add 1 to the top number of the stack, and then subtract one, essentially cancelling themselves out. The brackets denote a block that gets pushed onto the stack, and then the semicolon pops it off right away. So, at the end, we just have the original "1" that was pushed on, and at the end of a GolfScript program, the stack gets printed. This answer was inspired by this one.

K Zhang

Posted 2015-04-03T22:02:04.493

Reputation: 5 698

Trigraphs detected. Activating automatic -1 system. Error: -1 failed (4792, RPLS) – CalculatorFeline – 2016-03-19T23:49:14.783

This is sneaky, because it tricks you into thinking it failed to trick you. +1 – Rɪᴋᴇʀ – 2016-03-20T04:35:15.950

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);

Output:
http://jsbin.com/furino/2/edit?js,output JsBin doesn't seem to be able to execute this code. Use the browser console instead.

Why?

scrollMaxX and screenX are already existing variables. They are built in in the browser. Thus, the result may vary. The let keyword only temporarily changes their value.

Another JavaScript one: It doesn't exactly follow the rules, it only outputs if the variables are equal or not.

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);

Why?

NaN is not equal to NaN by IEEE float specifications. Thanks to Alex Van Liew for pointing out that this doesn't just apply to Javascript.

Stefnotch

Posted 2015-04-03T22:02:04.493

Reputation: 607

NaN isn't equal to NaN by IEEE float specifications. In fact, a quick way to test if you have a NaN in C is to compare it with itself. So this applies to all languages, not just JS. – Alex Van Liew – 2015-07-30T18:02:48.970

1@AlexVanLiew Interesting. I didn't know that! Ok, changing my answer slightly and adding credit where it is due. – Stefnotch – 2015-08-01T04:02:52.363

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.

The output when areEqual(4,4) is called (or any other couple of numbers really):

false

Why?

In Prolog, the operator "=" is not affectation ; it's "Unification". Therefore Amod = Amod * A fails because Amodhas already been unified with A, and thus cannot possibly be unified with Amod * A. Prolog then immediatly stops executing the current rule and returns false.

Fatalize

Posted 2015-04-03T22:02:04.493

Reputation: 32 976

2I think it should be the other way around, you have to output "true" when the two value are different, not "false" when they are equals ^^' – Katenkyo – 2015-06-22T13:04:33.853

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})

Output:

-3 = 3

Why?

[a:b] is a map, not a list. Not so sneaky, I know :(

Cain

Posted 2015-04-03T22:02:04.493

Reputation: 1 149

You're supposed to have a equal to b at the end. – mbomb007 – 2015-06-22T21:34:48.017

The end of the original fallacy is 2 = 1, so the end of any answer here should not be "true" – Cain – 2015-06-24T20:42:52.820

I was thinking of the BONUS underhanded. Never mind. "Instead of printing the equals sign, you can print out just the two variables (aMod and bMod), and then have code that appears to compare the two variables for equality but in actuality lies that they equal (and prints some form of true)." – mbomb007 – 2015-06-24T20:50:43.317

0

C

Classic proof fallacy requires classic C syntax misunderstanding. Sadly I have met some "high-level-only" developers who are convinced C is broken because of results similar to this code. If you know how C works it becomes fairly obvious, but if you saw the code and assumed it was a different language, it might not be.

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!");
}

Of course it doesn't work quite as well when written more idiomatically with #include <stdio.h> and int's thrown in front of the declarations.

LambdaBeta

Posted 2015-04-03T22:02:04.493

Reputation: 2 499

How does it work though? – CalculatorFeline – 2016-03-19T23:45:00.953

First note that in c if you 'forget' the int in a declaration, it assumes type int in order to be backwards compatible with k&r c. Next look up the , operator in c and pay attention to its precedence. Next note the = instead of == in the last if statement. – LambdaBeta – 2016-04-25T05:54:49.390