text:
Recreate a 'Snake' game in a console/terminal
Games are fun
This Code Golf here was so fun I had to make a version for other classic games similar in complexity: Shortest Way of creating a basic Space Invaders Game in Python
This time, however, try to recreate the classic 'Snake' game, in which you start out as a small shape, constantly moving to collecting pieces to increase your score. When you collect a piece, your 'tail' grows, which follows the path you have made. The objective is to last the longest without crashing into your own tail, or into the walls
Qualifications:

You, the characters that make up the tail, the walls, and the pieces you collect should all be different characters
Show a HUD with the score. The score increases by 1 point for each piece you collect
The player loses when they collide with their own tail or the wall
A piece spawns in a random area immediately after a piece is collected, not to mention at the start of the game
Speed of the game doesn't matter, as long as it is consistent
The 'cells' should be 2x1 characters, since the height of block characters is ~twice the width Can be 1x1, because 2x1 is just ugly and I didn't really think of that
The keys for changing the direction should be awsd, left, up, down, right respectively
The starting direction should always be up
You must show the edges of the wall. The score may overlap the wall

Shortest code that meets the above criteria wins. Imaginary Bonus Points for creativity.

The snake isn't supposed to grow when eating?

hm? "When you collect a piece, your 'tail' grows, which follows the path you have made.", so yes, the snake grows.

Without the awsd and the starting direction should always be up requirements, M-x snake would work

@scrblnrd3 M-: (progn(define-key snake-mode-map"a"'snake-move-left)...(setq snake-initial-velocity-x 0 snake-initial-velocity-y 1)(snake)) would do the trick then.

Related: Nibbles Nostalgia

JavaScript (553 512 bytes)
Link to playable version

c=0;a=b=d=-1;e=[f=[20,7],[20,8]];i=Math.random;~function n(){if(c&&(87==a||83==a
))c=0,d=87==a?-1:1;if(d&&(65==a||68==a))d=0,c=65==a?-1:1;p([j=e[0][0]+c,k=e[0][1
]+d])||!j||39==j||!k||10==k?b+=" | GAME OVER":(e.unshift([j,k]),p(f)?(f=[1+38*i(
)|0,1+9*i()|0],b++):e.pop());for(m=h="";11>h;h++){for(g=0;40>g;g++)l=g+","+h,m+=
!g||39==g||!h||10==h?"X":e[0]==l?"O":p(l)?"*":f==l?"%":" ";m+="\n"}x.innerHTML=m
+b;!b.sup&&setTimeout(n,99)}();onkeydown=function(o){a=o.keyCode};function p(o){
return e.join(p).indexOf(p+o)+1}

I tried to make it output to the real console at first (with console.log and console.clear), but it was flickering too much, so I put it into console-like HTML. It will work with this:
<pre id=x>

Also I implemented it with 2x1 cells first, but it just looked worse than 1x1. That would be a minor change though.
Uses awsd keys on keyboard.
Update:
I was able to cut it down to 512 (exactly 0x200) bytes by improving the tail search and doing some more magic.
You now get 2 points when a piece spawns in your tail (it's a feature). I also fixed the overlapping when the snake bites itself.

beautiful! and you're right, it does look better as 1x1 than 2x1. the only worry I really had there was up and down being way faster than left and right but it's doable considering the constraints. The flashing in the console I don't mind so much (see my space invaders program, its fairly flickering) but I suppose a plain text web page works too! one qualm though... is there any way to restart without needing to refresh? :(

Doesn't work with awsd

@Blazer That would take more 13 characters :-/ ... and you have the F5 key anyway.

@Neal Yeah I used the arrow keys but fixed it now.

@copy I suppose I didn't make it a requirement

I can't seem to get input to work in chrome, it just hits the wall.
Edit, never mind, uses WSAD >.> works great

Doesn't work in Firefox 3.6, and Chrome thinks it's in Galician.

@JoeyAdams fixed it; was a doctype problem on my HTML page. The Galician thing is expected behaviour - "snake" is obviously a Galician word.

The link no longer works. It redirects to a homepage of a forum with an untrusted certificate.

@JanDvorak My old hoster went offline. Fixed, thanks

16 bit 8086
526 bytes / 390 bytes
Decode this using a Base64 decoder and call it "snake.com" then execute from Windows command prompt. Tested on WinXP, you may need to use DosBox to get the right video mode. Control keys are 'wasd' and space to exit. Press 'w' to start.
uBMAzRC5AD+2AOipAb1AAbgAoI7Auf//v4sMsAHzqrgAtLksAfOqg8cU/sx19OgsAYs+8gKwAuj4
ALQAzRpCiRYOA4kWEAPouAC0C80hCsB0IbQIzSG+ygKDxgOAPAB0EjgEdfSLRAGzAP/Qo1cBiB7w
AulqAIEGdAGu/7P+uNECgMMEw7MCuNsCgMMGw4s+8gKLHvACisPolwADv+YCJoo16I0AiT7yAoD+
A775AnREiz70AiaKHbAA6HUAA7/mAok+9AKA/gB0FscGVwHNAoEudAGu/zPJtj/o2QDofQC0AM0a
OxYOA3X2/wYOA+lZ/8YEAE7+BIA8CnT16F4AaOAB6EQAM9K5LQD38YvCweACBQoA9+WL+OguALlL
ADPS9/HB4gKDwgsD+iaAPQB10rADiMRXq4HHPQGrq4HHPAGrq4HHPQGrX8OhEAO62wD34rntf/fx
iRYQA4vCw772Ar8K9bUEshCstACL2AHDi4f6ArMDtwXR+LEAwNEC/smA4Q8miA0p7/7PdevoIQA6
xHQE/st13ugKAP7NdcroAwB1+8O3BSbGBQEp7/7PdfaBx0EG/srDuBAQM9uAwwLNEID7CnX2w7gD
AM0QzSB3dgEgxgIAYYcBZIUBIMYCAHd8AXN+ASDGAgAA+wAF/P8EAAIAH4ofigAAAADRxeD/TJlO
gQPvQrVA4++BVdVjgQ==

Here's a character mode version that's 390 bytes long:
uAMAzRC4ALiOwLlQADP/uCCf86uzF6u4AA+xTvOruCCfq7LdfCxUPOr6BgBiz5+AqF8Aqu0AM0aQ
okWhgKJFogC6MUAtAvNIQrAdCG0CM0hvlYCg8YDgDwAdBI4BHX0i0QBswD/0KNSAYgefALpdgCBB
m8Bov+z/rhdAoDDBMOzArhnAoDDBsOLPn4Cix58AiaJHQOclgmijUmiR2JPn4CgP4DvoUCdFOLPo
ACJoodJscFAAADv3JYiT6AAoD+AHQkxwZSAVkCgS5vAaL/vwEAudAHJoA9qnUEJsYFzIPHAuLx6F
4AtADNGjsWhgJ19oMGhgIC6Uz/xgQATv4EgDwKdPXoPgBo5wHoIgC5FwD38Wn6oADoFgC5TgD38U
ID0gP6JoA9AHXhJscFA93DoYgCutsA9+K57X/38YkWiAKLwjPSw76CAr8CALkEALSfrAQwq+L6w8
0gd3EBIFcCAGGCAWSAASBXAgB3dwFzeQEgVwIAYP+gAP7/AgACqtAH0AcAAAAA

This character mode one's three bytes longer (but the snake's better):
uAMAzRC4ALiOwLlQADP/uCCf86uzF6u4AA+xTvOruCCfq/7LdfCxUPOr6BsBiz6BAibHBQEKtADN
GkKJFokCiRaLAujHALQLzSEKwHQhtAjNIb5ZAoPGA4A8AHQSOAR19ItEAbMA/9CjUwGIHn8C6XgA
gQZwAaD/s/64YAKAwwTDswK4agKAwwbDiz6BAosefwImiR0Dv3VYJoo1JscFAQqJPoECgP4DvogC
dFOLPoMCJoodJscFAAADv3VYiT6DAoD+AHQkxwZTAVwCgS5wAaD/vwEAudAHJoA9qnUEJsYFzIPH
AuLx6F4AtADNGjsWiQJ19oMGiQIE6Ur/xgQATv4EgDwKdPXoPgBo6gHoIgC5FwD38Wn6oADoFgC5
TgD38UID0gP6JoA9AHXhJscFA93DoYsCutsA9+K57X/38YkWiwKLwjPSw76FAr8CALkEALSfrAQw
q+L6w80gd3IBIFoCAGGDAWSBASBaAgB3eAFzegEgWgIAYP+gAP7/AgACqtAH0AcAAAAA

points for creativity, but i think using dosbox is cheating because the challenge is to make the game work in an ascii console or terminal, not a dosbox. also, shouldn't code golf be source code, not binary?

@Blazer: That is the source code - I typed the machine code in using a hex editor - that's how l337 I am! ;-)  The DosBox thing is only needed if your video drivers have trouble with mode 13 graphics (mine card is OK with it). It wouldn't be difficult to do an ascii version (probably smaller too)

The "390-byte" version decodes to only 388 bytes and hangs when run under dosbox.  Looks like something may have been lost in transmission. :(  Still, the other two versions are extremely cool!

Is there an ungolfed version of the code? (I don't know this language)

@n.1: The program is 8086 machine code, you can load it into a debugger (D86) and view the code as written, albeit without label names.

@Blazer Binary?

These days, at least, the standard for the site is to present programs like this in assembly, but to count their bytes in machine code (as produced by a non-optimizing assembler).

shell/sh, 578 chars
I tried to be POSIX compliant (being as much portable as possible and avoid bashisms, even the random-number-generator does not need /proc). You can e.g. play it in your native terminal or via a SSH-session: run with 'dash -c ./snake'
There is also an unuglyfied/readable variant in ~2800 bytes, which can be seen here.
Some notes:
shell-scripting is not suited for coding games 8-)

to be fair, we only used so called 'builtins', which means:

no external calls of programs like 'clear', 'stty' or 'tput'
because of that, we redraw the whole screen on every move
the only used builtins (aka native commands) are:

echo, eval, while-loop, let, break, read, case, test, set, shift, alias, source

there is no random number generator (PRNG), so we have to built our own
getting a keystroke blocks, so we have to spawn another thread

for getting the event in parent-task we use a tempfile (ugly!)

the snake itself is a list, which is cheap:

each element is a (x,y)-tuple
loosing the tail means: shift the list by 1
adding a (new) head means: append a string

the grid is internally an array, but shell/sh does not know this:

we "emulated" array(x,y) via an ugly eval-call with global vars

and finally: we had a lot of fun!

#!/bin/sh
alias J=do T=let E=echo D=done W=while\ let
p(){ eval A$1x$2=${3:-#};}
g(){ eval F="\${A$1x$2:- }";}
r(){
E $((1+(99*I)%$1))
}
X=9
Y=8
L="8 8 $X $Y"
I=41
W I-=1
J
p $I 1
p $I 21
p 1 $I
p 41 $I
D
p 3 3 :
>L
W I+=1
J
E -ne \\033[H
y=22
W y-=1
J
Z=
x=42
W x-=1
J
g $x $y
Z=$Z$F
D
E "$Z"
D
E $B
. ./L
case $D in
a)T X+=1;;d)T X-=1;;s)T Y-=1;;*)T Y+=1;;esac
g $X $Y
case $F in
\ |:)p $X $Y O
L="$L $X $Y"
case $F in
:)W I+=1
J
x=`r 39`
y=`r 19`
g $x $y
[ "$F" = \  ]&&{
p $x $y :
break
}
D
T B+=1;;*)set $L
p $1 $2 \
shift 2
L=$@;;esac;;*).;;
esac
D&
while read -sn1 K
J
E D=$K>L
D

Does this actually work? if the snake is going to the right and you press a it stops. Weird.

Yes, because you bite yourself - thats the way it must be IMHO. We discussed that internally and everybody agrees on this.

echo -n is definitely not portable. If the first operand is -n, or if any of the operands contain a backslash ( '' ) character, the results are implementation-defined. Using echo for anything other than literal text without any switches is not portable. http://pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html

nyuszika7h: any idea how to circument this?

nyuszika7h: i found a way to remove the main 'echo -n' call - so there is only one call left. it's calling the escape-sequence for 'go to home-position (0,0)'

C# .NET Framework 4.7.2 Console (2,456 2,440 2,424 2,408 2,052 1,973 1,747 1,686 bytes)
This was fun, but I really had to think what variables were what, because they are only one letter.
using m=System.Console;using System;using System.Collections.Generic;using System.Threading;class s{static void Main(){m.CursorVisible=0>1;new s()._();}int l;Action<string> w=(x)=>m.Write(x);Action<int,int>n=(x,y)=>m.SetCursorPosition(x,y);(int x,int y)d,c,a;int h,u;List<(int x,int y)>p;void _(){while(1>0){f();h=25;u=25;p=new List<(int x,int y)>();l=0;d=(0,-1);c=(u/2,h/2);e();m.SetWindowSize(u+4,h+4);m.SetBufferSize(u+4,h+4);while(1>0){k();if(t())break;g();r();}f();m.SetWindowSize(u+4,h+6);m.SetBufferSize(u+4,h+6);n(1,h+3);w("        Game over,\n   press any key to retry.");f();m.ReadKey(1>0);m.Clear();}}private bool t(){if(c.x<0||c.y<0||c.x>=u||c.y>=h){r();n(c.x+2,c.y+2);w("X");return 1>0;}for(i=0;i<p.Count;i++){for(int j=0;j<i;j++){if(p[i].x==p[j].x&&p[i].y==p[j].y){r();n(c.x+2,c.y+2);w("X");return 1>0;}}}return 0>1;}private void e(){a=(z.Next(u),z.Next(h));l++;}void f(){while(m.KeyAvailable)m.ReadKey(1>0);}int i;void k(){var b=DateTime.Now;while((DateTime.Now-b).TotalMilliseconds<230)Thread.Sleep(10);if(!m.KeyAvailable)return;var a=m.ReadKey(1>0).Key;switch(a){case ConsoleKey.A:if(d.x==0)d=(-1,0);break;case ConsoleKey.W:if(d.y==0)d=(0,-1);break;case ConsoleKey.S:if(d.y==0)d=(0,1);break;case ConsoleKey.D:if(d.x==0)d=(1,0);break;}f();}void g(){c.x+=d.x;c.y+=d.y;p.Add((c.x,c.y));while(p.Count>l)p.RemoveAt(0);if(c.x==a.x&&c.y==a.y)e();}void r(){n(1,1);w("/");w(new string('-',u));w("\\");n(1,h+2);w("\\");w(new string('-',u));w("/");for(i=0;i<h;i++){n(1,i+2);w("|");n(u+2,i+2);w("|");}for(i=0;i<h;i++){for(int j=0;j<u;j++){n(i+2,j+2);w(" ");}}n(a.x+2,a.y+2);w("@");for(i=0;i<p.Count;i++){n(p[i].x+2,p[i].y+2);w("#");}n(2,0);w("Score:"+l);}Random z=new Random();}

Some screenshots:

<no longer have binaries, you can compile yourself>

Console.Write("Score:"+l);Console.WriteLine() -> Console.WriteLine("Score:"+l)

Have you tried tuples as in (int X,int Y)d; ...; d=(0,-1)? That might save bytes. I also can't see why are you doing Vector2 d;Vector2 c;Vector2 a; instead of Vector2 d,c,a. I think you can also store the Console.SetCursorPosition function as a Action<...> single-letter variable. You can subtract DateTime with the - operator. You can also declare loop variables globally and simply zero them out when needed, without declaring them.

[suggestions continue] You can use 1>0 or store true in a variable instead of using the keyword. You might be able to use the glorious --> operator in the loops. In the DateTime b = DateTime.Now part, b can be var. You might or might not be able to save some bytes using dynamic (often lets you merge differently-typed declarations).

Pulling m.write(String) into it's own one-letter long function would probably save a ton

There's also a few blocks  that use b.width and b.height a lot that could probably be saved to another 1 letter-named local var

I'm using lambda (int x,int y)=>{etc} instead of Action for Console.SetCursorPosition, but I get the exact same length as before (1,973). If I remove the int types (x,y)=>{etc} then I get shorter!

Few more observations: h and u look to be the same value of 25 and never change meaning you can just drop one (unless I'm missed something). Your switch can end with default handling D (side-effect of all non-WASD being read as D but oh well) and doesn't need a break. while(p.count>1)p.remove(0) is a lot of code to get the last element (not sure how to do it better offhand though). There's a still few variable declarations that can be combined (e.g. int l,h,u).

Applesoft Basic - 478 (462)
This was my first ever code golf, but it was written back in 1989, and it mostly implements the snake game as requested (but without food, the snakes just continuously grow, and it's actually two players, not one) using only two lines of Applesoft Basic.
There were a number of two-line program contests at the time, such as in Dr. Dobbs journal.  I spent 6 months figuring out how to fit this into two lines which have a limit of 255 characters (and only one branch)
More info at:  http://davesource.com/Projects/SpeedWaller/
The program typed in is exactly two lines:
1ONSCRN(X,Y)<>7ANDB<>0ANDSCRN(U,V)<>7GOTO2:HOME:GR:X=10:Y=20:U=30:V=Y:I=201:J=202:K=203:M=205:W=215:A=193:S=211:Z=218:O=1:Q=-1:P=49152:COLOR=7:HLIN0,39AT0:HLIN0,39AT39:VLIN0,39AT0:VLIN0,39AT39:VTAB22: ?"WASZ IJKM  "C:ONB=0GOTO2:CALL-678:RUN
2PLOTX,Y:PLOTU,V:B=PEEK(P):G=B<>ZANDB<>W:H=B<>AANDB<>S:O=G*(O*H+(B=S)-(B=A)):L=H*(L*G+(B=Z)-(B=W)):G=B<>IANDB<>M:H=B<>JANDB<>K:Q=G*(Q*H+(B=K)-(B=J)):R=H*(R*G+(B=M)-(B=I)):X=X+O:Y=Y+L:U=U+Q:V=V+R:FORN=1TO99:NEXT:C=C+1:VTAB22:HTAB12:?C:GOTO1

The listing when formatted looks like this:
1 ONSCRN(X,Y)<>7 AND B<>0 AND SCRN(U,V) <> 7 GOTO 2: HOME : GR :
  X=10 : Y=20 : U=30 : V=Y : I=201 : J=202 : K=203 : M=205 : W=215 :
  A=193 : S=211 : Z=218 : O=1 : Q=-1 : P=49152 : COLOR=7 : HLIN 0,39
  AT 0 : HLIN 0,39 AT 39 : VLIN 0,39 AT 0 : VLIN 0,39 AT 39 : VTAB 22 :
  ? "WASZ IJKM  "C : ON B=0 GOTO 2 : CALL -678 : RUN
2 PLOT X,Y : PLOT U,V : B=PEEK(P) : G= B<>Z AND B<>W: H=B<>A AND B<>S :
  O=G*(O*H+(B=S)-(B=A)) : L=H*(L*G+(B=Z)-(B=W)) : G=B<>I AND B<>M :
  H=B<>J AND B<>K : Q=G*(Q*H+(B=K)-(B=J)) : R=H*(R*G+(B=M)-(B=I)) :
  X=X+O : Y=Y+L : U=U+Q : V=V+R : FOR N=1 TO 99 : NEXT : C=C+1 :
  VTAB 22 : HTAB 12 : ? C : GOTO 1

The game is actually two players and includes "instructions" at the bottom of the page showing the keys as well as a counter so you can see how many steps you survived.  It's 478 characters, 16 of those are the instructions and counter output, so 462 if you want to shave those off.

As described, this sounds more like the Tron light cycles mini game than the snake game.

Yes, the Tron Light Cycles game is essentially 2 player snake.  That's true.

TI-Basic, 307 bytes
This one is very special to me, since I learned to program with a similar snake game on my TI-83+ (in high school, during boring classes). Also, on these calculators, golfing the programs was a real concern because of the limited space and performance
The controls are the direction keys, but they could easily be changed for awsd (although noone would want that since it's an abc layout)
codes for the keys would be: A: 41, W: 85, S: 81, D: 51
ClrHome
99→dim(ʟX
ʟX→Y
{8,16→dim([A]
For(X,1,16
For(Y,1,8
If X=1 or X=16 or Y=1 or Y=16
Then
Output(Y,X,":
1→[A](Y,X
End:End:End
8→X:7→Y:-1→V
Repeat [A](Y,X
1+I(I<99→I
Y→ʟY(I
X→ʟX(I
Output(Y,X,0
1→[A](Y,X
If X=N and Y=O or not(N
Then
Repeat not([A](O,N
randInt(2,7→O
randInt(2,15→N
End
Output(O,N,1
Output(1,1,S
S+1→S
Else
1+J(J<99→J
ʟY(J
Output(Ans,ʟX(J),"
0→[A](Ans,ʟX(J
End
getKey→G
not(G)U+(G=26)-(G=24→U
not(G)V+(G=34)-(G=25→V
X+U→X:Y+V→Y
End

Ruby 1.9 /Windows only/ (354 337 355 346 bytes)
require'Win32API';G=(W=Win32API).new g="crtdll","_getch",t=[],?I
B=(c=?#*39+h="#
#")+((S=' ')*38+h)*20+c;n=proc{c while B[c=rand(800)]!=S;B[c]=?*;S}
n[h=760];k={97=>-1,100=>1,119=>d=-41,115=>41}
(B[h]=?O;system'cls';$><<B<<$.;sleep 0.1
d=k[G.call]if W.new(g,"_kbhit",[],?I).call>0
t<<h;B[h]=?o;B[h+=d]==?*?B[h]=n[$.+=1]:B[t.shift]=S)while B[h]==S

Plays in a 20x40 board in the windows console.  The score is shown under the board.
Use WASD to control the snake, any other key to exit (forcefully!).  Edit the sleep time at the end of line 5 to control the speed.  (Or save 10 characters and make it nearly unplayable by removing the sleep entirely!)
Bonus feature: randomly fails to start (when initial piece is generated in snake's location).
I needed ~100 chars to work around the lack of a non-blocking getchar.  Apparently Ruby 1.9.3 includes a "io/console" library which would have saved roughly half of those.
And this solution is Windows specific.  There are published solutions to do the same type of thing in *nix systems, but I haven't tested them to compare the character count.
Edit:
Had to add 18 bytes after I realized that the tail only grows after eating, not after each step.
Edit 2: (Possibly) fixed crash issue, saved the 9 bytes by restricting to one food item.

I like the idea of multiple food items at once, however there is a big problem: the tail should move with the player, only growing by one character for every piece of food you collect.

You added the comment while I was working on fixing it...  If there is only supposed to be one piece, I can remove the 9.times{}, saving 9 chars.

the only requirement is that there be 1 or more piece of food at a time, so yes you could just make it 1 piece at a time, saving some characters

the game randomly crashed on me at ~140 points, not sure why. but otherwise very nice

Fixed the crash, I think.   If it crashes again, please let me know the ruby error message.

Python 3 - 644
from curses import *
import time
from collections import deque
from random import randrange as R
N,W,S,E=z=119,97,115,100
t=tuple
u=0,0
def m(s):
 a=lambda o,y,x:y.addch(o[0],o[1],x);q=lambda:(R(L-2),R(C-2));L,C=s.getmaxyx();curs_set(0);s.nodelay(1);s.border();s.refresh();r=newwin(L-2,C-2,1,1);n=deque();y,x=[L-2,0];d=N;n.append(u);c=N;p=q();a(p,r,N);a(u,s,48)
 while 1:
  if c in z:d=c
  if d==N:y-=1
  if d==S:y+=1
  if d==W:x-=1
  if d==E:x+=1
  l=n.pop()
  if (y,x) in n:return
  if (y,x)==p:p=q();a(p,r,N);n.append(l);s.addstr(0,0,str(len(n)))
  n.appendleft((y,x));a((y,x),r,S);a(l,r,32);r.refresh();time.sleep(.2);c=s.getch()
wrapper(m)

Does not quit cleanly. Piece might disappear if it spawns on top of the snake.

Bash (too many characters: ca. 1522)
t=tput
tc="$t cup"
tr="$t rev"
ts="$t sgr0"
ox=5
oy=5
((w=$($t cols)-2-2*ox))
((h=$($t lines)-2-2*oy))
trap "$t rmcup
stty echo
echo 'Thanks for playing snake!'
" EXIT
$t smcup
$t civis
stty -echo
clear
printf -v hs %$((w+2))s
printf -v v "|%${w}s|"
$tc $oy $ox
printf %s ${hs// /_}
for((i=1;i<=h+1;++i)); do
$tc $((oy+i)) $ox
printf %s "$v"
done
$tc $((oy+h+2)) $ox
printf %s ${hs// /¯}
dx=0
dy=-1
hx=$((w/2))
hy=$((h-2))
l=2
xa=($hx $hx)
ya=($hy $((hy+1)))
$tr
for((i=0;i<${#xa[@]};++i)); do
$tc $((ya[i]+1+oy)) $((xa[i]+1+ox))
printf \
done
$ts
print_food() {
$tc $((fy+1+oy)) $((fx+1+ox))
printf "*"
}
nf() {
rf=1
while((rf))
do
rf=0
((fx=RANDOM%w))
((fy=RANDOM%h))
for ((i=0;i<${#ya[@]};++i))
do
if((ya[i]==fy&&xa[i]==fx))
then
rf=1
break
fi
done
done
print_food
}
nf
ps() {
s="SCORE: $l"
$tc $((oy-1)) $((ox+(w-${#s})/2))
printf "$s"
}
ps
while :
do
read -t 0.2 -s -n1 k
if (($?==0))
then
case $k in
w|W)((dy==0))&&{ dx=0;dy=-1;};;
a|A)((dx==0))&&{ dx=-1;dy=0;};;
s|S)((dy==0))&&{ dx=0;dy=1;};;
d|D)((dx==0))&&{ dx=1; dy=0;};;
q|Q)break;;
esac
fi
((hx=${xa[0]}+dx))
((hy=${ya[0]}+dy))
if((hx<0||hy<0||hx>w||hy>h))
then
go=1
break
fi
for((i=1;i<${#ya[@]}-1;++i))
do
if((hx==xa[i]&&hy==ya[i]))
then
go=1
break 2
fi
done
$tc $((ya[-1]+1+oy)) $((xa[-1]+1+ox))
printf \
$tr
$tc $((hy+1+oy)) $((hx+1+ox))
printf \
$ts
if((hx==fx&&hy==fy))
then
((++l))
ps
nf
else
ya=(${ya[@]::${#ya[@]}-1})
xa=(${xa[@]::${#xa[@]}-1})
fi
ya=($hy ${ya[@]})
xa=($hx ${xa[@]})
done
if((go))
then
$tc 3 3
echo GAME OVER
read -t 3 -s -n1
fi

Binary - 617 274 Bytes
Base 64:
jtiO0LgAuI7AMf+50Ae4IAJg86u4//+5JgC/qALzq7kRAKtguSkAMcDzq7j//6thgceeAOLsuSYAv0oN86
thic+9BgDojADkYCR/PEh0HDxLdBM8TXQKPFB17IHHoADrDoPHBOsJg+8E6wSB76AAsAkmgD0HD5TEdAYm
gD0gdYCqT2AGHgeJ6UG+GH0B7on3R0f986T8B2FXiT4YfYD8AXQJi74YfbAgquskRUW/MAKDBhR9AaEUfb
MK9vOGxAQwqoPvA4jgMOQIwHXu6AQAX+l0/2Bmuf//AABm9/G5///38YnXgef/D4H/gAJ95on6g8Iog+oo
g/ooffiD+hJ91IHH0wDB5wImgD0JdMewB6phww==

Hex:
d88ed08e00b88eb831c0b9ff07d020b86002abf3ffb8b9ff0026a8bff302b9ab001160ab29b93100f3
c0b8abffff61abc781009eece226b9bf000d4aabf38961bdcf00068ce8e40024603c7f74483c1c744b
3c13744d3c0a755081eca0c7eb00830e04c709ebef83eb048104a0efb00026093d800f07c494067480
26203d80754faa0660071ee989be417d18ee01f7894747f3fdfca461078957183e807d01fc0974be8b
7d1820b0ebaa4524bf45023006837d14a1017d140ab3f3f6c486300483aa03efe088e430c008ee7504
e85f0074e960ffb966ffff0000f766b9f1fffff1f7d789e7810fffff810280e67dfa89c283832828ea
fa837d2883f812fad47dc78100d3e7c126023d807409b0c7aa07c361

Create a .com file from the above hex and run it in DOSBox.
Even though the qualifications says:

Speed of the game doesn't matter, as long as it is consistent

You should use the command cycles 1 if you want the game to be playable
There is also a version with no score which is 232 bytes
8ed88ed0b800b88ec031ffb9d007b8200260f3abb8ffffb92600bfa802
f3abb91100ab60b9290031c0f3abb8ffffab6181c79e00e2ecb92600bf
4a0df3ab6189cfbd0600e86c00e460247f3c48741c3c4b74133c4d740a
3c5075ec81c7a000eb0e83c704eb0983ef04eb0481efa000b00926803d
070f94c4740626803d207580aa4f60061e0789e941bee87c01ee89f747
47fdf3a4fc076157893ee87c80fc0174098bbee87cb020aaeb054545e8
03005feb9460b9ffff66f7f181e2ff0f81fa80027df089d783c22883ea
2883fa287df883fa127dde81c7d300c1e70226803d0974d1b007aa61c3

JavaScript (Node) (348 bytes)
B=_=>s.includes(c=0|Math.random()*4)?B():c;E=i=>s.includes(i)?+(i==s[0
]):i^o?9:2;D=_=>console.log(I+`\n ##\n#${E(0)}${E(1)}#\n#${E(2)}${E(3)
}#\n ##`);o=B(s=[I=0]);f='w';process.stdin.setRawMode(1).on('data',k=>
f=k);setInterval(_=>D(s.includes(z=s[0]+{w:-2,s:2,a:-1,d:1}[f])|z<0|z>
3|s[0]+z==3&&process.exit(),s=[z,...s],z^o?s.pop():o=B(I++)),99);D()

Pretty is not a requirement, right? Or easy? Or big?

You start in the top-left corner of a 2x2 grid, facing up (so you better push "d" real quick). A "9" represents a background character, a "1" is the head of your snake, any "0"s are tails, and a "2" is a piece you're trying to collect.
Browser-playable version

// Mocking Node
process = {
  stdin: {
    setRawMode: () => ({
      on(_, callback) {
        addEventListener('keydown', e => callback(e.key))
      }
    })
  }
}
process.exit = () => {
  for (let i = 0; i < 9999; ++i) clearInterval(i)
  throw new Error('Game Over!')
}

// Allow restarting
document.getElementById('run')
  .addEventListener('click', () => {
    for (let i = 0; i < 9999; ++i) clearInterval(i)
    main()
  })

function main() {
  // The game
  B=_=>s.includes(c=0|Math.random()*4)?B():c;E=i=>s.includes(i)?+(i==s[0]):i^o?9:2;D=_=>console.log(I+`\n ##\n#${E(0)}${E(1)}#\n#${E(2)}${E(3)}#\n ##`);o=B(s=[I=0]);f='w';process.stdin.setRawMode(1).on('data',k=>f=k);setInterval(_=>D(s.includes(z=s[0]+{w:-2,s:2,a:-1,d:1}[f])|z<0|z>3|s[0]+z==3&&process.exit(),s=[z,...s],z^o?s.pop():o=B(I++)),99);D()
}
<button id=run>run</button>

A slowed-down version (A 99ms interval is pretty difficult)

// Mocking Node
process = {
  stdin: {
    setRawMode: () => ({
      on(_, callback) {
        addEventListener('keydown', e => callback(e.key))
      }
    })
  }
}
process.exit = () => {
  for (let i = 0; i < 9999; ++i) clearInterval(i)
  throw new Error('Game Over!')
}

// Allow restarting
document.getElementById('run')
  .addEventListener('click', () => {
    for (let i = 0; i < 9999; ++i) clearInterval(i)
    main()
  })

function main() {
  // The game
  B=_=>s.includes(c=0|Math.random()*4)?B():c;E=i=>s.includes(i)?+(i==s[0]):i^o?9:2;D=_=>console.log(I+`\n ##\n#${E(0)}${E(1)}#\n#${E(2)}${E(3)}#\n ##`);o=B(s=[I=0]);f='w';process.stdin.setRawMode(1).on('data',k=>f=k);setInterval(_=>D(s.includes(z=s[0]+{w:-2,s:2,a:-1,d:1}[f])|z<0|z>3|s[0]+z==3&&process.exit(),s=[z,...s],z^o?s.pop():o=B(I++)),499);D()
}
<button id=run>run</button>

You know you've won when you get a max-call-stack-exceeded error :).
If you want a version that's a little nicer to play, I also golfed a 3x3 version down to 381 bytes.
B=_=>s.includes(c=0|Math.random()*9)?B():c;D=_=>s.map((c)=>b[c]=+(s[0]
==c),b=[...1e9-1+''],b[o]=2)+console.log(I+`\n ##${b.map((h,i)=>i%3?h:
'#\n#'+h).join('')}#\n ###`);o=B(s=[I=0]);f='w';process.stdin.
setRawMode(1).on('data',k=>f=k);setInterval(_=>D(s.includes(z=s[0]+{w:
-3,s:3,a:-1,d:1}[f])|z<0|z>8|(z%3!=1&&s[0]%3+z%3==2)&&process.exit(),s
=[z,...s],z^o?s.pop():o=B(I++)),99);D()

Browser-playable version

// Mocking Node
process = {
  stdin: {
    setRawMode: () => ({
      on(_, callback) {
        addEventListener('keydown', e => callback(e.key))
      }
    })
  }
}
process.exit = () => {
  for (let i = 0; i < 9999; ++i) clearInterval(i)
  throw new Error('Game Over!')
}

// Allow restarting
document.getElementById('run')
  .addEventListener('click', () => {
    for (let i = 0; i < 9999; ++i) clearInterval(i)
    main()
  })

function main() {
  // The game
  B=_=>s.includes(c=0|Math.random()*9)?B():c;D=_=>s.map((c)=>b[c]=+(s[0]==c),b=[...1e9-1+''],b[o]=2)+console.log(I+`\n ##${b.map((h,i)=>i%3?h:'#\n#'+h).join('')}#\n ###`);o=B(s=[I=0]);f='w';process.stdin.setRawMode(1).on('data',k=>f=k);setInterval(_=>D(s.includes(z=s[0]+{w:-3,s:3,a:-1,d:1}[f])|z<0|z>8|(z%3!=1&&s[0]%3+z%3==2)&&process.exit(),s=[z,...s],z^o?s.pop():o=B(I++)),99);D()
}
<button id=run>run</button>

Slowed down version

// Mocking Node
process = {
  stdin: {
    setRawMode: () => ({
      on(_, callback) {
        addEventListener('keydown', e => callback(e.key))
      }
    })
  }
}
process.exit = () => {
  for (let i = 0; i < 9999; ++i) clearInterval(i)
  throw new Error('Game Over!')
}

// Allow restarting
document.getElementById('run')
  .addEventListener('click', () => {
    for (let i = 0; i < 9999; ++i) clearInterval(i)
    main()
  })

function main() {
  // The game
  B=_=>s.includes(c=0|Math.random()*9)?B():c;D=_=>s.map((c)=>b[c]=+(s[0]==c),b=[...1e9-1+''],b[o]=2)+console.log(I+`\n ##${b.map((h,i)=>i%3?h:'#\n#'+h).join('')}#\n ###`);o=B(s=[I=0]);f='w';process.stdin.setRawMode(1).on('data',k=>f=k);setInterval(_=>D(s.includes(z=s[0]+{w:-3,s:3,a:-1,d:1}[f])|z<0|z>8|(z%3!=1&&s[0]%3+z%3==2)&&process.exit(),s=[z,...s],z^o?s.pop():o=B(I++)),299);D()
}
<button id=run>run</button>

Haskell, 579 bytes
import System.Process;import System.IO;p=('#'<$j)++"##\n";j=[0..20];r=fromEnum<$>withBinaryFile"/dev/urandom"ReadMode hGetChar;e(a,b)x|x=a|0<1=b;m s@(h@(x,y):t)d f=e(putStrLn"You Lost",do system"clear";putStr$foldr(++)p[show$length t,"\n",p,do y<-j;'#':[let z|elem(x,y)s='@'|f==(x,y)='F'|0<1=' 'in z|x<-j]++"#\n"];c<-hWaitForInput i 99;d<-e(getChar,pure d)c;a<-r;b<-r;let n|d>'s'=(x,y-1)|d>'r'=(x,y+1)|d>'a'=(x+1,y)|0<1=(x-1,y)in m(e(id,init)(h==f)$n:s)d$e((mod a 17+2,mod b 17+2),f)$h==f)$or[h`elem`t,x<0,y<0,x>20,y>20];main=hSetBuffering i NoBuffering>>m[(9,8)]'w'(9,8);i=stdin

Try it online!

C (gcc), 581 bytes
#define S++s;for(i=0,j=0;m[i][j];i=rand()%h)j=rand()%w;m[i][j]=2;
#define F for(i=0;i<h;++i){for(j=0;j<w;++j)
i,j,w=24,h=12;x=6,y=9;s;*t;c='w';
main(n){int m[h][w];for(memset(m,0,4*w*h);i<h;)*m[i++]=m[i][w-1]=1;for(srand(time(0));j<w;)j++[*m]=m[h-1][j]=1;m[y][x]=-1;S for(fcntl(0,4,2048);1;*t=-s){F n=m[i][j],putchar(n+s?n<0?'O':n-1?n-2?' ':'$':'#':'@');puts("");}printf("score:%d\n\n",s);usleep(200000);while(read(0,&n,1)+1)c=n-97&&n-'w'&&n-'s'&&n-'d'?c:n;c&2?y-=((c&4)-2)/2:(x-=(c&1)*2-1);t=m[y]+x;if(*t==2){S}else if(*t){puts("you died");break;}else F if(m[i][j]<0)++m[i][j];}}}

Try it online!
Some bytes can be saved by replacing variables w and h with fixed values, and characters O @#$ with two-digits integers, but I prefer to keep it as it is in order to make it easier to customize.

534 bytes

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
What code compiles in the most number of languages?
Excluding trivial programs, what code compiles in the most number of languages?
(By "trivial" I mean to exclude answers such as the empty program or text that will be echoed directly.)
The following code apparently compiles in all of the following programming languages (and prints something different in each one):
C, C++, Perl, TeX, LaTeX, PostScript, sh, bash, zsh and Prolog.
%:/*:if 0;"true" +s ||true<</;#|+q|*/include<stdio.h>/*\_/
{\if(%)}newpath/Times-Roman findfont 20 scalefont setfont(
%%)pop 72 72 moveto(Just another PostScript hacker,)show((
t)}. t:-write('Just another Prolog hacker,'),nl,halt. :-t.
:-initialization(t). end_of_file. %)pop pop showpage(-: */
int main(){return 0&printf("Just another C%s hacker,\n",1%
sizeof'2'*2+"++");}/*\fi}\csname @gobble\endcsname{\egroup
\let\LaTeX\TeX\ifx}\if00\documentclass{article}\begin{doc%
ument}\fi Just another \LaTeX\ hacker,\end{document}|if 0;
/(J.*)\$sh(.*)"/,print"$1Perl$2$/"if$_.=q # hack the lang!
/
sh=sh;test $BASH_VERSION &&sh=bash;test $POSIXLY_CORRECT&&
sh=sh;test  $ZSH_VERSION && sh=zsh;awk 'BEGIN{x="%c[A%c[K"
printf(x,27,27)}';echo "Just another $sh hacker," #)pop%*/

That's 10 different languages.  I found it via pts oldalai (who also has a magnificent Christmas poem written in C, C++, Perl and TeX).  Can anyone do better?

The technical term being Polyglot

Here's 16 language polyglot

If sh, bash, and zsh count as different languages even when it's essentially only using sh then I think you need to specify precisely what you count as different languages. E.g. Perl 4 vs Perl 5.10 have some significant differences.

@PeterTaylor: Point taken, and many languages are likely to be similar, e.g., C/C++, Tex/LaTeX.  Perhaps that's the nature of the game - to win you have to target the language that has the most number of near-variants.

@st0le: Thanks for that, I failed to find the name for this type of program (and I am surprised to find that this is the first use of the polyglot tag on this site).

@shamp00, infact when you try to access a deleted question on stackoverflow they show you a polyglot :D see here

Coming to your no empty file restriction, IIRC an empty file  doesn't compile in GCC.

There are languages (e.g. Whitespace, BrainF**k and Perl), where pretty much any character combination is a valid program. They can be claimed by any program.

Code to print the name of the interpreter, which can distinguish between Thomson (osh), Bourne, Bourne-again, Korn, Z, (T)C, Policy-compliant Ordinary, Yet Another, rc, akanga, es shells, wish, tclsh, expect, perl, python, ruby, php, JavaScript (SpiderMonkey shell and JSPL at least), MS/Wine cmd.exe, command.com (MSDOS, FreeDOS...)

SO's original polyglot: http://meta.stackexchange.com/questions/28625/whats-the-joke-in-the-stack-overflow-404-page-code

3 Languages - C, C++, and Python
#ifdef _cplusplus
    #include <iostream>
    #define print() int main(){cout << "Hello world! -- from C++" << endl;}
#elif (defined __STDC__) || (defined __STDC_VERSION__)
    #include <stdio.h>
    #define print() int main(){printf("Hello world! -- from C\n");}
#else
import builtins
print = lambda : builtins.print("Hello world! -- from Python")
#endif

print()

Something different is printed in each language. In C & C++, lines starting with '#' are preprocessing directives, but those same lines are comments in Python.

5 languages- Thue, Brainf***, Boolf***, Treehugger, and Javascript
/*::=
alert::=~This is Thue!
::=
-><[[--->+<]>-.[---->+++++<]>-.+.++++++++++.+[---->+<]>+++.-[--->++<]>-.++++++++++.+[---->+<]>+++.+[->++<]>.---[----->+<]>-.+++[->+++<]>++.++++++++.+++++.--------.---[->+++<]>+...---------.[-]]
^^[[--->+^]>-.[---->+++++^]>-.+.++++++++++.+[---->+^]>+++.-[--->++^]>-.++++++++++.+[---->+^]>+++.>-[--->+^]>-.-[--->+^]>+.-------------..+++.[--->+^]>---.++[->+++^]>++..--.+++++++++++++.[--->+^]>-----.[-]]
-+[+;;+;+;+;+;+;+;;;;+;+;+;;+;+;+;;+;+;+;;+;+;;+;;+;;;+;;;;;;+;+;;+;+;;+;+;+;;+;+;;+;;+;;;+;;;;;;+;+;;;+;+;;;;+;+;+;;;;+;+;;+;+;;;;+;+;;+;;;+;;+;+;;+;;+;;+;;+;;+;;+;+;+;+;+;+;;;+;+;+;+;+;+;;;+;+;+;+;+;+;;+;+;;;;+;+;;]
*/alert("This is Javascript!")

Note that the Treehugger portion times out in the web-based implementation, unfortunately, so you should use a different Treehugger interpreter.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
List of paths to nested dictionary
Given a list of nested menu items,
items = [
    '3D/Axis',
    '3D/CameraTracker',

    'Color/Invert',
    'Color/Log2Lin',

    'Color/Math/Add',
    'Color/Math/Multiply',

    'Other/Group',
    'Other/NoOp',

    'Views/JoinViews',
    'Views/ShuffleViews',

    'Views/Stereo/Anaglyph',
    'Views/Stereo/ReConverge',
]

..and a dummy function to be triggered by each item:
def msg(path):
    """Dummy function used in menu
    """
    return path.lower()

Programatically create a hierarchal collection of dictionaries, which is equivalent to manually typing this:
menu = {
    '3D': {'Axis':                     lambda: msg('3D/Axis'),
           'CameraTracker':            lambda: msg("3D/CameraTracker")},

    'Color': {'Invert':                lambda: msg('Color/Invert'),
              'Log2Lin':               lambda: msg('Color/Log2Lin'),

              'Math': {'Add':          lambda: msg('Color/Add'),
                       'Multiply':     lambda: msg('Color/Multiply')}},

    'Other': {'Group':                 lambda: msg('Other/Group'),
              'NoOp':                  lambda: msg('Other/NoOp')},

    'Views': {'JoinViews':             lambda: msg('Views/JoinViews'),
              'ShuffleViews':          lambda: msg('Views/ShuffleViews'),
              'Stereo': {'Anaglyph':   lambda: msg('Views/Stereo/Anaglyph'),
                         'ReConverge': lambda: msg('Views/Stereo/ReConverge')}}},

..which could be tested as follows:
assert menu['3D']['Axis']() == '3d/axis'
assert menu['Color']['Invert']() == 'color/invert'
assert menu['Color']['Math']['Add']() == 'color/math/add'
assert menu['Views']['Stereo']['Anaglyph']() == 'views/stereo/anaglyph'

Code golf questions should go to [codegolf.se], it was decided that they don't belong here anymore (AFAIK).

@dbr If you'd like this migrated, go ahead and flag for it.

...except we usually don't take gratuitously language-specific questions here :-/

A simple recursion will do the work
def build_nested_helper(path, text, container):
    segs = path.split('/')
    head = segs[0]
    tail = segs[1:]
    if not tail:
        container[head] = lambda: msg(text)
    else:
        if head not in container:
            container[head] = {}
        build_nested_helper('/'.join(tail), text, container[head])

def build_nested(paths):
    container = {}
    for path in paths:
        build_nested_helper(path, path, container)
    return container

menu = build_nested(items)

squashed code: 159 chars
def f(p,t,c):
 s=p.split('/');a=s[0];b=s[1:]
 if b:
  if a not in c:c[a]={}
  f('/'.join(b),t,c[a])
 else:c[a]=lambda:msg(t)
menu={}
for i in items:f(i,i,menu)

squash s=p.split('/');a=s[0];b=s[1:] to a,b=p.split('/',1)

@eumiro nice one! didn't know the second argument before.

#!/usr/bin/env python3

from itertools import groupby
from pprint import pprint

items = [
    '3D/Axis',
    '3D/CameraTracker',

    'Color/Invert',
    'Color/Log2Lin',

    'Color/Math/Add',
    'Color/Math/Multiply',

    'Other/Group',
    'Other/NoOp',

    'Views/JoinViews',
    'Views/ShuffleViews',

    'Views/Stereo/Anaglyph',
    'Views/Stereo/ReConverge',
]

def fun(group, items, path):
    sep = lambda i:i.split('/', 1)
    head = [i for i in items if len(sep(i))==2]
    tail = [i for i in items if len(sep(i))==1]
    gv = groupby(sorted(head), lambda i:sep(i)[0])
    return group, dict([(i, path+i) for i in tail] + [fun(g, [sep(i)[1] for i in v], path+g+'/') for g,v in gv])

menu = dict([fun('menu', items, '')])['menu']
pprint(menu)

{'3D': {'Axis': '3D/Axis', 'CameraTracker': '3D/CameraTracker'},
 'Color': {'Invert': 'Color/Invert',
           'Log2Lin': 'Color/Log2Lin',
           'Math': {'Add': 'Color/Math/Add',
                    'Multiply': 'Color/Math/Multiply'}},
 'Other': {'Group': 'Other/Group', 'NoOp': 'Other/NoOp'},
 'Views': {'JoinViews': 'Views/JoinViews',
           'ShuffleViews': 'Views/ShuffleViews',
           'Stereo': {'Anaglyph': 'Views/Stereo/Anaglyph',
                      'ReConverge': 'Views/Stereo/ReConverge'}}}

fun() takes 6 lines
Just change path+i to (path+i).lower() to get what you want.

JavaScript (V8), 134 bytes
menu=items.reduce((a,x,_,$,c=a,s=x.split`/`)=>s.slice(0,-1).map(v=>c=c[v]?c[v]:c[v]={})&&(c[s[s.length-1]]=()=>x.toLowerCase())&&a,{})

Try it online!

As a starting point,
def populate_dict(item, existing_dict, fullpath = None):
    if len(item) == 1:
        existing_dict[item[0]] = lambda p=item[0]: msg(fullpath + "/" + item[0])
    else:
        head, tail = item[0], item[1:]
        existing_dict.setdefault(head, {})
        populate_dict(
            tail,
            existing_dict[head],
            fullpath = "/".join([x for x in (fullpath, head) if x is not None]))

menu = {}
for i in items:
    populate_dict(i.split("/"), menu)

..which can be squashed down to:
def p(i,e,fp=""):
 if len(i)<2:e[i[0]]=lambda p=i[0]:msg(fp+"/"+i[0])
 else:p(i[1:], e.setdefault(i[0], {}),"/".join([fp, i[0]]).lstrip("/"))
menu = {}
for i in items:p(i.split("/"),menu)

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Write a program that always outputs "2012" - even if it's modified!
This idea is not mine, though I don't know where it originated. I once met it in a programming contest very long ago (1998, if I remember correctly). The task is to write a program in your favorite language that outputs 2012 and only 2012. The catch is that the program must still output 2012 after any one of its characters is modified. The modification can be either insertion, deletion or replacement. Of course, the modification will be such that the program is still syntactically valid.
Since I don't know all the programming languages, I have to ask the audience to help me and test the answers submitted.
Added: Many have commented that my definition of acceptable modifications is too vague. Here's my second attempt: The allowed modifications will leave your program syntactically valid and will not cause it to crash. There, I think that should cover all the compile-time, link-time and run-time errors. Though I'm sure that there will be some odd edge case in some language anyway, so when that comes up we'll look at it individually.

How about runtime errors like reading a most likely invalid address?

@PeterTaylor - There are 3 answers already, the C one with heavy revising. You can look for inspiration there.

@eBusiness - Slippery slope. For an interpreted language syntax errors can also be "runtime errors". However I'm on the side of the contestant. Runtime errors are also disallowed (that is, the changed character will not make those).

@Vilx-: Adding link-time errors to that list might be useful as well. ;)

Hint: In theory, your code should have 2012 written twice. :)

@muntoo: You're going to have to prove that; I can't see the number of "2012"s going below 3.

You need not write 2012 even once, just write 2011+1 instead.  I donno if you could encode 2012 as a series of mathematical operations so that 2012 isn't ever even "encoded twice".

Anyone figured out if this is impossible in APL or GolfScript or similarly terse?

This has got me thinking about DNA and redundancy and the potential for cosmic rays to flip bits in my programs. Interesting stuff.

... You need some sleep.

@Vilx- Not until I finish listening to Dream Theater! (But yeah... [GMT-8:00].)

@muntoo: And I'm saying that you need at least 3. Even if 3 is bigger than 2, "at least" implies that it is doable at least. In any case, one could get cute and say "you only need 2011+1" or similar, but that's besides the point, and not likely helpful in code golf, in any case.

Well... actually... this wasn't really meant as a golf... but seems like people enjoy doing that, so have fun! :)

@Vilx-: Now you tell me. :P

Well, I didn't really mention the word "golf" anywhere, did I? XD

@Vilx-: Indeed.

The original version where the program had to output 2012 was interesting, but now that you also allow for the program to crash, it’s much less interesting.

@timwi.  I think you misread it, it's not allowed to crash.  Also, if a modification causes the program to print/echo 2012 twice does it fail?

@mellamokb: The question as phrased clearly allows programs in which a single-character modification may make it compile and then crash.

From OP (in Added section): The allowed modifications will leave your program syntactically valid and will not cause it to crash.  I read that as you can't crash it with your one-character modification.  However that was a clarification to the question that probably wasn't present when you wrote your previous comment :)

Actually it was already present when he wrote the previous comment, and yes, that's exactly what I mean - you don't have to worry that the modification will make your program crash. Or even cause it to behave in an "undefined way" (which is often the case with C/C++).

@Vilx-, how much output is allowed? 20122012 would work for PHP/HTML. Does 2012 just need to appear in the output, or should it be the only output?

@zzzzBov - it has to be the ONLY output. Just the 4 characters "2012" - no more, no less.

I've make a python script to judge all the python solutions. The script breaks the first and the third python solutions, with many different methods. And the second solution use lambda to guard itself, is unbreakable. The second python solution is in python 3. I modified it into python 2 format and then judge program broke it. Here is the judge script.  from StringIO import StringIO import sys def run(prog, atexp=True): stdout = sys.stdout fakeOut = StringIO() try: sys.stdout = fakeOut # exec prog # running exec directly will break some solutions by mistake

I think this is where you get most of your rep... (right now +488)

@EriktheGolfer - Umm, ok?

@Vilx- I mean, this is the post that has granted you most of your rep points. If you made this post CW, you will entirely transform to an almost-low-rep user. (Don't do it)

@EriktheGolfer - I don't have a button to do that anyway. :) Also, I don't care much about rep.

It's funny how everyone instinctively puts the program size in their answer even though this is not code golf.

I worked pretty hard to make this work in my fungoid esolang, but as ; (terminate with no output) could be inserted (or replace) just about anywhere and having to detect that (and not produce doubled output) was basically impossible. eg. if >"2012"@ prints correctly (and assume partially hardened), then >;"2012"@ prints nothing. >">"2012"@"... with ... being some kind of validation check would catch a similarly inserted semicolon...but it would also detect most other changes and output 20122012. Oof.

Would a proof that this task is impossible in some language be a valid submission?

@Khuldraesethna'Barya - Well, it's not what I had in mind, but why not? It's certainly on topic as far as I'm concerned.

C, 53 characters
main(){register*a="2012";(puts("2012"==a?a:"2012"));}

A bit longer than the scripting language answers, and follows the same basic principle. Relies on the fact that due to the constraints of C's syntax, the only letters that would be possible to change without making the program invalid are within the strings!
Edit: Shaved off 4 characters.
Reedit: Robustness increased, shaved off one character.
Re-redit: Longer, but more robust. Just try your & now! (Correctly this time).
Update: Shortened a bit; defeats most approaches seen so far.
Update: Changed int to void; should defeat the last possible approach to break it I can think of.
Update: I thunk of another approach; replacing the last a (may it rot) with 0; using two-letter names should deal with that problem.
Update: Last update revoked; assuming changes causing runtime errors are disallowed; a will work just fine.
Update: Backtracking some more; attempting to dereference *a will also segfault; so using void to tease a compile error out of it should not be necessary.
Update: And a final shortening; that relies on the string "2012" being placed at but one address (which is common); and that literal strings are read-only (also common).
Update: It cost me two characters, but I defeated your puny semi-colon!

main(){int a="2012";puts(strcmp(a,"2012")?"2012":&a);}

@M.Joanis: Excellent point; addressed. :)

1-a instead of the last -a gives output 012.

@Howard: That last a is nothing but trouble, no matter how I phrase it. :P

Out of interest, why register int ?

@PaulR: Good point.

@PaulR: Now changed to register void; The register is there to prevent &; the void is there to prevent *.

I can still put a ! before the last st, although that causes a runtime error on my VC++2008, so I guess it don't count. Not sure what the puts() should do according to the C standard.

@Vilx-: Putting a ! before the last st returns 0; which is NULL; and any attempt to dereference that should quite rightly give a segmentation fault. puts() needs to dereference the pointer to do it's thing, so it's well-behaved.

Well, I expected that. Though it's also feasible (intuitive) that it could have detected the special case of NULL and output nothing. But you're right.

@Vilx-: C doesn't really "do" special cases; especially not of NULL. ;)

Now a small mistake: you have to invert the ternary otherwise you may just change the literal string.

main(){register*a="2012";puts("2012"==a?&a:"2012");} This doesn't work on ideone, but it works on my cygwin installation. Hm.

@Howard: Did that. :)

@M.Joanis: Hate to break it to you, but the cygwin is wrong: Using & with a register variable is explicitly verboten by the standard.

@WillihamTotland: Yeah, it doesn't make any sense... I'm just suprized it works the exact same way it did when I compiled de version in my very first comment above. /me sad @ cygwin

@M.Joanis: It's understandable, tho'; what the cygwin compiler is doing is probably treating the register keyword as auto; which in and of itself isn't all that terrible; most compilers probably that anyway. The issue is that it imbues register with the semantics of auto; and forgets that while most other compilers might deal with it like that; that doesn't make it any more right.

Using "2012"-=a or "2012"=-a results in UB.

@muntoo: Getting compile errors for both of those from where I'm sitting.

OK... correct me if this is invalid C, but it just worked on my VS2010. Insert a ; between puts and (.

@Vilx-: That is indeed correct and legal. Attempting to defeat it as we speak.

@Vilx-: And it's defeated. :)

Arrrrgh! *Returns to the shadows to plot his revenge*

How about using a comma instead of a semicolon?

@PeterTaylor That gives me a compiler error.

+1, Congratulations, I think you've nailed it.  I wrote a simple test harness that tried to compile and run every possible one-char variation of your code, and every single one of them either did not compile, crashed or printed 2012!  (I only used printable ASCII characters for the insertion and substitution tests, but I doubt expanding the repertoire would help.)

Wow... awesome... This will highly likely be the accepted answer, but I'll wait a while before accepting so that people don't lose interest.

@IlmariKaronen: Heh, that's a lot of effort; thanks for going through all that. :)

putc ruins the show.

@Fors: In my test, making puts putc throws a compile error.

When I compile it using Clang and GCC it doesn't throw a compile error, but it does using ICC (but then ICC throws an error on main(){putc(48);} as well).

I guess that in the end it is odd that Clang and GCC accepts putc(a). Oh well, putc as least ruins the show using Clang or GCC, as they are showing some odd behaviour.

@IlmariKaronen You should mention which compiler (and compiler settings) you used. For example, this program is easily invalidated on a compiler that doesn't merge string literals, so that "2012"==a is false and the output can be changed by changing the last string literal. I think replacing the last "2012" by 1 ? "2012" : "2012" would fix that.

putc requires a stream as second parameter; as does fputs. But what about "2012"!=a?

@Titus: If you mean switching == for != in the ternary, that gets you nowhere; instead of outputting a it now outputs "2012".

Some env. main(){register*a="2012";(puts("2012"==a?0:"2012"));} print nothing

Haskell, 19
(\xx@2012->xx)$2012

or, as a full program,
29
main=print$(\xx@2012->xx)2012

For a bit more fun:
(\l@(_:_:t:[])->t:l)['0'..'2']

To get one that can't be modified in such a way that yields merely a runtime error, we can encode the information in the lengths of lists which can't be modified using just one-character-changes, i.e.
map(head.show.length)[[(),()],[],[()],[(),()]]

To make it more modifiable (safely), we can also use the number itself as list element – just need to make it strings to prevent exchanging commas for plus':
map(head.show.length)[["2012","2012"],[],["2012"],["2012","2012"]]

As this string is just the result of the expression, we can also again substitute it with that – not a problem thanks to Haskell's lazyness
64 72
a=map(head.show.length.init)[[a,a,a],[a],[a,a],[a,a,a]]
main=putStrLn a

The init acts as "minus one, but non-negative" here.

We can also include the type system in the redundancy scheme and then write the number in a way that could be modified with one-character changes...
u :: Enum a => (a,[b])->(a,b)
u(a,[b]) = (succ a , b)
p :: (a,b)->(a,[b])
p(a,b) = (a,[b])

ι :: (Int,())           -- Integral type to make sure you can't make it 0/0
ι = (\n -> (n-n,()))0

twothousandandtwelve = map(head.show.fst) [ u.p.u.p$ι , ι , u.p$ι , u.p.u.p$ι ]

(GHCi> twothousandandtwelve ≡> "2012")
You could now change any one u to p vice versa, but that would always mess up the deepness of list stackings in the second tuple element and thereby trigger a compile-time error.
This idea could be expanded further in such a way that whole texts could be encoded compactly, easy to read and edit, and still safe from modifing single characters.

And yet another one...
main = print N2012
data Counter = Τv |Πy |Υj |Cε |Ho |Φϑ |Ωm |Sg |Πl |Pt |Yϑ |Γσ |Km |Φz |Εα |Av |Ζρ |Ηρ |Εv |Κs |Rζ |Γϑ |Οc |Dι |Rυ |Λd |Bγ |Wt |Xε |Ωη |Ιa |Hζ |Ed |Qj |Wπ |Κw |Qu |Γο |Oι |Mσ |Ωκ |Yg |Kυ |Aj |Du |Λζ |Nζ |Θτ |Pε |Yf |Βa |Τγ |Qx |Jη |Pδ |Iq |Ωn |Fv |Kl |Ψη |Δj |Θσ |Hd |Θq |Υs |Ht |Fρ |Jh |Lζ |Hμ |Υι |Ρζ |Ρv |Dυ |Wo |Iχ |Iζ |Γy |Kr |Sσ |Iμ |Μο |Xw |Εμ |Cσ |Yξ |Aq |Jf |Hσ |Oq |Hq |Nυ |Lo |Jκ |Ρz |Οk |Θi |Θα |Αη |Gh |Lξ |Jm |Ων |Zu |Μc |Qη |Κγ |Αψ |Χζ |Hρ |Γρ |Uϑ |Rj |Χγ |Rw |Mω |Πζ |Θρ |Ωd |Υh |Nt |Tη |Qψ |Θω |Εχ |Iw |Σx |Ηn |Mτ |Xt |Yx |Φε |Hh |Wη |Mf |Ψχ |Νγ |Βξ |Aϑ |Qp |Τϑ |Φm |Uy |Gy |Cd |Bχ |Λl |Οτ |Εa |Df |Li |Aι |Yi |Νκ |Vc |Γx |Φρ |Φp |Nξ |Kf |Tw |Λξ |Φn |Λa |Oψ |Υχ |Fψ |Xω |Τq |Οσ |Σj |Θψ |Το |Νr |Ιπ |Τi |Dτ |Φf |Μn |Χm |Ηε |Wa |Αχ |Uδ |Λf |Ρu |Qk |Wα |Uρ |Τζ |Lg |Qy |Τν |Jϑ |Βδ |Mε |Μι |Πβ |Bη |Eκ |Κz |Ηh |Fδ |Σp |Εγ |Qφ |Μτ |Νχ |Ψν |Pw |Χz |Εϑ |We |Nπ |Tυ |Wg |Bh |Tρ |Ζν |Λm |Ag |Dσ |Πι
                |Oη |Nν |Χl |Χp |Sξ |Πt |Οϑ |Wο |Yη |Cp |Tm |Ξs |Εβ |Ιb |Ρρ |Fs |Um |Ep |Jλ |Rρ |Ρξ |Ua |Οq |Γξ |Zη |Nη |Qτ |Nc |Ez |Xσ |Yφ |Ρy |Yε |Ετ |Φκ |Λω |Ωα |Μκ |Φw |Mt |Tk |Sf |Ηξ |Οb |Νπ |Κε |Mι |Kz |Vi |Ξx |Ψs |Αο |Qδ |Kt |Aσ |Οm |Ψδ |Λγ |Ακ |Hα |Wϑ |Τμ |Γγ |Jδ |Ικ |Ηϑ |Μp |Zo |Κn |Qz |Δe |Pe |Jο |Qι |Tu |Jν |Ξμ |Πω |Αm |Θw |Nε |Dy |Zξ |Υα |Dβ |Hο |Χv |Gr |Ωl |Jb |Σl |Vζ |Ξ  |Nx |Qs |Βh |Qg |Νx |Co |Rσ |Νυ |Χg |Ρt |Wy |Ηκ |Οa |Yμ |Uj |Uξ |Op |Μr |Ζα |Ξw |Mυ |Ar |Ργ |Zζ |Sv |Vy |Βo |Κι |Vϑ |Ξι |Uζ |Fμ |Su |Ιξ |Fϑ |Hi |Hw |Mv |Χχ |Θg |Sν |Pp |Mπ |Pk |Bκ |Lυ |Ρλ |Ιr |Uλ |Νo |Κο |Nh |Lε |Sw |Ξλ |Zυ |Mr |Bv |Κπ |Aγ |Dv |Pd |Ξσ |Μg |Oπ |Χξ |Nj |Kψ |Ξπ |Mκ |Gn |Ωe |Gγ |Pν |Yz |Nl |Οο |Ic |Pz |Ξf |Νω |Υμ |Ηq |Nw |Θm |Μx |Jε |Φy |Οz |Ξz |Ti |Οψ |Φγ |Tψ |Oγ |Zϑ |Ιk |Σw |Rf |Υi |Ωp |Vr |Υτ |Xl |Οβ |Πb |Δν |Οu |Jα |Ττ |Κl |Pf |Iκ |Gk |Πe |Σu |Δβ |Ωh |Nλ |Ξt |My |Πs |Βr |Mγ |Δω |Le |Zρ |Θv |Σs |Ηd |
               Bn |Κu |Δξ |Pτ |Ηα |Δu |Πμ |Ρh |Bω |Τλ |Gt |Αρ |Sh |Aο |Θδ |Δπ |Wq |Tφ |Γo |Γf |Λβ |Xυ |Mη |Δw |Qυ |Vν |Βτ |Γα |Μm |Μπ |Κζ |Θd |Fε |Ρτ |Οn |Αs |Wu |Ξh |Μz |Αν |Aε |Yq |Τε |Cz |Ωu |Ec |Ds |Wρ |Θϑ |Κp |Τδ |Mδ |Ηy |Go |Sb |Rξ |Σϑ |Yο |Jg |Vh |Kσ |Nδ |Ηψ |Γh |Rk |Eο |Μk |Ζk |Ψο |Ψμ |Zσ |Pβ |Ρd |Us |Hυ |Βi |Mχ |Σr |Βι |Sχ |Zγ |Δα |Sτ |Γp |Ns |Sn |Νn |Pξ |Νa |Sω |Σi |Τφ |Xο |Eδ |Ba |To |Vj |Sl |Κκ |Δh |Τχ |Gυ |Ρϑ |Bs |Dh |Μσ |Vd |Iϑ |Kg |Νμ |Dμ |Σγ |Πg |Γg |Εt |Fa |Ψn |Ρx |Αj |Mβ |Kλ |Ξψ |Fω |Qζ |Θj |Kπ |Gf |Oe |Yυ |Κk |Wω |Bδ |Lο |Cβ |Nf |Ol |Σo |Fn |Τβ |Βω |Dn |Ha |Πλ |Ss |Σy |Kϑ |Lp |Dδ |Dψ |Ωo |Xγ |Χk |Ωσ |Δa |Sκ |Jμ |Κt |Rc |Ηc |Lχ |Oε |Μλ |Cs |Il |Tι |Ra |Zα |Ωr |Ob |Wβ |Ον |Γν |St |Xλ |Kv |No |Rε |Kd |Mν |Np |Ωc |Δζ |Nβ |Zπ |Ok |Vι |Tδ |Vδ |Γz |Χα |Μs |Βυ |Xc |Xo |Vp |Γχ |Υf |Θπ |Πj |Pi |Γj |By |Φk |Υq |Ny |Rο |Γd |Ωj |Αy |Εo |Κy |Uc |Rm |Ph |Αδ |Ιl |Ιx |Δτ |Zt |Nq |Ct |Φi |Uv |Eπ
                |Κm |Rλ |Vu |Χσ |Τn |Μe |Φη |Ξβ |Εz |Σω |Bb |Ψε |Sε |Ρm |Δο |Vξ |Φo |Ωε |Zb |Σc |Dζ |Ξp |Rη |Ιψ |Δσ |Χη |Kj |Eμ |Qν |Ri |Ip |La |Νξ |Αγ |As |Nr |Δi |Oν |Ζx |Xκ |Pr |Ελ |Λb |Ψk |Ωβ |Pl |Ιy |Cμ |Ζc |Αg |Σρ |Dw |Ρq |Ιη |Pζ |Σa |Uq |Ρμ |Lω |Fh |Ζδ |Αd |Cψ |Κσ |It |Qκ |Fν |Αb |Ηg |Ιν |Ls |Jr |Ow |Je |Zx |Ld |Jl |Ζd |Μo |Χτ |Kα |Μβ |Mo |Σλ |Xρ |Μq |Ψb |Νd |Ρβ |Wδ |Μf |Κρ |Ηb |Ξτ |Qα |Λv |Zψ |Φt |Sδ |Εh |Rκ |Rμ |Χι |Κυ |Ηj |Pχ |Pη |Jσ |Ρσ |Ιχ |Kζ |Εδ |Nω |Iψ |Γμ |Vσ |Ψρ |Χυ |Αw |Kn |Al |Gj |Zj |Αc |Aζ |Ζi |Bz |Vπ |Πw |Αu |Qf |Bf |Ξo |Ρε |Λy |En |Ey |Wi |Σχ |Τc |Dχ |Fg |Ρo |Zm |Ψω |Fq |Μa |Ηt |Wc |Kε |Κτ |Χψ |Κβ |Λφ |Κq |Υm |Πx |Pj |Mi |Δy |Κχ |Lϑ |Wτ |Lη |Nd |Ωk |Iπ |Tα |Bο |Uε |Lc |Rp |Θx |Ρη |Lu |Μζ |Εd |Gρ |Χμ |Vγ |Ιζ |Πυ |El |Uk |Hc |Ξξ |Λx |Ιο |Μy |Ζm |Jw |Iε |Σφ |Αk |Σf |Ac |Ab |Αq |Δf |Θκ |Υa |Ζτ |Jc |Xμ |Sι |Κv |Ζj |Ει |Oω |Ηδ |Φv |Dα |Fτ |Ko |Et |Ψζ |Jx |Mk |Th |Βλ |Λχ |Οo |Υπ |
               Cζ |Θy |Λk |Γδ |Iυ |Σξ |Υϑ |Cι |Cχ |Εσ |Βψ |Iα |Τη |Eυ |Lφ |Lδ |Υw |Ξο |Uσ |Δb |Nϑ |Ζγ |Δz |Cο |Mb |Ξy |Γυ |Εk |Αζ |Vα |Τυ |Ιω |Wυ |Cτ |Ιγ |Yω |Ωy |Ηp |Ψψ |Ah |Dq |Βv |Ιw |Ox |Ξv |Οζ |Tχ |Πψ |Qb |Rδ |Aψ |Zμ |Ζg |Ψφ |Nφ |Δρ |Χe |Vχ |Ηυ |Ml |Σσ |Ζμ |Sz |Πκ |Sγ |Kq |Dη |Υk |Dt |Ξe |Sc |Νs |Μv |Ev |Ji |Rχ |Xπ |Αo |Lμ |Gδ |Fσ |Λϑ |Λe |Σb |Id |Hb |Γι |Βz |Sβ |Tg |Ζο |Δk |Dl |Λσ |Κϑ |Aw |Uγ |Lx |Uψ |Hs |Ωχ |Δφ |Wσ |Π  |Εe |Ro |Λο |Ud |Fχ |Δψ |Νh |Θμ |Zd |Kb |Οδ |Ex |Να |Φσ |Φω |Pm |Λυ |Xq |Si |Σδ |Gα |Bu |Βw |Eχ |Ρι |Gβ |Vο |Yh |Σε |Χq |Hι |Re |Zχ |Ζp |Eρ |Ωγ |Bξ |Hδ |Oξ |Γc |Μγ |Wφ |Πη |Wj |Ιq |Γs |Πο |Κj |Un |Rι |Dφ |Τl |Ωz |Pμ |Wr |Gω |Gi |Εu |Σq |Ρl |Iν |Zy |Rb |Νk |Ky |Uκ |Ησ |Hy |Ir |Tp |Εc |Bw |Εο |Cm |Εw |Ψf |Yχ |Ιρ |Hβ |Ιz |Vλ |Εj |Oδ |Qρ |Θν |Aρ |Ov |Zω |Gψ |Ij |Ξη |Ps |Φh |Οg |Dp |Ta |Ty |Οe |Uο |Rγ |Οr |Θp |Hλ |Νι |Vk |Νz |Tl |Ψi |Λs |Hη |Ζκ |Rz |Hx |Fξ |Ξn |Φe |Sπ |Ηw |Dκ |Ζω
                |Sr |Vψ |Ντ |Vω |Lv |Νg |Fκ |Jψ |Ζs |Oβ |Υζ |Δg |Fυ |Yκ |Χd |Zf |Φμ |Lt |Ξd |Oφ |Τp |Κh |Ψx |Vυ |Qπ |Θφ |Nψ |Ρχ |Rx |Υz |Ξκ |Ξχ |Qn |Pu |Υψ |Az |Xj |Σd |Φξ |Ws |Xα |Βm |Βf |Lh |Hv |Aω |Hν |Kχ |Ρψ |Aδ |Χx |Sη |Φx |Cκ |Jz |Dr |Xu |Ηζ |Ξζ |Gτ |Ca |Af |Aν |Bι |Mc |Ψg |Ωv |Ωs |Qω |Mψ |Lλ |Μα |Kμ |Vl |Yσ |Οι |Ve |Dν |Eg |Ιυ |Xι |Zν |Xϑ |Νζ |Ni |Sφ |Se |Ζa |Xδ |Νv |Wι |Jv |Jt |Ιh |Υv |Cη |Τd |Ψι |Τu |Ge |Πc |Bυ |Mϑ |Χλ |Δλ |Σψ |Μϑ |Απ |Vg |Κα |Sψ |Ζz |Λδ |Aκ |Λκ |Ga |Κb |Db |Jo |Τa |Fw |Τs |Βϑ |Eτ |Wk |Ξu |Ψl |Αι |Νψ |Δι |Qμ |Υn |Bτ |Ηs |Yw |Ye |Iο |Dο |Γe |Rβ |Qv |Xs |Ηη |Yo |Χj |Dω |Οπ |Uβ |Mλ |Qh |Fο |Βd |Ζr |Οv |Zφ |Αi |Dλ |Pb |Οx |Rv |Uz |Εν |Ψτ |Na |Aη |Βu |Ιd |Ηm |Υd |Wn |Qσ |Οp |Αr |Ηλ |Σι |Br |Cu |Ωζ |Θγ |Qo |Bρ |Bψ |Zβ |Πφ |Ρκ |Qϑ |Bj |Vε |Zz |Ζϑ |Za |Θt |Τψ |Ρο |Jq |Πf |Jφ |Τα |Xχ |Χn |Vo |Αt |Bg |Gs |Bi |Rϑ |Nι |Ρa |Υr |Υν |Λo |Γφ |Δo |Yρ |Χc |Ξα |Gq |Γm |Ωμ |Ζυ |Wζ |At |Mw |
               Cf |Επ |Fo |Οh |Tσ |Ηv |Sα |Ζq |Dk |Jπ |Ιm |Mj |Oi |Ψa |Qγ |Rn |Dξ |De |Γk |Ψm |Lα |Cl |Θο |Γq |Λc |Tx |Nm |Ki |Υο |Χr |Φs |Κi |Φλ |Vq |Αω |Ch |Tμ |Xb |Ζπ |Ym |Ζn |Eω |Ξj |Υκ |Τg |Uo |Ai |Sy |Τe |Ητ |Tτ |Λg |Bp |Δq |Χo |Pπ |Dγ |Δγ |Yπ |Ys |Ωδ |Ψσ |Sζ |Πξ |Rφ |Hj |Uf |Td |Ξk |Xψ |Οj |Cx |Φπ |Gλ |Φδ |Ej |Yψ |Ae |Φφ |Jγ |Qχ |Ξγ |Δp |Σg |Is |Eσ |Λπ |Cδ |Ιe |Cυ |Oh |Hm |Tb |Qi |Οl |Bε |Eψ |Hn |Ja |Σν |Γr |Ηu |Ζξ |Ζb |Nu |Θξ |Κd |Qο |Lq |Λw |Ηf |Kξ |Ευ |Rr |Τm |Εξ |Ψp |Χh |Ξi |Fπ |Μφ |Fu |Cξ |Aα |Pγ |Sk |Cω |Ηr |Αp |Ββ |Bx |Fp |Tζ |Pω |Λp |Lm |Jp |Bl |Φc |Vf |Τz |Εy |Λμ |Rd |Νf |Πρ |Ηx |Μψ |Γη |Bα |Συ |Iσ |Γt |Κξ |Io |Ζφ |Γl |Θf |Γλ |Υγ |Ψh |Xg |Tn |Iu |Bφ |Πχ |Λq |Χπ |Bϑ |Εm |Κφ |Λt |Ιu |Ρs |Ιβ |Ωg |Yν |Lσ |Ζι |Eι |Aτ |Φa |Pα |Θz |Ψκ |Θs |Θη |Ηl |Φζ |Bt |Ρυ |On |Ξε |Tf |Gp |Mα |Μi |Kβ |Σο |Ωξ |Νl |Iz |Fk |Dj |Bπ |Nz |Xr |Mp |Χω |Sϑ |Hu |Αμ |Js |Βn |If |Τw |Ηz |Σz |Po |Yj |Ημ |Yβ |Σm |Do
                |Ηχ |Κg |Θo |Ζh |Ψj |Ψu |Ωφ |Δμ |Γa |Bν |Ιε |Oz |Νq |Υp |Qλ |Υc |Υy |Kc |Kh |Ew |Wγ |Νβ |Ωλ |Οξ |Zι |Yr |Sυ |Γπ |Bm |Μj |Pa |Os |Χδ |Κδ |Εx |Iγ |Eη |Fλ |Tγ |Yλ |Hξ |Φq |Τξ |Ql |Δn |Zn |Ot |Sa |Φψ |Nμ |Ξr |Ξc |Φj |Gl |Oλ |Rπ |Am |Mο |Gx |Fd |Cg |Χu |Lι |Wv |Ζt |Jυ |Pσ |Σκ |Wκ |Pv |Ιg |Ωι |Δx |Φl |Eb |Δυ |Cr |Nχ |Ογ |Νφ |Gu |Ασ |Λi |Rτ |Eh |Xη |Md |Wm |Tt |Πα |Υe |Βk |Ju |Dρ |Χβ |Οs |Γi |Kι |Κe |Mm |Χf |Oκ |Vb |Γβ |Οy |Vv |Νϑ |Hl |Λα |Wξ |Om |Βφ |Ρp |Φβ |Βb |Αυ |Υδ |Χφ |Pλ |Νρ |Υλ |Ul |Kγ |Qc |Νm |Πz |Hφ |Es |Ψπ |Xm |Xξ |Tν |Eλ |Ao |Ak |Ka |Ζη |Xk |Γψ |Βπ |Fβ |Βρ |Xx |Βζ |Iτ |Pϑ |Εb |Ψγ |Τk |Gm |Yn |Xν |Νu |Hϑ |Εr |Τπ |Uw |Mh |Og |Μυ |Tj |Λν |Qm |Xn |Ην |Νi |Kη |Zv |Ιι |Ση |Yk |Dx |Aχ |Ou |Fy |Cα |Θl |Γκ |Ax |Vκ |Cn |Cλ |Ξϑ |Wε |Υl |Ψt |Ωa |Θe |Ξω |Ηo |Ll |Bζ |Kw |Αβ |Δc |Oυ |Βj |Jβ |Νε |Eϑ |Ξg |Tz |Cc |Ry |Sρ |Ψz |Yα |Pq |Υg |Jn |Vμ |Σk |Ck |Ωt |Zg |Pι |Hω |Λλ |Aμ |Wλ |Ιλ |Βc |Ξa |
               Jk |Πϑ |Ιt |Εψ |Hε |Ωϑ |Εη |Ie |Κω |Yc |Iβ |Ου |Hg |Θr |Nn |Uμ |Ζv |Ζχ |Jρ |Pο |Ng |Be |Δv |Fζ |Ρe |Qe |Cq |Κf |Θλ |Tϑ |Ξq |Me |Βq |Oα |Θc |Qr |Δt |Dm |Yu |Ru |Σh |Λr |Yy |Εε |Μχ |Mφ |Δδ |Kφ |Cγ |Ζσ |Iω |Au |Wb |Κc |Πq |Ωω |Pυ |Γn |Nγ |Cv |Βχ |Φg |Gο |Ug |Kο |Βκ |Wμ |Hτ |Hχ |Ue |Οw |Sμ |Sm |Υω |Yb |Χa |Ιi |Κν |Πu |Κψ |Uτ |Lβ |Fj |Pn |Εf |Τσ |Qε |Ψo |Λρ |Oϑ |Πν |Ts |Ηο |Μρ |Ff |Ψβ |Ne |Nκ |Bλ |Bσ |Mx |Πp |Υσ |Ιn |Αz |Fz |Ηa |Uν |Mζ |Δϑ |Yι |Ζe |Ψα |Tο |Βg |Lπ |Ζf |Αλ |Em |Θh |Gπ |Γω |Kω |Tξ |Σn |So |Im |Φυ |Ξb |Ii |Λι |Xz |Kδ |Μω |Uυ |Wf |Χb |Sλ |Lγ |Οη |Ιs |Xβ |Pκ |Bc |Ιp |Od |Αn |Va |Tω |Ζw |Ιτ |Θε |Ρi |Gι |Τh |Υx |Nτ |Δη |Εφ |Kx |Xa |Gν |Ft |Yt |Qd |Gσ |Ξυ |Εs |Nσ |Νc |Λj |Υu |Ρc |Ψξ |Δm |Qβ |Μu |Υb |Nk |Ωτ |Κr |Δd |Iλ |Πa |Ωρ |Χν |Μh |Jξ |Μμ |Fc |Iφ |Zr |Ux |Φb |Πo |Gd |Eζ |Αα |Νν |Λz |Vη |Pψ |Ωf |Lρ |Cb |Ν |Α |Χ |Ω |Zτ |Τκ |Αε |Bβ |Uι |Fi |Ui |Βx |Ωq |Βp |Λh |Uu |Ωw |Xp |Ζβ |Λτ
 | N2012 deriving(Enum); instance Show Counter where show = show . fromEnum

I'm afraid this compiles just fine modified, although an exception is thrown at runtime.

@JeffBurdges: sure, I take this to be included in "and will not cause it to crash".

For the a=map(head.show.length)[[a,a],[],[a],[a,a]] solution, insert a between []. I really like this post, though! Very clever solutions.

I've verified that all 5825 variations of your 29-character program (replacing or inserting ASCII characters 32-126) work as expected. Here's the test script I used. It can easily be tweaked to test other programs, including other languages. Warning: It took almost 1 hour to run on my laptop :)

Couldn't you make it two characters less by using x instead of xx?

@FrerichRaabe: sure, but it wouldn't be modification-safe anymore.

[a] -> [] in the 64-char solution

on this solution (\l@(_:_:t:[])->t:l)['0'..'2'] if you would change @ to a space the solution would be still be syntactically valid (and in fact will have a type of Num a=>[a]->[a]) but would not be a string of "2012".

this also disqualifies your first solution :( although note this doesn't change the full program solutions as there is no Function Show instance :)

on the 72 solution you could also write a=[[a,a,a],[a],[a,a],[a,a,a]]>>=show.length.init which is shorter - but i'm not sure if it's unmodifiable...

JavaScript
I believe this is runtime error proof, any single change should either result in a compile error or a single alert saying 2012.
Edit: Code would make a runtime error on something like if("alert(2012 "==r), I moved the try section to deal with it.
Edit: Nice one Vilx-, but fixable :-) Now there is a bracket mismatch for inserting that semicolon.
Edit: But then a comma could do the same thing as the semicolon, that is a host of options, I think I have fixed it, but there is an awful lot of code now.
Edit: Simplified a bit.
Edit: One more in an infinite series of bugfixes.
Edit: This kinda feels more long and complicated than bulletproof, but it should at least take care of ~eval and !eval.
var q="alert(2012 "
var p=1
try{
    if("alert(2012 "==q){
        if(eval(((p=5,q+")")||alert(2012)))){
            if(p!==5){
                alert(2012)
            }
        }
    }
    else{
        alert(2012)
    }
}
catch(e){
    alert(2012)
}

Wow that's impressive. I spent a few minutes trying to break it but I couldn't, congratulations, but why the ||alert(2012)?

Because for instance q-")" returns NaN, which eval convert to "NaN" before evaling it, which simply turns it back to NaN. Strange thing to do, but technically legit, so that doesn't invoke the catch.

Same thing as the C solution - insert a ; between eval and (.

For the comment readers, the semicolon vulnerability is fixed, I believe the code to be clean now.

Not sure if this counts or not, but putting a ~ in front of the eval causes it to echo 2012 twice instead of once.  Not sure if that disobeys the rules or not :P

Adding a semicolon after else also alerts "2012" twice :P

Adding a ! after eval( breaks it.

Why the try while modified code can error?

Perl, 49 chars
  do{
use strict;$_=2012;;2012==$_&&0-print||die}

Based on J B's answer, but this one actually satisfies the spec.  An exhaustive check indicates that every one-character deletion, insertion or replacement either leaves the output unchanged or causes the program to crash when run (as indicated by a non-zero return value and output to stderr), at least as long as insertions and replacements are restricted to printable ASCII characters.
(Without the restriction, the task is impossible in Perl: a little-known feature of the Perl parser is that it stops when it encounters a Ctrl-D or a Ctrl-Z character, so inserting either of those in front of any file turns it into a valid Perl program that does nothing.)
Edit: Shaved off one more char by replacing 1==print with 0-print.

Breaks with Perl 5.28 where print starts returning 'true' instead of 1 :-P

@JB: Well, you can downvote it when that happens. :)  (For the benefit of other readers, this is a joke.  As far as I know, there are no plans to change the return value of print in any version of Perl 5, even if it isn't explicitly documented.)

Brainfuck
I am trying to convince myself that this is possible, and I am fairly certain I may have stretched it a bit too far. I have made a few assumptions about my environment:

An infinite loop is considered a 'crash'. A similar condition could possibly be achieved by decrementing past zero or to the left of memory location zero in certain interpreters. Many interpreters are difficult to crash at runtime. I avoid the halting problem by using only the simplest, most obvious infinite loop.
Unmatched square braces are considered a compile error.
This will only work in an environment where the program's output is piped back to it's own input. I use that to verify that it did indeed output '2012'. This is the only way I could get around simply deleting one of the output characters.

Unfortunately, if you get any stricter I fear this will be impossible. Here is my solution:
++++++++++++++++++++++++++++++++++++++++++++++++++
.--.+.+.
,--------------------------------------------------[]
,------------------------------------------------[]
,-------------------------------------------------[]
,--------------------------------------------------[]
,[]EOF = 0

Basically, you can change the output code, or the verification code, but not both. One of them is guaranteed to work. If one of them doesn't it will 'crash'.

would you have preferred he used whitespace instead?

Fail if adding . after any ]. You can claim . don't output 0 to resolve

Python2
import sys;xx='2012';(
1/(sys.stdout.write(xx=='2012' and xx or 2012)==None))

I had to change Ray's test script slightly to test this as the stdout redirect was breaking it. Passing empty dicts to exec avoids polluting the namespace
exec(prog, {}, {})

Great! You make it!

Brain-Flak, 44 + 3 = 47 bytes [Non-Competing]
This uses Brain-Flak's -A flag and outputs the characters 2012 to STDOUT
((((((((()()()){}){}){}()){})[()])[()])()())

Try it online!
Alternative, 50 bytes
(((((()()()()){}){}){}){})({({}[()])}{}[()()()()])

Try it online!
Explanation
Any single character modification to either of the codes above will cause the program to error.

Ha! The right language for the challenge.

Sisi, non-competing
Finally I think I found one of my languages that works. It's horrendously long, and the language is newer than the question, but it still feels like an accomplishment.
1 set xx 2012
2 set y xx=2012
3 jumpif y 55
4 set xx 2012
828 set x xx
829 set ax xx
830 set xa xx
831 set axx xx
832 set xax xx
833 set xxa xx
834 set bx xx
835 set xb xx
836 set bxx xx
837 set xbx xx
838 set xxb xx
839 set cx xx
840 set xc xx
841 set cxx xx
842 set xcx xx
843 set xxc xx
844 set dx xx
845 set xd xx
846 set dxx xx
847 set xdx xx
848 set xxd xx
849 set ex xx
850 set xe xx
851 set exx xx
852 set xex xx
853 set xxe xx
854 set fx xx
855 set xf xx
856 set fxx xx
857 set xfx xx
858 set xxf xx
859 set gx xx
860 set xg xx
861 set gxx xx
862 set xgx xx
863 set xxg xx
864 set hx xx
865 set xh xx
866 set hxx xx
867 set xhx xx
868 set xxh xx
869 set ix xx
870 set xi xx
871 set ixx xx
872 set xix xx
873 set xxi xx
874 set jx xx
875 set xj xx
876 set jxx xx
877 set xjx xx
878 set xxj xx
879 set kx xx
880 set xk xx
881 set kxx xx
882 set xkx xx
883 set xxk xx
884 set lx xx
885 set xl xx
886 set lxx xx
887 set xlx xx
888 set xxl xx
889 set mx xx
890 set xm xx
891 set mxx xx
892 set xmx xx
893 set xxm xx
894 set nx xx
895 set xn xx
896 set nxx xx
897 set xnx xx
898 set xxn xx
899 set ox xx
900 set xo xx
901 set oxx xx
902 set xox xx
903 set xxo xx
904 set px xx
905 set xp xx
906 set pxx xx
907 set xpx xx
908 set xxp xx
909 set qx xx
910 set xq xx
911 set qxx xx
912 set xqx xx
913 set xxq xx
914 set rx xx
915 set xr xx
916 set rxx xx
917 set xrx xx
918 set xxr xx
919 set sx xx
920 set xs xx
921 set sxx xx
922 set xsx xx
923 set xxs xx
924 set tx xx
925 set xt xx
926 set txx xx
927 set xtx xx
928 set xxt xx
929 set ux xx
930 set xu xx
931 set uxx xx
932 set xux xx
933 set xxu xx
934 set vx xx
935 set xv xx
936 set vxx xx
937 set xvx xx
938 set xxv xx
939 set wx xx
940 set xw xx
941 set wxx xx
942 set xwx xx
943 set xxw xx
944 set yx xx
945 set xy xx
946 set yxx xx
947 set xyx xx
948 set xxy xx
949 set zx xx
950 set xz xx
951 set zxx xx
952 set xzx xx
953 set xxz xx
954 set xxx xx
955 print xx

About Sisi
Sisi is a toy language inspired by assembly and QBasic. It is good for this challenge because its syntax is extremely limited.

It has only four commands: set, print, jump, and jumpif.
All commands have fixed arity.
All lines must have line numbers, which are strictly increasing.
Expressions are only allowed in set statements. They can only contain (at most) one operation, which must be binary. In particular: changing print xx to print -xx is a syntax error.
Variable names must be composed of lowercase letters.
Most importantly: there is no comment syntax!

The program
The core of the program is this part:
1 set xx 2012
2 set y xx=2012
3 jumpif y 55
4 set xx 2012
955 print xx

We store 2012 in xx, then test whether that was successful and store the test result in y. If y is truthy, jump to line 55. (Jumps to nonexistent line numbers simply fast-forward to the next line.)
Radiation hardening

If the assignment in line 1 is modified, then y is falsey, the jump doesn't happen, and line 4 sets xx to 2012.
If the assignment in line 2 or the jump condition in line 3 is modified, we don't care: xx will get set to 2012 whether we take the jump or not.
The jump target in line 3 can be changed to as small as 5 or as large as 955. Any possible modification gets it to the print on line 955 sooner or later. It isn't possible with one modification to jump backwards (creating a loop) or past the end of the program.
If the assignment in line 4 is modified, we don't care: line 1's assignment will be correct and we will jump past line 4.
If line 955 is modified, we may have a problem. The one unfortunate thing about Sisi is that uninitialized variables default to 0, so a modification like print ax isn't an error. The ugly but effective solution is lines 828-954, which assign 2012 to every possible variable with an edit distance of 1 from xx. This ensures that any modification to the final print xx will still print 2012.
If a line number is modified, either: 1) it will be out of order and be a syntax error, or 2) it won't affect the program flow. The main modification we might be worried about--changing line 4 to 94, thereby inserting it after the jump to 55--doesn't matter because all it does is assign 2012 to xx again.

Good one! I can't think of a way to circumvent this. "A" for effort from me, that's for sure! :)

T-SQL 2012, 55
DECLARE @n CHAR(4)='2012'PRINT IIF(@n='2012',@n,'2012')

What SQL dialect is this? Looks like Transact-SQL (aka SQL Server), but it has invalid syntax for that.

@Vilx-: I tested it in SQL Server 2008 myself when I was trying to break it, and it worked just fine.

@mellamokb - That's odd. It's exactly what I did, and it complained that you cannot assign a default value to variable (you need a separate SET statement), and there is no IIF (only CASE).

@Vilx-: Ah, you are correct.  I realize now I was actually testing on SQL Azure.  With SQL Server 2008 I get those same errors as you.  However, it seems to work fine in SQL Server 2012/Azure.  Here's a demo with SQL 2012: http://www.sqlfiddle.com/#!6/d41d8/27

OK, congratulations, I can't find any obvious ways of breaking this! :) That's not to say there aren't any. ;)

Note: linked fiddle now gives an error, possibly because SQLfiddle is using SQL Server 2014 and doesn't offer 2012 anymore.

Ruby 1.9 - 43 chars
qq=[:p,2012]
b if qq!=[:p,2012]
send(
*qq)

Not tested, so break away.

Excel, 14 characters (cheating slightly):
{=2012} (in a 2x1 array with one cell hidden)

Any valid change to the array will affect the contents of both cells, and attempting to change just one cell triggers an error message.
Of course, this breaks down if you take the view that it's really only one formula, as opposed to 2 formulas that are constrained to be identical.

Java 7
class M{
  static String c(){
    String a = "2012",
           b = "2012";
    return a.equals(b)           // 1
            ? a                  // 2
            : a.equals("2012")   // 3
               ? a               // 4
               : b;              // 5
  }

  public static void main(String[]a){
    System.out.print(c());
  }
}

Explanation:

Without changing anything it will take the following path: 1 → 2 (and it will return a's value of 2012).
If the content of String a is modified in any way it will take the following path: 1 → 3 → 5 (and it will return b's unchanged value of 2012).
If the content of String b is modified in any way it will take the following path: 1 → 3 → 4 (and it will return a's unchanged value of 2012).
If a.equals(b) on @1 is modified to a.equals(a), b.equals(b), or !a.equals(b) it will still take the same following path: 1 → 2 (and it will return a's unchanged value of 2012).
If a on @2 is changed to b it will still take the following path: 1 → 2 (and it will return b's unchanged value of 2012).
If either a or b is changed to the opposite on the lines 3, 4 or 5 it will still take the following path: 1 → 2 (and it will return a's unchanged value of 2012)
If the content of the String on @3 is modified in any way it will still take the following path: 1 → 2 (and it will return a's unchanged value of 2012)
Changing M in class M or a in main(String[]a) to another valid character can be done without any changes to the functionality of the code.
Any other change will result in a Compile-error (excluding some of the enters/whitespaces, which can be removed/added).

Try all these modifications here, to verify they all still print 2012.
If you can find any way to break it following OP's rules I'd love to know, so I can think of something to fix it.
Unlike most similar questions where a single char is modified, this question allows the basic structure of the programming language in question to be intact, so Java can finally compete in one enter one (let's face it, Java will -almost- never win anything on this SE xD).

What is a negative sign is inserted in path 4 before the a? Will the program still output 2012, or will it output -2012?

@KritixiLithos It's a String, so you can't insert a - before the a or b. Here is a screenshot of the Compile error.

Taxi, 396 bytes
2012 is waiting at Starchild Numerology.2012 is waiting at Starchild Numerology.Go to Starchild Numerology: w 1 r 3 l 2 l 3 l 2 r.Pickup a passenger going to Equal's Corner.Pickup a passenger going to Equal's Corner.Go to Equal's Corner: w 1 l.Pickup a passenger going to The Babelfishery.Go to The Babelfishery: n 3 r 1 r 1 r.Pickup a passenger going to Post Office.Go to Post Office: n 1 l 1 r.

Formatted for humans, that's:
2012 is waiting at Starchild Numerology.
2012 is waiting at Starchild Numerology.
Go to Starchild Numerology: w 1 r 3 l 2 l 3 l 2 r.
Pickup a passenger going to Equal's Corner.
Pickup a passenger going to Equal's Corner.
Go to Equal's Corner: w 1 l.
Pickup a passenger going to The Babelfishery.
Go to The Babelfishery: n 3 r 1 r 1 r.
Pickup a passenger going to Post Office.
Go to Post Office: n 1 l 1 r.

From reading other answers, the solution seems to be to pick a fragile language, set the value, check the value, print the value.

Tcl, 55 chars.
if {$a=={puts 2012}} [set a {puts 2012}] {
puts 2012
#}

Check if the code is unmodified, then execute it, or print 2012.
I consider accessing a undefined variable as syntax error.

## Tcl, 138 Characters
set a {set a {$a};if {\$a=={$a}} {puts 2012}};if {[info ex a]&&$a=={set a {$a};if {\$a=={$a}} {puts 2012}}} [subst -noc $a] {
puts 2012
#}

Ok, this is a quine variant: either the code is unmodified, then execute it, or simply print 2012
The last line is a little bit special: It is a comment, but the } closes the brace.

Mathematica 24
this is a simple fix to @Dr.belisarius answer (unfortunately, I can't add comments yet)
2012//.Except@2012->2012

Changing Replace (/.) to RepeatedReplace (//.) fixes the problem @Dillon found, since /// is a syntax error.

SmileBASIC
OPTION STRICT
VAR A$=@2012
GOTO A$@2012
IF SHIFT(A$)THEN VAR B
?A$VAR C
B=C

First, we enable strict mode. This forces you to declare all variables before using them, and prevents things like changing ?A$ to ?B$.
Next, a string variable called "A$" is created, and the value is set to "@2012". To make sure the value of A$ hasn't been messed with, the program will try to jump to a label, and the only label in the program is @2012.
Now, A$ is definitely "@2012", but before printing it, the @ needs to be removed. SHIFT() removes the first item in a string or array (just like pop(), but from the other end).
To discard the value returned by SHIFT, it is passed to an IF/THEN block, which does nothing.
Just in case someone tries to comment out that line, we declare a variable "B", which is used later. If the VAR is commented out, the last line will throw an Undefined variable error.
Now, A$ is printed, and there's another VAR to prevent comments.
The final line just makes sure the variables B and C have both been declared.

OK... I don't know anything about SmileBASIC, so this is purely a guess: ?-A$VAR C - could this output -2012?

That won't work because A$ is a string.

Wait, I have an idea! What about: ?B$VAR C?  :)

That will trigger an error because "B$" hasn't been declared.

Sinclair ZX81/Timex TS1000/1500 BASIC, 54 tokenized BASIC bytes used
 1 LET A$="2012"
 2 PRINT "2012" AND A$="2012";"2012" AND A$<>"2012"

Regardless of the value in A$ 2012 is still shown on the screen. I have used string literals because it's faster for writing to the screen (in BASIC at least) and also saves BASIC bytes. So A$ can contain any string value possible on the ZX81 tokenized "one-touch" entry system.

Rust, 105 bytes
fn main(){use std::io::{Write,stdout};stdout().write_all({let a=b"2012";if a==b"2012"{a}else{b"2012"}});}

Try it online
Most of the length comes from writing directly to stdout vs using the print! macro. Unfortunately, the format string in print!("{}", x); can be easily modified and is checked at compile time so you can't pass in the value as a string directly.

I don't know any Rust, so this looks solid. One question - the place where it goes {a} - can't something be done with that? Like {!a} or {~a} or something? I'm just shooting blind here, but perhaps there's some operator that can be used on a string?

@Vilx- Neither of those operators are valid in that location. a's type is &[u8] (which is a slice) and write_all is expecting a &[u8] so it's not really possible with a single character change to modify a in that location without causing a compiler error, as far as I can tell at least.

Lenguage, 176848577745260300319721504 bytes
Not really fun though.
No modification/edit a byte: ----------[+>+++++<]>.--.+.+.+
Add a byte: ----------[+>+++++<]>.--.+.+.-
Remove a byte: ----------[+>+++++<]>.--.+.+<]
JavaScript, 48 bytes
q="e=alert(2012)"
q=="e=alert(2012)"?eval(q)+e:w

Try it online!

This language almost feels like cheating here. :D

Haskell, 65
import Data.List
nub$filter(\x->x==2012||x==2012)([2012]++[2012])

Perl, 84
use strict;use English;$ARG=
2032;s/.*/2012/unless$ARG eq 2012;$SUBSEP=2012;print;

Failed approach :
use strict;use English;"2012 2012"=~
/2012|2012|2012/;print$MATCH||$MATCH;

You Perl solution can be broken by replacing the first $& with something like $0.

And the Haskell one breaks if you replace the comma with a plus sign. Valiant attempt though.

I think nub$filter(\x->x==2012||x==2012)(2012:[2012]) might be safe for the Haskell solution.

I forgot the use English in perl, that'll fix it.  I think several fixes work for Haskell, including switching to strings.

Replacing the first $MATCH with *MATCH gives the output *main::&.

Does use strict even count as compile time in Perl?  I'd vote no myself.

The Perl solution is still pretty fragile. Some ways to break it (found while testing my own answer) include replacing print with *rint, prin:, p:int or #rint,  prepending = to the first line, or even replacing s/.*/ with s/./ or y/.*/ (which would be fixed by initializing $ARG to 2012 to begin with).  Also, your $SUBSEP trick still doesn't protect against inserting a * before the final semicolon, but a much easier solution is to just remove that unnecessary semicolon.

Ahh, thanks!  Perl isn't the optimal language for this one I guess.  lol

Indeed, it's too flexible.  I'd actually half convinced myself that a correct Perl solution was impossible before I hit upon the trick of testing the return value of print (which is not explicitly documented, but hey, this is code golf).

C# .NET, 83 bytes
class P{static void Main(){var q="2012";System.Console.Write(q=="2012"?q:"2012");}}

Try Online

Aaand it fails. Should output 2012, not 2014. XD But, yes, the approach seems to be valid. I cannot think of a way to break it.

I feel stupid now

Aaand this version fails because I can do "2012"=="2012"?"2014":"2012". You need the var. :)

Well I should probably stop trying to make this shorter then xD


text:
Convert number to comma separated number
Given a number, say, -2982342342363.23425785 convert it to -2,982,342,342,363.23425785.

Extra points for not using look-behind
Extra points for not using regular expressions.

Why -2982,342,342,363.23425785 and not -2,982,342,342,363.23425785?

typo. fixed :-)

How many extra points for not using look-behind and regexp? What is the objective winning criteria?

It is a bit strange to tag the challenge as regular-expression and give extra points if not using them...

Just to make sure, should the input be considered a char string, a double (or otherwise floating point primitive type), or it doesn't matter? I mean, if it's an application used in console, you'd rather decode a string (ARGS), but I somewhat sense this should be a function or a line of code (like the Java submission), so when it's a function, being a String or a Double kinda changes the math...

the input should be a number, integer or float is your pick

This is not [code-golf] - is it?

Does anyone else find it odd that the thousands to the left of the decimal point are separated by a comma but those to the right are not? I guess generally such numbers are only presented up to hundreths.

So, what's the winning criterion? I'm voting to close this challenge as off-topic since there isn't one. This is a really old challenge, so it's unlikely, but if @OP edits a winning criteria in and accepts the winning answer accordingly, I'd retract my CV.

I think we should edit in [code-golf] ourselves, as quite a few existing answers act as though it is one.

Java, 50 chars
String C(double d){return String.format("%,f",d);}

Works as specified in most locales.  Does the correct thing in all locales :)
Edit:
If you really want commas no matter the default locale, do:
String C(double d){return String.format(java.util.Locale.US,"%,f",d);}

which is 70 characters (60 if you've already imported java.util.*).

Thus you might need to set a US locale to comply to the spec... :-)

Where does other locales differ? I remember vaguely a weird country that doesn't do the whole comma thing.

@Radagaisus: See http://en.wikipedia.org/wiki/Decimal_mark

Spreadsheet, 6+dec.places chars 5 chars
Just enter the number in a cell with formatting #,##0.#########,##0. Works on OOo Calc and MS Excel. Couldn't quickly find something meaning "print as many decimal places as there are". That would shorten it a lot. Can use an int, so the problem is not anymore.
No look-behind, no regex.

Scala:
val l=List (12345.2345, 123456.2345, 1234567.2345, -12345.2345, -123456.2345, -1234567.2345)

def f(d: Double)={
val a=d.toString.split('.')
(if(d<0)"-"else"")+
a(0).toLong.abs.toString.reverse.sliding(3,3).mkString(",").reverse+"."+a(1)}

l.map(f)

144 chars without 1st and last line, but this isn't code golf, is it?. Imho no look behind and no regex used.
Result:
List(12,345.2345, 123,456.2345, 1,234,567.2345, -12,345.2345, -123,456.2345, -1,234,567.2345)

I haven't run this so I may be wrong, but won't it give an error if the given number has no decimal point (because a will only have 1 item so a(1) will be referencing a non-existent index)?

Since the number was not specified any further I assumed only numbers containing a decimal point, of different length and with and without negative sign. I did not consider pure Integers, hexadezimal notation, scientific notation (4.3e-23), numbers like '.4' or '-.4', '9.' or '-9.'. Numbers exceeding the range of Double aren't tested as well. However - since my function takes a Double as argument, an int-literal is implicitly converted to double, and f(4000) leads to 4,000.0 - but that is pure luck of mine. :)

C 89/90/ANSI
#include <stdio.h>
#include <string.h>

int main(int i, char* a[]) {

    char * p;

    p    = strtok(a[1], ".");    /* Get argument value; up to decimal point. */
    a[1] = strtok(0,    ".");    /* Overwrite original value with fractional part. */

    /* If the first char is a negative sign then print it and advance the string pointer: */
    if(*p == '-') printf("%c", *p++);

    /* Get remainder of integer part divided by 3 and load it into a digit-group iterator: */
    i = strlen(p) % 3;

    if(i == 0) i = 3;    /* If iterator is empty then fill it. */

    while(1) {
        /* Nested loop through 3-digit group; printing each char: */
        while(i-- > 0) printf("%c", *p++);

        /* If string pointer is at null (end of string) char then exit loop: */
        if(*p == 0) break;
        else printf(",");    /* Otherwise print a comma */

        i = 3;    /* and reload the digit-group iterator. */
    }

    /* If there is a fractional part then print it after a decimal point: */
    if(a[1] != 0) printf(".%s", a[1]);

    return 0;
}

Welcome to PPCG!

Thanks! Nice to be here.

Perl, regular expression
Using a regular expression and no look-behinds but look-aheads:
$v = "-2982342342363.23425785";
$v =~ s/\d(?=(\d{3})+(\.|$))/$&,/g;
print $v;

Each digit is replaced by itself plus a comma if it is followed by n digits where n is a multiple of three and immedetiately followed by a period or the end of the string.

Haskell, 105
f(a:b:c:n:s)|n/='-'=a:b:c:',':f(n:s)
f s=s
r=reverse
main=interact$uncurry((++).r.f.r).break(`elem`".\n")

This doesn't use regular expressions (obviously), but it does backtrack (namely, it reverses digits before adding separators).

Ruby 111 chars
parts = "-2982342342363.23425785".split('.')
parts[0].reverse.scan(/.{1,3}/).join(",").reverse + "." + parts[1]

PHP
Using the built in function for formatting numbers:
function format($number)
{
    $decimals=(strpos($number,'.')===false?0:strlen($number)-strpos($number,'.')-1);
    return number_format($number,$decimals,'.',',');
}

Doing it by hand:
function format($number)
{
    $parts=explode('.',$number);
    $temp="";
    $len=strlen($parts[0]);
    for($i=0;$i<$len;$i++)
    {
        if($i!=0 && $i%3==0)
        {
            $temp.=",".$parts[0][$len-$i-1];
        }
        else
        {
            $temp.=$parts[0][$len-$i-1];
        }
    }
    $parts[0]=strrev($temp);
    return implode('.',$parts);
}

That large for loop could probably be shortened a good bit if you use str_split.

vi, 25 chars
ebd0$F.99@='3hha,<C-V><ESC>'
0PZZ

The script moves the cursor to the last digit of the number, then tries to search backwards for a decimal point. From there (either the last digit, or the decimal point if there was one), the following process is executed 99 times: the cursor moves left 3 times, then attempts to move left again. If it was able to move left, then a comma is inserted; otherwise, the process aborts.
9 times is probably sufficient instead of 99, so this could be reduced to 18 24 characters.
EDIT: I realized that I wasn't accounting for possible edge cases with a negative sign in front, so I added six characters to deal with it. At the start, 'eb' will effectively move the cursor to the first digit of the number. 'd0' will delete everything before that (which is either the negative sign or nothing). Then at the end, '0' moves to the start of the line and 'P' inserts whatever was deleted earlier.

PHP, 56
No Regex, no look-behind.
function f($n){return number_format($n).strstr($n,'.');}

My first attempts tried calculating how many decimals to keep in order to use it as the optional second parameter for number_format but I couldn't think of concise logic.
My second attempt treated the number as a string, splitting on ., then re-assembling it.
Then I realized I could just let number_format truncate for me, then re-append the decimal section (if any) with strstr.

A different version, not using number_format, in a total of 95 bytes:
function f($n){return strrev(implode(',',str_split(strrev(strtok($n,'.')),3))).strstr($n,'.');}

Longer and a bit more readable:
function f($num) {
    $right = strstr($num, '.');

    $left = strtok($num, '.');
    $left = str_split(strrev($left), 3);
    $left = strrev(implode(',', $left));

    return $left . $right;
}

No need for character counts, this hasn't been tagged as [code-golf]. str_split never even occurred to me.

Ah, kinda near here.  Just assumed that because this was the codegolf stackexchange that everything was code golf.  Oh well, it was good practice.

'Programming puzzles and Code Golf'. Not to worry, most people have made the same assumption on this question. :-)

num.replace(/(\d+)(\..*)?/, ($0,$1,$2) -> $1.replace(/(\d)(?=(\d{3})+$)/g,'$1,') + ($2 || ''))
This is in coffee script. There's no look behind in JavaScript, but you can pass a function to .replace(!). The first regex separates the string over the dot and the second regex deals only with the first part. It's a shorter way than using .split() and I had problems mimicking look-behind.
edit: changed to work in webkit browsers.

In Lua:
local lns =
{
"-2982342342363.23425785",
"-2982342342363",
"2982342342363",
"-.23425785",
".23425785",
"1",
"22",
"-333",
"4444.",
"333.333",
"puke",
}
local results = {} -- Find converted strings here
for i, ns in ipairs(lns) do
  local sign, digits, frac = string.match(ns, "^(%-?)(%d-)(%.%d*)$")
  if frac == nil then
    frac, sign, digits = '', string.match(ns, "^(%-?)(%d-)$")
  end
  if digits == nil or digits == '' then
    results[i] = ns -- Only a fractional part (or no numbers), leave unchanged
  else
    local groups = {}
    local v = 0 + digits
    while v > 0 do
      local g = math.fmod(v, 1000)
      table.insert(groups, 1, g)
      v = math.floor(v / 1000)
    end
    results[i] = sign .. table.concat(groups, ",") .. frac
  end
end

Odd mix of regular expressions and arithmetic... It allows to handle non-numbers, sign, etc. in a quite concise way. I need the two steps RE as they are quite limited in Lua.
[EDIT] I don't really comply to the requirement as I made an array of strings instead of an array of numbers. On the other hand, by default Lua is compiled with 32bit floats, not 64bit doubles, so the given number is truncated to the first digit after the decimal point... So Lua remains out of the competition. Oh well, it was fun to play with Lua again.

And technically speaking, those are Lua Patterns not RegEx :D

Python2 - 219
def c(s):
 c=str(s)
 i=max([k for k in range(len(c)) if c[k]=='.']+[-1])
 o=(c[i::] if i>0 else '')
 if i>0: c=c[:i]
 c=list(c);i=0;m={0:1,1:2,2:3,3:1}
 while len(c):
  o=c.pop()+(',' if i==2 else '')+o;i=m[i]
 return o

or I can do this...
Python2 - 112
def c(s):
 import locale
 locale.setlocale(locale.LC_ALL, 'en_US')
 return locale.format("%d", s, grouping=True)

Personally I like the first one more... mainly because of the map instead of logic hack. The second one is verbatim from StackOverflow of all places.

Python 2.7, 127/122 bytes
taking input from stndin:
n=`input()*1.0`.split('.')
s=''
k=0
for y in n[0][::-1]:
 s+=y;k+=1
 if k in range(0,len(n[0]),3):s+=','
print s[::-1]+'.'+n[1]

as a function:
def c(n):
 s='';k=0
 for y in`n*1.0`[0][::-1]:
  s+=y;k+=1
  if k in range(0,len(n[0]),3):s+=','
  return s[::-1]+'.'+n[1]

could probably be golfed more...

Python (162 chars)
a=raw_input().split('.')
n=int(a[0])
a[0]=str(n%1000)
n=n/1000
while n>0:
    a[0]=str(n%1000)+','+a[0]
    n=n/1000
if len(a)>1:
    print a[0]+'.'+a[1]
else:
    print a[0]

Gah! New specs ruin this solution.
Well for integer input
(89 chars)
n=int(raw_input())
s=str(n%1000)
n/=1000
while n>0:
    s=str(n%1000)+','+s
    n/=1000
print s

Will put up one for float later.
For float input
(152 97 chars)
n=float(raw_input())
s=str(n%1000)
n=int(n/1000)
while n>0:
    s=str(n%1000)+','+s
    n/=1000
print s

Python 3: 100 or 102 characters
100 characters as a function:
def f(s):n=(s+'.').find('.');return''.join((('-'in s)<i<n and i%3==n%3)*','+c for i,c in enumerate(s))

102 reading from stdin:
s=input();n=(s+'.').find('.');print(''.join((('-'in s)<i<n and i%3==n%3)*','+c for i,c in enumerate(s)))

Python 2.7: 29 characters
A bit late to the party, but I just read about this new feature in 2.7 and figured this still deserves to be here:
f=lambda(n):'{:,f}'.format(n)

Used by calling f(-2982342342363.23425785) which returns "-2,982,342,342,363.234375". The error is due to floating-point precision: -2982342342363.23425785 gets represented as -2982342342363.234375.

Q, 27 chars (integer input)
{(|:)","sv 3 cut (|:) -3!x}

q){(|:)","sv 3 cut (|:) -3!x}[23498723]
"23,498,723"
Q, 48 chars (float input)
{,[;".",a@1](|:)","sv 3 cut(|:)(*:)a:"."vs -3!x}

q){,;".",a@1","sv 3 cut(|:)(*:)a:"." vs -3!x}[234554.21434]
"234,554.21434"

@sinedcm suggested that you can get it down to 24 as {(|:)","sv 3 cut(|)($)x}

C (99)
No regexes, no backtracking, not using built-in formatting of real numbers.
d=1000;f(x){x&&f(x/d)+printf("%d,",x%d);}main(x,y){scanf("%d.%d",&x,&y);f(x);printf("%c.%d",8,y);}

Some JavaScript approaches:
(1) 74 characters but fails on some inputs, recursive creation:
function r(n){return n<0?"-"+r(-n):n<1e3?""+n:r(n/1e3-n/1e3%1)+","+n%1e3}

It has two failure channels: (1) if the substring contains subnumbers with leading 0's it sometimes will produce e.g. 1,10 instead of 1,010, and (2) I don't actually know if n/1000 - (n/1000)%1 always yields an integer. With bugs corrected the smallest I can get it is 130 characters:
function r(n,f){f=Math.floor;return n<0?"-"+r(-n):n%1?r(f(n))+(""+n).match(/\..*/)[0]:n<1e3?""+n:r(f(n/1e3))+","+(""+n).slice(-3)}

(2) Split over lookahead and join with commas, 95 characters, one statement:
m=(""+n).split('.'),m[0].split(/(?=(?:.{3})+$)/).join(",").replace("-,","-")+(m[1]?"."+m[1]:"")

I can't see a better way to handle negatives in this case.
(3) Array inserts every 3 characters to the left of the '.', 100 characters, uses a Bad Part of JS (n < 0 is true or false
 which coerce to 1 or 0 when used with <).
t=(""+n).split(""),i=t.indexOf('.');for(i=(i<0?t.length:i)-3;n<0<i;i-=3)t.splice(i,0,',');t.join("")

Ruby (didn't golf or count. No regexps.)
def commaize(n)
  a,b=((negative=n<0) ? -n : n).to_s.split('.')
  "#{negative ? '-':''}#{a.reverse.chars.each_slice(3).map(&:join).join(',').reverse}.#{b}"
end

COBOL
   ID DIVISION.
   PROGRAM-ID. EDITNUM.
   DATA DIVISION.
   WORKING-STORAGE SECTION.
   01  REALLY-BIG-NUMBER PIC --,---,---,---,--9.9(8).
   PROCEDURE DIVISION.
       MOVE -2982342342363.23425785 TO REALLY-BIG-NUMBER
       DISPLAY REALLY-BIG-NUMBER
       GOBACK
       .

10 lines of code, of which six are mandatory. All the work is done by the MOVE statement, ably abetted by the data-definition.
The data-definition (01) uses a Picture-string to describe how the data is to be edited. Here, there will be a leading floating minus-sign, commas separating groups of three digits going left from (to-be-printed) decimal point. There are eight significant decimal places.
MOVE the value to the field, DISPLAY the field (if you want to see what the number looks like).

-2,982,342,342,363.23425785