18
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ Here is a Wikipedia link of the mathematical fallacy so people can better understand \$\endgroup\$
    – user34736
    Apr 4, 2015 at 13:03
  • 3
    \$\begingroup\$ I'm voting to close this question as off-topic because underhanded challenges are no longer on-topic on this site. meta.codegolf.stackexchange.com/a/8326/20469 \$\endgroup\$
    – cat
    Apr 18, 2016 at 14:48

8 Answers 8

17
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ Wow. That was very clever, "accidentally" forgeting to add semicolons making (almost) the whole program a run-on sentence. \$\endgroup\$
    – user155698
    Apr 4, 2015 at 16:10
3
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ since everyone uses Python . I know python, but I rarely use it \$\endgroup\$
    – rpax
    Jul 30, 2015 at 1:14
  • \$\begingroup\$ @rpax That's what I meant. \$\endgroup\$
    – mbomb007
    Jul 30, 2015 at 14:05
  • \$\begingroup\$ Sorry, I didn't read properly your answer. \$\endgroup\$
    – rpax
    Jul 30, 2015 at 15:53
2
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ Nice trick there with your newlines. \$\endgroup\$ Apr 5, 2015 at 0:57
  • \$\begingroup\$ Could you add an explanation for non-Rubyists? \$\endgroup\$ Jul 30, 2015 at 16:26
  • \$\begingroup\$ @kirbyfan64sos Sure, done. \$\endgroup\$
    – histocrat
    Jul 30, 2015 at 18:18
2
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ Trigraphs detected. Activating automatic -1 system. Error: -1 failed (4792, RPLS) \$\endgroup\$ Mar 19, 2016 at 23:49
  • \$\begingroup\$ This is sneaky, because it tricks you into thinking it failed to trick you. +1 \$\endgroup\$
    – Riker
    Mar 20, 2016 at 4:35
1
\$\begingroup\$

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.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ I 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 ^^' \$\endgroup\$
    – Katenkyo
    Jun 22, 2015 at 13:04
1
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Jul 30, 2015 at 18:02
  • 1
    \$\begingroup\$ @AlexVanLiew Interesting. I didn't know that! Ok, changing my answer slightly and adding credit where it is due. \$\endgroup\$
    – Stefnotch
    Aug 1, 2015 at 4:02
0
\$\begingroup\$

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 :(

\$\endgroup\$
3
  • \$\begingroup\$ You're supposed to have a equal to b at the end. \$\endgroup\$
    – mbomb007
    Jun 22, 2015 at 21:34
  • \$\begingroup\$ The end of the original fallacy is 2 = 1, so the end of any answer here should not be "true" \$\endgroup\$
    – Cain
    Jun 24, 2015 at 20:42
  • \$\begingroup\$ 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)." \$\endgroup\$
    – mbomb007
    Jun 24, 2015 at 20:50
0
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ How does it work though? \$\endgroup\$ Mar 19, 2016 at 23:45
  • \$\begingroup\$ 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. \$\endgroup\$
    – LambdaBeta
    Apr 25, 2016 at 5:54

Not the answer you're looking for? Browse other questions tagged or ask your own question.