Settings

Theme

Write a program that makes 2 + 2 = 5

codegolf.stackexchange.com

123 points by bryan_rasmussen 12 years ago · 75 comments

Reader

Kenji 12 years ago

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
  • wenderen 12 years ago

    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.
    • Kenji 12 years ago

      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.

    • wyager 12 years ago

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

Clex 12 years ago

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
    $
  • gizmo686 12 years ago

    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.

    • cdcarter 12 years ago

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

      • gizmo686 12 years ago

        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.

  • tbirdz 12 years ago

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

userbinator 12 years ago

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 !

  • kyrra 12 years ago

    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)
    • hnriot 12 years ago

      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.

      • pron 12 years ago

        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.

      • Too 12 years ago

        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.

  • cbsmith 12 years ago

    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.

  • benjiweber 12 years ago
  • sp332 12 years ago

    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.

    • vxNsr 12 years ago

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

  • xxs 12 years ago

    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.

Lockal 12 years ago

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
yiedyie 12 years ago

JavaScript ;)

http://codegolf.stackexchange.com/a/29944/12328

  • blueveek 12 years ago

    7 bytes: !''|2+2

    :)

    • notduncansmith 12 years ago

      5 bytes: 1|2+2

      • NaNaN 12 years ago

        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 ?

        • leorocky 12 years ago

          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.

        • notduncansmith 12 years ago

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

          • mraison 12 years ago

              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);
rkowalick 12 years ago

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
  • JadeNB 12 years ago

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

  • hpvic03 12 years ago

    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
  • eqnoob123 12 years ago

    Here's one in Ocaml that modifies the + operator

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

  • dom96 12 years ago

    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
im3w1l 12 years ago

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

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.)
  • tgb 12 years ago

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

    • comex 12 years ago

      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.

dgl 12 years ago

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;
  }
masak 12 years ago

Here's the Perl 6 solution:

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

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 `=`]

  • nitrogen 12 years ago

    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

X4 12 years ago

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.

  • NaNaN 12 years ago

    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.
anon4 12 years ago

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.

whoopdedo 12 years ago

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.
Too 12 years ago

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);
    }
isivaxa 12 years ago

  #!/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
Datsundere 12 years ago

Haskell:

  let 2 + 2 = 5
social_monad 12 years ago

Simple solution in R:

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

Combining a couple ideas, here's a Go solution

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

gdewilde 12 years ago

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

terranera 12 years ago

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

diego 12 years ago

My first thought in Clojure.

  (let [+ (partial + 1)]                                                                                                                                                                                
        (+ 2 2))
NaNaN 12 years ago

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

runarberg 12 years ago

Julia

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

  ##> 5
  • orangecat 12 years ago

    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).
san86 12 years ago

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

  • boost_ 12 years ago

    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
noobermin 12 years ago

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

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection