¿Qué tan borracho estoy y cuándo puedo volver a conducir?

8

Es fin de semana y ¿qué hacen los chicos geniales los fines de semana? Beber por supuesto! ¿Pero sabes lo que no es tan genial? Beber y conducir. Por lo tanto, decide escribir un programa que le diga qué tan cargado está y cuándo podrá conducir nuevamente sin que la policía lo detenga y pierda su licencia.

El reto

Dada una lista de bebidas que disfrutó esta noche, calcule su nivel de alcohol en sangre y el tiempo que tiene que esperar hasta que pueda subir a su automóvil y llegar a casa.

Entrada

La entrada será una lista de bebidas que tomaste esta noche. Esto se verá así:

4 tiros de alcohol
1 copas de vino
2 botellas de cerveza
3 vasos de agua

Los contenedores siempre serán plurales.

Como puede ver cada entrada consta de:

  • El tipo de bebida (alcohol, vino, cerveza, agua).
  • El recipiente para la bebida (tragos, vasos, botellas).
  • La cantidad x de las bebidas que tomaste de ese tipo como entero con x> 0,

Cada tipo de bebida agrega una cierta cantidad de alcohol a la sangre:

alcohol -> 0.5 ‰ / 100 ml
cerveza -> 0.1 ‰ / 100 ml
vino -> 0.2 ‰ / 100 ml
agua -> -0.1 ‰ / 100 ml

El agua es la excepción aquí, ya que diluye la sangre y disminuye el nivel de alcohol (sería muy bueno si eso realmente funcionara ...).

Cada contenedor tiene un cierto volumen:

disparos -> 20 ml
vasos -> 200 ml
botellas -> 500 ml

Salida

Tienes que generar dos números:

  • El nivel de alcohol en ‰
  • El tiempo en horas que tiene que esperar hasta llegar a 0.5 ‰ o menos, para que pueda conducir nuevamente. Pierdes 0.1 ‰ por hora.

Notas

  • El nivel de alcohol nunca puede caer por debajo de cero.
  • Lo mismo vale para el tiempo de espera. Si tiene 0.5 ‰ o menos, salida cero.
  • El orden de las bebidas no importa, por lo que el agua potable puede reducir el nivel de alcohol por debajo de cero en el proceso del cálculo. Si permanece allí, debe reemplazarlo con cero.

El nivel de alcohol para el ejemplo anterior se calcularía así:

4 tiros de alcohol -> 0.4 ‰
1 copas de vino -> 0.4 ‰
2 botellas de cerveza -> 1.0 ‰
3 vasos de agua -> -0.6 ‰

=> 0.4 + 0.4 + 1 - 0.6 = 1.2 ‰

Para alcanzar 0.5 ‰ necesitas perder 0.7 ‰. Pierdes 0.1 ‰ por hora, por lo que debes esperar 7 horas para volver a conducir.

Reglas

  • Puede tomar la entrada en cualquier formato que desee, pero debe usar las cadenas exactas como se indicó anteriormente. Puedes tomar los números como enteros.
  • Puede generar los dos números en cualquier orden, solo deje claro cuál usa en su respuesta.
  • Puede suponer que la entrada siempre tendrá al menos una entrada.
  • Función o programa completo permitido.
  • Reglas predeterminadas para entrada / salida.
  • Se aplican lagunas estándar .
  • Este es el , por lo que gana el conteo de bytes más bajo. Tiebreaker es una presentación anterior.

Casos de prueba

Entrada como lista de cadenas. Primero muestra el nivel de alcohol, valores separados por una coma.

["4 tragos de alcohol", "1 vaso de vino", "2 botellas de cerveza", "3 vasos de agua"] -> 1.2, 7
["10 tiros de alcohol", "1 botella de agua"] -> 0.5, 0
["3 copas de vino", "2 botellas de alcohol"] -> 6.2, 57
["6 disparos de cerveza", "3 vasos de agua"] -> 0, 0
["10 vasos de cerveza"] -> 2.0, 15

¡Feliz codificación!

Denker
fuente
1
"El nivel de alcohol nunca puede caer por debajo de cero". - ¿La matriz está en orden de concesión, o solo en total? Entonces, si tengo 1 trago de cerveza, y luego 2 tragos de agua, y luego 1 trago de cerveza, ¿debería producir 0% o .5%?
Kuilin Li
1
@KuilinLi No es, el orden no importa. Lo aclararé, gracias por el comentario!
Denker
1
Entonces, ¿debería producir 0 y el nivel de alcohol técnicamente puede caer por debajo de cero en el medio de la bebida? Porque de lo contrario, no tenemos forma de saber cuándo se bebió el agua si la matriz contiene agua ... Incluso podríamos suponer que, si la matriz contiene agua, beberemos el agua primero, y no tendrá ningún efecto en cualquier cosa.
Kuilin Li
1
@KuilinLi Lo dejé claro en el desafío ahora. El nivel de alcohol puede caer por debajo de cero en el proceso del cálculo, solo tiene que redondearlo a cero si permanece allí.
Denker
77
No bebo, así que mi entrada esfunction drive(a) { if (a.every(v=>/water/.test(v))) return [0, 0]; throw new TeetotalException; }
Neil

Respuestas:

1

Javascript (ES6), 109

Toma datos como matrices de matrices de cadenas / enteros, p. Ej.

[[4, "shots", "booze"],
[1, "glasses", "wine"],
[2, "bottles", "beer"],
[3, "glasses", "water"]]

Salidas a una matriz simple, p. Ej.[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?g-5:0])

Explicado

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 ? g - 5 : 0])                         // Output: Level / 10 and Level - 5 bound to 0
reubn
fuente
Bien jugado pero no siempre válido: prueba[[3,"shots", "booze"]]
edc65
@ edc65 ¡Buena captura!
Reubn
Solo necesita un pequeño ajuste y sigue siendo mucho mejor que el mío
edc65
6

TSQL, 301 , 299 , 219 , 206 bytes

La entrada va a la tabla temporal #I(dijiste cualquier formato :)

SELECT * INTO #I FROM (
  VALUES
    (4,'shots','booze')
   ,(1,'glasses','wine')
   ,(2,'bottles','beer')
   ,(3, 'glasses','water')
) A (Q, V, N)

Código:

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;

Gracias por las ideas para mejorarlo, Micky T :)

Liesel
fuente
Para 2012+ podría usar la IIFfunción en lugar de CASEdeclaraciones para algunos bytes
MickyT
1
También puede cambiar los nombres de sus columnas en las subconsultas para evitar tener que calificar en las cláusulas de unión, por ejemplo, JOIN(SELECT .. )A(Y,S)ON Y=Ny (L+ABS(L))/2,10*((L-.5+ABS(L-.5))/2)es más corto que la función IIF mencionada anteriormente. También puede ahorrar un poco si considera hacer una unión cruzada en los valores de tamaño y fuerza. por ejemploSELECT V,N,Q*S FROM(VALUES(...))A(N,S),(VALUES(...)B(V,Q)
MickyT
3

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]

Menos golf

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]
)
edc65
fuente
1

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

Para ser ejecutado con perl -p. Toma entrada orientada a línea en STDIN, produce salida en STDOUT.

Versión menos golfizada:

# 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

Gracias a dev-null por las sugerencias que ahorraron 11 bytes.

David Morris
fuente
@ dev-null gracias! Creo que la función tenía sentido para un acortamiento intermedio, y olvidé comprobar si todavía estaba ayudando.
David Morris
Si siempre recibe una entrada válida, puede cambiar \da.
andlrc
¿Podría agregar un ejemplo de ejecución del programa, para que quede claro qué formato de entrada y salida utiliza?
Denker