Quantas semanas?

13

Sua tarefa é produzir um único número; o número de semanas ISO em que um determinado período cruza. Para citar a Wikipedia:, An average year is exactly 52.1775 weeks longmas não se trata da média.

A entrada consiste em duas datas ISO separadas por espaço:

0047-12-24 2013-06-01

A data final nunca é anterior à data de início. Usaremos o calendário gregoriano extrapolado para simplificar.

Casos de teste:

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)

Sua solução deve lidar com datas entre 0001-01-01e 9999-12-31.

Filip Haglund
fonte
2
A entrada pode ser uma matriz de cadeias em vez de uma única cadeia separada por espaço? Como alternativa, as duas datas podem ser dois argumentos para uma função?
Maçaneta
Suponho que você queira dizer o Calendário Gregoriano Proléptico .
Brad Gilbert b2gills
Além disso, as semanas começam no domingo ou na segunda-feira? De acordo com o seu segundo caso de teste, é segunda-feira, mas apenas certifique-se.
Maçaneta
@Doorknob quote Citação da Wikipedia: "Uma data é especificada pelo ano de numeração ISO da semana no formato AAAA, um número da semana no formato ww prefixado pela letra 'W' e o número do dia da semana, um dígito d de 1 a 7 , começando na segunda-feira e terminando no domingo ". Começando na segunda-feira de acordo com a ISO 8601
Tensibai
2
De acordo com o padrão ISO,Weeks start with Monday.
Filip Haglund

Respostas:

2

Ruby, 89 88 86 bytes

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

Uma solução muito primitivo: dada a primeira data aea segunda data b, incremento a, cheque se é uma segunda-feira (em caso afirmativo, que já "virou" para uma nova semana), e parar uma vez que aé b.

Recebe a entrada no formato exato especificado na pergunta: uma única sequência separada por espaço. (A maneira como analisa a entrada é sofisticada: usa o operador "splat" de Ruby *. Este operador "expande" uma matriz ou um número enumerável, Time.gm *[2013, 06, 01]tornando - se assim Time.gm 2013, 06, 01.)

Importado de uma discussão de comentário:

Não nos preocupamos com "semanas em um ano"; só nos preocupamos com "semanas em geral". Portanto, se um ano tem 52 ou 53 semanas, não faz diferença.

Apenas para evitar futuras confusões sobre se isso lida corretamente com os limites do ano - acordo com a Wikipedia , todas as semanas sempre começam na segunda-feira e terminam no domingo.

Para alguns truques mais sofisticados, todos são equivalentes:

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
Maçaneta
fonte
Você não pode salvar 1 char substituindo a==bpor a<b?
Tensibai
1

VBA, 125 bytes

Esperando 2 entradas de função como strings

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

Certeza que isso pode ser jogado no golfe. Isso ocorre todos os dias entre as 2 datas e incrementa o contador toda vez que a data ISO é alterada.

DatePart("ww",f+i,2,2)é o número da semana ISO no VBA, os 2 primeiros meios Monday (complies with ISO standard 8601, section 3.17). então o segundo 2 significaWeek that has at least four days in the new year (complies with ISO standard 8601, section 3.17)

140 bytes com entrada única

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
JimmyJazzx
fonte
1

R, 76 bytes

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

Depois da conversa com o @Doorknob, é finalmente tão fácil quanto contar as segundas-feiras.

seq permitir criar um vetor de datas (de cada dia entre duas datas) e strftime transformá-lo no 'número do dia da semana', agora conta as vezes que é 1 para obter o número de vezes que você mudou a semana e adicionar 1 a leve em conta a semana anterior.

Outra abordagem em loop:

R, 85 bytes

n=1;d=as.Date(scan("","raw"));z=d[1];while(z<d[2]){n=n+(strftime(z<-z+1,"%w")==1)};n
Tensibai
fonte
1
Em relação à sua segunda abordagem, você deve adicionar apenas 1 ao número total de segundas-feiras se a primeira data não ocorrer na segunda-feira.
DavidC
Graças @DavidCarraher, lendo sua resposta me fez pensar que eu poderia remover o primeiro dia do intervalo, fixando assim o problema :)
Tensibai
0

Mathematica 135 79 96 84 74 bytes

Consistente com a sugestão de @ Doorknob, este

  • gera todas as datas no intervalo

  • conta o número de segundas-feiras ( ISOWeekDay== "1") no DateRange(excluindo d) e

  • adiciona 1ao 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}

DavidC
fonte