Maux de tête de vacances

14

Avertissement: NE PAS prendre l'avis médical de ce poste. Si vous souhaitez un avis médical, consultez un professionnel qualifié.

J'ai mal à la tête. J'ai besoin de pilules contre les maux de tête.

Je vous dirai les dernières doses que j'ai prises et vous me direz quand je pourrai prendre ma prochaine dose, sans surdosage.

Je vais vous donner cette chaîne: P: 00:00, I: 02:00, P: 04:00, I: 06:00

Et vous me donnerez ceci: Next P: 08:00, I: 10:00

Contribution:

Chaîne représentant l'heure à laquelle chaque médicament a été pris, au format suivant:

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

Cela signifie que le paracétamol a été pris à 00h00 et 04h00 et l'ibuprofène a été pris à 02h00 et 06h00.

Sortie (mise à jour):

Chaîne avec l'heure à laquelle la prochaine prise de chaque médicament peut être prise, dans le format suivant:

Next P: 08:00, I: 10:00
  • L'ordre de sortie doit être dans l'ordre dans lequel le médicament doit être pris. - Si l'ibuprofène doit être pris à 9h35 et le paracétamol et 10h22, la sortie doit êtreNext I: 09:35, P: 10:22
  • Si les heures pour la prochaine dose de chaque médicament sont les mêmes, l'ordre de sortie n'a pas d'importance: Next P: 08:00, I: 08:00OUNext I: 08:00, P: 08:00
  • Si un seul médicament est pris (dans la chaîne d'entrée), seul ce médicament doit être dans la chaîne de sortie: Next P: 02:00

Règles:

  • Il n'y aura jamais que deux types de médicaments, le paracétamol «P» et l'ibuprofène «I».
  • Le paracétamol peut être pris une fois toutes les 4 heures, un maximum de 4 fois au cours d'une période de 24 heures.
  • L'ibuprofène peut également être pris une fois toutes les 4 heures, un maximum de 4 fois au cours d'une période de 24 heures.
  • Le paracétamol et l'ibuprofène peuvent être pris ensemble ou à des moments différents. L'un ne compte pas pour le dosage de l'autre.
  • Les heures dans la chaîne d'entrée seront toujours consécutives, mais peuvent rouler sur minuit (23:00 -> 03:00)
  • Les durées de la chaîne d'entrée ne dépasseront pas 24 heures
  • Maximum 4 fois pour chaque médicament (8 max au total)
  • L'entrée sera toujours non vide et contiendra au moins un médicament et une fois

Exemples:

Deux doses de chaque à deux heures d'intervalle:

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

Dose unique de paracétamol

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

Dose maximale de paracétamol dans les 24 heures, dose unique d'ibuprofène

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

Cas de test:

"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"

C'est le golf de code, donc la réponse la plus courte en octets gagne.

MISE À JOUR:

La sortie peut maintenant être des abréviations de Paracetamol et Ibuprofen; PetI

Erresen
la source
Je serais bien d'avoir un certain effet de levier sur le format d'entrée et de sortie - meta post
Gurupad Mamadapur
@GurupadMamadapur sortie peut-être, mais extraire les heures et le type de médicament de l'entrée est la moitié du défi
Erresen
Je vous recommande de permettre aux gens d'abréger le paracétamol et l'ibuprofène en sortie car ils ajoutent une longueur inutile aux soumissions
Cyoce
@Cyoce ouais je suis d'accord, essayant une solution moi-même et c'est en fait un peu délicat - mis à jour les règles pour permettre une sortie abrégée
Erresen
@Lynn a accepté et mis à jour
Erresen

Réponses:

4

JavaScript (ES6), 367 362 354 358 octets

Version golfée:

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}

Non golfé / commenté:

// 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;
}

Pour l'utiliser, appelez F avec la chaîne comme argument comme ceci:

F("P: 04:00, I: 06:00")
Luc
la source
C'est super, mais j'ai eu quelques problèmes. Il semble échouer s'il n'y a qu'un seul type de pilule dans l'entrée, par exemple F("P: 22:00")-> ReferenceError: q is not defined. Cette entrée s'exécutera si P&I a déjà été référencé, mais avec d'anciens détails pour I.
Chris M
Merci! Je viens de le tester et vous avez raison sur l'erreur de référence. Je suppose que la variable q n'est pas réinitialisée et je n'ai pas fait assez attention lors des tests. Merci de m'avoir prévenu, je le réparerai plus tard.
Luke
Il s'est avéré être une solution facile, mais cela m'a coûté 4 octets.
Luke
1

Python 3-437 octets

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])

Explication:

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
la source
1

PHP, 228 241 239 227 226 octets

nécessite 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);

panne

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
la source
0

JavaScript (ES6), 246 octets

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

Explication:

En boucle sur chaque dose, les doses Iet Psont séparées en deux tableaux. 4 heures sont également ajoutées à chaque dose, et ces temps sont également enregistrés. Les tableaux sont remplis à l'envers pour faciliter la détection de 8 entrées. Le temps 4 heures après la première dose est également enregistré pour une utilisation lors du tri. À ce stade, chaque tableau peut être dans l'un des trois états suivants:

  • 8 entrées, auquel cas la dernière entrée est la première dose, et la prochaine dose doit être 24 heures après cette dose (c'est-à-dire à la même heure demain)
  • 2, 4 ou 6 entrées, auquel cas la première entrée se fait 4 heures après la dernière dose, et donc l'heure de la dose suivante
  • 0 entrées, auquel cas nous concatentons [], ce qui est aplati et donc exclu du résultat

Après avoir extrait les prochains temps de dose des deux matrices, il reste à les trier dans l'ordre. Cela se fait en les comparant au temps 4 heures après la première dose. Si l'une des deux fois est antérieure à cette heure, cela doit se référer à demain, et cette dose vient en dernier. Sinon, les temps sont simplement comparés directement. (Plutôt gênant, le médicament est avant l'heure, donc je dois le retirer pour le comparer correctement.)

Neil
la source