41
\$\begingroup\$

This challenge is quite simple. You will take an input which will be a year from 1801 to 2400, and output if it is a leap year or not.

Your input will have no newlines or trailing spaces:

1954

You will output in any way that you like that clearly tells the user if it is or isn't a leap year (I will accept y or n for yes/no)

You can get a list of leap years here: http://kalender-365.de/leap-years.php I would note that leap years are not ever four years always. 1896 is a leap year, but 1900 is not. The years that follow this "skip" are:

1900
2100
2200
2300

Test cases:

1936 ->  y
1805 ->  n
1900 ->  n
2272 ->  y
2400 ->  y 

EDIT: This is based on a standard Gregorian calendar: http://www.epochconverter.com/date-and-time/daynumbers-by-year.php

\$\endgroup\$
  • 9
    \$\begingroup\$ You should be more clear: A given year is a leap year if and only if it is (divisible by 4)∧((divisible by 100)→(divisible by 400)). \$\endgroup\$ – LegionMammal978 May 26 '15 at 11:34
  • \$\begingroup\$ Your input will have no newlines or trailing spaces. Dang it, that would have saved me 2 bytes... \$\endgroup\$ – Dennis May 26 '15 at 17:10
  • 2
    \$\begingroup\$ You should extend the accepted input range to AD 1601 thru 2400. This covers two 400-year Gregorian cycles (which proleptically start on Monday). \$\endgroup\$ – David R Tribble May 26 '15 at 18:17
  • 2
    \$\begingroup\$ Does falsy if leap year and truthy if not a leap year count as "clearly tells the user if it is or isn't"? \$\endgroup\$ – lirtosiast May 28 '15 at 21:27
  • \$\begingroup\$ @lirtosiast I think so. A lot of user assume so. \$\endgroup\$ – aloisdg Jul 20 '16 at 13:58

68 Answers 68

2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ LeapYearQ@{#}& for 14 \$\endgroup\$ – attinat Aug 15 at 6:39
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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

  • Saved 4 bytes by using $argn
\$\endgroup\$
  • 1
    \$\begingroup\$ Save one more byte on standard truthy/falsy with <1 instead of !() \$\endgroup\$ – Titus Feb 2 '17 at 2:45
2
\$\begingroup\$

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.
\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ I don't know Haskell, but can ==0 be <1? \$\endgroup\$ – lirtosiast May 28 '15 at 21:13
  • \$\begingroup\$ You are right, it can. \$\endgroup\$ – AplusKminus May 29 '15 at 9:04
  • 1
    \$\begingroup\$ You can drop the spaces before then and else. \$\endgroup\$ – dfeuer Mar 1 at 7:38
  • 1
    \$\begingroup\$ The conditional can be equivalently expressed as (4+sum[12|mod x 25<1]) for a total of 33 bytes: Try it online! \$\endgroup\$ – Laikoni Mar 3 at 9:24
2
\$\begingroup\$

Excel, 30 bytes

David Hammen's method (A1 serves as input):

=MOD(A1,IF(MOD(A1,25),4,16))=0

Built-in functions can get you down to 23 bytes. However, this approach doesn't work on 1900 because of bug compatibility with Lotus 1-2-3:

=MONTH(DATE(A1,2,29))=2

You could even save two more bytes by using Portugese locale:

=MÊS(DATA(A1;2;29))=2
\$\endgroup\$
2
\$\begingroup\$

x86 machine code, 14 bytes

00000000: adfd ad2d 3030 74fa 86c4 d50a a803       ...-00t.......

Unassembled

AD         LODSW           ; SI += 2 to start with last two digits
FD         STD             ; set direction for LODSW to decrement
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   -6         ; if so, look at the first two digits instead
86 C4      XCHG AL, AH     ; endian convert
D5 0A      AAD             ; base convert from 10 to binary
A8 03      TEST AL, 3      ; mod 4 = 0?

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:

  • 1936: 36 mod 4 == 0
  • 2400: 24 mod 4 == 0

NOT leap year:

  • 1805: 05 mod 4 == 1
  • 1900: 19 mod 4 == 3

Test Program Output

LEAP.COM test output

Download and test LEAP.COM.

\$\endgroup\$
1
\$\begingroup\$

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).

\$\endgroup\$
  • \$\begingroup\$ I don't know the language, but based the fact that there are no booleans, you may be able to save some characters by using something like y MOD (4+12*(y MOD 100=0))=0. \$\endgroup\$ – lirtosiast May 28 '15 at 22:49
1
\$\begingroup\$

Python, 37 bytes

def c(s):return s%16*(s%25<1)<(s%4<1)
\$\endgroup\$
1
\$\begingroup\$

Python, 50 48 bytes

import calendar as y
def a(b):print(y.isleap(b))
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ You don't really need the lambda here, and I would argue the answer is more valid without it. \$\endgroup\$ – VisualMelon Jan 13 '17 at 9:26
  • \$\begingroup\$ @VisualMelon In the meta section, they ask for a function. (If I remember) \$\endgroup\$ – aloisdg Jan 14 '17 at 15:24
  • 4
    \$\begingroup\$ Aye, but DateTime.IsLeapYear is a function ;) generally the rule is that it has to evaluate to a function if it isn't named, and strictly your current submission is meaningless (join the argument here!), while System.DateTime.IsLeapYear is fully typed (System.Func<int,bool>A=System.DateTime.IsLeapYear compiles fine) without demanding any user inference (or indeed the text in your answer which specifies the input and output types). \$\endgroup\$ – VisualMelon Jan 14 '17 at 17:22
1
\$\begingroup\$

Java 8, 17 bytes

y->y%4<1&y%100>0;

It almost looks like a golfing language lol

\$\endgroup\$
  • \$\begingroup\$ Fails for input 2400... \$\endgroup\$ – Olivier Grégoire Jan 10 at 9:39
  • \$\begingroup\$ The last 3 years of my life has been a lie \$\endgroup\$ – Shaun Wild Jan 11 at 12:10
1
\$\begingroup\$

BASH, 68 bytes

((!(y % 4) && ( y % 100 || !(y % 400)))) &&  echo "leap" || echo "no"
\$\endgroup\$
1
\$\begingroup\$

Retina, 24 bytes

[^04]00$

.+
$*
....

^$

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PHP, 45 bytes

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

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

\$\endgroup\$
1
\$\begingroup\$

Jelly, 8 bytes

ȷ2*ḍ¥×4ḍ

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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";
}
\$\endgroup\$
  • \$\begingroup\$ You can make it int l(int y){return(y%4==0&&y%100)+(y%400==0);} to save a few bytes \$\endgroup\$ – Zacharý Mar 29 '18 at 13:49
  • \$\begingroup\$ I think making +(y%400==0) +!(y%400) might work as well. \$\endgroup\$ – Zacharý Apr 1 '18 at 18:54
  • \$\begingroup\$ int l(int y){return!(y%4)&&y%100+!(y%400);} \$\endgroup\$ – Zacharý Nov 10 '18 at 20:21
1
\$\begingroup\$

Kotlin, 30 bytes

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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));
\$\endgroup\$
  • \$\begingroup\$ ew 8552. use something nicer like 4545 pls \$\endgroup\$ – ASCII-only Jan 8 at 6:18
  • \$\begingroup\$ jk, 31 \$\endgroup\$ – ASCII-only Jan 8 at 6:19
  • \$\begingroup\$ also pls fix your indentation in the explanation :| \$\endgroup\$ – ASCII-only Jan 8 at 6:27
  • \$\begingroup\$ fixed that year % 100 thing \$\endgroup\$ – ASCII-only Jan 8 at 6:42
1
\$\begingroup\$

Japt -!, 8 5 bytes

Locale dependent.

ÐUT k

Try it

\$\endgroup\$
  • \$\begingroup\$ You can do ÐUT91 Îv to output 1 for leap year and 0 for non-leap year. \$\endgroup\$ – Oliver Jan 8 at 17:56
  • \$\begingroup\$ @Oliver, yeah, I suppose it would be clearer if I reversed the output. Updated. I came up with a few other similar alternatives, all relying on new Date rolling over. \$\endgroup\$ – Shaggy Jan 8 at 18:05
  • \$\begingroup\$ @Oliver, found a shorter way. \$\endgroup\$ – Shaggy Jan 8 at 18:31
  • 1
    \$\begingroup\$ Every test case is returning false for me. \$\endgroup\$ – Oliver Jan 8 at 19:35
  • 1
    \$\begingroup\$ Why would a leap year be locale dependent? \$\endgroup\$ – Oliver Jan 8 at 19:41
1
\$\begingroup\$

Japt -h!, 8 bytes

Input is taken as a string.

k0 ò o%4

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Haskell, 35 bytes

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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)

\$\endgroup\$
1
\$\begingroup\$

Reg, 14 bytes

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

Try it online!

How it works (because it contains unprintable characters)

\$\endgroup\$
  • \$\begingroup\$ Maybe leave a note as to why you've spelt it Reg when the link goes to Keg, so people like me don't think you've just made a typo. \$\endgroup\$ – Jo King Aug 15 at 7:20
  • \$\begingroup\$ Okay. We have decided to rename "Unofficial Keg" as "Reg." \$\endgroup\$ – A _ Aug 15 at 7:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy