¿Cuantas semanas?

13

Tu tarea es generar un solo número; El número de semanas ISO que un intervalo de fechas determinado se cruza. Para citar Wikipedia: An average year is exactly 52.1775 weeks longpero no se trata del promedio.

La entrada consta de dos fechas ISO separadas por espacios:

0047-12-24 2013-06-01

La fecha de finalización nunca es anterior a la fecha de inicio. Utilizaremos el calendario gregoriano extrapolado por simplicidad.

Casos de prueba:

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)

Su solución debe manejar fechas entre 0001-01-01y 9999-12-31.

Filip Haglund
fuente
2
¿Puede la entrada ser una matriz de cadenas en lugar de una sola cadena separada por espacios? Alternativamente, ¿pueden las dos fechas ser dos argumentos para una función?
Pomo de la puerta
Supongo que te refieres al calendario gregoriano proleptico .
Brad Gilbert b2gills
Además, ¿comienzan las semanas el domingo o el lunes? Según su segundo caso de prueba, es lunes, pero solo asegurándose.
Pomo de la puerta
@Doorknob quote Cita de Wikipedia: "La fecha se especifica mediante el año de numeración semanal ISO en el formato AAAA, un número de semana en el formato ww con el prefijo de la letra 'W' y el número del día de la semana, un dígito d del 1 al 7 , comenzando con el lunes y terminando con el domingo "Comenzando el lunes según ISO 8601
Tensibai
2
De acuerdo con la norma ISO,Weeks start with Monday.
Filip Haglund

Respuestas:

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}

Una solución muy primitiva: dada la primera fecha ay la segunda fecha b, el incremento a, cheque si es un lunes (si es así, que hemos "dio la vuelta" a una nueva semana), y para una vez que aes b.

Toma entrada en el formato exacto especificado en la pregunta: una sola cadena separada por espacios. (La forma en que analiza la entrada es elegante: utiliza el operador "splat" de Ruby *. Este operador "expande" una matriz o enumerable, por lo que se Time.gm *[2013, 06, 01]convierte Time.gm 2013, 06, 01).

Importado de una discusión de comentarios:

No nos importan las "semanas en un año"; solo nos interesan las "semanas en general". Entonces, si un año tiene 52 o 53 semanas no hace ninguna diferencia.

Solo para evitar futuras confusiones sobre si esto maneja los límites de año correctamente acuerdo con Wikipedia , todas las semanas siempre comienzan el lunes y terminan el domingo.

Para algunos trucos más elegantes, todos son 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
Perilla de la puerta
fuente
¿No se puede guardar 1 carácter sustitución a==bpor a<b?
Tensibai
1

VBA, 125 bytes

Esperando 2 entradas de función como cadenas

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

Estoy bastante seguro de que esto se puede jugar al golf. Esto se repite todos los días entre las 2 fechas e incrementa el contador cada vez que cambia la fecha ISO.

DatePart("ww",f+i,2,2) es el número de semana ISO en VBA los primeros 2 significa Monday (complies with ISO standard 8601, section 3.17) . entonces segundo 2 significaWeek that has at least four days in the new year (complies with ISO standard 8601, section 3.17)

140 bytes con 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
fuente
1

R, 76 bytes

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

Después de la conversación con @Doorknob, finalmente es tan fácil como contar los lunes.

seq permite crear un vector de fechas (de cada día entre dos fechas) y el tiempo de trabajo lo transforma en el 'número del día de la semana', ahora cuenta las veces que es 1 para obtener el número de veces que cambiaste la semana y agrega 1 a Tener en cuenta la semana anterior.

Otro enfoque de bucle:

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
fuente
1
Con respecto a su segundo enfoque, solo debe agregar 1 al número total de lunes si la primera fecha no cae en lunes.
DavidC
@DavidCarraher Gracias, leer su respuesta me hizo pensar que podría eliminar el primer día de rango, solucionando así el problema :)
Tensibai
0

Mathematica 135 79 96 84 74 bytes

De acuerdo con la sugerencia de @ Doorknob, esto

  • genera todas las fechas en el rango

  • cuenta el número de lunes ( ISOWeekDay== "1") en DateRange(excluyendo d), y

  • se suma 1al 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
fuente