Skip to content

2020.01.06

Leap year Source: adopted from here

Introduction

Year 2020 is a leap year. The algorithm to determine whether a year is leap year is as follows:

Definition of Leap Year

Every year that is exactly divisible by four is a leap year, except for years that are exactly divisible by 100, but these centurial years are leap years if they are exactly divisible by 400.

For example, the years 1800 and 1900 were not leap years, but the years 2000 and 2020 were.

Question

Write a function isLeapYear to determine whether a given year is leap year.

isLeapYear 1800 / 0b
isLeapYear 1900 / 0b
isLeapYear 2000 / 1b
isLeapYear 2020 / 1b

Answer

The following implementation of isLeapYear is borrowed from the official documentation side of Kx Systems.

isLeapYear:{mod[;2] sum 0=x mod\: 4 100 400};
isLeapYear 1800 / 0b
isLeapYear 1900 / 0b
isLeapYear 2000 / 1b
isLeapYear 2020 / 1b

Detailed explanations on above implementation:

  • For any given year x, calculate the remainder of x divided by 4, 100 and 400, respectively.
x mod\: 4 100 400
  • This gives a boolean to indicate whether the year x is exactly divisible by 4, 100 and 400, respectively.
0=x mod\: 4 100 400
  • It shows x is exactly divisible by how many numbers among 4, 100 and 400. The result has a range of 0 to 3.
sum 0=x mod\: 4 100 400
  • mod[;2] is a function projection, i.e. converting a two-parameter function to a single-parameter function. Let's define s:sum 0=x mod\: 4 100 400 and s has values from 0 to 3:

    • s=0: It means that x is exactly divisible by none of 4, 100 and 400. In this case, mod[;2] s is 0.
    • s=1: It means that x is only exactly divisible by 4. In this case, mod[;2] s is 1.
    • s=2: It means that x is only exactly divisible by 4 and 100. In this case, mod[;2] s is 0.
    • s=3: It means that x is exactly divisible by each of 4, 100 and 400. In this case, mod[;2] s is 1.

What a clever implementation!

Alternatives

  • Use vector operation and function application (the dot)
isLeapYear1:{{x;y;z} . 0=x mod\: 100 400 4};
  • This implementation is also very efficient but it is more like Python style
isLeapYear2:{$[0=x mod 100;0=x mod 400;0=x mod 4]};
  • Use vector operation and functional evaluation
isLeapYear3:{eval enlist[$],0=x mod\: 100 400 4};
  • Use logic operator
isLeapYear4:{(0=x mod 400)| (0=x mod 4) & (0=x mod 100)};

Performance

Use the following command to run each function 100000 times and record the running time:

\t:100000 func each 1800 1900 2000 2020
Function Run Time (ms)
isLeapYear1 348
isLeapYear2 390
isLeapYear3 398
isLeapYear4 563
isLeapYear 572