| Bytes | Lang | Time | Link |
|---|---|---|---|
| 640 | Retina 0.8.2 | 200416T020645Z | math jun |
| 870 | Ruby plaF | 160704T014546Z | Value In |
| 805 | Python | 160702T000116Z | Chuck Mo |
| 900 | Javascript ES6 | 160630T204127Z | Dendrobi |
Retina 0.8.2, 640 bytes
Performs a series of substitutions to transform the input into the expected output.
-
no
x
extra
Wh
whole-milk
%
2-percent
N
skim
B
breve
X
deJ
1/2
half-J
1/3
1Q-J
2/3
2Qs-J
Q
-third
J
caf
^,
,
,1(?=\D.*E)
,soloZ
,2(?=\D.*E)
,doppioZ
Z,,,,E$
Z
,(\d+)
,$1UleZ
,1U
,sing
,2U
,doub
,3U
,trip
\d+(?!\d*U)
$&Y
U
-tup
,4-.
,quadr
,5-
,quin
,
Z
S
short
T
tall
G
grande
ZV
venti
M(?=[^,]*,\w*$)
MR
E
espresso
M$
macchiato
CP
con panna
A
americano
L
latte
C$
cappuccino
F
foam
WC
whip
R
drizzle
4Y
fourY
6Y
sixY
7Y
sevenY
9Y
nineY
10Y
ten
11Y
eleven
12Y
twelve
13Y
thirK
15Y
fifK
18Y
eighK
20Y
twenty
1Y
one
2Y
two
3Y
three
5Y
five
8Y
eight
1(\w*)Y
$1K
K
teen
V
vanilla
C
caramel
M
mocha
H
hazelnut
-
-
Z,*| ?,+
^ |Y
Most of it is pretty straightforward replacements. A few interesting parts are:
,1(?=\D.*E)
,soloZ
,2(?=\D.*E)
,doppioZ
Handles the special cases for drinks containing the word "espresso". It transforms the 1 and 2 into "solo" and "doppio" before we get to the stage where we transform those numbers into latin tuple form.
Z,,,,E$
Z
Removes the word "espresso" if "solo" or "doppio" is the only other modifier.
M(?=[^,]*,\w*$)
MR
Appends an R to any M with only one comma between it and the end of the string. This allows us to transform all Rs into "drizzle" later on.
1(\w*)Y
$1K
K
teen
Allows us to transform 14,16,17, and 19 into their word forms all at once, since we replace 4,6,7, and 9 beforehand.
Ruby -plaF,, 975 870 bytes
I got a random upvote on my old, almost-four-year-old answer to this question, and because of my comments on how horribly it went (you can check the post history if you want to see what I wrote before) I was inspired to make it better (aka: rewrite most of it from the ground up) and managed to golf over a hundred bytes off it. Still longer than the Python answer, but I'm much happier with how things turned out now.
About 20 bytes were saved by switching from trying to run regex patterns to affect specific parts of the comma structure to using the -aF, flag to autosplit a line of input on commas and save it to $F, allowing me to modify some elements before stitching it back together and finally modifying the output variable with the last few sub/gsub commands.
Honestly, the number of regex replacements made here means most of this could be a Retina program, but I don't know Retina well enough for that.
g=->n,c{n.grep(/^ ?#{c}/i)[0]}
n=%w"0 one two three four five six seven eight nine ten eleven twelve thir four fif";n+=n[6,4]<<'twenty'
$F[1].sub!(/(\d*)(\w)?/){i=eval$1;"#{i&&(%w"0 sing doub trip quadrup quintup"[i]||$1+"-tup")+"le"} #{g[%w"short tall grande venti",$2]if$2}"}
$F[2].gsub!(/(\d*)(\w)/){i=eval$1;"#{i&&n[i]}#{'teen'if(13..19)===i} #{g[%w"vanilla caramel mocha hazelnut",$2]}"}
$F[3].sub!(/.+/){%w"skim whole-milk breve two-percent"[$&.sum%26%4]}
$F[4].gsub!(/(x|-)?(\w+)/){"#{%w"extra no"[$1.ord%2]if$1} #{g[%w"caramelD mochaD whip foam",$2[0]].sub ?D,' drizzle'}"}
$_=$F*' '
sub(/^\S+/){%w"de - half- one-third- two-thirds-"[$&.sum%8]+"caf"}
sub'CP',' con pana'
sub'CM','caramel'+m=' macchiato'
e='espresso'
gsub(/[A-Z]/){g[%w"americano latte cappuccino"+[m,e],$&]}
gsub(/ +/,' ')
$_.strip!
sub(/[sd]...le/){g[%w"doppio solo",$&[0]]}if$_[e]
sub'o '+e,?o
Python, 824 815 807 805 bytes
f=lambda s,a=0:a==0and" ".join(" ".join(f(" "+s.split(",")[i],(["X,deC,1/2,half-C,1/3,oneT-C,2/3,twoTs-C,C,caf,T,-third","".join(" %i"%i+f(",%i-tupL,"%i,["1","x","2","y"])for i in range(6,21))+"1,solo,2,doppio,"*('E'in s)+"1,singL,2,doubL, 3,tripL, 4,quadrupL, 5,quintupL,x,1,y,2,S,short,T,tall,G,grande,V,Vnti","V, vanilla,H, hazelnut,10,ten,11,eleVn,12,twelV,13,thirT,14,4T,15,fifT,16,6T,17,7T,18,8een,19,9T,20,twenty,1,one,2,two,3,three,4,four,5,fiV,6,six,7,seVn,8,eight,9,nine,T,teen","Wh,whole-milk,%,two-percent,N,skim,B,breV","x,extra ,-,no ,F,foam,WC,whip,M,MR,R, drizzL","CM,xM,E,espresso,M, macchiato,CP, con panna,A,americano,L,latte,C,cappuccino,x,C"][i]+",C, caramel,M, mocha,L,le ,V,ve").split(","))for i in range(6-(s in",1,,,,E,2,,,,E"))).split())or a and f(s.replace(a[0],a[1]),a[2:])or s
Slightly more readable:
def f(s,a=0):
if a==0:
a=["X,deC,1/2,half-C,1/3,oneT-C,2/3,twoTs-C,C,caf,T,-third"]
a+=["".join(" %i"%i+f(",%i-tupL,"%i,["1","x","2","y"])for i in range(6,21))+"1,solo,2,doppio,"*('E'in s)+"1,singL,2,doubL, 3,tripL, 4,quadrupL, 5,quintupL,x,1,y,2,S,short,T,tall,G,grande,V,Vnti"]
a+=["V, vanilla,H, hazelnut,10,ten,11,eleVn,12,twelV,13,thirT,14,4T,15,fifT,16,6T,17,7T,18,8een,19,9T,20,twenty,1,one,2,two,3,three,4,four,5,fiV,6,six,7,seVn,8,eight,9,nine,T,teen"]
a+=["Wh,whole-milk,%,two-percent,N,skim,B,breV"]
a+=["x,extra ,-,no ,F,foam,WC,whip,M,MR,R, drizzL"]
a+=["CM,xM,E,espresso,M, macchiato,CP, con panna,A,americano,L,latte,C,cappuccino,x,C"]
return" ".join(" ".join(f(" "+s.split(",")[i],(a[i]+",C, caramel,M, mocha,L,le ,V,ve").split(","))for i in range(6-(s in",1,,,,E,2,,,,E"))).split())
elif a:
return f(s.replace(a[0],a[1]),a[2:])
else:
return s
Demo at https://repl.it/C8Hz/3
Javascript ES6, 902 900 bytes
s=>(R=(l,r)=>(l.split`.`.map((e,i,l)=>!(i%2)&&(r=r.split(e).join(l[i+1]+" "))),r),R("-.no.!.-tuple.1/2.half-caf.1/3.one-third-caf.2/3.two-thirds-caf.ECP.Econ panna.CM.RY.CR.RZ.EM.EY.WC.whip.Wh.whole-milk.A.americano.B.breve.C.cappuccino.D.extra.E.espresso.F.foam.G.grande.H.hazelnut.I.venti.L.latte.M.OZ.N.skim.O.mocha.R.caramel.S.short.T.tall.V.vanilla.X.decaf.Y.macchiato.Z.drizzle.%.two-percent",R(",1,,,,E.solo.,2,,,,E.doppio",s).split`,`.map((e,i)=>(`1VI.2MO.2CR.4xD`.split`.`.map(k=>k[0]==i&&(e=e.split(k[1]).join(k[2]))),i==1?(e=R("1!.single.2!.double.3!.triple.4!.quadruple.5!.quintuple",e.replace(/(\d+)/,"$1!"))):i==2?(e=R("10.ten.20.twenty.11.eleven.12.twelve.13.thir0.14.four0.15.fif0.16.six0.17.seven0.18.eigh0.19.nine0.0.teen.1.one.2.two.3.three.4.four.5.five.6.six.7.seven.8.eight.9.nine",e)):s.includes`E`&&(e=R("single.solo.double.doppio",e)),e)).join` `).replace(/\s+/g," ").trim())
"Ungolfed":
s=>(
R=(l,r)=>(l.split`.`.map((e,i,l)=>!(i%2)&&(r=r.split(e).join(l[i+1]+" "))),r), // consecutive string replacement function
R("-.no.!.-tuple.1/2.half-caf.1/3.one-third-caf.2/3.two-thirds-caf.ECP.Econ panna.CM.RY.CR.RZ.EM.EY.WC.whip. // replace all symbols with appropriate values
Wh.whole-milk.A.americano.B.breve.C.cappuccino.D.extra.E.espresso.F.foam.G.grande.H.hazelnut.I.venti.L.latte.
M.OZ.N.skim.O.mocha.R.caramel.S.short.T.tall.V.vanilla.X.decaf.Y.macchiato.Z.drizzle.%.two-percent",
R(",1,,,,E.solo.,2,,,,E.doppio",s) // if special espresso cases, directly replace entire string
.split`,`.map((e,i)=>( // split input at commas
`1VI.2MO.2CR.4xD`.split`.`.map(k=>k[0]==i&&(e=e.split(k[1]).join(k[2]))), // substitute duplicate symbols with unique symbols
i==1?(e=R("1!.single.2!.double.3!.triple.4!.quadruple.5!.quintuple",e.replace(/(\d+)/,"$1!"))): // if in shots section, expand all numbers
i==2?(e=R("10.ten.20.twenty.11.eleven.12.twelve.13.thir0.14.four0.15.fif0.16.six0.17.seven0.18.eigh0. // if in syrup section, expand all numbers
19.nine0.0.teen.1.one.2.two.3.three.4.four.5.five.6.six.7.seven.8.eight.9.nine",e)):
s.includes`E`&&(e=R("single.solo.double.doppio",e)), // replace single,double with solo,doppio if espresso is in the string
e)).join` `).replace(/\s+/g," ").trim()) // join sections, cleanup whitespaces
Example runs:
f(",3G,V,Wh,,L") -> triple grande vanilla whole-milk latte
f("X,2T,,N,,L") -> decaf double tall skim latte
f("1/2,V,,,,CM") -> half-caf venti caramel macchiato
f("2/3,3V,3V,B,WC,L") -> two-thirds-caf triple venti three vanilla breve whip latte
f(",G,,,xCR,CM") -> grande extra caramel drizzle caramel macchiato
f("X,4T,2M 2C,B,xWC -F xM,C") -> decaf quadruple tall two mocha two caramel breve extra whip no foam extra mocha drizzle cappuccino
f(",2,1V,B,,EM") -> doppio one vanilla breve espresso macchiato
f(",1,,,,E") -> solo
f(",2,,,,E") -> doppio
f(",3,,,,E") -> triple espresso