0

Let's have a function called isLeapYear, it's arguments are a year. It must return true if the year is leap and false if it is not.

The conditions, as wikipedia states, are:

if year is not divisible by 4 then common year else if year is not divisible by 100 then leap year else if year is divisible by 400 then leap year else common year.

Can we define wether it is a leap year with just two conditions rather than three?

TZubiri
  • 886
  • 11
  • 30
  • 1
    @wavemode: Your assumption on Wikipedia is wrong. Wikipedia's primary goal is to be as clear and simple as possible to the average user (and not as efficient as possible for programmers to benefit from). – barak manos Apr 20 '14 at 23:51
  • Unless you have a programming language that only allows two conditions per function, it's hard to see the value of this question :-) – paxdiablo Apr 20 '14 at 23:51
  • @barak manos: I wasn't making any assumption about wikipedia, just pointing out that the section he cites is specifically written as a programmable algorithm, so it *most likely* uses the fewest possible conditions – wavemode Apr 21 '14 at 00:00
  • 4
    This question appears to be off-topic because it is about writing hacky code without practical reason. http://codegolf.stackexchange.com/ is good place for such a question. – Alexei Levenkov Apr 21 '14 at 00:01
  • @wavemode: Wikipedia could just as well state that if a year is not divisible by 4, or divisible by 100 but not by 400, then it's a common year. Otherwise it's a leap year. That would be equivalent to a single `if/else` (or "two conditions" as OP states). Wikipedia didn't do so, probably because it was easier to describe using `if` + `else if` + `else`. – barak manos Apr 21 '14 at 00:04

2 Answers2

3

Yes, if you consider the following as "two conditions":

If a year is not divisible by 4, or divisible by 100 but not by 400, then it's a common year.

Otherwise, it's a leap year.

Implemented in C, for example:

int IsCommon(int year)
{
    if (year%4 != 0 || (year%100 == 0 && year%400 != 0))
        return 1;
    else
        return 0;
}

Please note however, that in terms of runtime-performance, there is not much to gain here by "condensing" Wikipedia's definition from "three conditions" into "two conditions". The logical operators (|| and &&) yield the same branching that a conditional statement such as if/else if would...


Here is an alternative solution, that relies on the way in which a switch/case statement is compiled, and performs only a single branching operation. Please note that it's a programmatic solution, not an algorithmic solution. It is suitable at least for C, C++ and Java (excluding minor semantics), but there are probably similar variations of it in other languages as well (for example, a dictionary in Python):

int IsCommon(int year)
{
    switch (year%400)
    {
        case   0:
        case   4:
        case ...
        case  96:
        case 104:
        case ...
        case 196:
        case 204:
        case ...
        case 296:
        case 304:
        case ...
        case 396:
            return 0;
    }
    return 1;
}

If my memory serves correctly, then a switch/case statement is compiled in the most efficient way when all cases are listed in an incremented and consecutive order, starting from 0. So you can further expand this code, as in the example below:

int IsCommon(int year)
{
    switch (year%400)
    {
        case   0: return 0;
        case   1: return 1;
        case   2: return 1;
        case   3: return 1;
        case   4: return 0;
        case   5: return 1;
        case   6: return 1;
        case   7: return 1;
        case ...
        case  96: return 0;
        case  97: return 1;
        case  98: return 1;
        case  99: return 1;
        case 100: return 1;
        case 101: return 1;
        case 102: return 1;
        case 103: return 1;
        case 104: return 0;
        case 105: return 1;
        case 106: return 1;
        case 107: return 1;
        case ...
        case 196: return 0;
        case 197: return 1;
        case 198: return 1;
        case 199: return 1;
        case 200: return 1;
        case 201: return 1;
        case 202: return 1;
        case 203: return 1;
        case 204: return 0;
        case 205: return 1;
        case 206: return 1;
        case 207: return 1;
        case ...
        case 296: return 0;
        case 297: return 1;
        case 298: return 1;
        case 299: return 1;
        case 300: return 1;
        case 301: return 1;
        case 302: return 1;
        case 303: return 1;
        case 304: return 0;
        case 305: return 1;
        case 306: return 1;
        case 307: return 1;
        case ...
        case 396: return 0;
        case 397: return 1;
        case 398: return 1;
        case 399: return 1;
    }
    return -1; // Just in order to prevent a compilation error (i.e., dummy)
}
barak manos
  • 29,648
  • 10
  • 62
  • 114
  • I agree with this. It depends on what you define as a condition. However, either way this is a better way to define it in terms of programming than the wikipedia (if, else if, if, else) logic. – PCoder123 Apr 20 '14 at 23:49
  • Your function could be shortened to the single line: `return year%4 != 0 || (year%100 == 0 && year%400 != 0);` – Edward Apr 21 '14 at 00:02
  • @Edward: The question is not about code (and there's no gain in making this function one-line shorter, even if the question **was** about code). I just added this to be used as an easy-to-read coding example of "two conditions", as stated by OP (assuming OP meant a single `if/else`). – barak manos Apr 21 '14 at 00:06
  • @barakmanos: if it's not about code, why would it be on StackOverflow? – Edward Apr 21 '14 at 00:12
  • @Edward: Algorithmic question, for example. In any case, the main purpose here is obviously not coding (and as I mentioned above, there's no gain in making this function one-line shorter **even if it was**). – barak manos Apr 21 '14 at 00:15
  • I'm sorry I meant use only 2 evaluations. The point of the question is just to have a faster function. Or just curiosity. The answer can be language agnostic or specific to a language (like, use code magic). Both would be interesting. – TZubiri Apr 21 '14 at 00:28
  • @user3555025: As I said in the answer above, in terms of runtime-performance, there is not much to gain here by "condensing" Wikipedia's definition from "three conditions" into "two conditions". The logical operators (`||` and `&&`) yield the same branching that a conditional statement such as `if/else` if would. – barak manos Apr 21 '14 at 00:30
  • @barakmanos But there are still 3 evaluations. I am looking for something with just 2 evaluations. – TZubiri Apr 21 '14 at 00:35
  • @JohnnyBravo: If you insist on just 2 evaluations, skip the `year%400` and hope that nobody uses the code to evaluate the year 2000 or the year 2400 or any other relevant year. There is no shortcut if you value accuracy. – Edward Apr 21 '14 at 01:03
  • Can you prove that it is not possible to do so with 2 evaluations? – TZubiri Apr 21 '14 at 03:09
  • @Johnny Bravo: Please see updated answer above, which includes an alternative solution. – barak manos Apr 21 '14 at 06:04
2

No, there are three conditions and not two.

Edward
  • 6,964
  • 2
  • 29
  • 55
  • If you're looking for an efficient **implementation** see [this answer](http://stackoverflow.com/questions/3220163/how-to-find-leap-year-programatically-in-c#answer-11595914) to a related question. – Edward Apr 21 '14 at 14:20