| Bytes | Lang | Time | Link |
|---|---|---|---|
| 166 | C GCC | 230805T143102Z | matteo_c |
| 111 | Javascript ES6 | 160214T190928Z | reubn |
| 206 | TSQL | 160214T064952Z | Liesel |
| 122 | Perl | 160214T121309Z | David Mo |
| 131 | JavaScript ES6 | 160214T102631Z | edc65 |
C (GCC), 176 166 bytes
-10 bytes thanks to @ceilingcat
float x;main(a){for(char b[9],c[9];~scanf("%d%s%s\n",&a,b,c);)x+=a*(*b-98?*b-103?.02:.2:.5)*(*c-98?c[1]-97?2:-1:c[1]-111?1:5);printf("%f %f",x>0?x:0,fmax(0,x*10-5));}
Javascript (ES6), 111
Takes input as arrays of arrays of strings/integers e.g.
[[4, "shots", "booze"],
[1, "glasses", "wine"],
[2, "bottles", "beer"],
[3, "glasses", "water"]]
Outputs to simple array e.g. [1.2, 7]
a=>(b=0,c={s:2,g:20,b:50,o:2,e:10,i:5,a:-10},a.map(([d,e,f])=>b+=d*c[e[0]]/c[f[1]]),g=b>0?b:0,[g/10,g>5?g-5:0])
#Explained
a => (
b = 0, // Counter For Alcohol Level
c = {s:2, g:20, b:50, o:2, e:10, i:5, a:-10}, // Look up for values
a.map( // Loops over array
([d, e, f]) => // Sets d,e,f to respective array indexes
b += d * c[e[0]] / c[f[1]] // Increases Level by values from lookup
),
g = b > 0 ? b : 0, // If Level is lower than 0 make it = 0
[g / 10, g > 5 ? g - 5 : 0]) // Output: Level / 10 and Level - 5 bound to 0
TSQL, 301, 299, 219, 206 Bytes
Input goes into temp table #I (you said any format :)
SELECT * INTO #I FROM (
VALUES
(4,'shots','booze')
,(1,'glasses','wine')
,(2,'bottles','beer')
,(3, 'glasses','water')
) A (Q, V, N)
Code:
SELECT IIF(L<0,0,L),IIF(10*L-.5<0,0,10*L-.5)FROM(SELECT SUM(Q*S*P)L FROM(VALUES('bo%',.5),('be%',.1),('wi%',.2),('wa%',-.1))A(W,S),(VALUES('s%',.2),('g%',2),('b%',5))B(X,P),#I WHERE N LIKE W AND V LIKE X)A;
Thanks for the ideas to improve it, Micky T :)
Perl, 133 119 + 3 = 136 122 bytes
%u=(o,.5,e,.1,i,.2,a,-.1,g,2,b,5,s=>.2);/(\d+) (.).* .(.)/;$x+=$1*$u{$2}*$u{$3}}{$_=($x>0?$x:0).$".($x-.5>0?$x-.5:0)*10
To be run with perl -p. Takes line-oriented input on STDIN, produces output on STDOUT.
Less-golfed version:
# char->number conversion table
# declared using barewords except for 's', which can't be a bareword
# because it's a keyword
%u=(o,.5, e,.1, i,.2, a,-.1, g,2, b,5, s=>.2);
# extract the number, first letter of first word, second letter of
# second word
/(\d+) (.).* .(.)/;
# do unit conversion and multiply up all factors
$x += $1 * $u{$2} * $u{$3}
# hack for -p to produce an END { ... print } block
}{
# format output
$_ = ($x > 0 ? $x : 0) . $" . ($x-.5 > 0 ? $x-.5 : 0)*10
Thanks to dev-null for suggestions saving 11 bytes.
JavaScript (ES6), 131
a=>a.map(s=>([a,b,c]=s.split` `,t+=a*[50,20,2]['bgs'.search(b[0])]*~-'0236'['aeio'.search(c[1])]),t=0)&&[t>0?t/100:0,t>50?t/10-5:0]
Less golfed
a=>(
t=0,
a.map(s=>(
[a,b,c] = s.split` `,
t += a * [50,20,2]['bgs'.search(b[0])] // char 0 is unique
* [-1,1,2,5]['aeio'.search(c[1])] // char 1 is unique
// golfed: add 1 to get a string of dingle digits, the sub 1 using ~-
)
),
[ t>0 ? t/100 : 0, t>50 ? t/10-5 : 0]
)