Скільки тижнів?


13

Ваше завдання - вивести єдине число; кількість тижнів ISO, що перетинається заданий діапазон дат. Цитую Вікіпедію:, An average year is exactly 52.1775 weeks longале це не про середнє.

Вхід складається з двох ISO-дат, розділених пробілом:

0047-12-24 2013-06-01

Дата закінчення ніколи не перевищує дату початку. Ми будемо використовувати екстрапольований григоріанський календар для простоти.

Тестові приклади:

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)

Ваше рішення має обробляти дати між 0001-01-01та 9999-12-31.


2
Чи може вхід бути масивом рядків замість одного рядка, розділеного пробілом? Як варіант, чи можуть дві дати бути двома аргументами функції?
Дверна ручка


Також починаються тижні в неділю чи понеділок? Згідно з вашим другим тестовим випадком, це понеділок, але просто впевнений.
Дверна ручка

@Doorknob quote Цитата у Вікіпедії: "Дату визначає рік нумерації тижнів ISO у форматі РРРР, номер тижня у форматі w, префіксований буквою" W ", і число будня, цифра d від 1 до 7 , починаючи з понеділка і закінчуючи неділею "Отже, починаючи з понеділка згідно з ISO 8601
Tensibai

2
Відповідно до стандарту ISO,Weeks start with Monday.
Філіп Хаглунд

Відповіді:


2

Рубі, 89 88 86 байт

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

Дуже примітивно рішення: враховуючи першу дату aі другу дату b, приріст a, перевірка , якщо це понеділок (якщо це так, ми «перекинувся» на новий тиждень), і зупинитися , як тільки aце b.

Вводиться в точному форматі, визначеному у запитанні: одна рядок, розділена пробілом. (Те, як він аналізує вхід, є химерним: він використовує оператор "splat" Рубі *. Цей оператор "розширює" масив або безліч, так Time.gm *[2013, 06, 01]стає Time.gm 2013, 06, 01.)

Імпортовано з обговорення коментарів:

Нас не хвилює "тижнів у році"; нас хвилює лише "тижня в цілому". Отже, чи має рік 52 чи 53 тижні, це не має ніякого значення.

Просто щоб уникнути плутанини в майбутньому з приводу того, чи правильно обробляються межі року - згідно Вікіпедії , всі тижні завжди починаються з понеділка і закінчуються в неділю.

Для ще декількох химерних хитрощів усі ці еквівалентні:

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

Чи не можете ви можете зберегти 1 символ замінити a==bна a<b?
Тенсібай

1

VBA, 125 байт

Очікуючи 2 функціональні входи як рядки

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

Досить впевнений, що це може бути гольф. Це циклічно, хоча щодня між двома датами та збільшеннями лічильника щоразу, коли дата ISO змінюється.

DatePart("ww",f+i,2,2)- номер тижня ISO в VBA, перші 2 значить Monday (complies with ISO standard 8601, section 3.17). то другий 2 означаєWeek that has at least four days in the new year (complies with ISO standard 8601, section 3.17)

140 байт з одного входу

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 байт

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

Після розмови з @Doorknob, нарешті, це так просто, як рахувати понеділки.

seq дозволяють створити вектор дат (кожного дня між двома датами), а стропіл перетворюйте його на "число дня в тиждень", тепер відраховується кількість разів, щоб отримати кількість часу, який ви змінили тиждень, і додати 1 до врахувати попередній тиждень.

Інший підхід:

R, 85 байт

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

1
Щодо другого підходу, вам слід додати 1 до загальної кількості понеділок, якщо перша дата не припадає на понеділок.
DavidC

@DavidCarraher Спасибі, прочитавши вашу відповідь, змусив мене подумати, що я можу зняти перший день діапазону, тим самим виправити проблему :)
Tensibai

0

Mathematica 135 79 96 84 74 байт

Відповідно до пропозиції @ Doorknob, це

  • генерує всі дати в діапазоні

  • підраховує кількість понеділок ( ISOWeekDay== "1") у DateRange(за винятком d) та

  • додає 1до загального.


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}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.