Ile tygodni?


13

Twoim zadaniem jest wyprowadzenie jednego numeru; liczba tygodni ISO, które przecina dany zakres dat. Cytując Wikipedię: An average year is exactly 52.1775 weeks longale nie chodzi tu o średnią.

Dane wejściowe składają się z dwóch rozdzielonych spacjami dat ISO:

0047-12-24 2013-06-01

Data końcowa nigdy nie jest wcześniejsza niż data początkowa. Dla uproszczenia użyjemy ekstrapolowanego kalendarza gregoriańskiego.

Przypadki testowe:

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)

Twoje rozwiązanie powinno obsługiwać daty od 0001-01-01i 9999-12-31.


2
Czy dane wejściowe mogą być tablicą ciągów zamiast pojedynczego łańcucha rozdzielanego spacjami? Alternatywnie, czy dwie daty mogą być dwoma argumentami funkcji?
Klamka


Czy tygodnie zaczynają się także w niedzielę czy poniedziałek? Według drugiego przypadku testowego jest poniedziałek, ale tylko upewniam się.
Klamka

@Doorknob 冰 Cytat z Wikipedii: „Data jest określana przez rok numeracji ISO w formacie RRRR, numer tygodnia w formacie ww poprzedzonym literą„ W ”, a numer dnia tygodnia, cyfra d od 1 do 7 , zaczynając od poniedziałku, a kończąc na niedzieli "Więc zaczynając od poniedziałku zgodnie z ISO 8601
Tensibai

2
Zgodnie z normą ISO,Weeks start with Monday.
Filip Haglund,

Odpowiedzi:


2

Rubin, 89 88 86 bajtów

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

To bardzo prymitywne rozwiązanie: biorąc pod uwagę pierwszą datę ai drugą datę b, przyrost a, sprawdź, czy jest to poniedziałek (jeśli tak, to mamy „przeniesiona” do nowego tygodnia), a kończy się z chwilą ajest b.

Pobiera dane wejściowe w dokładnym formacie określonym w pytaniu: pojedynczy ciąg oddzielony spacjami. (Sposób, w jaki analizuje dane wejściowe, jest fantazyjny: używa operatora Ruby „splat” *. Ten operator „rozszerza” tablicę lub wylicza, więc Time.gm *[2013, 06, 01]staje się Time.gm 2013, 06, 01.)

Zaimportowane z dyskusji na komentarzu:

Nie obchodzą nas „tygodnie w roku”; zależy nam tylko na „tygodniach ogółem”. Zatem to, czy rok ma 52 czy 53 tygodnie, nie ma znaczenia.

Aby uniknąć przyszłego pomyłki z tym, czy poprawnie obsługuje to granice roku - według Wikipedii wszystkie tygodnie zaczynają się zawsze w poniedziałek, a kończą w niedzielę.

W przypadku niektórych bardziej fantazyjnych sztuczek wszystkie są równoważne:

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

Czy nie można zapisać 1 char zastąpienie a==bprzez a<b?
Tensibai,

1

VBA, 125 bajtów

Oczekiwane są 2 wejścia funkcji jako ciągi

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

Jestem pewien, że można grać w golfa. To zapętla się codziennie między 2 datami i zwiększa licznik za każdym razem, gdy zmienia się data ISO.

DatePart("ww",f+i,2,2)to numer tygodnia ISO w VBA, który oznacza 2 pierwsze Monday (complies with ISO standard 8601, section 3.17). wtedy drugie 2 oznaczaWeek that has at least four days in the new year (complies with ISO standard 8601, section 3.17)

140 bajtów z pojedynczym wejściem

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 bajtów

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

Po rozmowie z @Doorknob jest to w końcu tak proste, jak liczenie poniedziałków.

seq zezwól na utworzenie wektora dat (każdego dnia między dwiema datami) i strftime przekształć go w „numer dnia w tygodniu”, teraz zlicza czasy 1, aby uzyskać liczbę zmian tygodnia i dodaj 1 do weź pod uwagę poprzedni tydzień.

Kolejne podejście do zapętlania:

R, 85 bajtów

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

1
Jeśli chodzi o drugie podejście, należy dodać 1 do całkowitej liczby poniedziałków, jeśli pierwsza data nie przypada w poniedziałek.
DavidC,

@DavidCarraher Dzięki, przeczytanie twojej odpowiedzi sprawiło, że pomyślałem, że mogę usunąć pierwszy dzień zasięgu, rozwiązując w ten sposób problem :)
Tensibai

0

Mathematica 135 79 96 84 74 bajty

Jest to zgodne z sugestią @ Doorknob

  • generuje wszystkie daty w zakresie

  • zlicza liczbę poniedziałków ( ISOWeekDay== „1”) w DateRange(z wyłączeniem d), i

  • dodaje 1do całości.


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}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.