g | x | w | all
Bytes Lang Time Link
179Hatchback241211T201259Zmadeforl
027AWK241206T205855Zxrs
00605AB1E181205T130636ZKevin Cr
006Vyxal241204T042215Zemanresu
034Regex any240421T111126Zemanresu
nan230914T210509ZRARE Kpo
016x86 machine code181221T214239Z640KB
006Thunno 2 t230610T134617ZThe Thon
005Arturo221111T211247Zchunes
047Go221111T210152Zbigyihsu
nanFig221111T204927ZSeggan
010Vyxal220107T131212ZSjoerdPe
100Pascal221110T132011ZKai Burg
037Python2150528T030606Zmathmand
125Python220110T160553ZMr.McNug
028Ruby220106T173003Zwteuber
039Forth gforth201113T090918ZRazetime
026Python 3201113T123858ZJitse
005Japt !190108T145713ZShaggy
025Excel190402T160708Zorthople
226Stackylogic160722T121519ZDestruct
108W d200101T104217Zuser8505
014Reg190815T044602Zuser8505
034PHP190314T233127ZJo King
019Haskell190402T115038Zprimo
039Haskell150528T204913ZAplusKmi
082Swift190301T191418Zonnoweb
035Haskell190301T075839Zdfeuer
008Japt h!190205T162112ZOliver
020Java 8160720T142516ZKevin Cr
019JavaScript190109T222440ZOliver
022TSQL160902T120839ZS.Karras
031Clam190108T014620ZMayube
009MathGolf190108T074257Zmaxb
046Common Lisp181222T114225ZRenzo
012APL150526T114942ZFUZxxl
033C gcc181205T114857Zbznein
007Jelly181205T020935ZDennis
030Kotlin181205T011429Zsnail_
021Javascript ES6150528T145954ZDavid Ha
043C++180326T072749ZHatsuPoi
042D181110T201900ZAdalynn
022Ruby180509T070410ZG B
049ActionScript 2.0180327T103717ZJhynjhir
103Whitespace180327T100240ZKevin Cr
014Bash180325T123715Zuser4180
009MATLAB + Aerospace Toolbox171018T200322ZTom Carp
008Jelly171018T194110ZErik the
030PHP160720T140056Zaross
040SmileBASIC170202T140131Z12Me21
028PHP170202T023453ZTitus
045PHP170113T123057ZDexa
030C160718T195408Zuser5634
015Mathematica161221T220323ZJungHwan
024Retina161221T163711ZMartin E
081C150527T175803ZToby Spe
068BASH160902T170759Zmichael5
023C#160902T083949Zadrianmp
159LOLCODE160722T154049ZAAM111
031PowerShell160720T154238ZThePoShW
026C#160720T135336Zaloisdg
048Python160720T055503ZDaniel
037Python160720T052040ZDestruct
011Pyth150526T185044ZDennis
012CJam150526T170924ZDennis
045PHP150604T100519ZNorthBri
056IBM System Z assembler150527T083613ZSteve Iv
013TIBASIC150526T152106Zlirtosia
027JavaScript ES6150526T130148Zedc65
057C150528T164949ZAndrea B
038Regex150527T072201Zrr-
028Julia150527T221109ZAlex A.
029R150527T204157ZMickyT
055sed150527T170112ZToby Spe
041Befunge98150527T164518ZMegaTom
077SpecBAS150527T092622ZBrian
027KDBQ150527T084635ZWooiKent
026Javascript ES6150526T212527ZQwertiy
014Pyth150526T105750ZJakube
013Pip150526T175919ZDLosc
027Mathematica150526T112514ZLegionMa
016CJam150526T114044ZMartin E

Hatchback, 179 bytes

0 0 121 16 1 0 2 4 0 3 100 0 4 400 0 5 1 0 7 2400 10 6 1 15 6 2 6 6 0 110 10 6 1 15 6 3 9 6 5 6 6 0 110 10 6 1 15 6 4 9 6 5 6 6 0 110 10 6 1 8 6 7 6 6 0 121 13 0 0 0 10 13 0 65535

AWK, 27 bytes

$0=$1%4<1&&$1%100||$1%400<1

Attempt This Online!

Prints 1 if leap year or nothing.

Raku (Perl 6) (rakudo), 47 bytes

My first attempt at Raku, a simple port:

say (my$x=@*ARGS[0])%4 <1&&$x%100 >1||$x%400 <1

Attempt This Online!\

But ATO doesn't seem to like it. Some test cases:

raku -e 'say (my$x=@*ARGS[0])%4 <1&&$x%100 >1||$x%400 <1' 1800
False
raku -e 'say (my$x=@*ARGS[0])%4 <1&&$x%100 >1||$x%400 <1' 1900
False
raku -e 'say (my$x=@*ARGS[0])%4 <1&&$x%100 >1||$x%400 <1' 2000
True
raku -e 'say (my$x=@*ARGS[0])%4 <1&&$x%100 >1||$x%400 <1' 199900
False
raku -e 'say (my$x=@*ARGS[0])%4 <1&&$x%100 >1||$x%400 <1' 1999000
False
raku -e 'say (my$x=@*ARGS[0])%4 <1&&$x%100 >1||$x%400 <1' 19990000

05AB1E, 9 7 6 bytes

тÖoooÖ

-1 byte porting @emanresuA's Vyxal answer, so make sure to upvote that answer as well!

Try it online or verify all test cases.

Original 9 7 bytes approach:

т‰0Kθ4Ö

Try it online or verify all test cases.

Explanation:

тÖ       # Check whether the (implicit) input is divisible by 100
         #  i.e. 1900 → 1
         #  i.e. 1936 → 0
         #  i.e. 1991 → 0
         #  i.e. 2000 → 1
  ooo    # Take 2 to the power that three times
         #  i.e. 1 → 2 → 4 → 16
         #  i.e. 0 → 1 → 2 → 4
     Ö   # Check whether the (implicit) input is divisible by that
         # (and output the result implicitly)
         #  i.e. 1900 and 16 → 0 (falsey)
         #  i.e. 1936 and 4 → 1 (truthy)
         #  i.e. 1991 and 4 → 0 (falsey)
         #  i.e. 2000 and 16 → 1 (truthy)
т‰       # Divmod the (implicit) input by 100
         #  i.e. 1900 → [19,00]
         #  i.e. 1936 → [19,36]
         #  i.e. 1991 → [19,91]
         #  i.e. 2000 → [20,00]
  0K     # Remove all 0s
         #  i.e. [19,00] → [19]
         #  i.e. [19,36] → [19,36]
         #  i.e. [19,91] → [19,91]
         #  i.e. [20,00] → [20]
    θ    # Pop and get the last item
         #  i.e. [19] → 19
         #  i.e. [19,36] → 36
         #  i.e. [19,91] → 91
         #  i.e. [20] → 20
     4Ö  # Check if it's divisible by 4
         # (and output the result implicitly)
         #  i.e. 19 → 0 (falsey)
         #  i.e. 36 → 1 (truthy)
         #  i.e. 91 → 0 (falsey)
         #  i.e. 20 → 1 (truthy)

Vyxal, 6 bytes

₁Ḋ›E²Ḋ

Try it Online! Shorter version of SjoerdPenning's answer.

₁Ḋ     # Divisible by 100? yes -> 1, no -> 0
  ›    # increment - yes -> 2, no -> 1
   E²  # 4 to the power of that - yes -> 16, no -> 4
     Ḋ # Check if the input is divisible by that - 16 if divisible by 100, 4 otherwise

Regex (any), 34 bytes

([13579][26]|[2468][048]|0[48])0*$

Try it online!

The ([13579][26]|[2468][048]|0[48]) matches two-digit strings that are multiples of 4 and aren't 00. The 0* extends that to potential matches of multiples of 40 or 400, both of which are necessarily leap years. This actually fails on inputs like 10000, but that's fine because it's out of the input range.

A leap year ERE is not a "language" per se but it should be easily adaptable to any flavor of regex

(I think it should work for any year, including negative years and also waaaaaaay in the future, assuming proleptic Gregorian calendar)

ereLEAP := /(([2468][048]|[13579][26]|(^|[0+-])[48])(00)?|0000|^[+-]?0*)$/

so an awk solution using it would be like


awk 'function leap(_) { 
         return _~"(([2468][048]|[13579][26]|(^|[0+-])" \
                  "[48])(00)?|0000|^[+-]?0*)$" ? "y" : "n" } ($2 = leap($1))^_'

and it properly captures the special edge cases, including strangely formatted inputs like negative zero :

-2400
-2000
-1600
-1200
-800
-400
-0
0
400
800
1200
1600
2000
2400

777778000
777778400
777778800
777779200
777779600
777780000
777780400
777780800
777781200
777781600
777782000
777782400

or ultra extreme inputs, like the year

9745314011399999080353382387875188310876226857595007526867
9064572129486907664261024656150658820102592253049162314086
6818345916986520309404657798729631265341953127769995647302
9870789655490053648352799593479218378873685597925394874945
746363615468965612827738803104277547081828589991914111200

x86 machine code, 16 bytes

00000000: fcad fdad 2d30 3074 fa86 c4d5 0aa8 03c3    ...-00t.........

Listing

FC         CLD             ; set direction for LODSW to increment
AD         LODSW           ; SI += 2 to start with last two digits
FD         STD             ; set direction for LODSW to decrement
       LD:
AD         LODSW           ; load two ASCII digit chars into AX
2D 3030    SUB  AX, '00'   ; convert to decimal, test if year ends in 00?
74 FA      JZ   LD         ; if so, look at the first two digits instead
86 C4      XCHG AL, AH     ; endian convert
D5 0A      AAD             ; base convert from 10 to word
A8 03      TEST AL, 3      ; mod 4 = 0?
C3         RET             ; return to caller

Input string in SI, output is ZF if is a leap year.

Explanation

If the year does not end in 00, it is a leap year if last two digits mod 4 is 0. If it does end in 00, it will be a leap year if the first two digits mod 4 is 0. Example:

Leap year:

NOT leap year:

Test Program Output

LEAP.COM test output

Thunno 2 t, 6 bytes

ɦḋ0o4Ḋ

Attempt This Online!

Port of Kevin Cruijssen's 05AB1E answer.

Explanation

ɦḋ0o4Ḋ  # Implicit input
ɦḋ      # Divmod by 100
  0o    # Remove 0s
    4Ḋ  # Divisible by 4?
        # Implicit output
        # of last item

Arturo, 5 bytes

leap?

Try it!

Go, 47 bytes

func(y int)bool{return y%4<1&&y%100>0||y%400<1}

Attempt This Online!

Fig, \$11\log_{256}(96)\approx\$ 9.054 bytes

?%25x%4x%16

Try it online!

Port of Vyxal. Outputs 0 for truthy, positive numbers for falsey.

?%25x%4x%16
?%25x       # If mod 25 is > 0
     %4x    # Print mod 4
        %16 # Else print mod 16

Vyxal, 13 10 bytes

-3 bytes Thanks to Kevin Cruijssen

25Ḋ[16|4]Ḋ

Outputs 1 for truthy, 0 for falsy

Try it Online!

Explanation

25Ḋ           - is it divisible by 25?
   [16   Ḋ    - if so: check if its divisible by 16
      |4]Ḋ    - if not: check if its divisible by 4

Vyxal, 7 bytes

A port of Kevin Cruijssen's answer

₁ḋ0ot4Ḋ

Try it Online!

Explanation

₁ḋ       - divmod the input by 100
  0o     - remove all instances of 0 from the result
    t4Ḋ  - grab the tail of the divmod result and check if it's divisible by 4

Pascal, 100 B

This is a complete program according to and requiring a processor complying to ISO standard 7185 “Pascal” (level 0 sufficient). It demonstrates the importance of sets in Pascal. Note, + and are left-associative thus the following is guaranteed to yield the expected result.

program p(input,output);var y:integer;begin read(y);write(0 in[y mod 4]-[y mod 100]+[y mod 400])end.

For the standard non-golfed version using Boolean operators and/or see RosettaCode.

Delphi/Free Pascal, 62 B

The .toInt64 “type helper” requires at least FPC version 3.0.0. In FPC, {$mode Delphi} or {$mode objFPC} have to be selected so paramStr returns “long strings”. Evidently, input is specified as the first argument on the command line.

{$mode Delphi}
uses sysUtils;begin write(isLeapYear(paramStr(1).toInt64))end.

This is pretty much the same as the RosettaCode implementation.

Python2 - 37 bytes

g=lambda x:(x%4or x%400and x%100<1)<1

Note that if a is a nonnegative integer, then a<1 is a short way of writing not bool(a). The last <1 thus effectively converts the expression in the parentheses to a boolean and negates the result.

Applying the function g to an integer n between 1801 and 2400 will return True if n is a leap year, and False otherwise.

Python, 125 bytes

y=int(input(""))
if y%100==0 and y!=2400:
    print("n")
else:
    if y%4==0:
        print("y")
    else:
        print("n")

Try it Online!

Ruby, 28 bytes

The lambda takes an Integer y representing the year and returns true or false.

->y{y%4<1&&y%100>0||y%400<1}

Use like this:

f=->y{y%4<1&&y%100>0||y%400<1}
f[2004]
# => true

or this:

f=->y{y%4<1&&y%100>0||y%400<1}
[1936,1805,1900,2272,2400].map(&f)
# => [true, false, false, true, true]

Try it online

Explanation

Forth (gforth), 48 39 bytes

: f 'd /mod over if d>s then 4 mod 0= ;

Try it online!

Same as Kevin Cruijssen's 05AB1E answer.

-9 bytes from Bubbler.

Python 3, 26 bytes

lambda n:n%4**-~(n%25<1)<1

Try it online!

Using Kevin Cruijssen's Java approach.


Python 3, 28 bytes

lambda n:(n%100or n/100)%4<1

Try it online!

Using Kevin Cruijssen's 05AB1E approach.

Japt -!, 8 5 bytes

Locale dependent; in my locale the timezone offset is GMT+0000 for leap years and GMT-0025 for all others.

ÐUT k

Try it or run all test cases

ÐUT k     :Implicit input of integer U
Ð         :Create Date object from (defaulting to the first day of the month)
 U        :  The year U
  T       :  The month 0 (months are 0-indexed in JS)
    k     :Get timezone offset as an absolute integer (0 or 25)
          :Implicit output of logical NOT of result

And here's my original 8-byte solution, which isn't locale dependent and outputs 1 or 0 for true & false:

ÐUT#< Îu

Try it (includes all test cases)

ÐUT#< Îu     :Implicit input of integer U
ÐUT          :As above but ...
   #<        :  With the date set to 60 (dates wrap over to the next month in JS, so this will give us either 29/02 or 01/03)
      Î      :Get 0-based index of month (1 or 2)
       u     :Modulo 2

Excel, 30 25 bytes

Because of an intentional bug in Excel to maintain compatibility with Lotus 1-2-3 the year 1900 is treated as a leap year. We can however shift the year by 400 before doing the calculation. The leap year bug then occurs in 1500, which we don't care about anyway. For the following formula A1 serves as input.

=DAY(DATE(A1+400,2,29))>1

Stackylogic, 226 bytes

Yes, that is right. I made a program in Stackylogic (non-TC), which was invented by Helka Homba, for the challenge found here.

Stackylogic has only binary input, so 10 (or more, any more digits will be ignored) bit binary must be used (least significant bit inputted first). Any dates outside the specified range might fail, as it simply checks what the inputted number is: it doesn't cover unnecessary dates

Not only is this my first challenge with stackylogic, but the first challenge with stackylogic at all.

Get ready for this mess:

1
0
1?
010
1?0
010
1?10
?1010
001010
?1010
?1010
?010
?10
?0
0
?
110
?10
11010
?010
11010
?1010
001010
?1010
?1010
?1010
?1010
?010
?0
110
?10
11010
?010
1010
01010
01010
?010
?0
110
?0
110
?0
110
1?0
?10
0?10
?10
?0
01
?
?<
0

This took me so long to make, because Stackylogic is the most confusing language I have encountered, and extremely unreadable: you have to know how the rest of the program has executed before you can read the current section being edited. I even had to add spaces for readability while creating it.

Meagre explanation

This is a simple explanation of what it does.

Stackylogic does not have any mathematical functions, so that made this harder. I had to hardcode most of it, to check if it was a specific number.

First, this program will do a NOR of the least significant bits, discarding them in the process. this means that if it is divisible by 4, it will proceed to the main part of the program, otherwise output 0.

Second, the pointer is carried over to the labyrinth of stackylogic, from here, if the next two bits are zero, it will instantly output 1 (as then it is divisible by 16, and so a leap year despite any other conditions), other wise it will check if it is not any of the numbers that is divisible by 4 but not a leap year, between 1801 and 2400.

To explain in detail, would involve making this post many times longer than it already is

W d, 10 8 bytes

Ö♦Ç⌂╬`§Γ

Explanation:

Uncompressed:

25m4&16|m!
25m        % If the input is modulo-able by 25:
   4&      % Return 4
     16|   % Otherwise, return 16
        m! % Modulo input by the value. Negate the value.

Reg, 14 bytes

1¿:%[4|]%[;]

Try it online!

How it works (because it contains unprintable characters)

PHP, 35 34 bytes

-1 byte thanks to 640KB

<?=date(L,strtotime($argv[1].-1));

Try it online!

Came across the L option in the PHP date formatter, which returns if the year of the date is a leap year. After that, it was just a matter of trying to get the timestamp of the year in the shortest way (though I'm not too confident this is the shortest)

Haskell, 19 bytes

f i=gcd 80i>gcd 50i

Try it online!

Haskell, 43 41 39 bytes

l x=mod x(if mod x 25<1then 16else 4)<1

If x is divisible by 25, check if it is also divisible by 16, making it divisible by the least common multiple of 25 and 16, which is 400.
If x is not divisible by 25, check if it is divisible by 4.

Inspired by @David Hammen's answer in JavaScript.

Swift, 82 bytes

func l(y:Int){y%4==0 && (y%100 != 0 || y%400==0) ?print("Y"):print("N")}
l(y:1936)

Try it online!

Haskell, 35 bytes

l x|x!25<1=x!16<1
l x=x!4<1
(!)=mod

Try it online!

Japt -h!, 8 bytes

Input is taken as a string.

k0 ò o%4

Try it online!

Java 8, 49 45 22 20 bytes

n->n%(n%25<1?16:4)<1

-2 bytes thanks to @OlivierGrégoire.

Try it online.

Some 22 bytes solutions:

n->n%25<1?n%16<1:n%4<1

Try it online.

n->(n%25<1?n%16:n%4)<1

Try it online.

java.time.Year::isLeap

Try it online.

Explanation:

n->                // Method with integer parameter and boolean return-type
   n%          <1  //  Return whether the integer is divisible by:
     (n%25<1?      //   If the input is divisible by 25:
             16    //    Check if its divisible by 16
            :      //   Else:
             4)    //    Check if its divisible by 4 instead

JavaScript, 19 bytes

y=>!(y%25?y%4:y%16)

Try it online!

T-SQL 37 22 bytes

Saved 15 bytes thanks to BradC's comment.

The usual hardcoded variable for lack of a stdin.

e.g.

DECLARE @ NVARCHAR(4) = '2016'

Then the solution is:

PRINT ISDATE(@+'0229')

Clam, 33 31 bytes

=a*rp|e%a*"400"0&%a*"100"e%a*40

Try it online!

-2 bytes thanks to ASCII-only

Outputs true for leap years. Outputs false for other years

Explanation

=a*rp|e%a*"400"0&%a*"100"e%a*40
=a*r                             read input and store in a*
    p                            Print..
       %a*"400"                    a* % 400
      e                            ==
               0                   0
     |                             OR
                 %a*"100"            a* % 100
                &                    AND
                          %a*4       a* % 4
                         e           ==
                              0      0

Very awkward explanation, but basically what it does is this:

print(year % 400 == 0 || (year % 100 && year % 4 == 0))

Clam follows JS rules for truthy and falsey values, meaning year % 100 is true if it does not equal 0 (and it's shorter than adding an e before it and an 0 after it)

Resulting JS:

myVar = read();
console.log(year % 400 == 0 || (year % 100 && year % 4 == 0));

MathGolf, 9 bytes

4♀`*]÷~≤*

Try it online!

Explanation

4         Push 4
 ♀        Push 100
  `*      Duplicate top two elements of stack and multiply (400)
    ]     Wrap stack in array ([4, 100, 400])
     ÷    Check input for divisibility with all array items
      ~   Dump array onto stack
       ≤  Check if divisibility by 100 is <= than divisibility with 400
        * Multiply with the divisibility bool for 4, works like logical and

The trick is that ensures that if a number is divisible by 100, it must also be divisible by 400, but if it's not divisible by 100, anything goes.

Common Lisp, 46 bytes

(=(mod(setq x(read))(if(>(mod x 25)0)4 16))0)

Try it online!

Based on the David Hammen’s method.

APL, 16 14 12 characters

Returns 0 for a leap year, 1 for a non-leap year.

≥/⌽×4 25 4⊤⎕

Try this solution on tryapl.org. Note that I have changed the solution to the dfn {≥/⌽×4 25 4⊤⍵} as tryapl.com does not support (take user input). Note that is an empty box, not a missing character.

The same solution in J:

4 25 4>:/@|.@:*@#:]

Explanation

Dyadic (encode) represents its right argument in the base specified by its left argument. I use base 4 25 4 in this solution. This represents the year y as a polynomial

y mod 400 = 100 a + 4 b + c where b < 100 and c < 4.

Let propositions α, β, and γ represent if a, b, and c are non-zero: Proposition γ is false if y is dividable by 4, βγ is false if y is dividable by 100 and αβγ is false if y is dividable by 400.

A truth table (* representing “don't care”) were proposition Δ represents if y is a leap-year obtains:

α β γ | Δ
0 0 0 | 1
1 0 0 | 0
* 1 0 | 1
* * 1 | 0

The following statement expresses Δ in α, β, and γ:

Δ = ¬((αβ) → γ)).

Due to the structure of this statement, one can express ¬Δ as the reduction ≥/⌽α β γ where ≥ implements ←. This leads to the answer I am explaining right now.

C (gcc), 33 bytes

f(i,a){a=!(i%4|!(i%100)&&i%400);}

Try it online!

Jelly, 7 bytes

ọ4,25>/

Try it online!

How it works

ọ4,25>/  Main link. Argument: n (1801 - 2400)

ọ4,25    Test how many times n is divisible by 4 and 25.
     >/  Verify that the order of 4 is higher than the order of 25.

Kotlin, 30 bytes

{it%4<1&&(it%100>0||it%400>0)}

Try it online!

Javascript (ES6), 21 characters

The standard rule is that y is a leap year if 4 divides y and if either 100 doesn't divide y or 400 does divide y. In code,

y%4 == 0 && (y%100 != 0 || y%400 == 0)

There's no need for that 100 and 400. Instead it suffices to check whether 16 or 4 divides y, with 16 chosen if 25 divides y, 4 otherwise. Golfed, this becomes

!(y%(y%25?4:16))

A javascript function that implements this is 21 characters long:

l=y=>!(y%(y%25?4:16))


Perl, 28 26 characters

Same idea, but in perl.

$_=$_%($_%25?4:16)?"n":"y"

Run using the -lp options. For example,

perl -lpe '$_=$_%($_%25?4:16)?"n":"y"'

With the test set as input, this produces

1936
y
1805
n
1900
n
2272
y
2400
y

C++, 50 43 bytes

-7 bytes thanks to Zacharý

int l(int y){return!(y%4)&&y%100+!(y%400);}

And the test code is :

auto t = {
    1936,1805,1900,2272,2400
};

for (auto&a : t) {
    std::cout << "Year : " << a << " is " << (l(a) ? "" : "NOT") << " a leap year\n";
}

D, 43 42 bytes

T l(T)(T y){return!(y%4)&&y%100+!(y%400);}

Try it online!

Another port of @HatsuPointerKun's C++ answer.

Ruby, 22 bytes

->n{1>n%(n%25<1?16:4)}

Try it online!

The challenge is quite old, but I noticed there was no valid Ruby answer yet. Nothing particularly original, anyway.

ActionScript 2.0, 49 bytes

function a(b){trace(!(b%4)&&b%100+!(b%400)?1:0);}
function a(b){                                  } - define a function
              trace(                          );  - that outputs
                                          ?       - if
                    !(b%4)                        - the input divides by 4
                          &&                      - and
                            b%100                 - doesn't divide by 100
                                 +                - plus
                                  !(b%400)        - does divide by 400
                                           1:0    - 1, else 0

Not a very good explanation, and I might have swapped some stuff, but this still confuses me, so this is the best you're going to get.

Whitespace, 103 bytes

[S S S N
_Push_0][S N
S _Duplicate_0][S N
S _Duplicate_0][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve][S N
S _Duplicate_input][S S S T T   S S T   N
_Push_25][T S T T   _Modulo][N
T   S T N
_If_0_jump_to_Label_TRUE][S S S T   S S N
_Push_4][T  S T T   _Modulo][N
T   S S N
_If_0_jump_to_Label_LEAP][N
S N
N
_Jump_to_Label_PRINT][N
S S T   N
_Create_Label_TRUE][S S S T S S S S N
_Push_16][T S T T   _Modulo][N
T   S S N
_If_0_jump_to_Label_LEAP][N
S N
N
_Jump_to_Label_PRINT][N
S S S N
_Create_Label_LEAP][S S S T N
_Push_1][N
S S N
_Create_Label_PRINT][T  N
S T _Print_as_integer]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Explanation in pseudo-code:

Integer i = STDIN-input as integer
If i modulo-25 is 0:
  If i modulo-16 is 0:
    Print 1
  Else:
    Print 0
Else-if i modulo-4 is 0:
  Print 1
Else:
  Print 0

Example runs:

Input: 1936

Command     Explanation                Stack            Heap       STDIN    STDOUT   STDERR

SSSN        Push 0                     [0]              {}
SNS         Duplicate top (0)          [0,0]            {}
SNS         Duplicate top (0)          [0,0,0]          {}
TNTT        Read STDIN as integer      [0,0]            {0:1936}   1936
TTT         Retrieve at heap 0         [0,1936]         {0:1936}
SNS         Duplicate top (1936)       [1936,1936]      {0:1936}
SSSTTSSTN   Push 25                    [1936,1936,25]   {0:1936}
TSTT        Modulo                     [1936,11]        {0:1936}
NTSTN       If 0: Jump to Label_TRUE   [1936]           {0:1936}
SSSTSSN     Push 4                     [1936,4]         {0:1936}
TSTT        Modulo                     [0]              {0:1936}
NTSSN       if 0: Jump to Label_LEAP   []               {0:1936}
NSSSN       Create Label_LEAP          []               {0:1936}
SSSTN       Push 1                     [1]              {0:1936}
NSSN        Create Label_PRINT         [1]              {0:1936}
TNST        Print top as integer       []               {0:1936}            1
                                                                                     error

Program stops with an error: No exit defined.
Try it online (with raw spaces, tabs and new-lines only).

Input: 2400

Command     Explanation                Stack            Heap       STDIN    STDOUT   STDERR

SSSN        Push 0                     [0]              {}
SNS         Duplicate top (0)          [0,0]            {}
SNS         Duplicate top (0)          [0,0,0]          {}
TNTT        Read STDIN as integer      [0,0]            {0:2400}   2400
TTT         Retrieve at heap 0         [0,2400]         {0:2400}
SNS         Duplicate top (2400)       [2400,2400]      {0:2400}
SSSTTSSTN   Push 25                    [2400,2400,25]   {0:2400}
TSTT        Modulo                     [2400,0]         {0:2400}
NTSTN       If 0: Jump to Label_TRUE   [2400]           {0:2400}
NSSTN       Create Label_TRUE          [2400]           {0:2400}
SSSTSSSSN   Push 16                    [2400,16]        {0:2400}
TSTT        Modulo                     [0]              {0:2400}
NTSSN       If 0: Jump to Label_LEAP   []               {0:2400}
NSSSN       Create Label_LEAP          []               {0:2400}
SSSTN       Push 1                     [1]              {0:2400}
NSSN        Create Label_PRINT         [1]              {0:2400}
TNST        Print top as integer       []               {0:2400}            1
                                                                                     error

Program stops with an error: No exit defined.
Try it online (with raw spaces, tabs and new-lines only).

Input: 1991

Command     Explanation                Stack            Heap       STDIN    STDOUT   STDERR

SSSN        Push 0                     [0]              {}
SNS         Duplicate top (0)          [0,0]            {}
SNS         Duplicate top (0)          [0,0,0]          {}
TNTT        Read STDIN as integer      [0,0]            {0:1991}   1991
TTT         Retrieve at heap 0         [0,1991]         {0:1991}
SNS         Duplicate top (1991)       [0,1991,1991]    {0:1991}
SSSTTSSTN   Push 25                    [0,1991,1991,25] {0:1991}
TSTT        Modulo                     [0,1991,16]      {0:1991}
NTSTN       If 0: Jump to Label_TRUE   [0,1991]         {0:1991}
SSSTSSN     Push 4                     [0,1991,4]       {0:1991}
TSTT        Modulo                     [0,3]            {0:1991}
NTSSN       if 0: Jump to Label_LEAP   [0]              {0:1991}
NSSN        Create Label_PRINT         [0]              {0:1991}
TNST        Print top as integer       []               {0:1991}            0
                                                                                     error

Program stops with an error: No exit defined.
Try it online (with raw spaces, tabs and new-lines only).

Bash, 14 bytes

date -d$1/2/29

Try it online!

Outputs via exit code, 0 for leap year and 1 otherwise.

date -d STRING will display the date indicated by STRING. $1/2/29 represents February 29th of $1, the argument. If STRING is not valid, i.e. Feb 29 does not exist, then date errors out.

MATLAB + Aerospace Toolbox, 9 bytes

@leapyear

Anonymous function that determines if the passed year is a leap year, returning 1 for leap and 0 for not.

Ok so MATLAB has a built-in... But there we are.


Octave, 13 bytes

@is_leap_year

Try it online!

Octave also has a built-in... cost's 4 more bytes than MATLAB though.

Jelly, 8 bytes

ȷ2*ḍ¥×4ḍ

Try it online!

PHP, 34 30 bytes

echo+!($argn%($argn%25?4:16));

I'm using the + sign to convert false (which would normally be converted to an empty string) to 0, because that seems to comply closer to the "clearness" requirement (maybe not?). With standard truthy/falsy rules, 1 byte can be saved.

Note: I shamelessly implemented the divisibility by 25 trick from @David Hammen. Without his algorithm it would be 37 bytes:

<?=+!(($b=$argv[1])%400^$b%100^$b%4);

Run like this:

echo 1900 | php -nR 'echo+!($argn%($argn%25?4:16));';echo

Tweaks

SmileBASIC, 40 bytes

INPUT Y?0DTREAD STR$(Y)+"/02/29"OUT,,,?1

Prints 0 1 if it's a leap year, otherwise prints 0 and errors.

DTREAD parses a date string in the form of YYYY/MM/DD and gives the year, month, and day. It can also return the day of the week, and trying to get the day of the week of a day that doesn't exist (Feb. 29 of a non-leap year) will cause an error.

This is shorter than the obvious answer using mod, because SB uses MOD instead of %, which takes up 3-5 characters.

PHP, 28 bytes

Why calculate when there´s a builtin?

<?=checkdate(2,29,$argv[1]);

prints 1 for leap year, empty string for no leap year.
Add + after <?= for 1/0.

PHP, 45 bytes

<?=date_create($argv[1].'-1-1')->format('L');

Not the shortest, but using built in functions. Totally not code-golf.

C, 37 34 30 bytes

l(y){y=y%(y%25?4:16)?110:121;}

Wandbox

Mathematica, 15 bytes

LeapYearQ@*List

Mathematica has a built-in for everything. List is there to make the integer input into a compact DateList object. Returns True or False.

Retina, 24 bytes

[^04]00$

.+
$*
....

^$

Try it online!

C, 81

I can do shorter, but this one neatly sticks to 'char' types, without parsing the argument (e.g. with atoi):

main(c,v)char**v;{char*p=*v+9;p-=2*(96==*p+p[1]);putchar("ynnn"[(2**p^p[1])&3]);}

It must be invoked with a name 4 characters long, because it makes the standard assumption that arguments immediately follow the program name, separated by NULs. Furthermore, it assumes that the single argument is encoded in ASCII and has no leading space.

Explanation:

main(c,v)
char**v;
{
    char *p = *v+9;
    if (p[0] + p[1] == '0'+'0')
        p -= 2;
    putchar("ynnn"[((*p << 1) ^ p[1])&3]);
}

*v+9 is the position of the 'tens' digit in v[1]+2.

If the 'tens' and 'units' characters add to 96, we end in 00, so back up two characters, so that 'tens' and 'units' point to the century number.

Now xor 'units' with twice the 'tens', mod 4. This works because 10==±2 mod 4, so the lower bit of the 'tens' can just toggle bit 1 of the 'units'. We use the result as an index into our remainders table, printing y only if the modular result is zero.

BASH, 68 bytes

((!(y % 4) && ( y % 100 || !(y % 400)))) &&  echo "leap" || echo "no"

C#, 23 bytes

y=>y%25<1?y%16<1:y%4<1;

Try it online!

Full source, including test cases:

using System;

namespace CountingLeapYears
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int,bool>s=y=>y%25<1?y%16<1:y%4<1;
            Console.WriteLine(s(1936)); //y
            Console.WriteLine(s(1805)); //n
            Console.WriteLine(s(1900)); //n
            Console.WriteLine(s(2272)); //y
            Console.WriteLine(s(2400)); //y
        }
    }
}

LOLCODE, 228 202 159 bytes

HOW IZ I f YR a
MOD OF a AN 100
O RLY?
YA RLY
MOD OF a AN 4
O RLY?
YA RLY
b R 1
OIC
NO WAI
MOD OF a AN 400
O RLY?
YA RLY
b R 0
NO WAI
b R 1
OIC
OIC
IF U SAY SO

Ungolfed:

HAI 1.3 BTW "HAI" does nothing functionally in current versions and does not throw an error if you omit it.
HOW IZ I leap YR input
    I HAS A output
    DIFFRINT MOD OF input AN 100 AN 0 BTW Thanks @LeakyNun, In LOLCODE any non-empty values, i.e. 0, "", etc. default to WIN.
    O RLY?
        YA RLY
            BOTH SAEM MOD OF a AN 4 AN 0
            O RLY?
                YA RLY
                    output R WIN BTW "WIN" is true, but in the actual program I used 1 as a truthy value because it's shorter.
            OIC
        NO WAI
            DIFFRINT MOD OF a AN 400 AN 0
            O RLY?
                YA RLY
                    output R FAIL BTW "Fail" is false, but in the actual program I used 0 as a falsy value.
                NO WAI
                    output R WIN
            OIC
    OIC
    FOUND YR output BTW This statement is implied in the golfed version.
IF U SAY SO BTW "KTHXBYE", just like "HAI" has no functional purpose and throws no error on omission.
KTHXBYE

In Python ungolfed, because LOLCODE is confusing:

def leap:
    if(year % 100 != 0):
        if(year % 4 == 0):
            output = true
    else:
        if(year % 400 != 0):
            output = false
        else:
            output = true
    return(output)

PowerShell, 31 bytes

I am excited to say that I golfed this shorter than the builtin!

param($a)!($a%(4,16)[!($a%25)])

Outputs true for leap years and false otherwise.

Builtin:

[datetime]::IsLeapYear($args[0])

Though, if I wanted to stretch the statement 'clearly tells the user if it is or isn't a leap year' and do something non-standard, I could save 3 bytes and use:

param($a)$a%(4,16)[!($a%25)]

This outputs 0 for leap years and 1 or higher for non-leap years, which I don't like since I'd prefer to return a more standard truthy value for leap years.

C#, 26 bytes

y=>DateTime.IsLeapYear(y);

C# lambda (Predicate) where the input is a int and the output is a bool. I use a builtin.

Python, 50 48 bytes

import calendar as y
def a(b):print(y.isleap(b))

Python, 37 bytes

def c(s):return s%16*(s%25<1)<(s%4<1)

Pyth, 11 bytes

!%|F_jQ*TT4

This full program read from STDIN and prints True for leap years and False otherwise.

Thanks to @Jakube for suggesting Pyth and basically porting my CJam code.

Verify the test cases yourself in the Pyth Compiler/Executor.

How it works

     jQ*TT   Returns the evaluated input in base 10 × 10.
  |F_        Swaps the digit order and reduces using logical OR.
             So far, we've achieved 1954 -> [19, 54] -> 54 || 19.
!%        4  Returns the logical NOT of the result modulo 4.
             This prints True for multiples of 4 and False otherwise.

CJam, 12 bytes

rS+2m<~e|4%!

This full program read from STDIN and prints 1 for leap years and 0 otherwise.

Verify the test cases yourself in the CJam interpreter.

How it works

r   e# Read from STDIN.
S+  e# Append a space.
2m< e# Rotate two characters to the left.
~   e# Evaluate.
    e# So far, we achieved "1954" -> "54 19" -> 54 19.
e|  e# Logical OR; keep the leftmost non-zero integer.
4%! e# Logical NOT of the kept integer modulo 4.
    e# This pushes 1 for multiples of 4 and 0 otherwise.

PHP - 45 bytes

$b=$argv[1]%400;echo !$b|!($b%4)&!!($b%100);

Nothing that special really, just abusing type-juggling.

IBM System Z assembler - 56 bytes.

(96 bytes of source. Previously 712 384 202 bytes of source, 168 byte executable).

Smaller version still. No longer saves caller's registers, changes to literal storage, changed addressing mode.

 l        CSECT      
         using l,15 
         l  5,y     
         n 5,f      
         bnz r      
         xr 4,4     
         l 5,y      
         d 4,c      
         ch 4,i     
         bne i      
         n 5,f      
         bnz r      
i        dc h'0'    
r        b  *       
y        dc f'2004' 
f        dc f'3'    
c        dc f'100'  
         end 

New version. This will ABEND with a S0C1 if it's a leap year, and loop if it isn't. Hopefully that fulfils the requirement of indicating the result.

l        CSECT             
         ASMDREG           
         SYSSTATE archlvl=2
         IEABRCX  DEFINE   
         save  (14,12)     
         larl  r9,s        
         using s,r9        
         st 13,w+4         
         la 13,w           
         st 13,w+8         
         la 5,2004         
         st 5,y            
         n 5,=f'3'         
         bnz r             
         xr r4,r4          
         l 5,y             
         d r4,=f'100'      
         ch r4,=h'0'       
         bne i             
         n 5,=f'3'         
         bnz r             
i        dc h'0'           
r        b  0              
s        dc 0d'0'          
y        ds f              
w        ds 18f            
         ltorg             
         end  

OK, so not the shortest (although it might be once we look at the actual executed code plus the interpreter size...)

leapyear CSECT                                                
         ASMDREG                                              
         SYSSTATE archlvl=2                                   
         IEABRCX  DEFINE                                      

         save  (14,12)                                        

         larl  r9,staticArea                                  
         using staticArea,r9                                  
         st r13,w_savea+4       .Save callers savearea        
         la r13,w_savea         .Address my savearea          
         st r13,w_savea+8         . and save it               

         open  (O,OUTPUT)             .open file              

         la r5,1936             .r5 = input year              
         st r5,years            .Save year                    

         cvd r5,double          .Convert year to p-decimal    
         mvc edarea,=xl8'4020202020202120' .Move in edit mask 
         ed edarea,double+4      .Make packed decimal year printable                              
         mvc outrec(4),edarea+4  .Move year string to output area                             
         bas r10,isitleap       .Call leap year routine       

         close (O)              .Close files            
         b return               .Branch to finish

isitleap ds 0h                                                      
         mvi outrec+5,c'N'      .Set default value                                   
         n r5,=f'3'             .Are last 2 bits 0 (Divisible by 4)?
         bnz notleap            .No - not leap                      
         xr r4,r4               .Clear R4                           
         l r5,years             .Reload r5 with year                
         d r4,=f'100'           .divide r4/r5 pair by 100           
         ch r4,=h'0'            .Remainder 0?                       
         bne isleap             .No - leap year                     
         n r5,=f'3'             .Quotient divisible by 4?           
         bnz notleap            .No - not leap                      

isleap   ds    0h                                                   
         mvi outrec+5,c'Y'      .Move in leap year indicator                                    

notleap  ds    0h                                                   
         put O,outrec           .Print output record                                    
         br r10                 .Return to caller                   

* Program termination                                               
return   ds 0h                                                      
         l r13,w_savea+4         .Restore callers savearea          
         return (14,12),,rc=0    .Restore registers and return    
* storage areas                                                     
staticarea  dc 0d'0'                                                
outrec      ds cl10                                                 
years       ds f                                                    
w_savea     ds 18f                save area                         
edarea      ds cl8                    .edit area                    
double      ds d                                                    
* Macros and literals                                               
         print nogen                                                
O        dcb   recfm=F,lrecl=6,dsorg=PS,ddname=O,macrf=PM           
         print gen                                                  
*                                                                   
         ltorg                         literal storage              
         end  

Output:

ABEND S0C1 for a leap year, S222 (when the CPU time has run out) if not.

1936 Y 1805 N 1900 N 2272 Y 2400 Y

(when run multiple times)

TI-BASIC, 20 17 16 13

Because it is tokenized, TI-BASIC is often competitive at simple math challenges, but not this one since there is no "divisible" command. Maybe it is after all, but this is still longer than CJam and Pyth.

This uses David Hammond's method.

not(fPart(Ans/4/4^not(fPart(sub(Ans

Old code at 16 bytes:

not(fPart(Ans/16not(fPart(sub(Ansnot(fPart(Ans/4

Ungolfed:

not(fPart(Ans/16) and not(fPart(Ans/100) and not(fPart(Ans/4))))

fPart( is "fractional part"; exponentiation has higher precedence than division. In TI-BASIC, close-parens are optional.

I use undocumented behavior of the sub( command, usually used to get a substring: when its argument is a number instead of a string, it divides the number by 100. It will work on a TI-83 or 84 series calculator.

20 -> 17 by rearranging code to allow removal of close-parens; 17 -> 16 by replacing 400 with 16; 16 -> 13 by using David Hammond's idea.

JavaScript (ES6) 27

The rule: (y%4==0) && (y%100!=0 || y%400==0)

Golfed: !(y%100<1&&y%400||y%4) (mainly using De Morgans's law)

A function implementing the rule:

l=y=>!(y%100<1&&y%400||y%4)

A test (run in Firefox) just to be sure:

l=y=>!(y%100<1&&y%400||y%4)

for(o=[],i=0;i<700;i++)
  y=i+1800,
  x=l(y),
  o[i/100|0]=(o[i/100|0]||'')+y+(x?' <b>Y</b>':' <i>N</i>')+'\n'
    
R.innerHTML='<td>'+o.join('</td><td>')+'</td>'
console.log(o[1])
td { white-space: pre; font-family: monospace; padding: 8px}

b { color: red; }
i { color: blue; }
<table>
  <tr id=R></tr>
</table>

C, 57 bytes

Takes the input from stdin, with or without trailing spaces/newline. Only works on little endian machines (yeah, like everyone is on BE these days). Outputs Y or N.

main(y){scanf("%d",&y);y=y%(y%100?4:400)?78:89;puts(&y);}

Explanation

Ungolfed:

int main(int y) {
   scanf("%d", &y);
   y = y % (y % 100 ? 4 : 400) ? 'N' : 'Y';
   puts(&y);
}

First, scanf reads the year as an integer in y. Then, y is modulo'ed with 4 or 400 depending on whether the year is divisible by 100. If the remainder is zero, the ASCII code for Y is assigned to y, otherwise it gets the ASCII code for N. The value of y is now 0x000000??, where 0x?? is the assigned character. Being on a little-endian machine, in memory this is stored as ?? 00 00 00. This is a NULL-terminated C string, containing only the assigned characters. The address of y is passed to puts and the char is printed (with a trailing newline).

Regex, 83 62 38

Thanks to Toby for tips about combining both halves of the regex.

If we focus on 1801..2400 range only and assume input are integers:

(?!00)([02468][048]|[13579][26])(00)?$

Test in Ruby (^ = \A and $ = \Z because Ruby) for the desired range:

r = /(?!00)([02468][048]|[13579][26])(00)?\Z/
(1801..2401).each do |year|
  leap = year % 4 == 0 && ((year % 100 != 0) || (year % 400 == 0))
  leap_regex = !year.to_s[r].nil?
  if leap != leap_regex
    print 'Assertion broken:', year, " ", leap, " ", leap_regex, "\n"
  end
end

(Bonus) for something that should work not only for 1801..2400, but for any non-negative year:

^\d*(0000|(?!00)([13579][26]|(^|[02468])[048])(00)?)$

Test in Ruby (^ = \A and $ = \Z because Ruby) for first 100000 years:

r = /\A\d*(0000|(?!00)([13579][26]|(\A|[02468])[048])(00)?)\Z/
100000.times do |year|
  leap = year % 4 == 0 && ((year % 100 != 0) || (year % 400 == 0))
  leap_regex = !year.to_s[r].nil?
  if leap != leap_regex
    print 'Assertion broken:', year, " ", leap, " ", leap_regex, "\n"
  end
end

Julia, 30 28 bytes

y->(y%4<1&&y%100>0)||y%400<1

This creates an unnamed function that accepts an integer argument and returns a boolean value. To call it, give it a name, e.g. f=y->....

Ungolfed:

function f(y)
    (y % 4 == 0 && y % 100 != 0) || y % 400 == 0
end

Example:

julia> for y in [1936, 1805, 1900, 2272, 2400] println(f(y)) end
true
false
false
true
true
true

R, 29

!(Y=scan())%%4&Y%%100|!Y%%400

Test run

> !(Y=scan())%%4&Y%%100|!Y%%400
1: 1936
2: 1805
3: 1900
4: 2272
5: 2400
6: 2200
7: 
Read 6 items
[1]  TRUE FALSE FALSE  TRUE  TRUE FALSE

sed, 55

s/00$//
y/0123456789/yNnNyNnNyN/
/N.$/y/ny/yn/
s/.\B//g

Note that non-leap years may be printed as n or N depending on whether they are even or odd. I consider this a creative interpretation of the rule which allows alternatives to 'yes' and 'no' without specifying that they have to be consistent.

Befunge-98, (41 bytes)

&:4%#v_:aa*%#v_28*%|
"y",;<;@,"n";>;  ;#[

Simplicity is awesome.

SpecBAS - 77

Not the shortest (but not the longest either).

1 INPUT y: PRINT y;"->";"ny"((y MOD 4=0 AND (y MOD 100<>0) OR y MOD 400=0)+1)

Uses the standard formula, then prints "n" or "y" based on return value (the final +1 at the end is due to strings being 1-based).

KDB(Q), 27 bytes

{0=x mod(4 400)0=x mod 100}

Explanation

               0=x mod 100      / boolean of 100 divisibility
        (4 400)                 / 0b -> 4, 1b -> 400
 0=x mod                        / boolean of 4/400 divisibility
{                         }     / lambda

Test

q){0=x mod(4 400)0=x mod 100}1936 1805 1900 2272 2400
10011b

Javascript ES6, 32, 29, 26

Any of following lines works:

f=y=>new Date(y,2,0).getDate()&1
g=y=>!(y&3)^!(y%100)>!(y%400)
h=y=>!(y&3|y%100<1&&y%400)

Pyth, 19 15 14 bytes

xFm!%Q^d2[2TyT

Way too easy. Try it online: Demonstration or Test harness

edit: Missed, that you can print Truthy/Falsy values, instead of n/y. -4 byte

edit 2: Used the square root idea of Martin. -1 byte

Explanation

                 implicit: Q = input number
         [         generate a list with the numbers:
          2          2
           T         10
            yT       2*10 = 20
  m              map each number d to:
   !%Q^d2          not(Q mod d^2) // True if Q % d^2 == 0 otherwise False
xF               fold by xor

Pip, 13 bytes

This one was more interesting than it at first appeared. It took some finagling, but I was finally able to replace those lengthy references to 400 with 4 and the h variable (=100).

!(a%h?aa/h)%4

Outputs 1 for leap year, 0 for non-leap year. Explanation:

               a is command-line argument (implicit)
  a%h?aa/h     If a is divisible by 100, divide it by 100; otherwise, leave it alone
 (        )%4  The result mod 4 is 0 if it's a leap year, nonzero otherwise
!              Negate and (implicitly) print

Mathematica, 40 27 bytes, 17 chars

#∣4∧(#∣100<U+F523>#∣400)

Uses 17 chars, but 27 bytes. Thanks to @alephalpha for the tip. Note that the vertical bars are actually U+2223 for divides. The <U+F523> should be replaced with the corresponding character.

CJam, 18 16 bytes

q~[YAK]f{2#%!}:^

Gives 1 (truthy) for leap years and 0 (falsy) otherwise.

Run all test cases here.

Explanation

q~                 e# Read and eval input.
  [YAK]            e# Push an array containing 2, 10, 20 (the square roots of the
                   e# relevant divisors).
       f{    }     e# Map this block onto that array, also passing in the input year.
         2#        e# Square the divisor.
           %!      e# Modulo followed by logical negation. Gives 1 if the year is divisible
                   e# by the given divisor and 0 otherwise.
                   e# At this point we have one of the following arrays:
                   e#   [0 0 0] - not a leap year
                   e#   [1 0 0] - a leap year
                   e#   [1 1 0] - not a leap year
                   e#   [1 1 1] - a leap year
              :^   e# Reduce XOR onto this array, which gives 1 if there is an odd number
                   e# of 1s and 0 if there's an even number.