Emoji Vending Machine
PHP, (1295 - 14) - 25% = 960.75 characters
Old scores 1315 1351 1361 1295 989 977
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]
) forInvalid 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.
C# 6 (.Net Framework 4.6), 1356 1324 1304 1311 1307 1238 1235 1231 1220 Letters - 14 Letters (Emoji Numbers) - (15% Jam Bonus + 10% ID Bonus) = 1017 993 978 972.75 969.75 918 915.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!!!"); ;)
{
var f = h.ReadLine();
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.