Question

J'ai un tableau de dates dans une plage d'une semaine stocké de manière inhabituelle.

Les dates sont stockées dans ce format numérique: 12150

De gauche à droite:

Le premier chiffre représente le jour: 1 = dimanche, 2 = lundi, 3 = mardi, ...., 7 = samedi

Les deux prochains chiffres représentent l'heure dans un système de 24 heures: 00 = minuit, 23 = 23 h

Les deux prochains chiffres représentent les minutes: 00-59

Étant donné une date d'entrée et une date de début et une date de fin, je dois savoir si la date d'entrée est comprise entre la date de début et la date de fin.

J'ai actuellement un algorithme qui pense que fonctionne 100% du temps, mais je ne suis pas sûr.

Dans tous les cas, je pense qu’il existe probablement un moyen plus simple et meilleur de procéder ainsi. Je me demandais si quelqu'un savait ce que cet algorithme était.

Sinon, ce serait bien si quelqu'un pouvait vérifier mon travail et vérifier qu'il fonctionnait réellement pour 100% des cas valides.

Ce que j'ai maintenant, c'est:

if (startDate < inputDate && 
    endDate > inputDate) {
        inRange = yes;    
}
else if (endDate < startDate) {
        if((inputDate + 72359) > startDate &&
          (inputDate + 72359) < endDate) {
          inRange = yes; 
        }
        else if((inputDate + 72359) > startDate &&
               (inputDate + 72359) < (endDate + 72359)) {
          inRange = yes;   
        }

}
Était-ce utile?

La solution

Que diriez-vous de

const int MAX = 72460; // Or anything more than the highest legal value
inRange = (MAX + inputDate - startDate) % MAX < 
          (MAX + endDate - startDate) % MAX;

Cela suppose bien sûr que toutes les dates sont bien formées (selon vos spécifications).

Ceci adresse le cas où le début est & "après &"; la fin. (par exemple, vendredi est dans la plage si début est mercredi et fin est lundi)

Cela peut prendre une seconde à voir (ce qui n’est probablement pas bon, car la lisibilité est généralement le facteur le plus important), mais je pense que cela fonctionne.

Voici l'astuce de base:

Legend: 

  0: Minimum time
  M: Maximum time

  S: Start time
  1,2,3: Input Time test points
  E: End Time

The S  E => Not in range
  2  In range
  3 > E => Not in range

The S > E case
                        0                 M
  Original              -1--E----2---S--3--
  Add Max               -------------------1--E----2---S--3--
  Subtract StartDate    ------1--E----2---S--3--      
  % Max                 S--3--1--E----2----

  1  In range
  2 > E => Not in range
  3  In range

Si vous voulez vraiment devenir fou (et être encore plus difficile à déchiffrer)

const int MAX = 0x20000; 
const int MASK = 0x1FFFF;
int maxMinusStart = MAX - startDate;
inRange = (maxMinusStart + inputDate) & MASK < 
          (maxMinusStart + endDate) & MASK;

qui devrait être légèrement plus rapide (module d’échange sur un bit et) ce que nous pouvons faire car la valeur de MAX n’a pas vraiment d’importance (tant qu’elle dépasse la valeur maximale bien formée) et nous sommes libres de choisissez-en un qui facilite nos calculs.

(Et bien sûr, vous pouvez remplacer le < par un <= si c'est ce dont vous avez vraiment besoin)

Autres conseils

Il y a une erreur de logique avec les dates dans ce format. Les informations relatives au mois et à l'année étant manquantes, vous ne pouvez pas savoir quel jour de calendrier est manquant. par exemple. 50755 pourrait être le jeudi 12 mars 2009, mais il pourrait tout aussi bien se passer il y a exactement une semaine ou 18 semaines. Pour vous, cela ne pourrait jamais être sûr à 100% si une date dans ce format est comprise entre une autre 2 date.

Ici, la condition de l'intérieur if ne peut jamais être vraie, puisque endDate < startDate:

if (endDate < startDate) {
  if((inputDate + 72359) > startDate &&
    (inputDate + 72359) < endDate) {
    // never reached
    inRange = yes; 
  }

Ce qui suit ne peut pas non plus être optimal, car la première partie est toujours vraie et la deuxième partie est identique à inputDate < endDate:

  if((inputDate + 72359) > startDate &&
     (inputDate + 72359) < (endDate + 72359))

Je pense que vous voulez quelque chose comme ça:

if (startDate < endDate)
  inRange = (startDate < inputDate) && (inputDate < endDate);
else
  inRange = (startDate < inputDate) || (inputDate < endDate);

vous devriez utiliser > = et < = si vous le voulez vraiment dans la plage

dis que je choisis cette date 10000 ou 72359, comment vous géreriez cela? il est à portée ou pas?

De plus, je ne connaissais pas les valeurs pour startDate et endDate puisque vous ne l'avez pas initialisé, corrigez-moi si je me trompais, la variable qui n'a pas été initialisée commencera par 0, NULL ou ''

donc je suppose que le startDate = 10000 et endDate 72359

btw pourquoi vous choisissez ce type de tableau (en tant que valeur int ou chaîne?) pourquoi la première valeur était day? pas date exemple:
010000 - & Gt; date 1er du mois 00:00
312359 - & Gt; date du 31 du mois 23:59

mais c'est à vous de décider: D

désolé si je me suis trompé, j'ai suivi un cours d'algorithme uniquement à l'université et c'était il y a 5 ans: D

Une meilleure approche pourrait être de normaliser vos données en convertissant toutes les valeurs du jour de la semaine en fonction de la date de début. Quelque chose comme ça:

const int dayScale = 10000;  // scale factor for the day of the week

int NormalizeDate(int date, int startDay) 
{
    int day = (date / dayScale) - 1;  // this would be a lot easier if Sunday was 0 
    int sday = startDay - 1;  

    if (day < sday)  
        day = (day + 7 - sday) % 7;

    return ((day+1) * dayScale) + (date % dayScale);
}

int startDay = startDate / dayScale;  // isolate the day of the week

int normalizedStartDate = NormalizeDate(startDate, startDay);
int normalizedEndDate = NormalizeDate(endDate, startDay);
int normalizedInputDate = NormalizeDate(inputDate, startDay);

inRange = normalizedInputDate >= normalizedStartDate && 
          normalizedInputDate <= normalizedEndDate;

Je suis à peu près sûr que cela fonctionnera comme prévu. Dans tous les cas, le concept est plus propre que les comparaisons multiples.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top