g | x | w | all
Bytes Lang Time Link
162AWK250411T205038Zxrs
056Vyxal210530T060043Zemanresu
052Canvas201105T065102ZRazetime
075CJam150908T065038ZDennis
04405AB1E190909T155904ZGrimmy
162Zsh190910T114039Zroblogic
087K ngn/k190910T094106Zscrawl
185PHP170111T121753ZStarx
046Jelly180126T213355Zellie
197Java 7170111T143232ZKevin Cr
128JavaScript ES6161110T144602ZArnauld
260Ceylon150908T203459ZPaŭlo Eb
729C150921T105558ZREVOLUTI
221ScriptCS C# script150916T001006ZJustin D
196C150914T152010ZCole Cam
126Powershell150909T222049ZJustin D
467C#150912T152641Zuser4139
167MATLAB / Octave150908T210500Zrayryeng
131Python 2150911T115224Zcjfaure
242bash150910T124634ZTarod
nanPip150911T005012ZDLosc
392C150910T225517ZFunmungu
229D150909T163644Zsigod
136JavaScript ES6150908T143825Zedc65
134ECMAScript 2015 –150910T112322ZToothbru
160CoffeeScript150910T112444ZBojidar
567pb150910T023020Zundergro
164Mathematica150909T143643ZCharlott
117Perl150908T162821Zphillipo
150Python 2150908T141519ZBlex
299Lua150908T091733ZFabiF
221R150908T095058ZTensibai
157R150908T231622Zflodel
141Moonscript150908T214053ZRyan Rus
143Julia150908T192039ZAlex A.
161Mouse150908T185651ZAlex A.
113golflua150908T195836Zmanatwor
153JavaScript150908T134614ZNainemom
169Python 3150908T184100Zmoorecm
164SpecBAS150908T161843ZBrian
187Lua 5.2150908T152059ZJakuje
154JavaScript ES6150908T081344ZQwertiy
117rs150908T142553Zkirbyfan
120Ruby150908T074922ZLevel Ri
144Perl150908T115009Zr3mainer
158Python 2150908T104444ZSimonPJ
279R150908T090047ZCath
067Pyth150908T072813ZPurkkaKo

AWK, 169 162 bytes

!$1{print"Congratulations on your new baby! :D"}$1{for($1<0&&x=$1=1;k++<=$1*2;k<=$1&&s=s" $"){k>$1&&k<=$1*2&&r=r" |";p=p"~";t=t"-"}print!x?s"\n"r:X}$0=t"\n"p"\n"t

Attempt This Online!

!$1{print             # if input is zero print
"Congratulations on your new baby! :D"}
$1{                   # if non-zero
if($1<0)              # if negative
{$1=1;x++}            # set size to one and flag
for(;k++<=(z=$1*2);   # cake is twice as long as candles
k<=$1&&s=s" $")       # append flames
{k>$1&&k<=z&&r=r" |"; # append candles
p=p"~";               # middle of cake
t=t"-"}               # top and bottom of cake
print!x?s"\n"r:X}     # if flag not set print candles
$0=t"\n"p"\n"t        # print base of cake

Vyxal, 56 bytes

[0>`  -~-
`$[`$|-~-
`+|2]*`  -~-`+↵§|`Ṅƛ on λ¢ λɽ ÷Ḃ! :D

Try it Online!

Canvas, 52 bytes

‽“pbn@;║L↶F{8ø⇵ohUY÷²[L┘↗HZ4vy)Cg⁰‟t}$¶|∙---¶~~~─∔r×

Try it here!

CJam, 76 75 bytes

ri_W>\_1e>)" $ |--~~--"2/f*Wf<N*"Congratulations on your new baby! :D"?_8>?

Try it online in the CJam interpreter.

How it works

ri           e# Read an integer from STDIN.
_W>          e# Check if it is greater than -1.
\_           e# Swap input and Boolean and copy the input.
1e>)         e# Take the maximum of input and 1 and increment the result.
             e# Let's call the result R.
" $ |--~~--" e# Push that string.
2/           e# Split it into [" $" " |" "--" "~~" "--"].
f*           e# Repeat each chunk R times.
Wf<          e# Discard the last character of each repeated chunk.
N*           e# Join the repreated chunks, separating by linefeeds.

"Congratulations on your new baby! :D"

?            e# If the input is non-zero, select the cake; else, keep the string.
_8>          e# Push a copy and discard the first 8 characters (single candle).
?            e# Select the unmodified cake/string if the input was non-negative,
             e# a candleless cake otherwise.

05AB1E, 45 44 bytes

_i“Ûà€‰€ž€¢‡Í! :D“ćuìëdiU„ $„ |}…-~-`)X·>δ∍»

Try it online!

_i                               # if input != 0:
  “Ûà€‰€ž€¢‡Í! :D“               #  dictionary string "congratulations on your new baby! :D"
                  ćuì            #  uppercase the first character
ë                                # else:
 di        }                     #  if input >= 0:
   >V                            #   set Y = input + 1 (by default, Y is 2)
     „ $                         #   push literal " $"
        „ |                      #   push literal " |"
…-~-                             #  push literal "-~-"
    `                            #  dump each character separately
     )                           #  wrap the entire stack in a list:
                                 #   [" $", " |", "-", "~", "-"] if input > 0
                                 #   ["-", "~", "-"] if input < 0
      ε   }                      #  for each item in that list:
       Y∍                        #   extend to length Y
         û                       #   palindromize
           »                     #  join the stack by newlines
                                 # implicit output

Zsh, 162 bytes

try it online!!

((!$1))&&<<<"Congratulations on your new baby! :D"&&exit
y=$[$1<0?2:2*$1] a=${(l:y:: $:)} b=${(l:y+1::-:)}
(($1>0))&&echo "$a\n${a//$/|}"
echo "$b\n${b//-/~}\n$b"

K (ngn/k), 87 bytes

{$[x<0;3#'2_*:;x;,'/(1+2*x)#;:"Congratulations on your new baby! :D"]("  -~-";"$|-~-")}

Try it online!

edit: whoops, easy 1-byte reduction i missed


if 2 lines of whitespace is permitted where the candles would be in the x<0 case, we can save 2 bytes with

{$[x<0;3#'*:;x;,'/(1+2*x)#;:"Congratulations on your new baby! :D"]("  -~-";"$|-~-")}

PHP, 197 185 bytes

<?php $t=($i=$argv[1])<0?3:2*$i+1;$n="
";$f='str_repeat';$d=$f('-',$t);$t=$f('~',$t);echo!$i?'Congratulations on your new baby! :D':($i>0?$f(' $',$i).$n.$f(' |',$i).$n:'')."$d$n$t$n$d";

Contributions:


More readable:

PHP, 197 bytes

<?php
$i=$argv[1];
$t=$i<0?3:2*$i+1;
$n="\n";
$f='str_repeat';
$d=$f('-',$t);
$t=$f('~',$t);
echo $i==0?'Congratulations on your new baby! :D':($i>0?$f(' $',$i).$n.$f(' |',$i).$n:'')."$d$n$t$n$d";

Jelly, 49 46 bytes

Ḥ‘»3“-~-”ẋ€;@⁶p⁾$|¤ẋ€$Yµ“ŒḅœÑḄŻ:Ṁ¿Þ5sṭ+¬ḅḣ;»¹?

Try it online!

-3 bytes from Erik

Java 7, 197 198 bytes

String c(int y){String a=" ",b=a,c="---",n="\n";for(int i=0;i<y;a+="$ ",b+="| ")if(y>0&i++>0)c+="--";c=c+n+c.replace('-','~')+n+c;return y<0?c:y>0?a+n+b+n+c:"Congratulations on your new baby! :D";}

Ungolfed:

String c(int y){
   String a = " ",
          b = a,
          c = "---",
          n = "\n";
    for(int i = 0; i < y; a += "$ ",
                          b += "| "){
      if(y > 0 & i++ > 0){
        c += "--";
      }
    }
    c = c + n + c.replace('-', '~') + n + c;
    return y < 0
            ? c
            : y > 0
               ? a + n + b + n + c
               : "Congratulations on your new baby! :D";
  }

Test code:

Try it here.

class M{
  static String c(int y){String a=" ",b=a,c="---",n="\n";for(int i=0;i<y;a+="$ ",b+="| ")if(y>0&i++>0)c+="--";c=c+n+c.replace('-','~')+n+c;return y<0?c:y>0?a+n+b+n+c:"Congratulations on your new baby! :D";}

  public static void main(String[] a){
    System.out.println(c(1));
    System.out.println();
    System.out.println(c(3));
    System.out.println();
    System.out.println(c(25));
    System.out.println();
    System.out.println(c(0));
    System.out.println();
    System.out.println(c(-1));
  }
}

Output:

 $ 
 | 
---
~~~
---

 $ $ $ 
 | | | 
-------
~~~~~~~
-------

 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ 
 | | | | | | | | | | | | | | | | | | | | | | | | | 
---------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---------------------------------------------------

Congratulations on your new baby! :D

---
~~~
---

JavaScript (ES6), 128 bytes

n=>n?[...n<0?(n=1,'  -~-'):'$|-~-'].map((c,i)=>(i<2?' '+c:c).repeat(i<2?n:n*2+1)).join`
`:'Congratulations on your new baby! :D'

Demo

let f =

n=>n?[...n<0?(n=1,'  -~-'):'$|-~-'].map((c,i)=>(i<2?' '+c:c).repeat(i<2?n:n*2+1)).join`
`:'Congratulations on your new baby! :D'

console.log(f(-1));
console.log(f(0));
console.log(f(1));
console.log(f(2));

Ceylon, 322 307 300 282 278 260 bytes

shared void run(){if(exists t=process.readLine(),exists n=parseInteger(t)){String r(String s)=>s.repeat(n);print(n>0thenr(" $")+"\n"+r(" |")+"\n"+r("--")+"-\n"+r("~~")+"~\n"+r("--")+"-"else(n<0then"---\n~~~\n---"else"Congratulations on your new baby! :D"));}}

The not yet golfed original (assuming negative cakes have width 3 instead of –2·n+1):

shared void birthdayCake() {
    if (exists text = process.readLine(), exists number = parseInteger(text)) {
        switch (number <=> 0)
        case (equal) {
            print("Congratulations on your new baby! :D");
        }
        case (smaller) {
            print("---\n~~~\n---");
        }
        case (larger) {
            print(" $".repeat(number));
            print(" |".repeat(number));
            print("--".repeat(number) + "-");
            print("~~".repeat(number) + "~");
            print("--".repeat(number) + "-");
        }
    }
}

This features the condition list in the if statement, each condition defining a value usable in the following conditions and in the body. Because they have the exist, the condition is only fulfilled when the values is not null, and thus the compiler knows the values is not null for the following code. (If nothing is entered (EOF), readline returns null. If parseInteger hits a non-integer, it also returns null. Our program then does nothing. As the behavior for those cases was not defined, I guess this is okay.)

Also we have the <=> operator, which maps to the Comparable.compare method, and returns a Comparison object, i.e. one of equal, smaller and larger. The compiler knows that those exhaust the Comparison type, so no else clause is needed in our switch statement.

The repeat method of class String does what one would expect. It is actually inherited from the same-named method in interface Iterable (as a string is, beside other stuff, just a list of characters).

Replacing my identifiers by one-letter ones and removing unneeded white space gives 322 characters:

shared void b(){if(exists t=process.readLine(),exists n=parseInteger(t)){switch(n<=>0)case (equal){print("Congratulations on your new baby! :D");}case(smaller){print("---\n~~~\n---");}case(larger){print(" $".repeat(n));print(" |".repeat(n));print("--".repeat(n)+"-");print("~~".repeat(n)+"~");print("--".repeat(n)+"-");}}}

Replacing the series of print by explicit \ns (and one single print) brings it down to 307:

shared void b(){if(exists t=process.readLine(),exists n=parseInteger(t)){switch(n<=>0)case(equal){print("Congratulations on your new baby! :D");}case(smaller){print("---\n~~~\n---");}case(larger){print(" $".repeat(n)+"\n"+" |".repeat(n)+"\n"+"--".repeat(n)+"-\n"+"~~".repeat(n)+"~\n"+"--".repeat(n)+"-");}}}

I tried alias-importing of repeat as r, but it doesn't help (the import declaration adds 40 characters, and we can only save 25 by replacing repeat with r).

What slightly helps, is using n.sign instead of n<=>0. While these two expressions have the same textual length, they have different types: the latter one is of type Comparison mentioned before (which has the three values smaller, larger and equal), the former one has type Integer, with the values -1, 1, 0 ... and because Integer has many more values, we also need an else clause. This is 300 characters long:

shared void b(){if(exists t=process.readLine(),exists n=parseInteger(t)){switch(n.sign)case(0){print("Congratulations on your new baby! :D");}case(-1){print("---\n~~~\n---");}case(1){print(" $".repeat(n)+"\n"+" |".repeat(n)+"\n"+"--".repeat(n)+"-\n"+"~~".repeat(n)+"~\n"+"--".repeat(n)+"-");}else{}}}

Here with whitespace:

shared void b() {
    if (exists t = process.readLine(), exists n = parseInteger(t)) {
        switch (n.sign)
        case (0) {
            print("Congratulations on your new baby! :D");
        }
        case (-1) {
            print("---\n~~~\n---");
        }
        case (1) {
            print(" $".repeat(n) + "\n" +
                        " |".repeat(n) + "\n" +
                        "--".repeat(n) + "-\n" +
                        "~~".repeat(n) + "~\n" +
                        "--".repeat(n) + "-");
        }
        else {}
    }
}

We can safe some more by resigning about our switch statement and using if, coming to 282 characters(=bytes):

shared void b(){if(exists t=process.readLine(),exists n=parseInteger(t)){if(n==0){print("Congratulations on your new baby! :D");}else if(n<0){print("---\n~~~\n---");}else{print(" $".repeat(n)+"\n"+" |".repeat(n)+"\n"+"--".repeat(n)+"-\n"+"~~".repeat(n)+"~\n"+"--".repeat(n)+"-");}}}

Formatted:

shared void b() {
    if (exists t = process.readLine(), exists n = parseInteger(t)) {
        if (n == 0) {
            print("Congratulations on your new baby! :D");
        } else if (n < 0) {
            print("---\n~~~\n---");
        } else {
            print(" $".repeat(n) + "\n" +
                        " |".repeat(n) + "\n" +
                        "--".repeat(n) + "-\n" +
                        "~~".repeat(n) + "~\n" +
                        "--".repeat(n) + "-");
        }
    }
}

We can safe another byte by swapping the cases around, since > is shorter than ==. Another "annoyance" is the repeated repeat(n) – we can define a local function (a closure, it remembers n from the defining block) with a shorter name:

String r(String s) => s.repeat(n);

This is a shorter way of writing this:

String r(String s) {
    return s.repeat(n);
}

We could use function instead of the return type for type inference, but this is not shorter. This gives us 278 bytes:

shared void b(){if(exists t=process.readLine(),exists n=parseInteger(t)){if(n>0){String r(String s)=>s.repeat(n);print(r(" $")+"\n"+r(" |")+"\n"+r("--")+"-\n"+r("~~")+"~\n"+r("--")+"-");}else if(n<0){print("---\n~~~\n---");}else{print("Congratulations on your new baby! :D");}}}

Formatted:

shared void b() {
    if (exists t = process.readLine(), exists n = parseInteger(t)) {
        if (n > 0) {
            String r(String s) => s.repeat(n);
            print(r(" $") + "\n" + r(" |") + "\n" + r("--") + "-\n" + r("~~") + "~\n" + r("--") + "-");
        } else if (n < 0) {
            print("---\n~~~\n---");
        } else {
            print("Congratulations on your new baby! :D");
        }
    }
}

Actually, using the then and else operators instead of the if statements allows us to save some calls of print (and some braces):

shared void run() {
    if (exists t = process.readLine(), exists n = parseInteger(t)) {
        String r(String s) => s.repeat(n);
        print(n > 0 then r(" $") + "\n" +
                        r(" |") + "\n" +
                        r("--") + "-\n" +
                        r("~~") + "~\n" +
                        r("--") + "-"
                    else (n < 0
                        then "---\n~~~\n---"
                        else "Congratulations on your new baby! :D"));
    }
}

This is just 261 bytes:

shared void run(){if(exists t=process.readLine(),exists n=parseInteger(t)){String r(String s)=>s.repeat(n);print(n>0thenr(" $")+"\n"+r(" |")+"\n"+r("--")+"-\n"+r("~~")+"~\n"+r("--")+"-"else(n<0then"---\n~~~\n---"else"Congratulations on your new baby! :D"));}}

(I used run instead of b for the function name because this way it can be run with ceylon run without passing a function name.)

My Github repository has a commented version of this.

C, 729 bytes

I'm new to programming, and new to Stack Exchange, however I still wanted to give it a shot with whatever my professor has taught me as of now:

#include<stdio.h>
int main(void)
{char a[2][100]={" "}, b[3][100],i;int c;for(i=1;i<100;i+=2){a[0][i]='$';a[1][i]='|';}for(i=0;i<100;++i){b[0][i]='-';b[1][i]='~';b[2][i]='-';}puts("enter ur age");scanf("%d", &c);if (c==0)printf("congratulations on your new baby!");else if (c<0){for(i=0;i<3;++i){printf("%c", b[0][i]);}printf("\n");for(i=0;i<3;++i){printf("%c", b[1][i]);}printf("\n");for(i=0;i<3;++i){printf("%c", b[2][i]);}printf("\n");}else{for(i=0;i<2*c;++i){printf("%c", a[0][i]);}printf("\n");for(i=0;i<2*c;++i){printf("%c", a[1][i]);}printf("\n");for(i=0;i<=2*c;++i){printf("%c", b[0][i]);}printf("\n");for(i=0;i<=2*c;++i){printf("%c", b[1][i]);}printf("\n");for(i=0;i<=2*c;++i){printf("%c", b[0][i]);}printf("\n");}return(0);}

The readable version of it is,

#include<stdio.h>
int main(void)
{

    char a[2][100]={" "}, b[3][100],i;
    int c;

    for(i=1; i<100; i+=2)
    {
        a[0][i]='$';
        a[1][i]='|';        
    }

    for(i=0; i<100; ++i)
    {
        b[0][i]='-';
        b[1][i]='~';
        b[2][i]='-';
    }   
    puts("enter ur age");
    scanf("%d", &c);
    if (c==0)
    printf("congratulations on your new baby!");
    else if (c<0)
    {

        for(i=0;i<3;++i)
        {
            printf("%c", b[0][i]);
        }
        printf("\n");
        for(i=0;i<3;++i)
        {
            printf("%c", b[1][i]);
        }
        printf("\n");

        for(i=0;i<3;++i)
        {
            printf("%c", b[2][i]);
        }
        printf("\n");
    }
    else
    {
        for(i=0;i<2*c;++i)
        {
            printf("%c", a[0][i]);
        }
        printf("\n");
        for(i=0;i<2*c;++i)
        {
            printf("%c", a[1][i]);
        }
        printf("\n");
        for(i=0;i<=2*c;++i)
        {
            printf("%c", b[0][i]);
        }
        printf("\n");
        for(i=0;i<=2*c;++i)
        {
            printf("%c", b[1][i]);
        }
        printf("\n");
        for(i=0;i<=2*c;++i)
        {
            printf("%c", b[0][i]);
        }
        printf("\n");

    }

    return(0);
}

ScriptCS (C# script), 221 bytes

Obviously this won't win any prizes, but...

var n=int.Parse(Env.ScriptArgs[0]);Console.WriteLine(n==0?"Congratulations on your new baby! :D":string.Join("\n",new[]{" $"," |","-","~","-"}.Select((s,i)=>string.Concat(Enumerable.Repeat(s,i>1?(n>0?n:1)*2+1:n>0?n:0)))))

C, 196 bytes

Prints leading spaces before empty candle cake. According to comments in the challenge, that's okay.

i,n;main(c,v)char**v;{c=atoi(v[1]);n=c<0;if(c)for(c=n?1:c;i++<10*c+10;)putchar(i%(2*c+2)?i<4*c+5?n|i%2?32:i<2*c+2?36:'|':i/(2*c+2)==3?'~':45:10);else puts("Congratulations on your new baby! :D");}

Ungolfed:

i,n;

int main(int c, char **v)
{
    c = atoi(v[1]);
    n = c < 0;
    if(c)
        for(c=n?3:c;i++<10*c+10;)
            putchar(i%(2*c+2) /* print '\n' at the end of each row */
                    ? i<4*c+5 /* first two rows are candles, last 3 are cake */
                        ? n || i % 2 /* alternate between space and candle */
                                ? ' '
                                : i<2*c+2 /* first row is '$', second is '|' */
                                    ? '$'
                                    : '|'
                        : i / (2*c+2) == 3 /* alternate rows between '-' and '~' */
                            ? '~'
                            : '-'
                    : '\n');
    else
        puts("Congratulations on your new baby! :D");
}

Powershell, 139 134 132 126 bytes

$n=$args[0];if($n){$d=3;if($n-gt0){' $'*$n;' |'*$n;$d=$n*2+1}'-'*$d;'~'*$d;'-'*$d}else{'Congratulations on your new baby! :D'}

C#, 467 Bytes

I know I won't win, but I think I at went overboard with while loops.

using System;class P{static void Main(string[]a){int i=int.Parse(a[0]);if(i==0){Console.Write("Congratulations on your new baby! :D");}else{int e=i;while(i-->0){Console.Write(" $");}if(e > 0){i = e;Console.Write("\n");while(i-- > 0){Console.Write(" |");}Console.Write("\n");i = e;} else {i=(e=1);}Console.Write("-");while(i-->0){Console.Write("--");}i=e;Console.Write("\n~");while(e-->0){Console.Write("~~");}Console.Write("\n-");while(i-->0){Console.Write("--");}}}}

Non minified version:

using System;
class P {
    static void Main(string[] a) {
        int i = int.Parse(a[0]);
        if(i == 0) {
            Console.Write("Congratulations on your new baby! :D");
        } else {
            int e = i;
            while(i-- > 0) {
                Console.Write(" $");
            }
            if(e > 0) {
                i = e;
                Console.Write("\n");
                while(i-- > 0) {
                    Console.Write(" |");
                }
                Console.Write("\n");
                i = e;
            } else {
                i = (e = 1);
            }
            Console.Write("-");
            while(i-- > 0) {
                Console.Write("--");
            }
            i = e;
            Console.Write("\n~");
            while(e-- > 0) {
                Console.Write("~~");
            }
            Console.Write("\n-");
            while(i-- > 0) {
                Console.Write("--");
            }
        }
    }
}

MATLAB / Octave, 194 198 195 189 171 167 bytes

Happy birthday to you Beta Decay! :)

Thanks to HamtaroWarrior for shaving off 4 bytes!


n=input('');m='$|'.';d='  '.';if(n==0)disp('Congratulations on your new baby! :D'),break;elseif(n<0)m=d;n=1;end,disp([[d repmat([m d],1,n)];repmat('-~-'.',1,2*n+1)]);

Sample Runs

I placed this into a script file called happy_birthday.m, then ran it a few times in the command prompt. Take note that when you enter in a negative number, there are two leading carriage returns, but that's allowed in this challenge:

>> happy_birthday
-1


---
~~~
---
>> happy_birthday
0
Congratulations on your new baby! :D
>> happy_birthday
1
 $ 
 | 
---
~~~
---
>> happy_birthday
2
 $ $ 
 | | 
-----
~~~~~
-----
>> happy_birthday
3
 $ $ $ 
 | | | 
-------
~~~~~~~
-------
>> happy_birthday
4
 $ $ $ $ 
 | | | | 
---------
~~~~~~~~~
---------
>> happy_birthday
5
 $ $ $ $ $ 
 | | | | | 
-----------
~~~~~~~~~~~
-----------

Code with spacing and explanations

% Get the input number from the user
n=input('');

% If the number is positive, the core candle sequence is going to be a column vector of a $ followed by a | character
m='$|'.';    

%// Array of one column and it has two spaces - going to use more than once
d = '  '.';

% If the number is 0, display the congratulations message and get out
if(n==0)
    disp('Congratulations on your new baby! :D')
    break;

% m stores the core candle sequence for displaying on the screen
% If the number is negative, the core candle sequence is going to be a column of two blank spaces
elseif(n<0)
    m=d; 
    n=1; % n is set to 1 as this is the number of "blank candles" we want to display
end

% This displays candles and the base together
% The top half is the displaying of the candles
% It is a column vector of spaces, followed by pairs of $,| in a column
% and another column of spaces - repeated n times
% The bottom half is the displaying of the cake
% The bottom half is a column vector of -,~,- for the base of the cake
% and is repeated 2*n + 1 times to match the candle display
disp([[d repmat([m d],1,n)];repmat('-~-'.',1,2*n+1)]);

The displaying part at the end is probably the most obfuscated part of the code. This is going to display a 5 row character matrix where the first two rows consists of the candles and the last three rows consists of the base of the cake.

The basis for the top half of the display is either two spaces in a column followed by another two spaces in another column in the case that the age is negative, or a $,- in a column followed by two spaces in another column. This is a 2 x 2 character matrix. The basis for the bottom half of the display is a single column vector of -,~,- which is a 3 x 1 character matrix.

The display command first tackles the first two rows of the cake by placing two spaces in the first column, followed pairs of a column of $,- or a column of spaces if n is negative, which gets changed to n=1, and another column of two spaces repeated for a total of n times. The next three rows simply replicate the -,$,- column vector for 2*n + 1 times to align the candles together with the base, thus completing the picture.

Try it online!

You can try this online using IDEOne's Octave compiler: http://ideone.com/4qXDdJ - however, there is a slight bug when reading in values from standard input. As such, the script is slightly modified where you have to change the value of n at the beginning of the code. Fork a new version of the script and change this to whatever integer value suits you in order to see what the output looks like.

Python 2, 131 bytes

x,y,n="$|-~-","  -~-",input()
for i in zip(y,*[y,y]*(n<0)+[x,y]*n)if n else["Congratulations on your new baby! :D"]:print"".join(i)

Happy belated birthday to OP :D Haven't been here in ages, I need to warm up my golfing skills again...using my favorite 90 degree list rotation trick with zip() here. The 0 case kinda threw me off, without it this code is 83 bytes.

As a bonus, taking the whitespace out of the y variable results in some interesting cake variations. Removing one space results in:

 $ $ $ $ $
-|-|-|-|-|-
~-~-~-~-~-~
-~-~-~-~-~-

and with the whitespace stripped entirely:

-$-$-$-$-$-
~|~|~|~|~|~
-----------

bash, 264 242 bytes

First of all: happy birthday, @BetaDecay :)

And now...

read n;p="printf ";e="echo ";x="exit";s="seq ";[ $n -eq 0 ]&&$e"Congratulations on your new baby! :D"&&$x;[ $n -gt 0 ]&&{ $p' %.s$ ' `$s 1 $n`;$e; $p' %.s| ' `$s 1 $n`;$e;};$p'%.s---' `$s 1 $n`;$e;$p'%.s~~~' `$s 1 $n`;$e;$p'%.s---' `$s 1 $n`

Pip, 74 + 1 = 75 bytes

Takes the age as a command-line argument. Requires the -n flag.

Y^"-~-"a?a<0?yX3(s.^"$|")XaALyX2*a+1"Congratulations on your new baby! :D"

Github repository for Pip

The command-line argument is stored in a. We split "-~-" into a list of characters and Yank it into the variable y. The rest of the program is a big ternary expression:

At the end of the program, the -n flag ensures that lists are printed with elements on separate lines, thus displaying a properly layered cake.

Here are the steps for an input of 2:

Candles
["$";"|"]
[" $";" |"]
[" $ $";" | |"]

Cake
["-";"~";"-"]
["-----";"~~~~~";"-----"]

Put it together
[" $ $";" | |";"-----";"~~~~~";"-----"]

Final output
 $ $
 | |
-----
~~~~~
-----

Happy birthday!

C, 392 bytes

(known segmentation fault if no arguments are given)

#include <stdio.h>
#define P(s) printf(s);
#define F for(i=0;i<n;i++)
#define A(s, e) F{P(s)}P(e "\n")
int main(int c, char**v){int i,n=atoi(v[1]);if(n<0){n=3;A("-",)A("~",)A("-",)}else if(!n)P("Congratulations on your new baby! :D\n")else{A(" $",)A(" |",)A("--","-")A("~~","~")A("--","-")}}

Unminified and copiously spaced

#include <stdio.h>
#define P(s) printf ( s ) ;
#define F for ( i = 0 ; i < n ; i++ )
#define A(s, e) F { P ( s ) } P ( e "\n" )
int main ( int c, char ** v )
{
        int i, n = atoi ( v [ 1 ] ) ; 
        if ( n < 0 ) 
        {   
                n = 3 ; 
                A ( "-", )
                A ( "~", )
                A ( "-", )
        }   
        else if ( ! n ) 
                P ( "Congratulations on your new baby! :D\n" )
        else
        {   
                A ( " $", )
                A ( " |", )
                A ( "--", "-" )
                A ( "~~", "~" )
                A ( "--", "-" )
        }   
}

D, 276 264 257 251 249 234 231 229 bytes

import std.conv,std.range,std.algorithm,std.stdio:w=writeln;void main(string[]a){int n=a[1].to!int;n>0?"$|-~-".each!((i,c)=>repeat((i<2?" ":"")~c,i<2?n:2*n+1).joiner.w):n?"---
~~~
---".w:"Congratulations on your new baby! :D".w;}

You can test it on DPaste. Just enter desired N as command line argument on input tab. Or compile and run it in real command line: rdmd birthday_golf.d <N>

Not minified version:

import std.conv;
import std.range;
import std.algorithm;
import std.stdio;

void main(string[] args)
{
    int n = args[1].to!int;

    n > 0
        ?
            "$|-~-".each!((i, c) =>
                repeat((i < 2 ? " " : "") ~ c, i < 2 ? n : 2*n + 1).joiner.writeln)
        :
            n
                ? "---\n~~~\n---".writeln
                : "Congratulations on your new baby! :D".writeln
        ;
}

JavaScript ES6, 136

Using alert for output - bad proportional font and the result is ugly. In the snippet below the alert is redirect to the snipped body, giving a better result.
The newline inside backticks is significant and counted.

Test running the snippet in Firefox.

/* Redefine alert for testing purpose */ alert=x=>O.innerHTML=x;

alert((n=+prompt())?[...'$|-~-'].map((c,i)=>(i>1?c:' '+c).repeat(i>1?n>0?n-~n:3:n>0&&n)).join`
`:'Congratulations on your new baby! :D')
<pre id=O></pre>

Less golfed

n=+prompt(); // get input and convert to number

if (n) { // if n != 0 prepare the cake
   output = [...'$|-~-'].map( // for each char of the five lines
     (c,i) => (i>1 ? c : ' '+c) // in line 0 and 1 symbols are space separated
     // if n < 0 repeat count is 0 for line 0 and 1, 3 for the other
     // if n > 0 repeat count is n for line 0 and 1, n+n+1 for the other
     .repeat(i>1 ? n>0 ? n-~n : 3 : n>0 && n) // 
   ).join`\n`;
}
else {
    output = 'Congratulations on your new baby! :D');
}

alert(output);

ECMAScript 2015 – 134 bytes

n=>n?[' $'.repeat(n=(n>0)*n),' |'.repeat(n),d='-'.repeat(c=n?1+2*n:3),'~'.repeat(c),d].join`
`:'Congratulations on your new baby! :D'

CoffeeScript, 160 bytes

f=(i,l=[" $ "," | ",_="---","~~~",_])->if!i then"Congratulations on your new baby! :D"else (if i<0then[_,l[3],_]else i++;(Array(i).join r for r in l)).join "\n"

Ungolfed:

f=(i)->
  l = [" $ "," | ","---","~~~","---"] # The layers
  if i == 0
    return "Congratulations on your new baby! :D"
  else if i < 0
    return [l[2], l[3], l[2]].join("\n")
  else
    i++
    return (Array(i).join(r) for r in l).join("\n")

Use it like:

f(10) # In the CoffeeScript console
alert(f(~~prompt("Y"))) # Browser, alert popup
console.log(f(~~prompt("Y"))) # Browser, log to console, and thus has monospace font

Try it online: link (Contains some custom display code, so everything looks soo nice...)

Ooops, almost forgot it! Happy birthday, @BetaDecay!

pb, 567 bytes

^w[B=45]{vb[-1]^b[0]>w[B!0]{t[B]b[0]<b[T]>>}<}w[B!0]{>}b[65]w[X!0]{<b[B-48]}>w[B!65]{t[B]<t[B*10+T]b[0]>b[T]>}b[0]<t[B]b[0]<[X]>b[T]<b[T]vw[B=0]{b[1]}t[B]b[0]^b[B*T]vw[X!3]{b[45]vb[126]vb[45]^^>}^<<t[B]<b[B+T]w[B!0]{<vw[X!3]{b[0]vb[0]vb[0]^^>}^<<t[B]vvw[T!0]{b[124]^b[36]v>>t[T-1]}v<w[X!-1]{b[45]vb[126]vb[45]^^<}}^[Y]^<[X]>w[B=0]{>vvw[X!-1]{b[0]vb[0]^<}^>}t[111]b[67]>b[T]>b[110]>b[103]>b[114]>b[97]>b[116]>b[117]>b[108]>b[97]>b[116]>b[105]>b[T]>b[110]>b[115]>>b[T]>b[110]>>b[121]>b[T]>b[117]>b[114]>>b[110]>b[101]>b[119]>>b[98]>b[97]>b[98]>b[121]>b[33]>>b[58]>b[68]

I have some regrets.

There are some ways that this could be better. For example, upon figuring out that the input is negative, I then proceed to deduce which negative number it is. This is unnecessary, and maybe one day I'll dive back into this code to stop it.

Don't try to run this in pbi's "watch" mode, if you input a negative it'll crash when it tries to print chr(-1).

Here's the explained version version where I took notes while writing the program. If you'd like to better understand how it works... good luck, and let me know if you figure it out.

# parse number

^w[B=45]{vb[-1]^b[0]>     # if negative, put a -1 at (0, 0)
    w[B!0]{t[B]b[0]<b[T]>>} # move all digits left
<}
w[B!0]{>}b[65]        # put an "A" at the end of the number
w[X!0]{<b[B-48]}      # subtract 48 from each byte to get the digits of the number
>w[B!65]{             # while there's no "A" at the second digit
    t[B]<t[B*10+T]      # set T to (first digit * 10) + second digit
    b[0]                # destroy first digit
    >b[T]               # override 2nd digit with T
    >}                  # point at second digit to restart loop
b[0]<t[B]b[0]<[X]>b[T]<b[T] # move number to (0, -1) and (1, -1)
vw[B=0]{b[1]}t[B]b[0]^b[B*T] # multiply (0, -1) by -1 if required
vw[X!3]{b[45]vb[126]vb[45]^^>} # draw the negative cake
^<<t[B]<b[B+T]w[B!0]{ # if it's positive
    <vw[X!3]{b[0]vb[0]vb[0]^^>} # erase the cake
    ^<<t[B]vvw[T!0]{b[124]^b[36]v>>t[T-1]} # draw the candles
    v<w[X!-1]{b[45]vb[126]vb[45]^^<}       # draw the cake
}^[Y]^<[X]>w[B=0]{>vvw[X!-1]{b[0]vb[0]^<}^>} # erase the part of the cake that would show up
# hardcoded string for input 0
t[111]b[67]>b[T]>b[110]>b[103]>b[114]>b[97]>b[116]>b[117]>b[108]>b[97]>b[116]>b[105]>b[T]>b[110]>b[115]>>b[T]>b[110]>>b[121]>b[T]>b[117]>b[114]>>b[110]>b[101]>b[119]>>b[98]>b[97]>b[98]>b[121]>b[33]>>b[58]>b[68]

Mathematica, 164 Bytes

Completely missed the candle-less cakes for n < 0, adding an additional 15 characters

r[a_,b_]:=StringRepeat[a,Abs@b];c=" $ ";t="---";m="~~~";f[n_]:=If[n>0,r[c,n]~~"\n",""]~~r[t,n]~~"\n"~~r[m,n]~~"\n"~~r[t,n];f[0]:="Congratulations on your new baby! :D"

Perl, 139 127 117 bytes

Does not require '-n' or '-p' options.

Revision 3 (with thanks to Dom Hastings below):

$==<>;map{print$_ x(!$=||(/ /?$=:($=<1||$=)*2+1)).$/}!$=?'Congratulations on your new baby! :D':split 0,' $0 |0-0~0-'

Revision 2:

$n=<>;map{print$_ x($n==0?1:(/ /?$n:($n<1?1:$n)*2+1)).$/}$n==0?('Congratulations on your new baby! :D'):(' $',' |','-','~','-')

Revision 1:

$n=<>;map{print$_ x(($l=length())>2?1:($l==2?$n:($n<1?1:$n)*2+1)).$/}$n==0?('Congratulations on your new baby! :D'):(' $',' |','-','~','-')

Here's a version of revision 3 that doesn't have the leading blank new lines on negative input - 132 bytes.

$==<>;map{print$_ x(!$=||(/ /?$=:($=<1||$=)*2+1)).(/ /&&$=<0?'':$/)}!$=?'Congratulations on your new baby! :D':split 0,' $0 |0-0~0-'

Python 2, 150 bytes

m=input()
n=m-1
p="---"+"--"*n
g="\n~~~"+"~~"*n+"\n"
if m>0:print" $"*m,"\n"," |"*m
s=p+g+p
print s if m!=0 else"Congratulations on your new baby! :D"

Close to author's Python :(

Lua, 299 Bytes

a=0+io.read() b=string.rep p=print if a==0 then p("Congratulations on your new baby! :D") else p(b(" ",a)..b("$ ",a)..("\n")..b(" ",a)..b("| ",a)) if a<0 or a==1 then p("---\n~~~\n---") else p(b(" ",a-1).."-"..b("-",2*a).."\n"..b(" ",a-1).."~"..b("~",2*a).."\n"..b(" ",a-1).."-"..b("-",2*a))end end

R, 228 226 220 221 Bytes


Last edit to correct the candleless cake, was as wide as the positive one on negative cases, thanks @CathG and @jbaums for the feedback

n=scan()
s=strsplit
p=paste0
a=b='-~-'
if(!n)cat('Congratulations on your new baby! :D')else{
if(n>0){a=p('  ',a);b=p('$|',b)}else n=1
a=s(a,'')
b=s(b,'')
d=data.frame(rep(c(a,b),n),a)
cat(do.call(p,d),sep="\n")}

R, 157

write(if(n<-scan()){
z=matrix(c("$","|","-","~","-"),N<-2*max(1,n)+1,5,T)
z[seq(1,N,1+(n>0)),1:2]=" "
z}else"Congratulations on your new baby! :D","",N,F,"")

Moonscript, 141 bytes

n=0+io.read!
m=3
f=(s='-')->print s\rep m
if n>0
 m=n
 m=1+2*m,f' $',f' |'
if n==0 print"Congratulations on your new baby! :D"else f f!,f'~'

Julia, 143 bytes

n=int(readline())
p=println
l="\n"
n>0&&p(" \$"^n*l*" |"^n)
d=2(n<0?1:n)+1
p(d>1?"-"^d*l*"~"^d*l*"-"^d:"Congratulations on your new baby! :D")

Pretty straightforward. Ungolfed:

# Read n from STDIN and convert to an integer
n = int(readline())

# Print the candles for positive n
n > 0 && println(" \$"^n * "\n" * " |"^n)

# Define d as the width of the cake
d = 2(n < 0 ? 1 : n) + 1

# Newborns can't eat cake
if d > 1
    println("-"^d * "\n" * "~"^d * "\n" * "-"^d)
else
    println("Congratulations on your new baby! :D")
end

Mouse, 164 161 bytes

?N:N.0=["Congratulations on your new baby"33!'" :D"$]N.0>[#P,32!'36,N.;#P,32!'124,N.;]N.0<[1N:]2N.*1+D:#P,45,D.;#P,126,D.;#P,45,D.;$P0I:(I.2%=0=^1%!'I.1+I:)"!"@

Mouse is clearly not an ideal choice for this task, but it was fun.

Ungolfed:

? N.                               ~ Read N from STDIN
N. 0 = [                           ~ Have a baby for N == 0
  "Congratulations on your new baby" 33 !' " :D" $
]
N. 0 > [                           ~ If N > 0...
  #P, 32 !' 36, N.;                ~ Print the candle flames
  #P, 32 !' 124, N.;               ~ Print the candle sticks
]
N. 0 < [                           ~ If N < 0...
  1 N:                             ~ Set N = 1
]
2 N. * 1 + D:                      ~ Assign D = 2N + 1
#P, 45, D.;                        ~ Print the top cake layer
#P, 126, D.;                       ~ Print the middle layer
#P, 45, D.;                        ~ Print the bottom
$P                                 ~ Define the printing macro...
  0 I:                             ~ Initialize I to 0
  ( I. 2% = 0 = ^                  ~ While I != the second input
    1% !'                          ~ Print the first input
    I. 1 + I:                      ~ Increment I
  )
  "!"                              ~ Print a newline
@

The stack can contain only integers. !' takes an integer off the stack and prints the ASCII character with that code.

golflua, 113 characters

\p(c)w(S.t(c,n))~$n=I.r()+0?n==0w"Congratulations on your new baby! :D"!??n>0p" $"p" |"n=n*2+1!?n=3$p"-"p"~"p"-"$

Sample run:

bash-4.3$ golflua -e '\p(c)w(S.t(c,n))~$n=I.r()+0?n==0w"Congratulations on your new baby! :D"!??n>0p" $"p" |"n=n*2+1!?n=3$p"-"p"~"p"-"$' <<< 5
 $ $ $ $ $
 | | | | |
-----------
~~~~~~~~~~~
-----------

bash-4.3$ golflua -e '\p(c)w(S.t(c,n))~$n=I.r()+0?n==0w"Congratulations on your new baby! :D"!??n>0p" $"p" |"n=n*2+1!?n=3$p"-"p"~"p"-"$' <<< 0
Congratulations on your new baby! :D

bash-4.3$ golflua -e '\p(c)w(S.t(c,n))~$n=I.r()+0?n==0w"Congratulations on your new baby! :D"!??n>0p" $"p" |"n=n*2+1!?n=3$p"-"p"~"p"-"$' <<< -5
---
~~~
---

JavaScript, 143 153 Bytes

for(v in k=' $ 0 | 0---0~~~0---'.split(+!(n=+prompt(c=''))))c+=k[v].repeat(n<0?1:n)+'\n';alert(n>0?c:n?c.slice(8):'Congratulations on your new baby! :D')

To see output in mono space font replace 'alert' by 'console.log'

Python 3, 169 bytes

n=int(input())
m=max(n*2+1,3)
f=' {}'*n+'\n'+' {}'*n+'\n'+'-'*m+'\n'+'~'*m+'\n'+'-'*m
if n==0:f='Congratulations on your new baby! :D'
print(f.format(*['$']*n+['|']*n))

SpecBAS, 164

Uses the apostrophe shortcut to move to new line

INPUT n: IF n=0 THEN PRINT "Congratulations on your new baby! :D" ELSE IF n<0 THEN PRINT "---"'"~~~"'"---" ELSE PRINT " $"*n'" |"*n'"-";"--"*n'"~";"~~"*n'"-";"--"*n

Formatted for easier reading

INPUT n
IF n=0 THEN PRINT "Congratulations on your new baby! :D" 
ELSE IF n<0 THEN PRINT "---"'"~~~"'"---" 
ELSE PRINT " $"*n'" |"*n'"-";"--"*n'"~";"~~"*n'"-";"--"*n

Lua 5.2, 187 Bytes

p=print n=io.read"*n"r=string.rep
if n==0 then p"Congratulations on your new baby! :D"else
m=3*math.max(n,1)if n>0 then p(r(" $ ",n))p(r(" | ",n))end
p(r("-",m))p(r("~",m))p(r("-",m))end

Minimalistic version. I'm open for improvements :)

JavaScript ES6, 154 chars

alert((n=+prompt())?((n>0?` $
 |
`:(n=1)&&"")+`--
~~
--`).replace(/../gm,x=>x.repeat(n)).replace(/(.).*/gm,"$&$1"):"Congratulations on your new baby! :D")

And one more (154 too)

alert((n=+prompt())?` $
 |
--
~~
--`.slice(n<0?(n=1)-9:0).replace(/../gm,x=>x.repeat(n)).replace(/(.).*/gm,"$&$1"):"Congratulations on your new baby! :D")

To see output in monospace font (and move ouptut to the console) use

alert=x=>console.log(x)

rs, 117 bytes

^0$/Congratulations on your new baby! :D
-.+/-1
$$r=)^^(\1)\n
$$m=-(--)^^(\1)\n
(\d+)/ ($ $r (| $r$m~(~~$r$m
^-[^-]+/

Live demo and test cases.

Ruby, 120 bytes

Revision 1 (120 bytes)

18 bytes saved thanks to manatwork

n=gets.to_i
puts ['Congratulations on your new baby! :D',%w{\ $ \ | - ~ -}.map{|e|e.ljust 2*n+1,e},'---
~~~
---'][n<=>0]

Revision 0 (138 bytes)

n=gets.to_i
n>0&&[' $',' |',?-,?~,?-].each{|e|puts''.rjust(2*n+1,e)}
puts ['Congratulations on your new baby! :D','','---
~~~
---'][n<=>0]

For positive numbers: this iterates through a string corresponding to each line of the cake. These are used as pad strings to right justify the empty string to length 2*n+1. This avoids any complications with having to print an odd number of characters, when the natural repetition is equal to the pitch of the candles (i.e. 2 characters.) n>0&& is necessary to avoid outputting a single column in case of input zero.

For all numbers: "n<=>0" finds the sign of the input. The baby message is output for n=0, and an empty string for positive n (as correct output has already been given above.) For negative n, Ruby interprets the -1 as meaning the last element of the array, and outputs the candleless cake.

Perl, 144 bytes

143 bytes of code, plus one extra byte for the -n switch to capture stdin.

if($_!=0){print$_>0?" \$"x$_.$/." |"x$_.$/:""x($_=1);$_=$_*2+1;print"-"x$_.$/."~"x$_.$/."-"x$_;exit}print"Congratulations on your new baby! :D"

Python 2, 158 bytes


i=input()
l='\n'
s=''
if i==0:s='Congratulations on your new baby! :D'
elif i<0:s='---\n~~~\n---'
else:n=i*2+1;a=l+'-'*n;s=' $'*i+l+' |'*i+a+l+'~'*n+a
print s

R, 279 bytes

Interactive version (286 bytes):

b<-function(){
n=scan()
if(n==0)cat("Congratulations on your new baby! :D\n")
if(n>0){k=2*n+1;m=rep("-",k);cat(paste(c(rep(c(" ","$"),l=k),"\n",rep(c(" ","|"),l=k),"\n",m,"\n",rep("~",k),"\n",m,"\n"),collapse=""))}
if(n<0){m=rep("-",3);cat(paste(c(m,"\n",rep("~",3),"\n",m,"\n"),collapse=""))}
}

Not interactive version (279 bytes):

b<-function(n){
if(n==0)cat("Congratulations on your new baby! :D\n")
if(n>0){k=2*n+1;m<-rep("-",k);cat(paste(c(rep(c(" ","$"),l=k),"\n",rep(c(" ","|"),l=k),"\n",m,"\n",rep("~",k),"\n",m,"\n"),collapse=""))}
if(n<0){m=rep("-",3);cat(paste(c(m,"\n",rep("~",3),"\n",m,"\n"),collapse=""))}
}

Pyth, 73 72 71 69 67 bytes

?Qjb+m*+\ dQ"$|"*RhyeS,1Q"-~-""Congratulations on your new baby! :D

Try it online.

Output for n < 0 contains 2 leading newlines, as permitted in comments. To get rid of them, use

?QjbfT+jR*\ hQ"$|"*RhyeS,1Q"-~-""Congratulations on your new baby! :D