Dolor de cabeza de vacaciones

14

Advertencia: NO tome el consejo médico de esta publicación. Si desea asesoramiento médico, acuda a un profesional calificado.

Me duele la cabeza. Necesito pastillas para el dolor de cabeza.

Le diré las últimas dosis que he tomado, y usted me dice cuándo puedo tomar mi próxima dosis, sin sobredosis.

Te daré esta cadena: P: 00:00, I: 02:00, P: 04:00, I: 06:00

Y me darás esto: Next P: 08:00, I: 10:00

Entrada:

Cadena que representa las veces que se ha tomado cada medicamento, en el siguiente formato:

P: 00:00, I: 02:00, P: 04:00, I: 06:00

Esto significa que el paracetamol se tomó a las 00:00 y las 04:00, y el ibuprofeno se tomó a las 02:00 y las 06:00

Salida (actualizada):

Encadena con el tiempo que se puede tomar la siguiente dosis de cada medicamento, en el siguiente formato:

Next P: 08:00, I: 10:00
  • El orden de salida debe estar en el orden en que se tomará el medicamento. - Si se toma ibuprofeno a las 09:35 y paracetamol y a las 10:22, la salida debe serNext I: 09:35, P: 10:22
  • Si los tiempos para la siguiente dosis de cada medicamento son los mismos, el orden de salida no importa: Next P: 08:00, I: 08:00ONext I: 08:00, P: 08:00
  • Si solo se toma un medicamento (en la cadena de entrada), solo ese medicamento debe estar en la cadena de salida: Next P: 02:00

Reglas:

  • Solo habrá dos tipos de medicamentos, paracetamol 'P' e ibuprofeno 'I'.
  • El paracetamol se puede tomar una vez cada 4 horas, un máximo de 4 veces en un período de 24 horas.
  • El ibuprofeno también se puede tomar una vez cada 4 horas, un máximo de 4 veces en un período de 24 horas.
  • El paracetamol y el ibuprofeno se pueden tomar juntos o en momentos separados. Uno no cuenta para la dosificación del otro.
  • Los tiempos en la cadena de entrada siempre serán consecutivos, pero pueden pasar la medianoche (23:00 -> 03:00)
  • Los tiempos en la cadena de entrada no abarcarán más de 24 horas.
  • Máximo de 4 veces por cada medicamento (8 máx en total)
  • La entrada siempre estará vacía y contendrá al menos un medicamento y una vez

Ejemplos:

Dos dosis de cada uno a intervalos de dos horas:

"P: 00:00, I: 02:00, P: 04:00, I: 06:00" -> "Next P: 08:00, I: 10:00"

Dosis única de paracetamol

"P: 22:00" -> "Next P: 02:00"

Dosis máxima de paracetamol en 24 horas, dosis única de ibuprofeno

"P: 04:05, P: 08:10, P: 12:15, I: 12:30, P: 16:25" -> "Next I: 16:30, P: 04:05"

Casos de prueba:

"I: 06:00" -> "Next I: 10:00"
"P: 22:00" -> "Next P: 02:00"
"P: 22:00, P: 02:00, I: 06:00" -> "Next P: 06:00, I: 10:00"
"P: 00:00, I: 02:00, P: 04:00, I: 06:00" -> "Next P: 08:00, I: 10:00"
"P: 04:05, P: 08:10, P: 12:15, I: 12:30, P: 16:25" -> "Next I: 16:30, P: 04:05"
"I: 06:32, P: 08:15, I: 10:44, P: 13:03" -> "Next I: 14:44, P: 17:03"
"P: 07:30, I: 07:30, P: 11:30, I: 11:30, P: 15:30, I: 15:30, I: 19:30" -> "Next P: 19:30, I: 07:30"
"I: 07:30, P: 11:30, I: 11:30, P: 15:30, I: 15:30, P: 19:30, I: 19:30" -> "Next P: 23:30, I: 07:30"
"P: 07:30, I: 07:30, P: 11:30, I: 11:30, P: 15:30, I: 15:30, P: 19:30, I: 19:30" -> "Next P: 07:30, I: 07:30" OR "Next I: 07:30, P: 07:30"

Este es el código de golf, por lo que gana la respuesta más corta int bytes.

ACTUALIZAR:

La salida ahora puede ser abreviaturas de paracetamol e ibuprofeno; PyI

Erresen
fuente
Sería bueno tener algo de influencia en el formato de entrada y salida - meta publicación
Gurupad Mamadapur
La salida de @GurupadMamadapur puede ser, pero extraer los tiempos y el tipo de medicamento de la entrada es la mitad del desafío
Erresen
Recomiendo que permita a las personas abreviar el paracetamol y el ibuprofeno en la producción, ya que agregan una longitud innecesaria a las presentaciones
Cyoce
@Cyoce, sí, estoy de acuerdo, probando una solución yo mismo y en realidad es un poco complicado - actualicé las reglas para permitir una salida abreviada
Erresen
@Lynn estuvo de acuerdo y actualizado
Erresen

Respuestas:

4

JavaScript (ES6), 367 362 354 358 bytes

Versión de golf:

A=i=>i>9?""+i:"0"+i,B=(s,a=":")=>s.split(a),C=(a,b,c,d)=>[...[s,t]=B((b>3?c:d)||":"),a+` ${A(s=b>3?+s:(+s+4)%24)}:`+A(t=+t)],F=s=>{a=B(s,m=", ");for(b=c=d=e=f=p=q=0;f<a.length;g=="P:"?(b++,d=d?h:p=h):(c++,e=e?h:q=h))[g,h]=B(a[f++]," ");[i,j,k]=C("P",b,p,d),[n,o,l]=C("I",c,q,e),r=B(h)[0];return"Next "+c?b?n*60+(n<r)*1440+j<i*60+(i<r)*1440+o?l+m+k:k+m+l:l:k}

Ungolfed / comentó:

// Returns a zero-padded string of the argument.
A=i=>i>9?""+i:"0"+i,

// Since we do a lot of splitting, alias it. Making the
// second argument optional (and defaulting to ':') saved
// 3 bytes
B=(s,a=":")=>s.split(a),

// Constructs a string for output, along with the time
// of the next dose, in the format [hour, minute, string].
// Arguments:               type
// a -> type (P/I)          String
// b -> amount of doses     Number
//      taken
// c -> first dose taken    String
// d -> last dose taken     String
//
// The first two values are split from the string, but
// before the array is returned, they are converted to
// integers (during the string construction).
C=(a,b,c,d)=>[...[s,t]=B((b>3?c:d)||":"),a+` ${A(s=b>3?+s:(+s+4)%24)}:`+A(t=+t)],

// Main function. Returns the time(s) for the next dose.
// Argument:                type
// s -> list of times of    String
//      and types of 
//      doses taken
F=s=>{
    a=B(s,m=", "); // Split the input by comma + space,
                   // and save that string, since we
                   // need it later when constructing
                   // the output string.
    // For loop has been restructured. Original:
    // for(b=c=f=0;f<a.length;g=="P:"?(b++,d=d?h:p=h):(c++,e=e?h:q=h))
    //     [g,h]=B(a[f++]," ");
    b = 0; // P-dose counter
    c = 0; // I-dose counter
    d = 0; // Last P-dose
    e = 0; // Last I-dose
    p = 0; // First P-dose
    q = 0; // First I-dose
    for (f = 0; f < a.length; f++) {
        [g, h] = B(a[f], " ");  // g contains the type,
                                // h contains the time
        if (g == "P:") {
            b++;                // increase the counter

            if (d == 0) {   // store h in p if this is
                p = h;      // the first dose of this
            }               // type
            d = h;
        } else {
            // See the above code block for comments
            c++;

            if (e == 0) {
                q = h;
            }
            e = h;
        }
    }
    // End of restructured for loop.

    // Construct the output strings, and get the times.
    // See comments at C function.
    [i, j, k] = C("P", b, p, d);
    [n, o, l] = C("I", c, q, e);

    // Get the amount of hours of the dose taken last.
    // We use this to get the correct order of the two
    // times.
    r = B(h)[0];

    // Return statement has been restructured. Original:
    // return "Next "+c?b?n*60+(n<r)*1440+j<i*60+(i<r)*1440+o?l+m+k:k+m+l:l:k
    //==================================================
    // Start creating the output string.
    output = "Next "
    // Use the following checks to figure out what needs
    // to be part of the output and in what order.
    if (c > 0) {
        if (b > 0) {
            // Compare the times of next doses
            // P_time = (i + (i < r) * 24) * 60
            // I'm using implicit conversion of
            // booleans to numbers. If the next
            // dose is past midnight, add 1 * 24
            // to the time, so it is compared
            // correctly.
            // Then add the minutes to the number.
            P_time = i*60+(i<r)*1440+o;
            I_time = n*60+(n<r)*1440+j;

            if (I_time < P_time) {
                output += l + m + k; // I first
            } else {
                output += k + m + l; // P first
            }
        } else {
            output += l; // Just I
        }
    } else {
        output += k; // Just P
    }

    // Finally, return the output
    return output;
}

Para usarlo, llame a F con la cadena como argumento así:

F("P: 04:00, I: 06:00")
Luke
fuente
Esto es genial, pero tuve un par de problemas. Parece fallar si solo hay un tipo de píldora en la entrada, por ejemplo F("P: 22:00")-> ReferenceError: q is not defined. Esta entrada se ejecutará si se ha hecho referencia a P&I anteriormente, pero con detalles antiguos de I.
Chris M
¡Gracias! Lo acabo de probar y tienes razón sobre el error de referencia. Supongo que la variable q no se restablece y no presté suficiente atención durante las pruebas. Gracias por avisarme, lo arreglaré más tarde.
Lucas
Resultó ser una solución fácil, pero me costó 4 bytes.
Luke
1

Python 3 - 437 bytes

a=input();i=p=l=-1;j=q=0
for x in a.split(", ")[::-1]:
    for y, z in [x.split(": ")]:
        s=lambda q,r,t:[t,sum([a*b for a,b in zip([60,1],map(int,q.split(':')))])][r%4<2]+[0,240][r<2]
        if y=="I":j+=1;i=s(z,j,i)
        else:q+=1;p=s(z,q,p)
        l=[l,p+i-239][j+q<2]
r=lambda d,e:("","%s: %02d:%02d, "%(d,(e/60)%24,e%60))[e>-1];p+=[1440,0][p>=l];i+=[1440,0][i>=l];print("Next "+[r("I",i)+r("P",p),r("P",p)+r("I",i)][p<i][:-2])

Explicación:

a=input();i=p=l=-1;j=q=0
for x in a.split(", ")[::-1]: #Read in reverse order, a="P: 01:00"
    for y, z in [x.split(": ")]:#Y="P", Z="00:00"
        s=
        lambda q,r,t:[t,sum([a*b for a,b in zip([60,1],map(int,q.split(':')))])]#Convert "01:01" to 61
        [r%4<2]#In case it's the first or fourth string calculate a new value, otherwise: return the original value
        +[0,240][r<2]#In case it's the last string: add 4 hours. Otherwise, leave it.
        if y=="I":j+=1;i=s(z,j,i)#Calculate for i
        else:q+=1;p=s(z,q,p)#Calculate for p
        l=[l,p+i-239][j+q<2]#Sets the last record. Since we read in reverse order, this should be the first one. We've added 4 hours though so remove those again
r=lambda d,e:("","%s: %02d:%02d, "%(d,(e/60)%24,e%60))[e>-1];#Print function, don't print anything when we have no value
p+=[1440,0][p>=l];i+=[1440,0][i>=l];    #Add a day if record is before the last record so we can correctly calculate the order
print("Next "+[r("I",i)+r("P",p),r("P",p)+r("I",i)][p<i][:-2])#print it and remove the last ","
Carra
fuente
1

PHP, 228 241 239 227 226 bytes

requiere PHP 7

Next<?foreach(explode(", ",$argv[1])as$d){[$m,$h,$i]=explode(":",$d);$x[$m][++$$m]=24+$h+$i/60;}foreach($x as$m=>$d)$r[$m]=$d[$$m-3]?:$d[$$m]-20;sort($r);foreach($r as$m=>$t)$o[]=" $m: ".date("i:s",$t%24*60);echo join(",",$o);

Descompostura

Next<?                              // print "Next"
foreach(explode(", ",$argv[1])as$d) // loop through string split by comma+space
{
    [$m,$h,$i]=explode(":",$d);         // separate drug, hours and minutes
    $x[$m][++$$m]=24+$h+$i/60;          // append time to array, track count in ${$m}
}                                       // (i.e. $P for drug "P" etc.)
foreach($x as$m=>$d)                // loop through drugs
    $r[$m]=                             // add time to result
        $d[$$m-3]                           // if more than 3 medications, use $$m-3
            ??$d[$$m]-20                    // else use last medication - 20 hours
    ;
sort($r);                           // sort results by time
foreach($r as$m=>$t)$o[]=" $m: "    // prepare for output: drug name and formatted time:
    .date("i:s",$t%24*60)           // use hrs as mins and mins as secs to avoid TZ problems
;
echo join(",",$o);                  // print
Titus
fuente
0

JavaScript (ES6), 246 bytes

s=>s.split`, `.map(s=>(m[s[0]].unshift(t=s.replace(/\d+/,h=>(h=(1+h)%24)>9?h:`0`+h),s),l=l||t.slice(1)),l=0,m={I:[],P:[]})&&`Next `+[].concat(m.I[7]||m.I[0]||[],m.P[7]||m.P[0]||[]).sort((i,p)=>((i=i.slice(1))<l)-((p=p.slice(1))<l)||i>p).join`, `

Explicación:

Al recorrer cada dosis, las dosis Iy Pse separan en dos conjuntos. También se agregan 4 horas a cada dosis, y esos tiempos también se guardan. Las matrices se completan a la inversa para facilitar la detección de 8 entradas. El tiempo 4 horas después de la primera dosis también se guarda para su uso durante la clasificación. En este punto, cada matriz puede estar en uno de tres estados:

  • 8 entradas, en cuyo caso la última entrada es la primera dosis, y la siguiente dosis debe ser 24 horas después de esta dosis (es decir, la misma hora mañana)
  • 2, 4 o 6 entradas, en cuyo caso la primera entrada es 4 horas después de la última dosis y, por lo tanto, el tiempo de la siguiente dosis
  • 0 entradas, en cuyo caso concatenamos [], que se aplana y, por lo tanto, se excluye del resultado

Habiendo extraído los siguientes tiempos de dosis de las dos matrices, queda ordenarlos en orden. Esto se hace comparándolos con el tiempo 4 horas después de la primera dosis. Si una de las dos veces es antes de esta hora, esto debe referirse a mañana, y esa dosis es la última. De lo contrario, los tiempos simplemente se comparan directamente. (De manera bastante inconveniente, el medicamento es antes de tiempo, así que tengo que quitarlo para compararlo adecuadamente).

Neil
fuente