47
\$\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

The Catalogue

The Stack Snippet at the bottom of this post generates the catalogue from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

## [><>](https://esolangs.org/wiki/Fish), 121 bytes

/* Configuration */

var QUESTION_ID = 50798; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 8478; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });  
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];
  
  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });
    
    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });
    else console.log(body);
  });
  
  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;
    
    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    lang = jQuery('<a>'+lang+'</a>').text();
    
    languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang, user: a.user, size: a.size, link: a.link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang_raw.toLowerCase() > b.lang_raw.toLowerCase()) return 1;
    if (a.lang_raw.toLowerCase() < b.lang_raw.toLowerCase()) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body {
  text-align: left !important;
  display: block !important;
}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 500px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/all.css?v=ffb5d0584c5f">
<div id="language-list">
  <h2>Shortest Solution by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

\$\endgroup\$
5
  • 12
    \$\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\$ Commented May 26, 2015 at 11:34
  • \$\begingroup\$ Your input will have no newlines or trailing spaces. Dang it, that would have saved me 2 bytes... \$\endgroup\$
    – Dennis
    Commented May 26, 2015 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\$ Commented May 26, 2015 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
    Commented May 28, 2015 at 21:27
  • \$\begingroup\$ @lirtosiast I think so. A lot of user assume so. \$\endgroup\$
    – aloisdg
    Commented Jul 20, 2016 at 13:58

79 Answers 79

1 2
3
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
1
\$\begingroup\$

Reg, 14 bytes

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

Try it online!

How it works (because it contains unprintable characters)

\$\endgroup\$
2
  • \$\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
    Commented Aug 15, 2019 at 7:20
  • \$\begingroup\$ Okay. We have decided to rename "Unofficial Keg" as "Reg." \$\endgroup\$
    – user85052
    Commented Aug 15, 2019 at 7:33
1
\$\begingroup\$

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

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
\$\endgroup\$
7
  • \$\begingroup\$ You can do ÐUT91 Îv to output 1 for leap year and 0 for non-leap year. \$\endgroup\$
    – Oliver
    Commented Jan 8, 2019 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
    Commented Jan 8, 2019 at 18:05
  • \$\begingroup\$ @Oliver, found a shorter way. \$\endgroup\$
    – Shaggy
    Commented Jan 8, 2019 at 18:31
  • 1
    \$\begingroup\$ Every test case is returning false for me. \$\endgroup\$
    – Oliver
    Commented Jan 8, 2019 at 19:35
  • 1
    \$\begingroup\$ Why would a leap year be locale dependent? \$\endgroup\$
    – Oliver
    Commented Jan 8, 2019 at 19:41
1
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ 100 -> 'd, drop -> d>s, and some logic rearrangement gives 39 bytes. \$\endgroup\$
    – Bubbler
    Commented Nov 16, 2020 at 0:57
  • \$\begingroup\$ added it to the answer.. \$\endgroup\$
    – Razetime
    Commented Nov 16, 2020 at 2:03
1
\$\begingroup\$

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!

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

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.

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

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

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
\$\endgroup\$
3
  • \$\begingroup\$ -3 chars: %^4}!%25 \$\endgroup\$
    – naffetS
    Commented Nov 11, 2022 at 21:08
  • \$\begingroup\$ how does that work exactly? \$\endgroup\$
    – Seggan
    Commented Nov 11, 2022 at 21:43
  • \$\begingroup\$ n % 4^!(n%25) \$\endgroup\$
    – naffetS
    Commented Nov 12, 2022 at 0:02
1
\$\begingroup\$

Go, 47 bytes

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

Attempt This Online!

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

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

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.

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

C (gcc), 33 bytes

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

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript, 19 bytes

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

Try it online!

\$\endgroup\$
0
\$\begingroup\$

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!

\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
1 2
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.