Hacker News new | comments | show | ask | jobs | submit login
A Formula for the Number of Days in Each Month (cmcenroe.me)
222 points by tolmasky on Dec 5, 2014 | hide | past | web | favorite | 105 comments



Simple (warning: I did not verify this result):

    -(       11 x^11)/907200
    +(      163 x^10)/181440
    -(       37 x^9 )/1260
    +(    13481 x^8 )/24192
    -(  2055371 x^7 )/302400
    +(   240683 x^6 )/4320
    -( 28268521 x^5 )/90720
    +( 85774775 x^4 )/72576
    -(446998571 x^3 )/151200
    +( 46351537 x^2 )/10080
    -(   221017 x   )/56
    +1416
That is a nice continuous, infinitely differentiable function.

Source: http://www.wolframalpha.com/input/?i=interpolating+polynomia...

To get something more impressive, I would use the discrete Fourier transform. That leads to http://en.wikipedia.org/wiki/Trigonometric_interpolation. That gives you a nice formula with lots of sines and cosines.


This is especially handy when you want to figure out how many days are in that pesky month between January and February.


Looking at the Wolfram Alpha plot, it appears that the month about halfway between November and December is the longest of the year, with almost 33 days.

We could call it Gloomember, the month that seems to go on and on.


I say we call it Partyember because it is the month most likely to have five full weekends.


I forgot how many days were in that month some time back in the 19A0s.

http://boingboing.net/2011/10/11/mixtape-of-the-lost-decade....


Is there some joke to this article? I can't make any sense of it...


Closer to a new media art installation.


CancelGymMember?


Smarch?


In Java the thirteenth month is "Undecimber". Works better for me, I always associate Smarch with lousy weather.

http://en.wikipedia.org/wiki/Undecimber


No, we want a nice discrete function. The Möbius function[1] μ(x) has some potentially useful properties - it produces discrete values in the range [-1,1], and it has a kind of pseudorandomness to its output. Some sort of variation on 30 + μ(n + x) or 30 - μ(n + x) should produce the right values for the number of days per month in a leap year. 30 - μ(x+192)[2] starts off promisingly, giving the right day counts for January through to July, but then it goes off the rails. I've mounted a quick brute-force search, but it looks like there's no n < 1000000 for either of those formulations that correctly matches January through August, let alone through to December, but never mind: there's plenty more natural numbers. Surely someone will find a formulation that works. It's not like anyone's been mistaken about the continuation of this number series before[3].

[1] http://en.wikipedia.org/wiki/M%C3%B6bius_function [2] http://www.wolframalpha.com/input/?i=30+-+%CE%BC%28n%2B192%2... [3] http://en.wikipedia.org/wiki/Mertens_conjecture


I don't want that, but you can always get there by replacing x by floor(x) everywhere it occurs, or, in strongly typed languages, by declaring the function to take an integer value.

For those that dislike taking powers of x, try this in Python:

  def f(x):
    return 62648012/4**x - 4*(15662003/4**x) + 28

  map( f, xrange( 1, 13))


TIL that the month before January doesn't have the same number of days as December.


I tried DFT, the result is not pleasant and there is no really obvious way to generate the coefficients with a compact formula.


That's a shame, it'd be nice to have a formula that "wrapped around" properly.

I've been happy with the rhyme for a while. I can't remember it properly (in my head it ends "all the rest have strawberry jam, except my grandmother who rides a bicycle"), but it's obviously enough.

Now that I see it all laid out, though, I wonder if I can do better -- "Odd is 31 days to July, then it flips." Now the people in school counting on their knuckles all makes sense.


You shouldn't believe everything you read on the Internet/I guess I should have added a smiley.


I tried it well before you wrote your comment because I hoped that the alternating pattern would yield something short but February messes everything up.


I believe Zeller's Congruence had already solved this, no?

Zeller's is based upon calculating the day of the week, but it also calculates days in the month and accounts for leap years. Plus, it's been around since the 19th century and is used in many major programming languages to calculate date (its implementation is sometimes a first year Comp Sci course project for introductory programming): http://en.wikipedia.org/wiki/Zeller%27s_congruence

For a programming example that does this same thing: https://github.com/mwhawkins/JavaZellers

How did this make the front page of HN being a problem which has already been solved and well documented for almost 200 years? Not to knock the author, as they put in some time apparently, but was just curious.


> How did this make the front page of HN being a problem which has already been solved and well documented for almost 200 years? Not to knock the author, as they put in some time apparently, but was just curious.

Zeller's Congruence is an algorithm. This is a formula. It made it to the front page because it was a clever hack and people like me love those.


Zeller's Congruence is a formula as well (well, more than one depending on which calendar you want to use). Go look at the wikipedia article.

More seriously, any algorithm that doesn't do user I/O is expressible as a fixed formula. What distinction are you trying to draw?


> More seriously, any algorithm that doesn't do user I/O is expressible as a fixed formula.

This is probably true for some very weak definition of the terms, but not, I think, in any sense that a random person would recognise as a 'formula'. For example, what is the formula for the algorithm "on input `n`, output the first position in the decimal expansion of `pi` at which a copy of the decimal expansion of `n` begins"?


The fact that I can't tell you a formula doesn't mean there isn't one. For example, it's trivial for me to come up with input for that problem that you (or anyone else in the world) would be unable to solve. When the answers are unknown, I don't find it all that surprising that it's difficult to list or otherwise classify them.

If you believe that f(x) = |x| is a "formula" giving the distance of a real number from zero, it's just as conditionally defined as (but less infinite than) the infinite lookup table you hypothesize.

On a more fun-fact note, there was a result some years ago expressing pi as an infinite series in powers of 16, with the headlining implication being "it may be possible to calculate the nth digit of pi (in base 16, or other powers of 2) directly, without needing to know the preceding digits" (I don't know the state of things since then, and details may have been jumbled in my memory). I suspect that there are implications for the puzzle you pose.


> If you believe that f(x) = |x| is a "formula" giving the distance of a real number from zero, it's just as conditionally defined as (but less infinite than) the infinite lookup table you hypothesize.

If you allow a formula to be an infinite look-up table, then the statement "every [always halting] algorithm is a fixed formula" becomes true, but, I think, almost meaningless—it just says that the algorithm produces an output for every input. This is what I meant by saying:

    This is probably true for some very weak definition of the terms, but not, I think, in any sense that a random person would recognise as a 'formula'.
> On a more fun-fact note, there was a result some years ago expressing pi as an infinite series in powers of 16, with the headlining implication being "it may be possible to calculate the nth digit of pi (in base 16, or other powers of 2) directly, without needing to know the preceding digits" (I don't know the state of things since then, and details may have been jumbled in my memory). I suspect that there are implications for the puzzle you pose.

No 'may' about it—it is possible to find the hexadecimal (and thus binary, 'quaternary', or octal, but not higher) digits using this algorithm. However, the discoverers explicitly disclaim its utility for finding decimal digits of pi in this way, and, indeed, say that no such 'look-ahead' algorithm is known (see p. 55 of http://link.springer.com/article/10.1007%2FBF03024340).


What do you mean, but not higher? If you want a base-256 digit, calculate the two base-16 digits that make it up. That's actually a simpler process than you'd have to go through for the nth octal digit (compare -- the second octal digit of pi is composed of, as high bit, the low bit of the first hex digit, followed by the two high bits of the second hex digit. But the 8th 256-ary digit of pi is just the concatenation of the 15th and 16th hex digits). In general, since you can calculate any adjacent 4 bits of the binary expansion, you can then aggregate those bits however you like, making it easy to get the nth digit in any power of two. The only complication is that, since you generate bits in blocks of four, you may end up having calculated as many as 6 bits that you didn't need.

You object to my characterizing the pi-reading function you describe as an infinite lookup table. But it can't be implemented as an "intuitive" algorithm either. No matter how you code a function to solve that problem, it will always be trivial to provide input that your function cannot handle (if you have a representation of pi that you search, then you're relying on an infinite lookup table. If you calculate pi on the fly, you won't be able to handle large numbers as input). So I don't see why a defective (because you don't have enough time, or space, to run it) algorithm tranforming into a defective (because you don't have enough space to store it, but hey, time is no longer a concern) formula is a big problem for the equivalence between algorithms and formulae.

Also, I have to note that you've referred to the following mathematical result:

    pi = \sum_{k=0}^\infty (16^{-k} * [4/(8k+1) - 2/(8k+4) - 1/(8k+5) - 1/(8k+6)]) 
as an "algorithm" instead of a "formula" ;)


> What do you mean, but not higher? If you want a base-256 digit, calculate the two base-16 digits that make it up.

I'm sorry; you're quite right, and I was wrong.

> No matter how you code a function to solve that problem, it will always be trivial to provide input that your function cannot handle (if you have a representation of pi that you search, then you're relying on an infinite lookup table. If you calculate pi on the fly, you won't be able to handle large numbers as input).

I'm not sure why you say that I won't be able to handle large numbers as input. It might take a long time (like, a universe-endingly long time), but so would printing out the decimal expansion of 10↑↑10 (https://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation), and I don't think that anyone would claim that that means that exponentiation algorithms "can't handle" this kind of exponentiation. (I dunno; maybe people would claim that.)

> So I don't see why a defective (because you don't have enough time, or space, to run it) algorithm tranforming into a defective (because you don't have enough space to store it, but hey, time is no longer a concern) formula is a big problem for the equivalence between algorithms and formulae.

My problem is that I think that there is no such equivalence, unless the definition of 'formula' is made so broad as to be essentially synonymous with 'algorithm'—at which point it's true but un-interesting. All I am arguing is (as a constructivist would) that it is worthwhile to maintain meaningful distinctions.

> Also, I have to note that you've referred to the following mathematical result `pi = [elided]` as an "algorithm" instead of a "formula" ;)

I did not mean to do that; I was referring to the process of using that formula (which is, as it were, an 'inert' object) to produce hexadecimal digits as an algorithm.


I can't find any way to calculate days in month using Zeller's Congruence °_° That's seems to calculate only the day of the month (and it's awesome!). Even the Java program use a fixed array to output the days in month! XD


If you give up on February and just resign yourself to treating it as an exception, then the formula in the article, 30 + (x + [x/8])%2, is trivial to compute in your head.

Zeller's Congruence is quite a bit harder to do in your head.

For mental calculation of day of week, I use a method given in a Martin Gardner book, but this only works for 1900-1999. I'll give a fix to extend it to other centuries.

Let Y be the last two digits of the year, let M be the month (1-12), and D be the day of the month (1-31). Let [X] denote the integer part of X.

Compute w = [Y/12] + Y%12 + [Y%12/4]

Compute w = w + month_offset(M), where month_offset is defined by this table:

    M   month_offset
    1     1
    2     4
    3     4
    4     0
    5     2
    6     5
    7     0
    8     3
    9     6
   10     1
   11     4
   12     6
Compute w = w + D

w%7 gives the day of the week, with Saturday being day 0. A couple notes.

1. You can reduce mod 7 as you go. For example, to get the day of the week of 1969-07-16, you could think "[69/12] = 5, add 9 (69%12) giving 14 == 0 mod 7. [9/4] = 2, so we are at 2. Add month_offset(7) == 0, giving 0. Add 16 (D), and we have 3 mod 7, so Wednesday".

2. Month_offset is easy to remember if you think of it this way:

   1 4 4

   0 2 5

   0 3 6

   1 4 6
That's 12^2, 5^2, 6^2, and 12^2+2. I don't know why that makes it easy, but Gardner suggested it, and I have not forgotten it in something like 40 years, even though I rarely use it.

3. If the year is a leap year, subtract 1 for dates in January and February.

4. For years in 2000-2099, subtract 1 from the result. For years in 1800-1899, add 2. If you forget what the century correction is, you can work it out in your head. For instance, to find the correction for 20xx, work out the day of week of 1999-12-31: 99=12x8+3, [3/4]=0, month_offset(12)=6, so 8+3+0+6+31==6 mod 7, or Friday. Now work out 2000-01-01 without a century correction: 0=0x12+0, [0/4]=0, month_offset(1)=1. 2000 is a leap year, so need to subtract 1 in January, so we have 0+0+0+0+1-1+1==1 mod 7, so Sunday. However, it should be Saturday since it comes after Friday, and so the century correction must be -1 for 20xx.

5. Gardner's method is really one of the other well known methods (I forget which one) adjusted to make mental calculation easier.

Addendum: this is described in chapter 7, "Tricks of Lightning Calculators" from the Martin Gardner collection "Mathematical Carnival".


Regarding day of the week, this simple trick/observation seems surprisingly unknown (called Doomsday Rule: http://en.wikipedia.org/wiki/Doomsday_rule).

In any year, 4/4, 6/6, 8/8, 10/10, 12/12 fall on the same day, so do 9/5, 5/9, 7/11, 11/7 (mnemonic: 9-to-5, 7-11). If you know what day that is for the year (Friday for 2014, Sat for 2015), you can quickly calculate the day of the week for many of the days.

Jan/Feb/Mar require a little bit thought, but with practice reasonably quick.


Well, a lot of people have never heard of Zeller's Congruence. Also, the process is kind of interesting, not just the result. That's why that article on deriving the fast inverse square root constant did well here, even though many people already know the result.


The age of the solution and number of people knowing about it... Well. :)


Thirty days hath September

April, June, and November

All the rest have 31

Except for the very special one.

...

The knuckles method, for those who don't know: Make a fist. Start with January on your first knuckle. Counting knuckles AND the gaps between knuckles, so each knuckle is 31 days, the gap between is 30 days (or 28/29 for february). Repeat on the last knuckle before reversing.

...

So--

KNUCKLE_gap_KNUCKLE_gap_KNUCKLE_gap_KNUCKLE

JAN_feb_MAR_apr_MAY_jun_JUL (repeat last knuckle and reverse)

AUG (knuckle repeat)_sep_OCT_nov_DEC (ending on your middle knuckle)

ALLCAPS = KNUCKLE = 31 days


I always just found it easiest to remember the summer months (July and August) are the back to back 31 day ones, and the rest alternate. Add to that, there are plenty of "anchor" months to start from, which you know without having to figure it out. (Presumably you remember that February is short, that Halloween is Oct. 31, and that New Years Eve is Dec. 31, for instance.)


As I learned it, the poem went

    Thirty days hath September,
    April, June, and November
    And all the rest have thirty-one
    excepting February alone
    And that has twenty-eight days clear
    and twenty-nine in each leap year
That way's more explicit, but I like yours better. It reminds me of a homework problem I had in real analysis, which said "show that [the standard infinite series for e] is both strictly increasing and bounded above and therefore converges to a very special real number".

On the due date, someone came into class saying "I could show that the series was increasing and bounded above, and therefore converged to a real number, but I didn't know how to show that the limit of the series was, quote, very special." :D


Re: the knuckle technique. I prefer to simply start over again from the first knuckle, as opposed to reversing direction.

It gives you one less thing to remember, since you don't have to remember to repeat on the last knuckle.


I learned it that you move onto the other hand.


Me too and it must mean something that I still use this method from time to time. Why is is so difficult to just remember?


> Why is is so difficult to just remember?

Probably because there is almost a pattern, but not quite.


I prefer to reverse, because it emphasizes that there is a double-31 pair of consecutive months which is unique in the pattern and a good thing to know/remember (that both July and August are long months)


Instead of reverse just start over from the first knuckle again. You get 31 in either case.


first says reverse, second says i prefer to start over, third says i prefer to reverse, you say start over.


That sounds harder than the ryhme, which we were forced to learn early on.

The knuckle method seems to me to be the "simple" way to count cows--just count the legs and divide by four.


This poem is such bullshit. You can substitute loads of other months and make it very wrong:

Thirty Days hath December,

March, July and November,

All the rest have 31

Except January.


Yes, like most poems, this is one that you're better off remembering than trying to reconstruct on the fly.


For me it's that the odd-numbered nomths have 31 days, and the even-numbered ones have less, in the first half of the year, and vice versa for the second half.

That's better than the poem in that you can't mix it up, AND it's faster than audiating all of that.


As with most algorithms, there are trade-offs :). An advantage of the poem is that it can be learned by small children. I disagree that your approach can't be mixed up... I'm still trying to figure out what nomth is so I can implement it ;)

I certainly wouldn't recommend my usual approach though: alternate 31/"not 31" starting from October (Halloween is the 31st) or March (my birthday is close enough to the end of the month for me to remember that March has 31 days.)


> I'm still trying to figure out what nomth is so I can implement it

A 'nomth' is a month in which a feast occurs (http://en.wikipedia.org/wiki/Feasts_of_Jesus_Christ).


Of course, if you change the poem that gives you the correct number of days per month, then you won't get the right answer. That doesn't make the correct poem "bullshit."


It means that the poem is not very resilient. It's pretty easy to misremember.


Great, in your distaste for the method that can involve knuckles, you have recreated it exactly.

  1. alternate 31 and 30
  2. reset in month 8
  3. alter feb to 28
In my mind using modulus and floor in a mathematical formula is no more valid than using cases. A clever formula would avoid all of them.


ROUND((61 + COS(3 * month - 22.5)) / 2)

Admittedly rounding is still cheating but it allows compacter solutions than being spot-on every time. Handling February is left as an exercise for the reader.


> In my mind using modulus and floor in a mathematical formula is no more valid than using cases

Agreed. Using floor it seems like you can construct a function that's effectively defined piecewise, by constructing a floor expression that's zero outside of a specified input domain, and 1 within the domain. Then you multiply the floor expression by the piecewise expression that you'd use to define a piecewise function over that domain.

Nevertheless I found the article to be an interesting read on mathematical reasoning - a thought process for designing functions with particular behavior. Is there a rigorous way of describing why mod and floor seem like cheating in a way, aside from the fact that they can be used to construct piecewise functions? Is the ideal hack in this scenario a continuous, smooth function? (And something more interesting than the result of polynomial interpolation?)


> Using floor it seems like you can construct a function that's effectively defined piecewise, by constructing a floor expression that's zero outside of a specified input domain, and 1 within the domain. Then you multiply the floor expression by the piecewise expression that you'd use to define a piecewise function over that domain.

And you can fit a polynomial the same way by (using the example at hand) defining

    f(x) =  c_1(x-2)(x-3)...(x-12)
         +  c_2(x-1)(x-3)...(x-12)
         +  c_3(x-1)(x-2)...(x-12) [but the (x-3) factor is missing!]
         +  .      .            .
         +  .       .           .
         +  .        .          .
         + c_12(x-1)(x-2)...(x-11)
And then choosing c_1 such that the c_1 term is equal to 31 when x=1, c_2 such that the c_2 term is equal to 28 when x=2, and so forth. You'll get a well-defined polynomial, impeccably "mathematical" -- in fact, you should get the polynomial listed in Someone's comment (since there should only be one 11th-degree polynomial passing through those 12 points). The traditional way to fit a polynomial to points is by reducing a matrix, linear-algebra style, but this approach is equivalent and, as you can see, amounts to nothing more than defining several functions which are zero except at the point of interest, and then scaling them to take the proper value at the point of interest. Why is that more "valid" than using a modulus?

Frankly, I'm much more concerned by the OP using "2 mod x" when 1 is a legal value for x.


// without floats, multiplication, division, modulo:

int result = (30|m^(m>>3)) - (((m^13)+1)>>4<<1);


meant to upvote, accidentally downvoted.


Your solution (which does not account for leap years, btw) simplifies to:

  def days(month):
      return [31,28,31,30,31,30,30,31,30,31,30,31][month]


I can't wait for 0/0/2015 ;)


Ha, nice one. I'm mixing my Es with my Ps


The easiest function would be a mapping from 12 input values to 12 output values.

For example, see the Collatz conjecture which only defines two cases (but one could have 12): http://en.wikipedia.org/wiki/Collatz_conjecture


There was a Hacker News article about why August has 31 days, breaking the 30/31 alternating days. I can't find it but here's an article about it.

http://www.infoplease.com/spot/history-of-august.html

It just makes it a more interesting formula because of that!


    days = 28 + ((0x3bbeecc>>(month*2))&3);


I like yours for the minimum number of operations needed:

    28+((0x3bbeecc>>(m*2))&3)
But here's my own attempt anyway, which wins on number of characters typed =)

    30+(m&1^m>7)-m*(m==2)


Where does this come from?


The basic idea is to encode the array within a single integer:

   0 + [anything, 31,28,31,30,31,30,31,31,30,31,30,31]
  28 + [anything,  3, 0, 3, 2, 3, 2, 3, 3, 2, 3, 2, 3]
              00, 11,00,11,10,11,10,11,11,10,11,10,11

   reverse:   11,10,11,10,11,11,10,11,10,11,00,11, 00
            0011  1011  1011  1110  1110  1100   1100
          0x   3     b     b     e     e     c      c   
We have 4 possible values in the array, so we need 2 bits per value. We have one dummy value + 12 required values, so we need a total of 2*13 = 26 bits which fits easily into a 4 byte integer (either 32 bits unsigned or 31 bits signed). To retrieve one element from the "array", we need to shift our constant 2 bits per month or twice by the numer of months. Then we need to mask everything but the lowest 2 bits (&3).


Great explaination. This is the sort of post that makes me love HN.


It basically just stores [3, 0, 3, 2, ...] as 2-bit numbers, and the shift then corresponds to indexing.


Anybody knows the reason behind August having 31 days? This is the source of the complexity of the days-in-a-month problem. All I can find is this legend, which could even be true.

http://timesofindia.indiatimes.com/home/stoi/Why-does-Februa...



Great analysis. The next step would be to see if the code to implement the function can be shorter than 12 bytes (and array of bytes holding the number of days in the month such that f(x) = days_of_month[x]; is longer than the computation. Of course from a pure cycle counting advantage doing it as a calculation will always be faster as memory is slow to access.


How about 15 bytes? (x86, month in ecx, result in eax)

  // 28 + ((0x3bbeecc>>m>>m)&3);
  b8 cc ee bb 03    mov  eax,0x3bbeecc
  d3 f8             sar  eax,cl
  d3 f8             sar  eax,cl
  83 e0 03          and  eax,0x3
  83 c0 1c          add  eax,0x1c


I think you can save a byte on the add with

    04 1c             add al, 0x1c
(but i've never written any x86 assembly)


You are right. I was lazy, I compiled it with gcc -O2 and extracted the assembler with objdump -Mintel -d.


In fact you can save 2 bytes if you only care about the result in AL, bringing it down to 13 bytes:

    b8 cc ee bb 03    mov  eax,0x3bbeecc
    d3 f8             sar  eax,cl
    d3 f8             sar  eax,cl
    24 03             and  al, 3
    04 1c             add  al, 28


I feel like you should be able to get away with a 2-byte constant of 0x3bec, but I haven't been able to simplify the bitshift amount enough, from (n >> 2 << 2) + 2 * (n % 2).

ETA: I think the simplest I can get it is:

  days(n) = 28 + (0x1df6 << (1^n&3) >> n) & 3
My intuition is that the 1^n&3 isn't going to be cheaper.


If you want to trade bytes of instructions for bytes of constants, you could store the number of days - 28, so you only need two bits of constant per month.


Once you do that, you can trade your array for a 32-bit integer:

f(n) = 28 + ((0x3bbeecc >> n >> n) & 3)


I think this has to win for fewest/cheapest instructions and genuinely clever, practical programming. I've been doing a lot of cache optimization lately, so I'm a fan of anything that reduces the amount of bits required to store information.


Ohh I like that a lot.


I mean, you have to load the instructions, too. That being said those have pretty intelligent pre-fetching baked in, but if it's the computational bottleneck, you can get the values into registers for the lookup.

I'm not sure this post is meant to be a model for good implementation advice, though, performance-oriented or otherwise. Just an interesting tidbit.

EDIT: I'm trying to figure out how to write code using registers instead of indexes into memory and it ends up with lots of conditionals instead of basically one instruction. The conversation about speed is... tricky. Can some people who are more expert help out?


Great start. Now let's add leap years. =)


    days y m = 28 + (m + (m `div` 8)) `mod` 2 + 2 `mod` m + 2 * (1 `div` m) 
               + ((2 `div` m) `mod` 2) * (leap y)
      where leap y = multiple 4 y - multiple 100 y + multiple 400 y
              where multiple int y = ((y + (int - 1)) `mod` int + 1) `div` int


but that's trival, isn't that already solved?

    function f(x) { return 28 + maybeLeap(x) + (...); }
I remember it's something related with "(x % 4) == 0" and "not ends_with(00)"


OP is trying to express the day count as a pure math expression. maybeLeap() probably won't do here.


Except for every 400th year.


how about this?

        leap = function(x) { 
          if ((x % 4) != 0) {
            return 0;
          }
          return Number(
            (x % 100) != 0 || (x % 400) == 0
          );
        }

        function(x) { return 28 + leap(x) + (...) };


For something more or less related, check out the calculation of the date of Easter: http://en.wikipedia.org/wiki/Computus. Some versions, like Gauss' algorithm, also relied heavily on moduli.


Here's mine. No floating point logic required.

let days = (i ^ (i >> 3) | 30) - 1 / (i * 9 % 17) * 2


What language would this work in? let looks like ocaml but those don't look like the write syntactical ways to do math stuff IIRC


Just execute it using the shell:

   echo $(( i = <month>, (i ^ (i >> 3) | 30) - 1 / (i * 9 % 17) * 2 ))


It's actually an excerpt from c#. It's not syntactically valid on its own.


doesn't work in JS:-

function days2(i) { return (i ^ (i >> 3) | 30) - 1 / (i * 9 % 17) * 2 }

1 30.77777777777778 2 28 3 30.8 4 29 5 30.818181818181817 6 29.333333333333332 7 30.833333333333332 8 30.5 9 29.846153846153847 10 30.6 11 29.857142857142858 12 30.666666666666668


That makes sense. js doesn't have integer division.


Can be shortened to 28+(x+~~(x/8))%2+2%x+2*~~(1/x)


29 + 2 * ABS(SIGN(month - 2)) - FLOOR(ABS(month - 7.5)) % 2


A perfect illustration of why a simple lookup table is often the better implementation. I'll stick to the knuckles method—thank you very much.


Was I the only one who expected to see a Dirac delta function used for February? I was pleasantly surprised.


Compiles down to something like a hundred bytes of code. What a savings!


Why is it any better/faster than a simple switch case like this in Clojure: #(case % 1 31 2 28 3 31 4 30 5 31 6 30 7 31 8 31 9 30 10 31 11 30 12 31)


#([31 28 31 30 31 30 31 31 30 31 30 31] (dec %))

> Why is it any better/faster than a simple switch case like this in Clojure

It's not about better or faster. It's fun to think of things like this. :)


Or in C: f(int m) { return [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][m] }

The OP didn't claim it was better than anything, it's just a nice exercise in style!


Thirty days have September, April, June, and November. All the rest have 31, Except for February all alone, It has 28 each year, but 29 each leap year.


What's the formula for the number of days in a month+year (so that it calculates leap years formulaically too?


Javascript:

var f = function(i){return new Date(2014,i,0).getDate();};

JSON.stringify([1,2,3,4,5,6,7,8,9,10,11,12].map(f)) == JSON.stringify([31,28,31,30,31,30,31,31,30,31,30,31]);

:P


This is awesome. Well done, OP.


my digital attempt:-

function days(m) { return 30 + ((m + (m > 6)) % 2) - 2 * (m == 2) }


    def days_in_month(month_num):
        if month_num in [1, 3, 5, 7]:
            return 31
        elif month_num in [4, 6, 9, 11]:
           return 30
        return 28




Applications are open for YC Winter 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: