# Emoji Vending Machine

You will simulate a vending machine. The items are 56 different emojis, which can be represented as two surrogate UTF-8 characters, from: 🍅(U+D83C U+DF45) to 🍼 (U+D83C U+DF7C). In HTML these emojis can be represented in UTF-16 form as &#x1F345 through &#x1F37C. In base 10 the first UTF-8 character has value 55356. The value of the second character ranges from 57157 to 57212. Here is a CJam program that generates all the relevant emojis. To avoid confusion, this challenge will be scored in characters, not bytes. Some emojis are 2 characters, some are 3. http://www.lettercount.com will give you an accurate count for this challenge.

## Pricing 💵💵💵

There are 8 different price categories:

• $1.00 : 🍅🍆🍇🍈🍉🍊🍋 •$1.50 : 🍌🍍🍎🍏🍐🍑🍒
• $2.00 : 🍓🍔🍕🍖🍗🍘🍙 •$2.50 : 🍚🍛🍜🍝🍞🍟🍠
• $3.00 : 🍡🍢🍣🍤🍥🍦🍧 •$3.50 : 🍨🍩🍪🍫🍬🍭🍮
• $4.00 : 🍯🍰🍱🍲🍳🍴🍵 •$4.50 : 🍶🍷🍸🍹🍺🍻🍼

## Displaying the Vending Machine

This is what the user sees when the program starts and after making a purchase. You can use regular numbers instead of emoji numbers, but emoji numbers have the benefit of being the same width as other emojis. If you use emoji numbers you can subtract 14 characters from your score, because emoji numbers are 3 characters each.

  1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣
A 🍅🍆🍇🍈🍉🍊🍋
B 🍌🍍🍎🍏🍐🍑🍒
C 🍓🍔🍕🍖🍗🍘🍙
D 🍚🍛🍜🍝🍞🍟🍠
E 🍡🍢🍣🍤🍥🍦🍧
F 🍨🍩🍪🍫🍬🍭🍮
G 🍯🍰🍱🍲🍳🍴🍵
H 🍶🍷🍸🍹🍺🍻🍼


If the user enters G5 that selects 🍳. Entering E6 selects 🍦.

To add money, the user should input / and then the code for a coin or bill. The coins are (N)ickel ($0.05), (D)ime ($0.10), and (Q)uarter ($0.25). The bills are (O)ne ($1.00), (F)ive ($5.00), (T)en ($10.00). Every time the user adds a bill or coin, the program should output Balance: [New Balance]. Only one bill or coin can be added each time.Here is an example containing three lines of input:

/D
Balance: $0.10 /Q Balance:$0.35
/F
Balance: $5.35  ## Selecting Items The user selects an item by entering the item code, like B2 or C3. If the user has not added any money, the program should output Item Cost: [Cost of Item]. If the user has added money, but it is not enough to buy the item, the output should be Insufficient Funds. Item Cost: [Cost of Item]. If the user did add enough money, the program should output: Item at [Item Location] Purchased. Remaining Balance: [Balance - Cost of Item]. Then on its own line, print out the emoji of the purchased item. Then print out the entire vending machine (See "Displaying the Vending Machine") with the purchased item replaced with 🚫(U+D83D U+DEAB) Base 10: (55357 57003). ## Ending the Program If the user buys an item which brings his/her balance down to$0.00, the program should automatically terminate. Alternatively, if the user enters "Done" at any time, the program must give the user his/her remaining balance in change. Change must be in only Nickels, Dimes, and Quarters, and must be the smallest amount of coins possible. For example if the remaining balance is $1.45, the output should be QQQQQDD. ## Sample Run (Input starts with "-")  1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣ A 🍅🍆🍇🍈🍉🍊🍋 B 🍌🍍🍎🍏🍐🍑🍒 C 🍓🍔🍕🍖🍗🍘🍙 D 🍚🍛🍜🍝🍞🍟🍠 E 🍡🍢🍣🍤🍥🍦🍧 F 🍨🍩🍪🍫🍬🍭🍮 G 🍯🍰🍱🍲🍳🍴🍵 H 🍶🍷🍸🍹🍺🍻🍼 -E1 Item Cost:$3.00
-/F
Balance: $5.00 -E1 Item at E1 Purchased. Remaining Balance:$2.00
🍡
1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣
A 🍅🍆🍇🍈🍉🍊🍋
B 🍌🍍🍎🍏🍐🍑🍒
C 🍓🍔🍕🍖🍗🍘🍙
D 🍚🍛🍜🍝🍞🍟🍠
E 🚫🍢🍣🍤🍥🍦🍧
F 🍨🍩🍪🍫🍬🍭🍮
G 🍯🍰🍱🍲🍳🍴🍵
H 🍶🍷🍸🍹🍺🍻🍼
-Done
QQQQQQQQ


## Invalid Codes

• If the input starts with / but is not a valid money input, output Money not Accepted.
• If the input is an item that has already been purchased, output Item out of stock
• If the input is a digit-letter combination that is not in range (like A0 or J2, output "Invalid code"
• For all other invalid input, output "Error"

## Bonus (-15%) : Jam

When vending an item, there is a 10% chance the machine will jam, and the item gets stuck. Output JAM!!! one time. In this case the user must input "punch" or "kick". Each time the user does so, there is a 20% chance that the item will break free, and vend as normal. Until the jam clears, the only inputs recognized are "punch" and "kick". All other inputs do nothing. Here is a sample:

-A4
• @steveverrill Good point. I've changed it. My question is, do non-U.S. keyboards have a $button, or is there a code for it? – geokavel Dec 1 '15 at 17:00 • the $ symbol is part of the ASCII character set, so it's safe to assume pretty much all keyboards and languages can handle it. It is the only currency symbol in the 7-bit ASCII character set. As a result, other symbols such as the GBP symbol or the EUR symbol € can be incorrectly rendered due to incompatible string encodings, but it virtually never happens with $. – Level River St Dec 1 '15 at 20:29 • @steveverrill I know they can handle it, but is there a physical keyboard button for it? – geokavel Dec 1 '15 at 20:32 • My British and Spanish keyboards have it in addition to the relevant local currency symbols, and I think the others do too. Besides being the most widely used currency symbol in the world (including for many currencies that are not called dollars), the $ symbol has special meaning in most programming languages, so not having it available on the keyboard would be a serious limitation. I'm typing this on my Spanish keyboard and it's actually easier to get $(shift + 4) than € (alt gr + E) so you can see that the latter symbol added as an afterthought. – Level River St Dec 1 '15 at 20:40 ## 2 Answers # PHP, (1295 - 14) - 25% = 960.75 characters ## Old scores 1315135113611295989977 That was fun, and it's the first answer – yeah. $i=[A=>[🍅,🍆,🍇,🍈,🍉,🍊,🍋],B=>[🍌,🍍,🍎,🍏,🍐,🍑,🍒],C=>[🍓,🍔,🍕,🍖,🍗,🍘,🍙],D=>[🍚,🍛,🍜,🍝,🍞,🍟,🍠],E=>[🍡,🍢,🍣,🍤,🍥,🍦,🍧],F=>[🍨,🍩,🍪,🍫,🍬,🍭,🍮],G=>[🍯,🍰,🍱,🍲,🍳,🍴,🍵],H=>[🍶,🍷,🍸,🍹,🍺,🍻,🍼]];$p=[A=>1,B=>1.5,C=>2,D=>2.5,E=>3,F=>3.5,G=>4,H=>4.5];$v=[N=>.05,D=>0.1,Q=>.25,O=>1,F=>5,T=>10];a:$m='';$w=$x=0;$q=$c[0];$r=$c[1];$f=fgets;$n=rand;$u=number_format;if('Done'==$c&&$e=1)foreach([Q,D,N]as$_)while($b&&round($b-$v[$_],2)>=0&&$m.=$_)$b-=$v[$_];elseif('/'==$q){$v[$r]?$b+=$v[$r]:$m="Money not accepted ";$m.="Balance: $".$u($b,2);}elseif(in_array($q,range(A,Z))){if(0<$r&&8>$r--&&($_=$p[$q])){$b&&$b<$_?$m="Insufficient funds. ":0;if($b<$_)$m.="Item cost: $".$u($_,2);elseif(👾==$i[$q][$r])$m="Item out of stock.";else{$t=0;if(H==$q&&$r<6){$t=$n(13,19);$s=$n(13,19);echo"ID required: {$t}x$s = ?
";if($f(STDIN)!=$t*$s)$m=🔞;else$t=0;}if(!$t){$b-=$_;if(1>$n(0,9)){$w=1;}$x=$i[$q][$r];$m="Item at$c purchased. Remaining balance: $".$u($b,2).($w?"":"
$x");$i[$q][$r]=👾;if(!$b)$e=1;}}}else$m="Invalid code";}if($c&&!$m&&!$e)$m=Error;system(clear);echo" 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣";foreach($i as$k=>$_){echo"
$k ";foreach($_ as$_)echo"$_ ";}echo"
$m ";if($w){echo"JAM!!!
";for(;$c!=kick&&$c!=punch||7>$n(0,9);$c=trim($f(STDIN)));echo"$x
";}$e?exit:$c=trim($f(STDIN));goto a;  As vending machines remind me of the 90s I used goto and for purchased items the Space Invader 👾 is shown. The machine is redrawn after every command. Ungolfed (somehow) $i=[A=>[🍅,🍆,🍇,🍈,🍉,🍊,🍋],B=>[🍌,🍍,🍎,🍏,🍐,🍑,🍒],C=>[🍓,🍔,🍕,🍖,🍗,🍘,🍙],D=>[🍚,🍛,🍜,🍝,🍞,🍟,🍠],E=>[🍡,🍢,🍣,🍤,🍥,🍦,🍧],F=>[🍨,🍩,🍪,🍫,🍬,🍭,🍮],G=>[🍯,🍰,🍱,🍲,🍳,🍴,🍵],H=>[🍶,🍷,🍸,🍹,🍺,🍻,🍼]];
$p=[A=>1,B=>1.5,C=>2,D=>2.5,E=>3,F=>3.5,G=>4,H=>4.5];$v=[N=>.05,D=>0.1,Q=>.25,O=>1,F=>5,T=>10];

a:
$m='';$w=$x=0;$q=$c[0];$r=$c[1];$f=fgets;
$n=rand;$u=number_format;

if('Done'==$c&&$e=1)
foreach([Q,D,N]as$_) while($b&&round($b-$v[$_],2)>=0&&$m.=$_)$b-=$v[$_];
elseif('/'==$q){$v[$r]?$b+=$v[$r]:$m="Money not accepted ";$m.="Balance: $".$u($b,2); }elseif(in_array($q,range(A,Z))){
if(0<$r&&8>$r--&&($_=$p[$q])){$b&&$b<$_?$m="Insufficient funds. ":0; if($b<$_)$m.="Item cost: $".$u($_,2); elseif(👾==$i[$q][$r])
$m="Item out of stock."; else{$t=0;
if(H==$q&&$r<6){
$t=$n(13,19);
$s=$n(13,19);
echo"ID required: {$t}x$s = ?
";
if($f(STDIN)!=$t*$s)$m=🔞;
else
$t=0; } if(!$t){
$b-=$_;
if(1>$n(0,9)){$w=1;
}
$x=$i[$q][$r];
$m="Item at$c purchased. Remaining balance: $".$u($b,2).($w?"":"
$x");$i[$q][$r]=👾;
if(!$b)$e=1;
}
}
}else
$m="Invalid code"; } if($c&&!$m&&!$e)$m=Error; system(clear); echo" 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣"; foreach($i as$k=>$_){
echo"
$k "; foreach($_ as$_) echo"$_ ";
}
echo"
$m "; if($w){
echo"JAM!!!
";
for(;$c!=kick&&$c!=punch||7>$n(0,9);$c=trim($f(STDIN))); echo"$x
";
}

$e?exit:$c=trim($f(STDIN)); goto a;  👾 Tested on OS X with PHP 5.5 and 5.6 👾 Edits • Added 12 bytes. Fixed exit on Done and golfed some strings. • Added 306 bytes. Fixed one or two bugs and added support for the bonuses. With the bonuses it's now nearly 15 bytes shorter. • Added 66 bytes. Had to format the money differently, also had to accept more values ([A-Z][0-9]) for Invalid code. • Saved 10 bytes. Found one whitespace and turned some .= into = were applicable. • Saved 36 bytes due to some refactoring. • Saved 20 bytes by refactoring some loops and assignments. • Wow, that was very fun to play! The only issue I noticed: You need to format prices like 3 and 3.5 into$3.00 and $3.50. – geokavel Dec 1 '15 at 17:15 • Also, when I type in J5 I should get the message : "Invalid code". – geokavel Dec 1 '15 at 17:21 • @geokavel Thanks for your feedback. I've added the correct money format and it also accepts more variants for Invalid code now. It's a fun challenge - even though it has lots of options … 1K characters speak for themselves … :) – insertusernamehere Dec 1 '15 at 20:40 • Congratulations, by a narrow margin, you are the winner! Thank you to both players for being worthy competitors, and fervently trying to out-golf each other! – geokavel Dec 9 '15 at 5:48 • @geokavel It was a fun challenge and a nice ping pong between Stephan and me. If somebody will come up with a shorter solution in the future, I'll be there. ;) – insertusernamehere Dec 9 '15 at 9:54 # C# 6 (.Net Framework 4.6), 13561324130413111307123812351231 1220 Letters - 14 Letters (Emoji Numbers) - (15% Jam Bonus + 10% ID Bonus) = 1017993978972.75969.75918915.75 904.5 Letters using h=System.Console;class c{static void Main(){double b=0,z,p,x=0,i=57157,j,n,r,c,m;var a=1==0;var d=new System.Collections.Hashtable();for(;i<57213;)d.Add(x++,""+(char)55356+(char)i++);for(var e=new System.Random();;){for(w(" 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣"),x=0;x<8;x++,w(""))for(h.Write((char)('A'+x)),i=0;i<7;)h.Write(" "+d[x*7+i++]);for(;;){var k=h.ReadLine();if(k[0]==47){var l=k[1];z=b;b+=l=='N'?.05:l=='D'?.1:l=='Q'?.25:l=='O'?1:l=='F'?5:l=='T'?10:0;a=a|z!=b;w(z!=b?$"Balance {b:0.00}":"Money not Accepted");}else{if(k=="Done"){for(;b/.25>=1;b-=.25)h.Write("Q");for(;b/.1>=1;b-=.1)h.Write("D");for(;b/.05>=1;b-=.05)h.Write("N");return;}r=k[0]-65;c=k[1]-49;if(r<0|r>7|c<0|c>6)w("Invalid code");else{p=1+r/2;if(!a|p>b)w($"{(a&p>b?"Insufficient Funds. ":"")}Item Cost:${p:0.00}");else{m=r*7+c;if(d[m]=="🚫")w("Item out of stock");else{if(r>6&c<6){j=e.Next(13,20);n=e.Next(13,20);w($"ID required: {j}x{n} = ?");if(int.Parse(h.ReadLine())!=j*n){w("🔞");break;}}b-=p;w($"Item at {k} Purchased. Remaining Balance: ${b:0.00}");if(e.Next(10)==1)for(w("Jam!!!");;){var f=h.ReadLine();if((f=="punch"|f=="kick")&e.Next(10)<2)break;}w(""+d[m]);d[m]="🚫";if(b==0)return;break;}}}}}}}static void w(string s)=>h.WriteLine(s);}  slightly more ungolfed for use in LinqPad 5 (C# 6). Use h=System.Console in F4. void Main() { double b=0,z,p,x=0,i=57157,j,n,r,c,m; var a = 1==0; var d = new Hashtable(); for (; i < 57213;) d.Add(x++, ""+(char)55356 + (char)i++); for (var e = new Random(); ;) { for (w(" 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣"), x = 0; x < 8; x++, w("")) for (h.Write((char)('A' + x)), i = 0; i < 7;) h.Write(" " + d[x * 7 + i++]); for (; ;) { var k = h.ReadLine(); if (k[0] == 47) { var l = k[1]; z = b; b += l == 'N' ? .05 : l == 'D' ? .1 : l == 'Q' ? .25 : l == 'O' ? 1 : l == 'F' ? 5 : l == 'T' ? 10 : 0; a = a|z!=b; w(z != b ?$"Balance {b:0.00}" : "Money not Accepted");
}
else
{
if (k == "Done")
{
for (; b / .25 >= 1; b -= .25) h.Write("Q");
for (; b / .1 >= 1; b -= .1) h.Write("D");
for (; b / .05 >= 1; b -= .05) h.Write("N");
return;
}
r = k[0] - 65;
c = k[1] - 49;
if(r<0|r>7|c<0|c>6)w("Invalid code");
else
{
p = 1 + r / 2;
if (!a | p > b) w($"{(a&p>b?"Insufficient Funds. ":"")}Item Cost:${p:0.00}");
else
{
m = r * 7 + c;
if (d[m] == "🚫")
w("Item out of stock");
else
{
if (r > 6 & c < 6)
{
j = e.Next(13, 20);
n = e.Next(13, 20);
w($"ID required: {j}x{n} = ?"); if (int.Parse(h.ReadLine()) != j * n) { w("🔞"); break; } } b -= p; w($"Item at {k} Purchased. Remaining Balance: \${b:0.00}");
if (e.Next(10) == 1)
for (w("Jam!!!"); ;)
{
if ((f == "punch" | f == "kick") & e.Next(10) < 2)
break;
}
w(""+d[m]);
d[m] = "🚫";
if (b == 0) return;
break;
}
}
}
}
}
}
}

void w(string s)=>h.WriteLine(s);


edit: thanks for the for(;;) hint ;)

edit: Strike !! Better than PHP ;-)

edit: Removed 24 Letters. Still something left for php.

edit: Removed 20 Letters by switching from decimal to double.

edit: Removed 7 Letters by switching to Emoji Numbers

edit: Removed 4 Letters by switching everything to double instead of a mix of double and ints.

edit: Removed 69 Letters - found dead code o_O Best Entry C# :D

edit: Removed 3 Letters - switched last if-else statement

edit: Removed 4 Letters - switched from short-circuit operators (&& and ||) to normal & and |

edit: Removed 11 Letters - switched from h.WriteLine to w() with conditional verbatim string.

• Looks good. I was able to test it here with static input. Is there a way for me to test it online or on Mac with dynamic input? – geokavel Dec 1 '15 at 17:31
• You can test it with dynamic input here, although the emojis show up as ??. – geokavel Dec 1 '15 at 17:37
• The only issue I've found with yours is that "Invalid code" should only show up for a number-digit combo that is not in range. All unspecified errors should output "Error". – geokavel Dec 1 '15 at 17:41
• on my way @insertusernamehere :D – Stephan Schinkel Dec 3 '15 at 13:38
• hey .... i've got it down to under php :) @insertusernamehere – Stephan Schinkel Dec 11 '15 at 15:55