Long year

You are encouraged to solve this task according to the task description, using any language you may know.
Most years have 52 weeks, some have 53, according to ISO8601.
- Task
Write a function which determines if a given year is long (53 weeks) or not, and demonstrate it.
11l
F is_long_year(year)
F p(year)
R (year + (year I/ 4) - (year I/ 100) + (year I/ 400)) % 7
R p(year) == 4 | p(year - 1) == 3
L(year) 2000..2100
I is_long_year(year)
print(year, end' ‘ ’)
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Action!
BYTE FUNC P(CARD y)
RETURN ((y+(y/4)-(y/100)+(y/400)) MOD 7)
BYTE FUNC IsLongYear(CARD y)
IF P(y)=4 OR P(y-1)=3 THEN
RETURN (1)
FI
RETURN (0)
PROC Main()
CARD y
BYTE LMARGIN=$52,oldLMARGIN
oldLMARGIN=LMARGIN
LMARGIN=0 ;remove left margin on the screen
Put(125) PutE() ;clear the screen
FOR y=1900 TO 2400
DO
IF IsLongYear(y) THEN
PrintC(y) Put(32)
FI
OD
LMARGIN=oldLMARGIN ;restore left margin on the screen
RETURN
- Output:
Screenshot from Atari 8-bit computer
1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195 2201 2207 2212 2218 2224 2229 2235 2240 2246 2252 2257 2263 2268 2274 2280 2285 2291 2296 2303 2308 2314 2320 2325 2331 2336 2342 2348 2353 2359 2364 2370 2376 2381 2387 2392 2398
Ada
The Ada calendar package handles dates for years 1901 through 2399. This program outputs all the long years within that range.
-------------------------------------------------------------
-- Calculate long years
-- Reference: https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
-------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;
with Ada.Calendar.Formatting; use Ada.Calendar.Formatting;
procedure Main is
First_Day : Time;
Last_Day : Time;
package AC renames Ada.Calendar;
type Counter is mod 10;
Count : Counter := 0;
begin
for Yr in Year_Number loop
First_Day := AC.Time_Of (Year => Yr, Month => 1, Day => 1);
Last_Day := AC.Time_Of (Year => Yr, Month => 12, Day => 31);
-- If Jan 1 is Thursday or Dec 31 is Thursday then
-- the year is a long year
if Day_Of_Week (First_Day) = Thursday
or else Day_Of_Week (Last_Day) = Thursday
then
if Count = 0 then
New_Line;
end if;
Put (Yr'Image);
Count := Count + 1;
end if;
end loop;
end Main;
- Output:
1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195 2201 2207 2212 2218 2224 2229 2235 2240 2246 2252 2257 2263 2268 2274 2280 2285 2291 2296 2303 2308 2314 2320 2325 2331 2336 2342 2348 2353 2359 2364 2370 2376 2381 2387 2392 2398
ALGOL 68
BEGIN # find "long years" - years which have 53 weeks this is equivalent to #
# finding years where 1st Jan or 31st Dec are Thursdays #
# returns the day of the week of the specified date (d/m/y), Sunday = 1 #
PROC day of week = ( INT d, m, y )INT:
BEGIN
INT mm := m;
INT yy := y;
IF mm <= 2 THEN
mm := mm + 12;
yy := yy - 1
FI;
INT j = yy OVER 100;
INT k = yy MOD 100;
(d + ( ( mm + 1 ) * 26 ) OVER 10 + k + k OVER 4 + j OVER 4 + 5 * j ) MOD 7
END # day of week # ;
# returns TRUE if year is a long year, FALSE otherwise #
PROC is long year = ( INT year )BOOL:
day of week( 1, 1, year ) = 5 OR day of week( 31, 12, year ) = 5;
# show long years from 2000-2099 #
print( ( "long years 2000-2099:" ) );
FOR year FROM 2000 TO 2099 DO
IF is long year( year ) THEN print( ( " ", whole( year, 0 ) ) ) FI
OD
END
- Output:
long years 2000-2099: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
ALGOL-M
BEGIN
COMMENT
FIND ISO CALENDAR YEARS HAVING 53 WEEKS. THE SIMPLEST
TEST IS THAT A GIVEN YEAR WILL BE "LONG" IF EITHER THE
FIRST OR LAST DAY IS A THURSDAY;
% CALCULATE P MOD Q %
INTEGER FUNCTION MOD(P, Q);
INTEGER P, Q;
BEGIN
MOD := P - Q * (P / Q);
END;
COMMENT
RETURN DAY OF WEEK (SUN=0, MON=1, ETC.) FOR A GIVEN
GREGORIAN CALENDAR DATE USING ZELLER'S CONGRUENCE;
INTEGER FUNCTION DAYOFWEEK(MO, DA, YR);
INTEGER MO, DA, YR;
BEGIN
INTEGER Y, C, Z;
IF MO < 3 THEN
BEGIN
MO := MO + 10;
YR := YR - 1;
END
ELSE MO := MO - 2;
Y := MOD(YR, 100);
C := YR / 100;
Z := (26 * MO - 2) / 10;
Z := Z + DA + Y + (Y / 4) + (C /4) - 2 * C + 777;
DAYOFWEEK := MOD(Z, 7);
END;
% RETURN 1 IF YEAR IS LONG, OTHERWISE 0 %
INTEGER FUNCTION ISLONGYEAR(YR);
INTEGER YR;
BEGIN
INTEGER THURSDAY;
THURSDAY := 4;
IF (DAYOFWEEK(1,1,YR) = THURSDAY) OR
(DAYOFWEEK(12,31,YR) = THURSDAY) THEN
ISLONGYEAR := 1
ELSE
ISLONGYEAR := 0;
END;
% MAIN PROGRAM STARTS HERE %
INTEGER YEAR;
WRITE("ISO YEARS THAT WILL BE LONG IN THIS CENTURY:");
WRITE("");
FOR YEAR := 2000 STEP 1 UNTIL 2099 DO
BEGIN
IF ISLONGYEAR(YEAR) = 1 THEN WRITEON(YEAR);
END;
END
- Output:
ISO YEARS THAT WILL BE LONG IN THIS CENTURY: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
ALGOL W
Uses the Day_of_week procedure from the Day_of_the_week task.
begin % find "long years" - years which have 53 weeks %
% this is equivalent to finding years where %
% 1st Jan or 31st Dec are Thursdays %
% finds the day of the week - Sunday = 1 %
integer procedure Day_of_week ( integer value d, m, y );
begin
integer j, k, mm, yy;
mm := m;
yy := y;
if mm <= 2 then begin
mm := mm + 12;
yy := yy - 1;
end if_m_le_2;
j := yy div 100;
k := yy rem 100;
(d + ( ( mm + 1 ) * 26 ) div 10 + k + k div 4 + j div 4 + 5 * j ) rem 7
end Day_of_week;
% returns true if year is a long year, false otherwise %
logical procedure isLongYear ( integer value year );
Day_of_week( 1, 1, year ) = 5 or Day_of_week( 31, 12, year ) = 5;
% show long years from 2000-2099 %
write( "long years 2000-2099:" );
for year := 2000 until 2099 do begin
if isLongYear( year ) then writeon( I_W := 5, S_W := 0, year )
end for_year
end.
- Output:
long years 2000-2099: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Amazing Hopper
Task solves with Amazing Hopper flavour Basico:
#include <basico.h>
#proto esañolargo(_X_)
algoritmo
año=1800, c=5
imprimir ("Long (53 week) years between 1800 and 2100:\n\n" )
iterar grupo ( ++año, #( año<=2100 ), \
cuando ( #( es año largo( año )==4 || es año largo( año-1 )==3 ) ){ \
imprimir ( año, " ", solo si( #( c==0 ) , NL; c=6 ), --c ) } )
terminar
subrutinas
es año largo (y)
retornar ' #( (y + floor(y / 4) - floor(y / 100) + floor(y / 400)) % 7 ) '
- Output:
Long (53 week) years between 1800 and 2100: 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
APL
dec31weekday ← {7|⍵+⌊(⍵÷4)+⌊(⍵÷400)-⌊⍵÷100}
isolongyear ← {(4 = dec31weekday ⍵) ∨ 3 = dec31weekday ⍵ - 1}
- Output:
{⍵/⍨isolongyear ⍵}1800+⍳300 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
AppleScript
on isLongYear(y)
-- ISO8601 weeks begin on Mondays and belong to the year in which they have the most days.
-- A year which begins on a Thursday, or which begins on a Wednesday and is a leap year,
-- has majority stakes in the weeks it overlaps at *both* ends and so has 53 weeks instead of 52.
-- Leap years divisible by 400 begin on Saturdays and so don't so need to be considered in the leap year check.
tell (current date) to set {Jan1, its day, its month, its year} to {it, 1, January, y}
set startWeekday to Jan1's weekday
return ((startWeekday is Thursday) or ((startWeekday is Wednesday) and (y mod 4 is 0) and (y mod 100 > 0)))
end isLongYear
set longYears to {}
repeat with y from 2001 to 2100
if (isLongYear(y)) then set end of longYears to y
end repeat
return longYears
- Output:
{2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099}
On the other hand, since the cycle repeats every 400 years, it's possible to cheat with a precalculated look-up list:
on isLongYear(y)
return (y mod 400 is in {4, 9, 15, 20, 26, 32, 37, 43, 48, 54, 60, 65, 71, 76, 82, 88, 93, 99, 105, 111, 116, 122, 128, 133, 139, 144, 150, 156, 161, 167, 172, 178, 184, 189, 195, 201, 207, 212, 218, 224, 229, 235, 240, 246, 252, 257, 263, 268, 274, 280, 285, 291, 296, 303, 308, 314, 320, 325, 331, 336, 342, 348, 353, 359, 364, 370, 376, 381, 387, 392, 398})
end isLongYear
set longYears to {}
repeat with y from 2001 to 2100
if (isLongYear(y)) then set end of longYears to y
end repeat
return longYears
Arturo
longYear?: function [year][
date: to :date .format: "dd/MM/yyyy" ~"01/01/|year|"
or? date\Day = "Thursday"
and? leap? year
date\Day = "Wednesday"
]
print "Years with 53 weeks between 2000 and 2100:"
print select 2000..2100 => longYear?
- Output:
Years with 53 weeks between 2000 and 2100: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
AutoHotkey
Long_year(y) {
A := Mod(y + floor(y/4) - floor(y/100) + floor(y/400), 7)
y--, B := Mod(y + floor(y/4) - floor(y/100) + floor(y/400), 7)
return A=4 || B=3
}
Examples:
loop, 100{
y := 1999+A_Index
res .= Long_year(y) ? Y " ": ""
}
MsgBox % "Long Years 2000-2100 : " res
return
- Output:
Long Years 2000-2100 : 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
AWK
# syntax: GAWK -f LONG_YEAR.AWK
BEGIN {
for (cc=19; cc<=21; cc++) {
printf("%2d00-%2d99: ",cc,cc)
for (yy=0; yy<=99; yy++) {
ccyy = sprintf("%02d%02d",cc,yy)
if (is_long_year(ccyy)) {
printf("%4d ",ccyy)
}
}
printf("\n")
}
#
printf("\n%4d-%4d: ",by=1970,ey=2037)
for (y=by; y<=ey; y++) {
if (strftime("%V",mktime(sprintf("%d 12 28 0 0 0",y))) == 53) {
printf("%4d ",y)
}
}
printf("\n")
exit(0)
}
function is_long_year(year, i) {
for (i=0; i<=1; i++) {
year -= i
if ((year + int(year/4) - int(year/100) + int(year/400)) % 7 == 4-i) {
return(1)
}
}
return(0)
}
- Output:
1900-1999: 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2000-2099: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 2100-2199: 2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195 1970-2037: 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037
BASIC
Applesoft BASIC
10 DEF FN M7(N) = N - 7 * INT (N / 7)
20 DEF FN WD(Y) = FN M7(Y + INT (Y / 4) - INT (Y / 100) + INT (Y / 400))
30 DEF FN LY(Y) = (4 = FN WD(Y)) OR (3 = FN WD(Y - 1))
40 HOME : INVERSE : PRINT "**** LIST OF ISO LONG YEARS ****": NORMAL
50 INPUT "START YEAR? ";S
60 INPUT "END YEAR? ";E
70 PRINT : FOR Y = S TO E
80 IF FN LY(Y) THEN PRINT S$Y;:S$ = " "
90 NEXT Y
ASIC
REM Long year
CLS
PRINT "**** List of ISO long years ****"
PRINT "Start year";
INPUT S
PRINT "End year";
INPUT E
PRINT
FOR Y = S TO E
GOSUB CALCLY:
IF LY <> 0 THEN
PRINT Y;
ENDIF
NEXT Y
PRINT
END
CALCLY:
REM Nonzero if Y is long
LY = 0
AY = Y
GOSUB CALCWD:
IF WD = 4 THEN
LY = -1
ENDIF
AY = Y - 1
GOSUB CALCWD:
IF WD = 3 THEN
LY = -1
ENDIF
RETURN
CALCWD:
REM Weekday of AY-12-31, 0 = Sunday
WD = AY
TMP = AY / 4
WD = WD + TMP
TMP = AY / 100
WD = WD - TMP
TMP = AY / 400
WD = WD + TMP
WD = WD MOD 7
RETURN
- Output:
**** List of ISO long years **** Start year?1995 End year?2045 1998 2004 2009 2015 2020 2026 2032 2037 2043
BASIC256
function p(y)
return (y + int(y/4) - int(y/100) + int(y/400)) mod 7
end function
function isLongYear(y)
return (p(y) = 4) or (p(y - 1) = 3)
end function
for y = 2000 to 2100
if isLongYear(y) then print y
next y
end
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
BBC BASIC
INSTALL @lib$ + "DATELIB"
REM The function as per specification.
DEF FNLongYear(year%)=FN_dow(FN_mjd(1, 1, year%)) == 4 OR FN_dow(FN_mjd(31, 12, year%)) == 4
REM Demonstrating its use.
PROCPrintLongYearsInCentury(20)
PROCPrintLongYearsInCentury(21)
PROCPrintLongYearsInCentury(22)
END
DEF PROCPrintLongYearsInCentury(century%)
LOCAL year%, start%
start%=century% * 100 - 100
PRINT "The long years between ";start% " and ";start% + 100 " are ";
FOR year%=start% TO start% + 99
IF FNLongYear(year%) PRINT STR$year% + " ";
NEXT
PRINT
ENDPROC
- Output:
The long years between 1900 and 2000 are 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 The long years between 2000 and 2100 are 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 The long years between 2100 and 2200 are 2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195
Chipmunk Basic
10 cls
20 rem WD(Y) = WEEKDAY OF Y-12-31, 0 = SUNDAY
30 def fnwd(Y) = (Y + INT(Y / 4) - INT(Y / 100) + INT(Y / 400)) mod 7
40 rem LY(Y) = NONZERO IF Y IS LONG
50 def fnly(Y) = (4 = FNWD(Y)) OR (3 = FNWD(Y-1))
60 print "**** LIST OF ISO LONG YEARS ****"
70 input "START YEAR? ",s
80 input "END YEAR? ",e
90 print
100 for y = s to e
110 if fn ly(y) then print y,
120 next y
130 print
140 end
- Output:
Similar as Commodore BASIC entry.
Commodore BASIC
100 REM M7(N) = N MOD 7
110 DEF FNM7(N) = N - 7*INT(N / 7)
120 :
130 REM WD(Y) = WEEKDAY OF Y-12-31, 0 = SUNDAY
140 DEF FNWD(Y) = FNM7(Y + INT(Y / 4) - INT(Y / 100) + INT(Y / 400))
150 :
160 REM LY(Y) = NONZERO IF Y IS LONG
170 DEF FNLY(Y) = (4 = FNWD(Y)) OR (3 = FNWD(Y-1))
180 :
190 PRINT CHR$(147); CHR$(18); "**** LIST OF ISO LONG YEARS ****"
200 INPUT "START YEAR"; S
210 INPUT "END YEAR"; E
220 PRINT
230 :
240 FOR Y = S TO E
250 : IF FNLY(Y) THEN PRINT Y,
260 NEXT Y
270 PRINT
- Output:
**** LIST OF ISO LONG YEARS **** START YEAR? 1995 END YEAR? 2045 1998 2004 2009 2015 2020 2026 2032 2037 2043 READY.
FreeBASIC
function p(y as unsigned integer) as unsigned integer
return ( y + int(y/4) - int(y/100) + int(y/400) ) mod 7
end function
function islongyear( y as uinteger ) as boolean
if p(y) = 4 then return true
if p(y-1) = 3 then return true
return false
end function
print islongyear(1998)
print islongyear(2020)
print islongyear(2021)
- Output:
true true false
Gambas
Public Sub Main()
For y As Integer = 2000 To 2100
If isLongYear(y) Then Print y,
Next
End
Function p(y As Integer) As Integer
Return (y + (y \ 4) - (y \ 100) + (y \ 400)) Mod 7
End Function
Function isLongYear(y As Integer) As Boolean
If p(y) = 4 Then Return True
If p(y - 1) = 3 Then Return True
Return False
End Function
- Output:
Same as BASIC256 entry.
GW-BASIC
10 INPUT "Enter a year: ", Y
20 X = Y
30 GOSUB 100
40 IF P = 4 THEN L = 1
50 X = Y - 1
60 GOSUB 100
70 IF P = 3 THEN L = 1
80 IF L = 1 THEN PRINT Y; " is a long year." ELSE PRINT Y;" is not a long year."
90 END
100 P = X + INT(X/4) - INT(X/100) + INT(X/400)
110 P = P MOD 7
120 RETURN
IS-BASIC
100 PROGRAM "Longyear.bas"
110 DEF RD(Y)=Y*365+INT(Y/4)-INT(Y/100)+INT(Y/400)
120 DEF LONGYEAR(Y)=(4=MOD(RD(Y),7)) OR(4=MOD((RD(Y-1)+1),7))
130 INPUT PROMPT "Start year: ":S
140 INPUT PROMPT "End year: ":E
150 FOR Y=S TO E
160 IF LONGYEAR(Y) THEN PRINT Y,
170 NEXT
180 PRINT
MSX Basic
10 CLS
20 REM WD(Y) = WEEKDAY OF Y-12-31, 0 = SUNDAY
30 DEF FNWD(Y) = (Y + INT(Y/4) - INT(Y/100) + INT(Y/400)) MOD 7
40 REM LY(Y) = NONZERO IF Y IS LONG
50 DEF FNLY(Y) = (4 = FNWD(Y)) OR (3 = FNWD(Y-1))
60 PRINT "*** LIST OF ISO LONG YEARS ***"
70 INPUT "START YEAR ";S
80 INPUT " END YEAR ";E
90 PRINT
100 FOR Y = S TO E
110 IF FNLY(Y) THEN PRINT Y,
120 NEXT Y
130 PRINT
140 END
- Output:
Similar as Commodore BASIC entry.
Nascom BASIC
10 REM Long year
20 REM FNM7(N)=MOD(N,7)
30 DEF FNM7(N)=N-7*INT(N/7)
40 REM FNWD(Y)=Weekday of Y-12-31, 0 Sunday
50 DEF FND(Y)=Y+INT(Y/4)-INT(Y/100)+INT(Y/400)
60 DEF FNWD(Y)=FNM7(FND(Y))
70 REM FNLY(Y)=Nonzero if Y is long
80 DEF FNLY(Y)=(4=FNWD(Y))OR(3=FNWD(Y-1))
90 CLS
100 PRINT "**** ";
110 PRINT "List of ISO long years";
120 PRINT " ****"
130 INPUT "Start year";S
140 INPUT "End year";E
150 PRINT
160 FOR Y=S TO E
170 IF FNLY(Y) THEN PRINT Y;
180 NEXT Y
190 PRINT
200 END
- Output:
**** List of ISO long years **** Start year? 1995 End year? 2045 1998 2004 2009 2015 2020 2026 2032 2037 2043
Palo Alto Tiny BASIC
10 REM LONG YEAR
20 PRINT "*** LIST OF ISO LONG YEARS ***"
30 INPUT "START YEAR"B
40 INPUT "END YEAR"E
50 FOR Y=B TO E
60 GOSUB 200
70 IF L#0 PRINT Y," ",
80 NEXT Y
90 PRINT
100 STOP
190 REM L NONZERO IF Y IS LONG
200 LET L=0,J=Y
210 GOSUB 400
220 IF W=4 LET L=1
230 LET J=Y-1
240 GOSUB 400
250 IF W=3 LET L=1
260 RETURN
370 REM CALCULATE DAY OF WEEK W GIVEN
380 REM OF J-12-31, GIVEN YEAR J
390 REM SUNDAY = 0, SATURDAY = 6
400 LET W=J+J/4-J/100+J/400
410 LET W=W-(W/7)*7
420 RETURN
- Output:
*** LIST OF ISO LONG YEARS *** START YEAR:1995 END YEAR:2045 1998 2004 2009 2015 2020 2026 2032 2037 2043
PureBasic
Procedure.b p(y)
ProcedureReturn (y + Int(y/4) - Int(y/100) + Int(y/400)) % 7
EndProcedure
Procedure.b isLongYear(y)
ProcedureReturn Bool((p(y) = 4) Or (p(y - 1) = 3))
EndProcedure
If OpenConsole()
For y = 2000 To 2100
If isLongYear(y)
PrintN(Str(y))
EndIf
Next y
Print(""): Input()
CloseConsole()
EndIf
- Output:
Same as BASIC256 entry.
QuickBASIC
Translated from Delphi
DEFINT A-Z
DECLARE FUNCTION p% (Yr AS INTEGER)
DECLARE FUNCTION LongYear% (Yr AS INTEGER)
DIM iYi, iYf, i
CLS
PRINT "This program calculates which are 53-week years in a range."
PRINT
INPUT "Initial year"; iYi
INPUT "Final year (could be the same)"; iYf
IF iYf >= iYi THEN
FOR i = iYi TO iYf
IF LongYear(i) THEN
PRINT i; " ";
END IF
NEXT i
END IF
PRINT
PRINT
PRINT "End of program."
END
FUNCTION LongYear% (Yr AS INTEGER)
LongYear% = (p%(Yr) = 4) OR (p%(Yr - 1) = 3)
END FUNCTION
FUNCTION p% (Yr AS INTEGER)
p% = (Yr + INT(Yr / 4) - INT(Yr / 100) + INT(Yr / 400)) MOD 7
END FUNCTION
- Output:
This program calculates which are 53-week years in a range. Initial year? 1900 Final year (can be the same)? 1999 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 End of program.
Run BASIC
function p(y)
p = (y + int(y/4) - int(y/100) + int(y/400)) mod 7
end function
function isLongYear(y)
isLongYear = (p(y) = 4) or (p(y -1) = 3)
end function
for y = 2000 to 2100
if isLongYear(y) then print y
next y
end
- Output:
Same as BASIC256 entry.
S-BASIC
$lines
rem - compute p mod q
function mod(p, q = integer) = integer
end = p - q * (p/q)
comment
return day of week (Sun = 0, Mon = 1, etc.) for a
given Gregorian calendar date using Zeller's congruence
end
function dayofweek (mo, da, yr = integer) = integer
var y, c, z = integer
if mo < 3 then
begin
mo = mo + 10
yr = yr - 1
end
else mo = mo - 2
y = mod(yr,100)
c = int(yr / 100)
z = int((26 * mo - 2) / 10)
z = z + da + y + int(y/4) + int(c/4) - 2 * c + 777
z = mod(z,7)
end = z
comment
The simplest of several possible tests is that
any ISO year starting or ending on a
Thursday is "long", i.e., spans 53 weeks
end
function islongyear(yr = integer) = integer
var thursday, result = integer
thursday = 4
if (dayofweek(1,1,yr) = thursday) or \
(dayofweek(12,31,yr) = thursday) then
result = -1 rem "true"
else
result = 0 rem "false"
end = result
rem - main program begins here
var year = integer
print "ISO years that will be long in this century:"
for year = 2000 to 2099
if islongyear(year) then print year;
next year
end
- Output:
ISO years that will be long in this century: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Tiny BASIC
PRINT "What year would you like?"
INPUT Y
LET X = Y
GOSUB 100
IF P = 4 THEN LET L = 1
LET X = Y - 1
GOSUB 100
IF P = 3 THEN LET L = 1
IF L = 1 THEN PRINT Y," is a long year."
IF L = 0 THEN PRINT Y," is not a long year."
END
100 LET P = X + X/4 - X/100 + X/400
110 IF P < 7 THEN RETURN
LET P = P - 7
GOTO 110
- Output:
What year would you like? 2020 2020 is a long year. What year would you like? 2021 2021 is not a long year.
True BASIC
FUNCTION p(y) = REMAINDER((y + INT(y/4) - INT(y/100) + INT(y/400)), 7)
FUNCTION isLongYear(y)
IF p(y) = 4 THEN
LET isLongYear = 1
ELSEIF p(y-1) = 3 THEN
LET isLongYear = 1
ELSE
LET isLongYear = 0
END IF
END FUNCTION
FOR y = 2000 TO 2100
IF isLongYear(y) > 0 THEN PRINT y
NEXT y
END
- Output:
Same as BASIC256 entry.
Visual Basic
Option Explicit
Function IsLongYear(ByVal Year As Integer) As Boolean
Select Case vbThursday
Case VBA.DatePart("w", VBA.DateSerial(Year, 1, 1)), _
VBA.DatePart("w", VBA.DateSerial(Year, 12, 31))
IsLongYear = True
End Select
End Function
Sub Main()
'test
Dim l As Long
For l = 1990 To 2021
Select Case l
Case 1992, 1998, 2004, 2009, 2015, 2020
Debug.Assert IsLongYear(l)
Case Else
Debug.Assert Not IsLongYear(l)
End Select
Next l
End Sub
Visual Basic for DOS
OPTION EXPLICIT
DECLARE FUNCTION p (Yr AS INTEGER) AS INTEGER
DECLARE FUNCTION LongYear (Yr AS INTEGER) AS INTEGER
DIM iYi AS INTEGER, iYf AS INTEGER, i AS INTEGER
CLS
PRINT "This program calculates which are 53-week years in a range."
PRINT
INPUT "Initial year"; iYi
INPUT "Final year (could be the same)"; iYf
IF iYf >= iYi THEN
FOR i = iYi TO iYf
IF LongYear(i) THEN
PRINT i; " ";
END IF
NEXT i
END IF
PRINT
PRINT
PRINT "End of program."
END
FUNCTION p (Yr AS INTEGER) AS INTEGER
p = (Yr + INT(Yr / 4) - INT(Yr / 100) + INT(Yr / 400)) MOD 7
END FUNCTION
FUNCTION LongYear (Yr AS INTEGER) AS INTEGER
LongYear = (p(Yr) = 4) OR (p(Yr - 1) = 3)
END FUNCTION
XBasic
PROGRAM "LongYear"
VERSION "0.0000"
DECLARE FUNCTION Entry ()
DECLARE FUNCTION p (y)
DECLARE FUNCTION isLongYear (y)
FUNCTION Entry ()
FOR y = 2000 TO 2100
IF isLongYear(y) THEN PRINT y,
NEXT y
END FUNCTION
FUNCTION p (y)
RETURN (y + INT(y/4) - INT(y/100) + INT(y/400)) MOD 7
END FUNCTION
FUNCTION isLongYear (y)
RETURN (p(y) = 4) OR (p(y - 1) = 3)
END FUNCTION
END PROGRAM
- Output:
Same as BASIC256 entry.
Yabasic
sub p(y)
return mod((y + int(y/4) - int(y/100) + int(y/400)), 7)
end sub
sub isLongYear(y)
return (p(y) = 4) or (p(y - 1) = 3)
end sub
for y = 2000 to 2100
if isLongYear(y) print y
next y
end
- Output:
Same as BASIC256 entry.
BCPL
get "libhdr"
let p(y) = (y + y/4 - y/100 + y/400) rem 7
let longyear(y) = p(y)=4 | p(y-1)=3
let start() be
for y = 2000 to 2100
if longyear(y) do writef("%N*N", y)
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
C#
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
public static class Program
{
public static void Main()
{
WriteLine("Long years in the 21st century:");
WriteLine(string.Join(" ", 2000.To(2100).Where(y => ISOWeek.GetWeeksInYear(y) == 53)));
}
public static IEnumerable<int> To(this int start, int end) {
for (int i = start; i < end; i++) yield return i;
}
}
- Output:
Long years in the 21st century: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
C
#include <stdio.h>
#include <math.h>
// https://webspace.science.uu.nl/~gent0113/calendar/isocalendar.htm
int p(int year) {
return (int)((double)year + floor(year/4) - floor(year/100) + floor(year/400)) % 7;
}
int is_long_year(int year) {
return p(year) == 4 || p(year - 1) == 3;
}
void print_long_years(int from, int to) {
for (int year = from; year <= to; ++year) {
if (is_long_year(year)) {
printf("%d ", year);
}
}
}
int main() {
printf("Long (53 week) years between 1800 and 2100\n\n");
print_long_years(1800, 2100);
printf("\n");
return 0;
}
- Output:
Long (53 week) years between 1800 and 2100 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
C++
// Reference:
// https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
#include <iostream>
inline int p(int year) {
return (year + (year/4) - (year/100) + (year/400)) % 7;
}
bool is_long_year(int year) {
return p(year) == 4 || p(year - 1) == 3;
}
void print_long_years(int from, int to) {
for (int year = from, count = 0; year <= to; ++year) {
if (is_long_year(year)) {
if (count > 0)
std::cout << ((count % 10 == 0) ? '\n' : ' ');
std::cout << year;
++count;
}
}
}
int main() {
std::cout << "Long years between 1800 and 2100:\n";
print_long_years(1800, 2100);
std::cout << '\n';
return 0;
}
- Output:
Long years between 1800 and 2100: 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Clojure
(defn long-year? [year]
(-> (java.time.LocalDate/of year 12 28)
(.get (.weekOfYear (java.time.temporal.WeekFields/ISO)))
(= 53)))
(filter long-year? (range 2000 2100))
- Output:
(2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099)
CLU
% We can't hide one procedure inside another, but
% we can hide the helper `p' in a cluster
longyear = cluster is test
rep = null
p = proc (n: int) returns (int)
return ((n + n/4 - n/100 + n/400) // 7)
end p
test = proc (y: int) returns (bool)
return (p(y)=4 | p(y-1)=3)
end test
end longyear
start_up = proc ()
po: stream := stream$primary_output()
for i: int in int$from_to(2000, 2100) do
if longyear$test(i) then
stream$putl(po, int$unparse(i))
end
end
end start_up
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Common Lisp
(defun december-31-weekday (year)
(mod (+ year (floor year 4) (- (floor year 100)) (floor year 400)) 7))
(defun iso-long-year-p (year)
(or (= 4 (december-31-weekday year)) (= 3 (december-31-weekday (1- year)))))
(format t "Long years between 1800 and 2100:~&~a~%"
(loop for y from 1800 to 2100 if (iso-long-year-p y) collect y))
- Output:
Long years between 1800 and 2100: (1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099)
Cowgol
include "cowgol.coh";
sub longyear(year: uint16): (r: uint8) is
sub p(y: uint16): (d: uint8) is
d := ((y + y/4 - y/100 + y/400) % 7) as uint8;
end sub;
r := 0;
if p(year) == 4 or p(year-1) == 3 then
r := 1;
end if;
end sub;
var year: uint16 := 2000;
while year <= 2100 loop
if longyear(year) != 0 then
print_i16(year);
print_nl();
end if;
year := year + 1;
end loop;
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Dc
[0q]s0
[1q]s1
[1r- r 1r- * 1r-]sO # O = logical OR
##.............................................................................
# C: for( initcode ; condcode ; incrcode ) {body}
# .[q] [1] [2] [3] [4]
# # [initcode] [condcode] [incrcode] [body] (for)
[ [q]S. 4:.3:.2:.x [2;.x 0=. 4;.x 3;.x 0;.x]d0:.x
Os.L.o
]sF # F = for
##.............................................................................
# [1] [0]
# (.) [cond_code] [then_code] [else_code] (if_CTE)
[ []S. 0:. 1:. x [0=0 1]x ;. s.L. x]sI # I = if
##-----------------------------------------------------------------------------
[S. l. l.4/+ l.100/- l.400/+ 7% s.L.]sp # p
##.............................................................................
[S. [l. lpx 4=1 0]x
[l. 1- lpx 3=1 0]x lOx
s.L.
]si # i = is_long_year
##.............................................................................
[
# f = from
# t = to
# y = year
# c = count
st sf # fetch args from stack
[lfsy 0sc]
[ly lt <0 1] # cond
[ly 1+ sy] # incr y
[
[ly lix] # is_long_year(y)
[
[lc 0 <1 0] # 0<c
[
[ lc 10% 0=1 0] # (c % 10) == 0
[ AP ]
[ [ ]P ]
lIx # if
]
[]
lIx # if
ly n
lc 1+ sc
]
[]
lIx # if
] lFx # for
]sD # D = doit = print_long_years
##.............................................................................
[Long years between 1800 and 2100:]P AP
1800 2100 lDx
AP
- Output:
Long years between 1800 and 2100: 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Delphi
Note: The Library System.DateUtils implement a WeeksInYear,but not working, return 52 always.
program Long_year;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
function p(const Year: Integer): Integer;
begin
Result := (Year + (Year div 4) - (Year div 100) + (Year div 400)) mod 7;
end;
function IsLongYear(const Year: Integer): Boolean;
begin
Result := (p(Year) = 4) or (p(Year - 1) = 3);
end;
procedure PrintLongYears(const StartYear: Integer; const EndYear: Integer);
var
Year, Count: Integer;
begin
Count := 0;
for Year := 1800 to 2100 do
if IsLongYear(Year) then
begin
if Count mod 10 = 0 then
Writeln;
Write(Year, ' ');
inc(Count);
end;
end;
var
Year: Integer;
begin
Writeln('Long years between 1800 and 2100:');
PrintLongYears(1800, 2100);
Readln;
end.
Draco
proc p(word y) word:
(y + y/4 - y/100 + y/400) % 7
corp
proc longyear(word y) bool:
p(y) = 4 or p(y-1) = 3
corp
proc main() void:
word y;
for y from 2000 upto 2100 do
if longyear(y) then writeln(y) fi
od
corp
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
EasyLang
func p y .
return (y + y div 4 - y div 100 + y div 400) mod 7
.
func longyear y .
return if p y = 4 or p (y - 1) = 3
.
for y = 2000 to 2100
if longyear y = 1
write y & " "
.
.
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Elixir
defmodule ISO do
def long_year?(y) do
{:ok, jan1} = Date.new(y,1,1)
{:ok, dec31} = Date.new(y,12,31)
Date.day_of_week(jan1) == 4 or Date.day_of_week(dec31) == 4
end
end
IO.inspect(Enum.filter(1990..2050, &ISO.long_year?/1))
- Output:
[1992, 1998, 2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048]
Factor
USING: calendar formatting io kernel math.ranges sequences ;
: long-year? ( n -- ? ) 12 28 <date> week-number 53 = ;
"Year Long?\n-----------" print 1990 2021 [a,b]
[ dup long-year? "yes" "no" ? "%d %s\n" printf ] each
- Output:
Year Long? ----------- 1990 no 1991 no 1992 yes 1993 no 1994 no 1995 no 1996 no 1997 no 1998 yes 1999 no 2000 no 2001 no 2002 no 2003 no 2004 yes 2005 no 2006 no 2007 no 2008 no 2009 yes 2010 no 2011 no 2012 no 2013 no 2014 no 2015 yes 2016 no 2017 no 2018 no 2019 no 2020 yes 2021 no
Forth
: dec31wd ( year -- weekday ) dup dup 4 / swap dup 100 / swap 400 / swap - + + 7 mod ;
: long? ( year -- flag ) dup dec31wd 4 = if drop 1 else 1 - dec31wd 3 = if 1 else 0 then then ;
: demo ( startyear endyear -- ) cr swap do i long? if i . then loop cr ;
- Output:
1995 2045 demo 1998 2004 2009 2015 2020 2026 2032 2037 2043 ok
Fortran
program longyear
use iso_fortran_env, only: output_unit, input_unit
implicit none
integer :: start, ende, i, counter
integer, parameter :: line_break=10
write(output_unit,*) "Enter beginning of interval"
read(input_unit,*) start
write(output_unit,*) "Enter end of interval"
read(input_unit,*) ende
if (start>=ende) error stop "Last year must be after first year!"
counter = 0
do i = start, ende
if (is_long_year(i)) then
write(output_unit,'(I0,x)', advance="no") i
counter = counter + 1
if (modulo(counter,line_break) == 0) write(output_unit,*)
end if
end do
contains
pure function p(year)
integer, intent(in) :: year
integer :: p
p = modulo(year + year/4 - year/100 + year/400, 7)
end function p
pure function is_long_year(year)
integer, intent(in) :: year
logical :: is_long_year
is_long_year = p(year) == 4 .or. p(year-1) == 3
end function is_long_year
end program longyear
- Output:
Enter beginning of interval 1800 Enter end of interval 2100 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 %
FutureBasic
BOOL local fn IsLongYear( year as int )
int year1 = year - 1
int p = (year + (year / 4) - (year / 100) + (year / 400)) % 7
int p1 = (year1 + (year1 / 4) - (year1 / 100) + (year1 / 400)) % 7
end fn = p == 4 || p1 == 3
for int y = 2000 to 2100
if ( fn IsLongYear( y ) ) then print y
next
HandleEvents
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Go
package main
import (
"fmt"
"time"
)
func main() {
centuries := []string{"20th", "21st", "22nd"}
starts := []int{1900, 2000, 2100}
for i := 0; i < len(centuries); i++ {
var longYears []int
fmt.Printf("\nLong years in the %s century:\n", centuries[i])
for j := starts[i]; j < starts[i] + 100; j++ {
t := time.Date(j, time.December, 28, 0, 0, 0, 0, time.UTC)
if _, week := t.ISOWeek(); week == 53 {
longYears = append(longYears, j)
}
}
fmt.Println(longYears)
}
}
- Output:
Long years in the 20th century: [1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998] Long years in the 21st century: [2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099] Long years in the 22nd century: [2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195]
Haskell
import Data.Time.Calendar (fromGregorian)
import Data.Time.Calendar.WeekDate (toWeekDate)
longYear :: Integer -> Bool
longYear y =
let (_, w, _) = toWeekDate $ fromGregorian y 12 28
in 52 < w
main :: IO ()
main = mapM_ print $ filter longYear [2000 .. 2100]
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
J
p =: 1 4 _100 400&(7 | [: <. +/ @: %~)"1 0
ily =: (4=p) +. 3=p@:<:
ply =: (#~ ily)@:([ + 1+i.@:-~)
- Output:
ply/ 1800 2100 1801 1807 1812 1818 1823 1829 1835 1840 1846 1852 1857 1863 1869 1874 1880 1885 1891 1897 1902 1908 1914 1919 1925 1930 1936 1942 1947 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2021 2026 2032 2038 2043 2049 2054 2060 2066 2071 2077 2083 2...
Java
import java.time.LocalDate;
import java.time.temporal.WeekFields;
public class LongYear {
public static void main(String[] args) {
System.out.printf("Long years this century:%n");
for (int year = 2000 ; year < 2100 ; year++ ) {
if ( longYear(year) ) {
System.out.print(year + " ");
}
}
}
private static boolean longYear(int year) {
return LocalDate.of(year, 12, 28).get(WeekFields.ISO.weekOfYear()) == 53;
}
}
- Output:
Long years this century: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
JavaScript
const isLongYear = (year) => {
const jan1 = new Date(year, 0, 1);
const dec31 = new Date(year, 11, 31);
return (4 == jan1.getDay() || 4 == dec31.getDay())
}
for (let y = 1995; y <= 2045; y++) {
if (isLongYear(y)) {
console.log(y)
}
}
- Output:
1998 2004 2009 2015 2020 2026 2032 2037 2043
jq
Works with gojq, the Go implementation of jq
Using Zeller's congruence
# Use Zeller's Congruence to determine the day of the week, given
# year, month and day as integers in the conventional way.
# Emit 0 for Saturday, 1 for Sunday, etc.
#
def day_of_week($year; $month; $day):
if $month == 1 or $month == 2 then
[$month + 12, $year - 1]
else
[$month, $year]
end
| $day + (13*(.[0] + 1)/5|floor)
+ (.[1]%100) + ((.[1]%100)/4|floor)
+ (.[1]/400|floor) - 2*(.[1]/100|floor)
| . % 7 ;
def has53weeks:
day_of_week(.; 1; 1) == 5 or day_of_week(.; 12; 31) == 5;
# To display results neatly:
def nwise($n):
def n: if length <= $n then . else .[0:$n] , (.[$n:] | n) end;
n;
"Long years from 1900 to 2100 inclusive:",
([range(1900;2101) | select(has53weeks)] | nwise(10) | join(", "))
- Output:
Long years from 1900 to 2100 inclusive: 1903, 1908, 1914, 1920, 1925, 1931, 1936, 1942, 1948, 1953 1959, 1964, 1970, 1976, 1981, 1987, 1992, 1998, 2004, 2009 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065 2071, 2076, 2082, 2088, 2093, 2099
Using mktime and gmtime
# Use jq's mktime and gmtime to produce the day of week,
# with 0 for Sunday, 1 for Monday, etc
# $year $month $day are conventional
def day_of_week_per_gmtime($year; $month; $day):
[$year, $month - 1, $day, 0, 0, 1, 0, 0] | mktime | gmtime | .[-2];
# 4 corresponds to Thursday
def has53weeks:
day_of_week_per_gmtime(.; 1; 1) == 4 or day_of_week(.; 12; 31) == 4;
def nwise($n):
def n: if length <= $n then . else .[0:$n] , (.[$n:] | n) end;
n;
"Long years from 1900 to 2100 inclusive:",
([range(1900;2101) | select(has53weeks)] | nwise(10) | join(", "))
- Output:
As above.
Julia
using Dates
has53weeks(year) = week(Date(year, 12, 28)) == 53
println(" Year 53 weeks?\n----------------")
for year in 1990:2021
println(year, " ", has53weeks(year) ? "Yes" : "No")
end
- Output:
Year 53 weeks? ---------------- 1990 No 1991 No 1992 Yes 1993 No 1994 No 1995 No 1996 No 1997 No 1998 Yes 1999 No 2000 No 2001 No 2002 No 2003 No 2004 Yes 2005 No 2006 No 2007 No 2008 No 2009 Yes 2010 No 2011 No 2012 No 2013 No 2014 No 2015 Yes 2016 No 2017 No 2018 No 2019 No 2020 Yes 2021 No
Kotlin
fun main() {
val has53Weeks = { year: Int -> LocalDate.of(year, 12, 28).get(WeekFields.ISO.weekOfYear()) == 53 }
println("Long years this century:")
(2000..2100).filter(has53Weeks)
.forEach { year -> print("$year ")}
}
- Output:
Long years this century: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Logo
to div :x :y
output int quotient :x :y
end
to dec31_weekday :year
output remainder (sum :year div :year 4 div :year -100 div :year 400) 7
end
to iso_long_year? :year
output or 4 = dec31_weekday :year 3 = dec31_weekday difference :year 1
end
for [y 1995 2045 1] [if iso_long_year? :y [print :y]]
- Output:
1998 2004 2009 2015 2020 2026 2032 2037 2043
Lua
function isLongYear (y)
local function p (y)
local f = math.floor
return (y + f(y/4) - f(y/100) + f(y/400)) % 7
end
return p(y) == 4 or p(y - 1) == 3
end
print("Long years in the 21st century:")
for year = 2001, 2100 do
if isLongYear(year) then io.write(year .. " ") end
end
- Output:
Long years in the 21st century: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Mathematica /Wolfram Language
firstyear = 2000;
lastyear = 2099;
years = Range[firstyear, lastyear];
firstday = Table[DayName[{years[[n]], 01, 01}], {n, Length[years]}];
lastday = Table[DayName[{years[[n]], 12, 31}], {n, Length[years]}];
Table[If[years[[n]] >= 1582,
If[firstday[[n]] == Thursday || lastday[[n]] == Thursday,
Style[years[[n]] " long year \n", Bold, Red] ,
years[[n]] " short \n"], "error \n"], {n, Length[years]}]
- Output:
{2000 short , 2001 short , 2002 short , 2003 short , 2004 long year , 2005 short , 2006 short , 2007 short , 2008 short , 2009 long year , 2010 short , 2011 short , 2012 short , 2013 short , 2014 short , 2015 long year , 2016 short , 2017 short , 2018 short , 2019 short , 2020 long year , 2021 short , 2022 short , 2023 short , 2024 short , 2025 short , 2026 long year , 2027 short , 2028 short , 2029 short , 2030 short , 2031 short , 2032 long year , 2033 short , 2034 short , 2035 short , 2036 short , 2037 long year , 2038 short , 2039 short , 2040 short , 2041 short , 2042 short , 2043 long year , 2044 short , 2045 short , 2046 short , 2047 short , 2048 long year , 2049 short , 2050 short , 2051 short , 2052 short , 2053 short , 2054 long year , 2055 short , 2056 short , 2057 short , 2058 short , 2059 short , 2060 long year , 2061 short , 2062 short , 2063 short , 2064 short , 2065 long year , 2066 short , 2067 short , 2068 short , 2069 short , 2070 short , 2071 long year , 2072 short , 2073 short , 2074 short , 2075 short , 2076 long year , 2077 short , 2078 short , 2079 short , 2080 short , 2081 short , 2082 long year , 2083 short , 2084 short , 2085 short , 2086 short , 2087 short , 2088 long year , 2089 short , 2090 short , 2091 short , 2092 short , 2093 long year , 2094 short , 2095 short , 2096 short , 2097 short , 2098 short , 2099 long year }
Modula-2
MODULE LongYear;
FROM InOut IMPORT WriteCard, WriteLn;
VAR year: CARDINAL;
PROCEDURE isLongYear(year: CARDINAL): BOOLEAN;
PROCEDURE p(year: CARDINAL): CARDINAL;
BEGIN
RETURN (year + year DIV 4 - year DIV 100 + year DIV 400) MOD 7;
END p;
BEGIN
RETURN (p(year) = 4) OR (p(year-1) = 3);
END isLongYear;
BEGIN
FOR year := 2000 TO 2100 DO
IF isLongYear(year) THEN
WriteCard(year, 4);
WriteLn;
END;
END;
END LongYear.
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Nim
import times
proc has53weeks(year: Positive): bool =
let dt = initDateTime(monthday = 1, month = mJan, year = year, hour = 0, minute = 0, second= 0)
result = dt.weekday == dThu or year.isLeapYear and dt.weekday == dWed
when isMainModule:
echo "Years with 53 weeks between 2000 and 2100:"
for year in 2000..2100:
if year.has53weeks:
echo year
- Output:
Years with 53 weeks between 2000 and 2100: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
МК-61/52
П0 ИП0 4 / [x] + ИП0 1 ВП 2
/ [x] - ИП0 4 ВП 2 / [x] +
^ ^ 7 / [x] 7 * - П1 4
- x#0 40 ИП1 3 - x#0 40 0 С/П
1 С/П
- Output:
Result for 2020-2030 years: 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0.
Oberon-07
As with other samples, uses the "p" function (here called dayOfYearEnd) on the wikipedia ISO week date page.
First, extend the minimal Dates module from the Leap year#Oberon-07 sample with an exported isLongYear method. Only the new parts are shown:
MODULE Dates;
CONST SUNDAY* = 0;
MONDAY* = 1;
TUESDAY* = 2;
WEDNESDAY* = 3;
THURSDAY* = 4;
FRIDAY* = 5;
SATURDAY* = 6;
(* returns the day of the week of 31st December of year *)
PROCEDURE dayOfYearEnd* ( year : INTEGER ) : INTEGER ;
BEGIN
RETURN ( year + ( year DIV 4 ) - ( year DIV 100 ) + ( year DIV 400 ) ) MOD 7
END dayOfYearEnd ;
(* returns TRUE if year is a long year (i.e., has 53 weeks), FaLSE otherwise *)
PROCEDURE isLongYear* ( year : INTEGER ) : BOOLEAN ;
BEGIN
(* year is a long year if 31st December is a Thursday
* or the first of January is a Thursday (and so the previous
* year had 31st December on a Wednesday)
*)
RETURN ( dayOfYearEnd( year ) = THURSDAY )
OR ( dayOfYearEnd( year - 1 ) = WEDNESDAY )
END isLongYear ;
END Dates.
Then, use the Dates module to test for long years:
MODULE LongYear;
IMPORT Dates, Out;
VAR year : INTEGER ;
BEGIN
FOR year := 2000 TO 2099 DO
IF Dates.isLongYear( year ) THEN
Out.Int( year, 5 )
END
END;
Out.Ln
END LongYear.
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Pascal
program long_year(input);
var
y: integer;
function rd_dec31(year: integer): integer;
begin
{ Rata Die of Dec 31, year }
rd_dec31 := year * 365 + year div 4 - year div 100 + year div 400
end;
function rd_jan1(year: integer): integer;
begin
rd_jan1 := rd_dec31(year - 1) + 1
end;
function weekday(rd: integer): integer;
begin
weekday := rd mod 7;
end;
function long_year(year: integer): boolean;
var
jan1: integer;
dec31: integer;
begin
jan1 := rd_jan1(year);
dec31 := rd_dec31(year);
long_year := (weekday(jan1) = 4) or (weekday(dec31) = 4)
end;
begin
for y := 1990 to 2050 do
if long_year(y) then
writeln(y)
end.
- Output:
1993 1999 2004 2010 2016 2021 2027 2032 2038 2044 2049
Free Pascal
Using DateUtils and WeeksInYear to not reinvent this.
program Long_year;
uses
SysUtils,
DateUtils;
procedure PrintLongYears(StartYear, EndYear: Uint32);
var
Year, Count: Uint32;
DateSep: char;
begin
DateSep := FormatSettings.DateSeparator;
Writeln('Long years between ', StartYear, ' and ', EndYear);
Count := 0;
for Year := StartYear to EndYear do
if WeeksInYear(StrToDate('01' + DateSep + '01' + DateSep + IntToStr(Year))) = 53 then
begin
if Count mod 10 = 0 then
Writeln;
Write(Year, ' ');
Inc(Count);
end;
if Count mod 10 <> 0 then
Writeln;
writeln('Found ', Count, ' long years between ', StartYear, ' and ', EndYear);
end;
begin
PrintLongYears(1800, 2100);
{$IFDEF WINDOWS}
Readln;
{$ENDIF}
end.
- Output:
Long years between 1800 and 2100 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 Found 54 long years between 1800 and 2100
PascalABC.NET
##
uses System;
function islongyear(year: integer): boolean;
begin
var startdate := new DateTime(year, 1, 1);
var enddate := new DateTime(year, 12, 31);
result := (startdate.DayOfWeek = DayOfWeek.Thursday) or (enddate.DayOfWeek = DayOfWeek.Thursday)
end;
(2000..2100).Where(y -> islongyear(y)).Println;
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Perl
use strict;
use warnings;
use DateTime;
for my $century (19 .. 21) {
for my $year ($century*100 .. ++$century*100 - 1) {
print "$year " if DateTime->new(year => $year, month => 12, day => 28)->week_number > 52
}
print "\n";
}
- Output:
1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195
Phix
with javascript_semantics function week_number(integer y,m,d) integer doy = day_of_year(y,m,d), dow = day_of_week(y,m,d), week = floor((doy-dow+10)/7) return week end function for c=20 to 22 do sequence long_years = {} integer century = (c-1)*100 for year=century to century+99 do if week_number(year,12,28)=53 then long_years &= year end if end for printf(1,"Long years in the %d%s century:%v\n", {c,ord(c),long_years}) end for
- Output:
Long years in the 20th century:{1903,1908,1914,1920,1925,1931,1936,1942,1948,1953,1959,1964,1970,1976,1981,1987,1992,1998} Long years in the 21st century:{2004,2009,2015,2020,2026,2032,2037,2043,2048,2054,2060,2065,2071,2076,2082,2088,2093,2099} Long years in the 22nd century:{2105,2111,2116,2122,2128,2133,2139,2144,2150,2156,2161,2167,2172,2178,2184,2189,2195}
PHP
function isLongYear($year) {
return (53 == strftime('%V', gmmktime(0,0,0,12,28,$year)));
}
for ($y=1995; $y<=2045; ++$y) {
if (isLongYear($y)) {
printf("%s\n", $y);
}
}
- Output:
1998 2004 2009 2015 2020 2026 2032 2037 2043
PL/0
The program waits for two numbers: startyear
and endyear
. Then displays long years from startyear
to endyear
.
var startyear, endyear, year, longyear, ayear, weekday;
procedure calcweekday;
begin
weekday := ayear + ayear / 4 - ayear / 100 + ayear / 400;
weekday := weekday - (weekday / 7) * 7
end;
procedure calclongyear;
begin
longyear := 0; ayear := year;
call calcweekday;
if weekday = 4 then longyear := 1;
ayear := year - 1;
call calcweekday;
if weekday = 3 then longyear := 1
end;
begin
? startyear;
? endyear;
year := startyear;
while year <= endyear do
begin
call calclongyear;
if longyear <> 0 then ! year;
year := year + 1
end
end.
- Input:
1995 2045
- Output:
1998 2004 2009 2015 2020 2026 2032 2037 2043
PowerShell
Function Is-Long-Year {
param([Int]$year)
53 -eq (Get-Date -Year $year -Month 12 -Day 28 -UFormat %V)
}
For ($y=1995; $y -le 2045; $y++) {
If (Is-Long-Year $y) {
Write-Host $y
}
}
- Output:
1998 2004 2009 2015 2020 2026 2032 2037 2043
Prolog
% See https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
p(Year, P):-
P is (Year + (Year//4) - (Year//100) + (Year//400)) mod 7.
long_year(Year):-
p(Year, 4),
!.
long_year(Year):-
Year_before is Year - 1,
p(Year_before, 3).
print_long_years(From, To):-
writef("Long years between %w and %w:\n", [From, To]),
print_long_years(From, To, 0),
nl.
print_long_years(From, To, _):-
From > To,
!.
print_long_years(From, To, Count):-
long_year(From),
!,
(Count > 0 ->
(0 is Count mod 10 -> nl ; write(' '))
;
true
),
write(From),
Count1 is Count + 1,
Next is From + 1,
print_long_years(Next, To, Count1).
print_long_years(From, To, Count):-
Next is From + 1,
print_long_years(Next, To, Count).
main:-
print_long_years(1800, 2100).
- Output:
Long years between 1800 and 2100: 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Python
'''Long Year ?'''
from datetime import date
# longYear :: Year Int -> Bool
def longYear(y):
'''True if the ISO year y has 53 weeks.'''
return 52 < date(y, 12, 28).isocalendar()[1]
# --------------------------TEST---------------------------
# main :: IO ()
def main():
'''Longer (53 week) years in the range 2000-2100'''
for year in [
x for x in range(2000, 1 + 2100)
if longYear(x)
]:
print(year)
# MAIN ---
if __name__ == '__main__':
main()
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Quackery
dayofweek
is defined at Day of the week#Quackery
[ dup dip
[ 1 1 rot dayofweek 4 = ]
31 12 rot dayofweek 4 = or ] is longyear ( n --> b )
say "Long Years in the 21st Century" cr
cr
100 times
[ 2000 i^ + longyear if
[ 2000 i^ + echo sp ] ]
- Output:
Long Years in the 21st Century 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Raku
(formerly Perl 6)
December 28 is always in the last week of the year. (By ISO8601)
sub is-long ($year) { Date.new("$year-12-28").week[1] == 53 }
# Testing
say "Long years in the 20th century:\n", (1900..^2000).grep: &is-long;
say "\nLong years in the 21st century:\n", (2000..^2100).grep: &is-long;
say "\nLong years in the 22nd century:\n", (2100..^2200).grep: &is-long;
- Output:
Long years in the 20th century: (1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998) Long years in the 21st century: (2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099) Long years in the 22nd century: (2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195)
REXX
/*REXX program determines If a (calendar) year is a short or long year */
/* (52 or 53 weeks). */
Parse Arg lo hi . /* obtain optional args. */
current=left(date('S'),4)
If lo=='' | lo=="," | lo=='*' Then lo=current /*Not given? Use default.*/
If hi=='' | hi=="," Then hi=lo /* " " " " */
If hi=='*' Then hi=current /*an asterisk: current yr*/
Do yr=lo To hi /* process single yr or range of */
Say ' year ' yr ' is a ',
right(word('short long',is_long(yr)+1),5) ' year'
End
Exit
/*----------------------------------------------------------------------*/
wd_1231:
/*************************************************************************
* returns the day of the week of 31 December year
*************************************************************************/
Parse Arg year
Return (year+year%4-year%100+year%400)//7
is_long:
Parse Arg year
Return wd_1231(year)==4 |, /* year ends in a Thursday */
wd_1231(year-1)==3 /* or previous year ends in a Wednesday */
- output when using the inputs of: 1990 2030
(Shown at three-quarter size.)
year 1990 is a short year year 1991 is a short year year 1992 is a long year year 1993 is a short year year 1994 is a short year year 1995 is a short year year 1996 is a short year year 1997 is a short year year 1998 is a long year year 1999 is a short year year 2000 is a short year year 2001 is a short year year 2002 is a short year year 2003 is a short year year 2004 is a long year year 2005 is a short year year 2006 is a short year year 2007 is a short year year 2008 is a short year year 2009 is a long year year 2010 is a short year year 2011 is a short year year 2012 is a short year year 2013 is a short year year 2014 is a short year year 2015 is a long year year 2016 is a short year year 2017 is a short year year 2018 is a short year year 2019 is a short year year 2020 is a long year year 2021 is a short year year 2022 is a short year year 2023 is a short year year 2024 is a short year year 2025 is a short year year 2026 is a long year year 2027 is a short year year 2028 is a short year year 2029 is a short year year 2030 is a short year
Ring
see "long years 2000-2099: "
for year = 2000 to 2100
num1 = (year-1900)%7
num2 = floor((year-1904)/4)
num3 = (num1+num2+5)%7
if num3 = 0 or (num1 = 6 and num3 = 1)
see "" + year + " "
ok
next
- Output:
long years 2000-2099: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
RPL
This is a direct transcription from Wikipedia's formula.
Code | Comments |
---|---|
≪ DUP 1 - 1 2 START → y ≪ y DUP 4 / IP + y 100 / IP - y 400 / IP + 7 MOD ≫ SWAP NEXT 3 == SWAP 4 == OR ≫ 'LONG?' STO |
( year -- weekday ) Calling 2 times... ... p() as a nested function, to get p(y-1)... ...then p(y) |
The following line of code delivers what is required:
≪ {} 2023 2100 FOR y IF y LONG? THEN y + END NEXT ≫ EVAL
- Output:
1: { 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 }
Ruby
require 'date'
def long_year?(year = Date.today.year)
Date.new(year, 12, 28).cweek == 53
end
(2020..2030).each{|year| puts "#{year} is long? #{ long_year?(year) }." }
- Output:
2020 is long? true. 2021 is long? false. 2022 is long? false. 2023 is long? false. 2024 is long? false. 2025 is long? false. 2026 is long? true. 2027 is long? false. 2028 is long? false. 2029 is long? false. 2030 is long? false.
Rust
extern crate time; // 0.2.16
use time::Date;
fn main() {
(2000..=2099)
.filter(|&year| is_long_year(year))
.for_each(|year| println!("{}", year));
}
fn is_long_year(year: i32) -> bool {
Date::try_from_ymd(year, 12, 28).map_or(false, |date| date.week() == 53)
}
- Output:
2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Scala
- Output:
Best seen running in your browser by Scastie (remote JVM).
import java.time.temporal.TemporalAdjusters.firstInMonth
import java.time.temporal.{ChronoField, IsoFields}
import java.time.{DayOfWeek, LocalDate, Month}
import scala.util.{Failure, Try}
private object LongYear extends App {
private val (currentCentury, maxWeekNumber) = (LocalDate.now().getYear / 100, ChronoField.ALIGNED_WEEK_OF_YEAR.range().getMaximum)
private val centuries = currentCentury * 100 until (currentCentury + 1) * 100
private val results = List(
centuries.filter(isThursdayFirstOrLast),
centuries.filter(year => maxIsoWeeks(year) == maxWeekNumber),
centuries.filter(mostThursdaysInYear)
)
// Solution 1, the first or respectively last day of the year is a Thursday.
private def isThursdayFirstOrLast(_year: Int): Boolean = {
LocalDate.of(_year, Month.DECEMBER, 31).get(ChronoField.DAY_OF_WEEK) == DayOfWeek.THURSDAY.getValue ||
LocalDate.of(_year, Month.JANUARY, 1).get(ChronoField.DAY_OF_WEEK) == DayOfWeek.THURSDAY.getValue
}
// Solution 2, if last week that contains at least four days of the month of December.
private def maxIsoWeeks(_year: Int) = {
// The last week that contains at least four days of the month of December.
LocalDate.of(_year, Month.DECEMBER, 28).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR)
}
// Solution 3, if there are 52 Thursdays in a year
private def mostThursdaysInYear(_year: Int) = {
val datum = LocalDate.of(_year, Month.JANUARY, 1).`with`(firstInMonth(DayOfWeek.THURSDAY))
datum.plusDays(52 * 7).getYear == _year
}
println(s"Years in this ${currentCentury + 1}st century having ISO week $maxWeekNumber :")
Try { // Testing the solutions
assert(results.tail.forall(_ == results.head), "Discrepancies in results.")
} match {
case Failure(ex) => Console.err.println(ex.getMessage)
case _ =>
}
results.zipWithIndex.foreach(solution => println(s"Solution ${solution._2}: ${solution._1.mkString(" ")}"))
}
Scheme
The demo code uses iota as defined in SRFI-1, so won't work in Schemes lacking that function. Racket requires the addition of (require srfi/1).
(define (dec31wd year)
(remainder (apply + (map (lambda (d) (quotient year d)) '(1 4 -100 400))) 7))
(define (long? year) (or (= 4 (dec31wd year)) (= 3 (dec31wd (- year 1)))))
(display "Long years between 1800 and 2100:") (newline)
(display (filter long? (iota 300 1800)))
- Output:
Long years between 1800 and 2100: (1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099)
Sidef
func is_long_year(year) {
Date.parse("#{year}-12-28", "%Y-%m-%d").week == 53
}
say ( "Long years in the 20th century:\n", (1900..^2000).grep(is_long_year))
say ("\nLong years in the 21st century:\n", (2000..^2100).grep(is_long_year))
say ("\nLong years in the 22nd century:\n", (2100..^2200).grep(is_long_year))
- Output:
Long years in the 20th century: [1903, 1908, 1914, 1920, 1925, 1931, 1936, 1942, 1948, 1953, 1959, 1964, 1970, 1976, 1981, 1987, 1992, 1998] Long years in the 21st century: [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099] Long years in the 22nd century: [2105, 2111, 2116, 2122, 2128, 2133, 2139, 2144, 2150, 2156, 2161, 2167, 2172, 2178, 2184, 2189, 2195]
Snobol
DEFINE('DEC31WD(Year)') :(END_DEC31WD)
DEC31WD DEC31WD = REMDR(Year + (Year / 4) - (Year / 100) + (Year / 400), 7) :(RETURN)
END_DEC31WD
DEFINE('ISOLONG(Year)') :(END_ISOLONG)
ISOLONG EQ(DEC31WD(Year), 4) :S(RETURN)
EQ(DEC31WD(Year - 1), 3) :S(RETURN)F(FRETURN)
END_ISOLONG
DEFINE('ISODEMO(Start,End)') :(END_ISODEMO)
ISODEMO OUTPUT = 'ISO long years between ' Start ' and ' End ':'
Year = Start
LOOP OUTPUT = ISOLONG(Year) Year
Year = Year + 1
LE(YEAR, 2045) :S(LOOP) F(RETURN)
END_ISODEMO
ISODEMO(1995, 2045)
END
- Output:
ISO long years between 1995 and 2045: 1998 2004 2009 2015 2020 2026 2032 2037 2043
Swift
func isLongYear(_ year: Int) -> Bool {
let year1 = year - 1
let p = (year + (year / 4) - (year / 100) + (year / 400)) % 7
let p1 = (year1 + (year1 / 4) - (year1 / 100) + (year1 / 400)) % 7
return p == 4 || p1 == 3
}
for range in [1900...1999, 2000...2099, 2100...2199] {
print("\(range): \(range.filter(isLongYear))")
}
- Output:
1900...1999: [1903, 1908, 1914, 1920, 1925, 1931, 1936, 1942, 1948, 1953, 1959, 1964, 1970, 1976, 1981, 1987, 1992, 1998] 2000...2099: [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099] 2100...2199: [2105, 2111, 2116, 2122, 2128, 2133, 2139, 2144, 2150, 2156, 2161, 2167, 2172, 2178, 2184, 2189, 2195]
Tcl
## Reference: https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
proc p {year} {
return [expr {($year + ($year/4) - ($year/100) + ($year/400)) % 7}]
}
proc is_long_year {year} {
return [expr {[p $year] == 4 || [p [expr {$year - 1}]] == 3}]
}
proc print_long_years {from to} {
for {set year $from; set count 0} {$year <= $to} {incr year} {
if {[is_long_year $year]} {
if {$count > 0} {
puts -nonewline [expr {($count % 10 == 0) ? "\n" : " "}]
}
puts -nonewline $year
incr count
}
}
}
puts "Long years between 1800 and 2100:"
print_long_years 1800 2100
puts ""
- Output:
Long years between 1800 and 2100: 1801 1807 1812 1818 1824 1829 1835 1840 1846 1852 1857 1863 1868 1874 1880 1885 1891 1896 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099
Terraform
Contents of main module:
module "iso-long-years" {
source = "./iso-long-years"
start_year = 1995
end_year = 2045
}
output "long-years" {
value = module.iso-long-years.long-years
}
Contents of iso-long-years module:
variable start_year {
type = number
}
variable end_year {
type = number
}
locals {
year_list = range(var.start_year, var.end_year+1)
}
module "iso-long-year" {
for_each = toset([for y in local.year_list: tostring(y)])
source = "../iso-long-year"
year = each.key
}
output "long-years" {
value = compact([for y in [for n in local.year_list: tostring(n)]:
module.iso-long-year[y].isLong ? y : ""])
}
Contents of iso-long-year module:
variable year {
type = string
default = ""
}
locals {
ystr = var.year != "" ? var.year : split("-",timestamp())[0]
y = tonumber(local.ystr)
e = local.y - 1
dec31 = local.y * 365 + floor(local.y/4) - floor(local.y/100) + floor(local.y/400)
jan1 = local.e * 365 + floor(local.e/4) - floor(local.e/100) + floor(local.e/400) + 1
}
output isLong {
value = (local.dec31 % 7 == 4 || local.jan1 % 7 == 4)
}
- Output:
Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: long-years = [ "1998", "2004", "2009", "2015", "2020", "2026", "2032", "2037", "2043", ]
TypeScript
const isLongYear = (year: number): boolean => {
const jan1: Date = new Date(year, 0, 1);
const dec31: Date = new Date(year, 11, 31);
return (4 == jan1.getDay() || 4 == dec31.getDay())
}
for (let y: number = 1995; y <= 2045; y++) {
if (isLongYear(y)) {
console.log(y)
}
}
- Output:
1998 2004 2009 2015 2020 2026 2032 2037 2043
UNIX Shell
Thursdays check using cal(1) and grep(1)
long_year() {
cal 1 $1 | grep -q ' 3 *$' && return 0
cal 12 $1 | grep -q ' 26 *$'
}
Straightforward check using GNU date(1)
December 28th is always in the last week of the year, so just check whether or not that's week 53:
long_year() {
expr $(date -d "$1-12-28" +%V) = 53 >/dev/null
}
Direct computation with built-in arithmetic in newer shells
dec31wd() {
# return weekday (time_t tm_wday, 0=Sunday) of December 31st of the given year
typeset -i y=$1
echo $(( (y + y / 4 - y / 100 + y / 400) % 7 ))
}
# the year is long if the year starts or ends on a Thursday (starts on a
# Thursday = the previous year ends on a Wednesday)
long_year() {
typeset -i y=$1
(( 4 == $(dec31wd $y) || 3 == $(dec31wd $(( y - 1 ))) ))
}
Demo code for any of the above:
for y in $(seq 1995 2045); do
if long_year $y; then
echo $y
fi
done | column
- Output:
1998 2004 2009 2015 2020 2026 2032 2037 2043
Wren
import "./date" for Date
var centuries = ["20th", "21st", "22nd"]
var starts = [1900, 2000, 2100]
for (i in 0...centuries.count) {
var longYears = []
System.print("\nLong years in the %(centuries[i]) century:")
for (j in starts[i]...starts[i]+100) {
var t = Date.new(j, 12, 28)
if (t.weekOfYear[1] == 53) {
longYears.add(j)
}
}
System.print(longYears)
}
- Output:
Long years in the 20th century: [1903, 1908, 1914, 1920, 1925, 1931, 1936, 1942, 1948, 1953, 1959, 1964, 1970, 1976, 1981, 1987, 1992, 1998] Long years in the 21st century: [2004, 2009, 2015, 2020, 2026, 2032, 2037, 2043, 2048, 2054, 2060, 2065, 2071, 2076, 2082, 2088, 2093, 2099] Long years in the 22nd century: [2105, 2111, 2116, 2122, 2128, 2133, 2139, 2144, 2150, 2156, 2161, 2167, 2172, 2178, 2184, 2189, 2195]
XPL0
\Long year
code Rem=2, CrLf=9, IntIn=10, IntOut=11, Text=12, Clear=40;
integer S, E, Y;
function integer Weekday(Y);
\Weekday of Y-12-31, 0 Sunday
integer Y;
return Rem((Y + Y / 4 - Y / 100 + Y / 400) / 7);
function integer IsLongYear(Y);
integer Y;
return 4 = Weekday(Y) ! 3 = Weekday(Y - 1);
begin
Clear;
Text(0, "**** List of ISO long years ****");
CrLf(0);
Text(0, "Start year: "); S:= IntIn(0);
Text(0, "End year: "); E:= IntIn(0);
CrLf(0);
for Y:= S, E do
if IsLongYear(Y) then [IntOut(0, Y); Text(0, " ")];
CrLf(0);
end
- Output:
**** List of ISO long years **** Start year: 1995 End year: 2045 1998 2004 2009 2015 2020 2026 2032 2037 2043
zkl
fcn isLongYear(y){ Time.Date.weeksInYear(y)==53 }
foreach nm,y in (T(T("20th",1900), T("21st",2000), T("22nd",2100))){
println("\nLong years in the %s century:\n%s".fmt(nm,
[y..y+99].filter(isLongYear).concat(" ")));
}
- Output:
Long years in the 20th century: 1903 1908 1914 1920 1925 1931 1936 1942 1948 1953 1959 1964 1970 1976 1981 1987 1992 1998 Long years in the 21st century: 2004 2009 2015 2020 2026 2032 2037 2043 2048 2054 2060 2065 2071 2076 2082 2088 2093 2099 Long years in the 22nd century: 2105 2111 2116 2122 2128 2133 2139 2144 2150 2156 2161 2167 2172 2178 2184 2189 2195
- Programming Tasks
- Solutions by Programming Task
- 11l
- Action!
- Ada
- ALGOL 68
- ALGOL-M
- ALGOL W
- Amazing Hopper
- APL
- AppleScript
- Arturo
- AutoHotkey
- AWK
- BASIC
- Applesoft BASIC
- ASIC
- BASIC256
- BBC BASIC
- Chipmunk Basic
- Commodore BASIC
- FreeBASIC
- Gambas
- GW-BASIC
- IS-BASIC
- MSX Basic
- Nascom BASIC
- Palo Alto Tiny BASIC
- PureBasic
- QuickBASIC
- Run BASIC
- S-BASIC
- Tiny BASIC
- True BASIC
- Visual Basic
- Visual Basic for DOS
- XBasic
- Yabasic
- BCPL
- C sharp
- C
- C++
- Clojure
- CLU
- Common Lisp
- Cowgol
- Dc
- Delphi
- Draco
- EasyLang
- Elixir
- Factor
- Forth
- Fortran
- FutureBasic
- Go
- Haskell
- J
- Java
- JavaScript
- Jq
- Julia
- Kotlin
- Logo
- Lua
- Mathematica
- Wolfram Language
- Modula-2
- Nim
- МК-61/52
- Oberon-07
- Pascal
- Free Pascal
- PascalABC.NET
- Perl
- Phix
- PHP
- PL/0
- PowerShell
- Prolog
- Python
- Quackery
- Raku
- REXX
- Ring
- RPL
- Ruby
- Rust
- Scala
- Scheme
- Sidef
- Snobol
- Swift
- Tcl
- Terraform
- TypeScript
- UNIX Shell
- Wren
- Wren-date
- XPL0
- Zkl