Combien de semaines?


13

Votre tâche consiste à sortir un seul numéro; le nombre de semaines ISO à l'intersection d'une plage de dates donnée. Pour citer Wikipedia:, An average year is exactly 52.1775 weeks longmais il ne s'agit pas de la moyenne.

L'entrée se compose de deux dates ISO séparées par des espaces:

0047-12-24 2013-06-01

La date de fin n'est jamais antérieure à la date de début. Nous utiliserons le calendrier grégorien extrapolé pour plus de simplicité.

Cas de test:

Format: input -> output
2015-12-31 2016-01-01 -> 1    (both are within week 53 of 2015)
2016-01-03 2016-01-04 -> 2    (the 3rd is within week 53, and the 4th is in week 1)
2015-12-24 2015-12-24 -> 1    (this single day is of course within a single week)

Votre solution doit gérer les dates entre 0001-01-01et 9999-12-31.


2
L'entrée peut-elle être un tableau de chaînes au lieu d'une seule chaîne séparée par des espaces? Alternativement, les deux dates peuvent-elles être deux arguments pour une fonction?
Poignée de porte

Je suppose que vous voulez dire le calendrier grégorien proleptique .
Brad Gilbert b2gills

De plus, les semaines commencent-elles le dimanche ou le lundi? Selon votre deuxième cas de test, c'est lundi, mais assurez-vous simplement.
Poignée de porte

@ Doorknob 冰 Citation Wikipedia: "Une date est spécifiée par l'année de numérotation hebdomadaire ISO au format AAAA, un numéro de semaine au format ww préfixé par la lettre" W "et le numéro de jour de semaine, un chiffre d de 1 à 7 , commençant par lundi et se terminant par dimanche "Donc, commençant le lundi selon ISO 8601
Tensibai

2
Selon la norme ISO,Weeks start with Monday.
Filip Haglund

Réponses:


2

Rubis, 89 88 86 octets

->s{a,b=s.split.map{|x|Time.gm *x.split(?-)}
n=1
(a+=86400).wday==1&&n+=1until a==b
n}

Une solution très primitive: étant donné la première date aet la deuxième date b, incrémentera , vérifier si elle est un lundi (si oui, nous avons « reconduits » à une nouvelle semaine), et arrêter une fois aest b.

Prend l'entrée au format exact spécifié dans la question: une seule chaîne séparée par des espaces. (La façon dont il analyse l'entrée est fantaisiste: il utilise l'opérateur "splat" de Ruby *. Cet opérateur "développe" un tableau ou un énumérable, doncTime.gm *[2013, 06, 01] devientTime.gm 2013, 06, 01 .)

Importé d'une discussion de commentaire:

Nous ne nous soucions pas des «semaines dans une année»; nous ne nous soucions que des «semaines globales». Donc, qu'une année compte 52 ou 53 semaines, cela ne fait aucune différence.

Juste pour éviter toute confusion future quant à savoir si cela gère correctement les limites de l'année ... selon Wikipedia , toutes les semaines commencent toujours le lundi et se terminent le dimanche.

Pour quelques astuces plus sophistiquées, elles sont toutes équivalentes:

until a==b;a+=86400;n+=a.wday==1?1:0;end
[a+=86400,n+=a.wday==1?1:0]until a==b
n+=(a+=86400).wday==1?1:0 until a==b
(a+=86400).wday==1&&n+=1 until a==b
(a+=86400).wday==1&&n+=1until a==b

Ne pouvez pas vous pouvez enregistrer 1 car le remplacement a==bpar a<b?
Tensibai

1

VBA, 125 octets

Attend 2 entrées de fonction comme chaînes

Function u(k,j)
f=DateValue(k)
For i=0 To (DateValue(j)-f)
q=DatePart("ww",f+i,2,2)
If q<>j Then u=u+1
j=q
Next
End Function

Je suis sûr que cela peut être joué au golf. Ceci est en boucle tous les jours entre les 2 dates et incrémente le compteur chaque fois que la date ISO change.

DatePart("ww",f+i,2,2)est le numéro de semaine ISO en VBA, les 2 premières moyennes Monday (complies with ISO standard 8601, section 3.17). puis deuxième 2 signifieWeek that has at least four days in the new year (complies with ISO standard 8601, section 3.17)

140 octets avec entrée unique

Function g(k)
y=Split(k)
f=DateValue(y(0))
For i=0 To (DateValue(y(1))-f)
q=DatePart("ww",f+i,2,2)
If q<>j Then g=g+1
j=q
Next
End Function

1

R, 76 octets

d=as.Date(scan("","raw"));sum(strftime(seq(d[1],d[2],"day")[-1],"%w")==1)+1

Après l'entretien avec @Doorknob, c'est finalement aussi simple que de compter les lundis.

seq permet de créer un vecteur de dates (de chaque jour entre deux dates) et strftime le transforme en `` numéro du jour de la semaine '', compte maintenant le nombre de fois où il est 1 pour obtenir le nombre de fois où vous avez changé de semaine et ajoutez 1 à prendre en compte la semaine précédente.

Une autre approche en boucle:

R, 85 octets

n=1;d=as.Date(scan("","raw"));z=d[1];while(z<d[2]){n=n+(strftime(z<-z+1,"%w")==1)};n

1
Concernant votre deuxième approche, vous ne devez ajouter 1 au nombre total de lundis que si la première date ne tombe pas un lundi.
DavidC

@DavidCarraher Merci, la lecture de votre réponse m'a fait penser que je pouvais supprimer le premier jour de plage, corrigeant ainsi le problème :)
Tensibai

0

Mathematica 135 79 96 84 74 octets

Conformément à la suggestion de @ Doorknob, cette

  • génère toutes les dates de la plage

  • compte le nombre de lundis ( ISOWeekDay== "1") dans DateRange(à l'exclusion d), et

  • ajoute 1au total.


Count[DateString[#,"ISOWeekDay"]&/@Rest@(DateRange@@StringSplit@#),"1"]+1&

Count[DateString[#,"ISOWeekDay"]&/@Rest@(DateRange@@StringSplit@#),"1"]+1&
/@ {"2015-12-31 2016-01-01", "2016-01-04 2016-01-05","2016-01-03 2016-01-04", 
"2015-12-24 2015-12-24", "1876-12-24 2016-01-01"}

{1, 1, 2, 1, 7255}

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.