Hacker News new | past | comments | ask | show | jobs | submit login
Write a program that makes 2 + 2 = 5 (codegolf.stackexchange.com)
123 points by bryan_rasmussen on June 1, 2014 | hide | past | favorite | 71 comments



I would like to post on there but it's protected from people with low reputation... Maybe someone here appreciates my solution in C:

  #include <stdio.h>
  
  int main(int argc, char* argv[]){
  	int arr[1];
  	int a = 2;
  	int b = 2;
  	arr[1] = 3;
  	printf("%d", a+b);
  
  	return 0;
  }
Explanation: I go out of bounds of the array arr, it only has one value but I access the second value. That's why b is likely to get overwritten with 3 and hence a+b=5


I think the line above the printf call should be

    arr[2] = 3;
I ran your program and I got 4. Then I changed arr[1] to arr[2] and got 5, as I expected.


It's only likely, but not certain that a or b get overwritten. How your stack is laid out is entirely up to the compiler. arr[1] is already out of bounds, however, we don't know for certain what's immediately above the array.


With compiler optimizations turned on, it's almost guaranteed not to happen, because a and b are very likely to be stored in CPU registers.


Or rather, a and b will be constant folded so that the printf call is optimized to "push #4; push ptrFmt; call printf"


A truly good compiler would replace that printf by a call to putchar or pass a constant string to 'write' (gcc almost (?) does that. See http://www.ciselant.de/projects/gcc_printf/gcc_printf.html)


The compiler is probably aligning all stack elements to 8 bytes.


Here's mine :

    $ cat test.c
    #include <stdio.h>
    
    int main() {
        int a = 3;
        int b = 3;
    
        // aren't we supposed to add 2 and 2 ??/
        a = 2;
        b = 2;
    
        printf("%d\n", a + b);
    
        return 0;
    }
    $ gcc -W -Wall -trigraphs test2.c 2>/dev/null
    $ ./a.out
    5
    $


Is the trick here the "-trigraphs" flag, or the fact that you are showing us test.c but compiling test2.c? Both approaches seem like they should work.


It's the trigraph ??/ which translates to a \.


The trigraph appears in the file "test.c". If you look at the compilation command, you will see that that is not the file that is actually compiled.


If you compile "test.c" you will see that that isn't relevant issue.


Very sneaky. For anyone else wondering why this works, look up trigraphs.


And after looking it up, you better then realise that if you actually ever use them in production code you better have a really good reason, or your colleagues will forever curse your name..

I think the above is probably the first time I've seen trigraphs used in the last 20 years or so.


http://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C

sorry for spoiling:

"??/" got replaced by "\"


That Java one is particularly amusing, as most programmers otherwise familiar with the language would never know about the integer cache (and their reaction upon discovering that there is one would probably be the same as mine - WTF?)

Edit: I had a feeling I'd heard of an "integer cache" somewhere else" in a WTF-eliciting context... http://thedailywtf.com/Articles/The-Integer-Cache.aspx !


It also leads to some interesting programming errors in Java.

    class A {
        public static void main(String[] args) {
            Integer a = 100, b = 100;
            Integer c = 10000, d = 10000;
            System.out.println(a == b);
            System.out.println(c == d);
        }
    }
Prints:

    true
    false
For those unaware, the == check above is doing an Object check (are they the same object). The cache makes the '100' return the same instance of an object. To do actual value checks, you'd need to do c.equals(d)


what a dumb language! operator overloading should have bound the equals method to the == operator without the programmer having to be aware of this. when in java do you ever want to compare if two objects are the same referenced with the same ptr? Never, so why not do the right thing by the user of the language.

At least be consistent between primitives and objectives.

Sadly, I have to use this language daily. My heart belongs to python, but java pays the bills.


You're forgetting legacy and history. Many Java programmers came to Java, myself included, from C (or C++). The == operator in C is a simple register comparison. If you compare two ints the the == operator will return true iff the two int values are the same, but if you compare two int pointers, then equal integer values may or may not be stored at the same address, which is exactly what we're seeing here. Since Java references are pointers, this behavior -- while probably not the right choice -- was less surprising to us, C programmers, than the alternative. Of course, auto-boxing made this behavior even stranger, but autoboxing was added to the language much later.


Python has exactly the same behavior if you compare integers using the is operator. Two int-variables with same value are only "is-equal" up until somewhere around 100000 also. Many beginners do this mistake as they think you should always use is in python and don't even know that == also exist.


Considering the Flyweight is a GoF Design Pattern, and that it talks about doing this specifically for managing integer objects... this shouldn't be a WTF for most people. It's a trick as old as the hills too. Smalltalk has had it going back decades.



It reminds me of a prank a relative of mine used to play on other people using punch-card computers. The computer had no math unit (!) so addition tables and multiplication tables were fed in on punch cards. Easy enough to change one of those and make perfect code give very odd answers.


Boy, he must've been hated, I personally am too young to remember the punch-card days of programming but my dad spent most of his younger days doing it that way and he said that one of the reasons his code has fewer bugs/mistakes than mine (aside from 30+ years exp on me) is because no one wanted to make a stupid mistake somewhere in their stack [of cards] that would mean going to that back of the line just because they used a plus instead of a minus or something (I don't remember the exact example).


The integer cache is well known for over 10 years, presently there is a JVM knob to make it larger: java.lang.Integer.IntegerCache.high So the solution is not surprising at all.

Personally I'd just employ an enhancing classload and replace some of bytecodes ICONST_2 with ICONST_3. (one byte change in the bytecode). Yet, overall uninteresting question.


UB abuse in C/C++ Linux x86-64 (works with gcc/clang/icc with any optimization level):

  #include <stdio.h>

  int main() {
    double x;
    printf("Input any number:\n> ");

    if (scanf("%lf", &x) == 1) {
      printf("Is 2 + 2 really equals %g? Let's try!\n", x);
      printf("2 + 2 = %g\n", 2 + 2);
    } else {
      printf("Invalid input!\n");
    }
  }
Output:

  Input any number:
  > 5
  Is 2 + 2 really equals 5? Let's try!
  2 + 2 = 5
Explanation: linux x86-64 calling convention uses xmm registers to pass fp values. In the first printf we initialize %xmm0 with some value. In the second printf we put integer 4 in %esi, however printf reads value again from %xmm0. Here is an assembly in GCC explorer (sorry for shortened link, that's how GCC explorer works): http://goo.gl/mY9phE



7 bytes: !''|2+2

:)


5 bytes: 1|2+2


I think all these bytes are not creative. !![]+2+2 ? !''|2+2 ? 1|2+2 ? Why the use of new operators? Why not just write 1+2+2 ?


Well if you made a general add function that always performed an or operation on the least significant bit, it would be pretty interesting. You'd always flip odd and even in any addition.


To make many more examples of why Javascript is not a language for beginners.


  var tens = ['10','10','10','10','10','10','10','10'].map(parseInt);
  var ten = tens[tens.length-1];
  var two = ten % 4;
  console.log(two + 2);


Here's a Ruby solution that really does modify the + operation:

  class Fixnum
    alias_method :old_plus, :+
    def +(*args)
      old_plus(*args).old_plus(1)
    end
  end

  2 + 2 #=> 5


As Flonk points out at http://codegolf.stackexchange.com/a/28794, nothing beats Haskell for casual re-definition of operators. (I seem to remember that this is even on the Haskell wiki somewhere, though I can't find it right now.)


Here's a ruby solution that only affects 2+2:

    class Fixnum
      alias_method :old_plus, :+
      def +(other)
        return 5 if (self == 2 && other == 2)
        old_plus(other)
      end
    end


Here's one in Ocaml that modifies the + operator

let (+) x y = match (x,y) with (2,2) -> 5 | (x,y) -> x+y;;


A shorter one:

let (+) 2 2 = 5 in 2+2;;


Here is a Nimrod version which does the same:

  proc `+`(x, y: int): int =
    result = x
    result.inc(y)
    result.inc

  echo(2 + 2) # => 5


  public class Main {
   	public static void main (String [] args) {
  		System.out.println("‮5=2+2‭"); // prints ‬4=2+2
  	}
  }


C:

    #include <stdio.h>
    #include <stdbool.h>
    #include <stdlib.h>

    int nums[5] = {1, 0, 1, 0, 1};
    static int cur;

    int main(int argc, char **argv) {
        for(int i = 1; nums[i] != 5 && i < 10; i++) {
            cur = i;
            if(i/4 == 1) {
                printf("2 + 2 <= %d = %s\n", cur, 2 + 2 <= i ? "true" : "false");
                printf("2 + 2 == %d = %s\n", cur, 2 + 2 == i ? "true" : "false");
                printf("\n");
            }
        }
    }
No strange array writes! No indirect writes at all!

It's finicky and I believe depends on register allocation, but when I compile it using whatever version of gcc-mp-4.9 I have installed from MacPorts at -O3, it outputs, among other things:

    2 + 2 == 5 = true
(For all they say about evil optimizing compilers, it was really hard to make this work.)


Can anyone explain? It didn't work for me but still gives odd results depending on optimization level that I don't understand.


Because nums is a length 5 array, and the loop condition checks nums[i], GCC assumes going into the loop that i is a valid index, i.e. i <= 4. The division then rules out the possibility that i < 4, so for the purposes of optimization, my version of GCC thinks that i always equals 4 at the printfs, even if it's actually higher.

It's based on an old Linux bug... I should learn more about GCC internals in order to tell tell why I couldn't get it to work without a loop. In general, any sequence where some property not holding would cause undefined behavior to occur allows a conforming compiler to assume it does hold, but for most basic examples neither GCC nor Clang does anything special.


Great explanation and fun exploit, thanks!


Because I can't post on stackoverflow either, here's my variant in C (requires glibc, and a deprecated function at that).

  #include <printf.h>
  #include <stdio.h>
  #include <string.h>

  int d_cb(FILE *stream, const struct printf_info *info, const void *const* args) {
    int num = (*(int*)(((int**)args)[0])), numw = info->width;
    char str[10], numn = num|numw, *out = str;
    num = num < 0 ? *out++ = '-', -num : numn;
    do { *out++ = '0' + num % 10; num /= 10; } while(num);
    fwrite(str, out - str, 1, stream);
    return 0;
  }

  void init() {
    register_printf_function('d', d_cb, 0);
  }

  int main() {
    init();
    printf("2+4 = %d, 2+2 = %1d\n", 2+4, 2+2);
    return 0;
  }


Here's the Perl 6 solution:

  multi infix:<+>(2, 2) { 5 }
  say 2 + 2;  # 5


Ruby solution (don't have enough rep to post to codegolf):

  def mad_addr(a,b)
    a == b && a == 2 ? (a.object_id + b.object_id)/a : a + b
  end
Explanation: If a and b are both equal to 2 we can sum the values of the object_id's (the object_id of 2 is 5), and then divide the sum by 2. [Edit to add] For all other numbers this should behave as expected.

I just learned the object_id of 2 is 5 while doing this exercise, and I would like to continue learning more about how Ruby works. So if you have feedback, criticisms, or other ideas regarding this solution please feel free to share :)

[edit: added missing `=`]


a == b && a = 2 ? (a.object_id + b.object_id)/a : a + b

It looks like you are missing an equals sign on a == 2.

I just learned the object_id of 2 is 5 while doing this exercise, and I would like to continue learning more about how Ruby works. So if you have feedback, criticisms, or other ideas regarding this solution please feel free to share :)

The object_id appears to be the tagged pointer that contains the value cast to an integer. Ruby stores all of its data types using a single underlying C data type (called VALUE in the Ruby source), using the bottom two bits to identify special values that aren't really pointers. This is why Fixnum can only hold 31 or 63 bits instead of 32 or 64 (including sign), for example:

    # Ruby irb on a 32-bit system
    > (1<<30 - 1).class
    => Fixnum
    > (1<<30).class
    => Bignum
See also:

https://en.wikipedia.org/wiki/Tagged_pointer


Thanks, nitrogen. Following your info led to a couple of other neat discoveries, and a bunch more useful material [1].

As a result here are some new ways I learned to get 5 from 2 + 2:

  require 'fiddle'
  a = 2
  b = 2
  Fiddle::Pointer.new(a.object_id << 1).to_value.ceil + b
  => 5
Note: This happens because calling `to_value` on the `Fiddle::Pointer` object returns a Float (2.0000000000000004) instead of Fixnum (which was a surprise to me).

And here's another using `Object#tap`:

  a = 2
  (a + a).tap{|x| a = x + 1}.send(:eval,'a')
  => 5
[1] These links were helpful for me. The last one is an MIT licensed book called, "Kestrels, Quirky Birds, and Hopeless Egocentricity."

http://stackoverflow.com/questions/1872110/is-ruby-pass-by-r...

http://patshaughnessy.net/2014/1/9/how-big-is-a-bignum

http://stackoverflow.com/questions/2818602/in-ruby-why-does-...

http://combinators.info/#kestrels

Edit: line formatting


If you want to dig even deeper into the way Ruby works, I recommend trying to write a C extension (or at least reading the documentation):

http://www.ruby-doc.org/docs/ruby-doc-bundle/ProgrammingRuby...


Asking: Isn't the only true solution the one using Decibels for Addition? Because everyone else either just redefines or overwrites a value. Also addition of decibels cannot be disproofed as fake.


After thinking for a while, I found that there is no true answer. If we are not dealing with normal calculating, every answer should redefine the calculating system or value in a tricky way. The simplest answer I can tell related to the addition of decibels is like this:

    function add(a, b): return 5
But it is just not so fun.


You know, this would be possible in C and C++ if you add some code at the start of main() that unprotects the executable section, goes through it and modifies each "load 4 in register X" instruction to "load 5", then forks a process that attaches itself as a debugger to the executable to monitor every add and change the result to 5 if it's 4.


Lua:

    local debug = require "debug" -- in case 5.2
    debug.setmetatable(1, {__tostring=function(n)
      return ("%g"):format(n+1)
    end})

    print(2+2)
Trying to make 2+2==5 evaluate as true is a lot harder. Although Lua lets you define a custom + operator, it's a fallback not an override.


How about the opposite? Make 2+3=4, here in C.

    add2And3(int *a, int *b)
    {
       *a = 3;
       *b = 2;
       printf("%d", *a + *b);  //4
    }
    void main()
    {
       int storage;
       add2And3(&storage, &storage);
    }


  #!/bin/bash
  tty
  if [[ $? -ne 0 ]] ; then
      # command returned nonzero
      echo "not a tty"
  else
      # command returned zero
      n=$?
      ((n=$n+2))
      ((n=$n+2))
      echo "0+2+2=$n";
  fi


Haskell:

  let 2 + 2 = 5


Simple solution in R:

   > '%+%' <- get( '+')
   > '+' <- function( e1, e2) 1 %+% e1 %+% e2
   > 2+2
   [1] 5
Regards


Combining a couple ideas, here's a Go solution

http://play.golang.org/p/XnPglbkLW4


Could you please explain why this works? How come int(a) produces 2.5?


scroll down to find the underhandedness


Haha thanks, very nice!


You have to add 1 to either the first or the second 2 or to the sum of the two.


#lang racket (define (add-bizzare x y) (round (+ (+ x 0.4) (+ y 0.4))))


My first thought in Clojure.

  (let [+ (partial + 1)]                                                                                                                                                                                
        (+ 2 2))


The JavaScript answer from @user1886419 is a great joke. lol


Julia

  !(a::Int) = !bool(a)
  !0 + 2 + 2

  ##> 5


Or more directly:

  julia> +(a::Int, b::Int) = if a==b==2 5 else a-(-b) end
  julia> 2+2
  5
  julia> 3+1
  4
(The else part can't use + or it will cause infinite recursion).


why not just overload the + operator in C++?


first thing i thought when i read the title:

    #include <iostream>

    class Int
    {
    private:
            int _value;

    public:
	    Int(int value) : _value(value) {}
	    Int operator + (const Int& b){ return Int(++_value + b._value); }
	    friend std::ostream& operator << (std::ostream& out, const Int& value){ out << value._value; return out; }
    };

    int main(int argc, char** argv)
    {
	    std::cout << Int(2) + Int(2) << std::endl;
            return 0;
    }
output: 5


I'm surprised no one has suggested this yet. In python

>Write a program that seemingly adds the numbers 2 and 2

a=2+2

>and outputs 5.

print(5)

Yeah, I know that isn't the intent here, but, following the wording of the contest rules exactly...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: