Dor de cabeça de férias

14

Aviso: NÃO siga conselho médico deste post. Se você quiser aconselhamento médico, procure um profissional qualificado.

Estou com dor de cabeça. Eu preciso de comprimidos para dor de cabeça.

Vou lhe dizer as últimas doses que tomei e você me diz quando posso tomar minha próxima dose, sem overdose.

Vou te dar essa string: P: 00:00, I: 02:00, P: 04:00, I: 06:00

E você me dará o seguinte: Next P: 08:00, I: 10:00

Entrada:

String representando os horários em que cada medicamento foi tomado, no seguinte formato:

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

Isso significa que o paracetamol foi tomado às 00:00 e 04:00 e o ibuprofeno foi tomado às 02:00 e 06:00

Saída (atualizada):

Cadeia de caracteres com a hora em que cada próximo medicamento pode ser tomado, no seguinte formato:

Next P: 08:00, I: 10:00
  • A ordem de saída deve estar na ordem em que o medicamento deve ser tomado. - Se o ibuprofeno deve ser tomado às 09:35 e Paracetamol e 10:22, a saída deve serNext I: 09:35, P: 10:22
  • Se o horário da próxima dose de cada medicamento for o mesmo, a ordem de saída não importará: Next P: 08:00, I: 08:00OUNext I: 08:00, P: 08:00
  • Se apenas um medicamento estiver sendo tomado (na sequência de entrada), apenas esse medicamento deverá estar na sequência de saída: Next P: 02:00

Regras:

  • Só haverá dois tipos de medicação: Paracetamol 'P' e Ibuprofen 'I'.
  • O paracetamol pode ser tomado uma vez a cada 4 horas, no máximo 4 vezes em um período de 24 horas.
  • O ibuprofeno também pode ser tomado uma vez a cada 4 horas, no máximo 4 vezes em um período de 24 horas.
  • Paracetamol e ibuprofeno podem ser tomados juntos, ou em momentos separados. Um não conta para a dosagem do outro.
  • Os horários na sequência de entrada sempre serão consecutivos, mas podem ocorrer durante a meia-noite (23:00 -> 03:00)
  • Os tempos na sequência de entrada não durarão mais que 24 horas
  • Máximo de 4 vezes para cada medicamento (8 máx. No total)
  • A entrada sempre estará vazia e conterá pelo menos um medicamento e uma vez

Exemplos:

Duas doses de cada uma em intervalos de duas horas:

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

Dose única de paracetamol

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

Dose máxima de paracetamol em 24 horas, dose ú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 teste:

"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 é o código golf, então a resposta mais curta int bytes vence.

ATUALIZAR:

A saída agora pode ser abreviação de Paracetamol e Ibuprofen; PeI

Erresen
fonte
Eu seria bom ter alguma influência sobre o formato de entrada e de saída - meta pós
Gurupad Mamadapur
@GurupadMamadapur saída talvez, mas extraindo a tempos e medicação tipo a partir da entrada é metade do desafio
Erresen
Eu recomendo que você permita que as pessoas
abreviem o
@Cyoce sim eu concordo, tentando uma solução mim e ele é realmente um pouco complicado - actualiza as regras para permitir a saída abreviado
Erresen
@Lynn concordou e foi atualizado
Erresen

Respostas:

4

JavaScript (ES6), 367 362 354 358 bytes

Versão Golfed:

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 / comentou:

// 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 usá-lo, chame F com a string como argumento:

F("P: 04:00, I: 06:00")
Lucas
fonte
Isso é ótimo, mas eu tive alguns problemas. Parece falhar se houver apenas um tipo de pílula na entrada, por exemplo F("P: 22:00")- -> ReferenceError: q is not defined. Essa entrada será executada se os P&I tiverem sido referenciados anteriormente, mas com detalhes antigos para eu.
Chris M
Obrigado! Acabei de testar e você está certo sobre o erro de referência. Eu acho que a variável q não é redefinida e não prestei atenção suficiente durante o teste. Obrigado por me informar, eu o corrigirei mais tarde.
Luke
Acabou sendo uma solução fácil, mas me custou 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])

Explicação:

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
fonte
1

PHP, 228 241 239 227 226 bytes

requer 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);

demolir

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
fonte
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`, `

Explicação:

Fazendo um loop sobre cada dose, as doses Ie Psão separadas em duas matrizes. Também são adicionadas 4 horas a cada dose, e esses tempos também são salvos. As matrizes são preenchidas no sentido inverso para facilitar a detecção de 8 entradas. O tempo de 4 horas após a primeira dose também é economizado para uso durante a classificação. Nesse ponto, cada matriz pode estar em um dos três estados:

  • 8 entradas, nesse caso a última entrada é a primeira dose e a próxima dose deve ser de 24 horas após esta dose (ou seja, a mesma hora de amanhã)
  • 2, 4 ou 6 entradas; nesse caso, a primeira entrada é de 4 horas após a última dose e, portanto, o horário da próxima dose
  • 0 entradas; nesse caso, concatentamos [], o que é achatado e, portanto, excluído do resultado

Depois de extrair os próximos tempos de dose das duas matrizes, resta classificá-los em ordem. Isto é feito comparando-os com o tempo 4 horas após a primeira dose. Se uma das duas vezes for anterior a essa hora, isso deve se referir a amanhã e essa dose chega por último. Caso contrário, os tempos são simplesmente comparados diretamente. (Bastante inconveniente, o medicamento é antes da hora, então eu tenho que retirá-lo para comparar adequadamente.)

Neil
fonte