Hacker News new | past | comments | ask | show | jobs | submit login
A function to sleep a 1000 years: explained (bowero.nl)
27 points by jandeboevrie on Dec 14, 2019 | hide | past | favorite | 17 comments



I guess I am the only one missing the point (disliking this as a code golf challenge) and cringing that the solution does not sleep for a precise 1000 years and overthinking that various other rules are not being taken into account (e.g. leap years, extra seconds per year, etc.).


Given the context of 'code golf' I don't mind the submitted solution being 'close enough', it even seems like the programmer in question was precise in their wording (if they were quoted properly).

Overall the thought of a pinned register being software updated once every 7 seconds for near a thousand years is the worst part.

I stand corrected; I'm so used to seeing these unrolled (which hopefully the hypothetical compiler's done) that I didn't consider the stack implications; that's the most cringy part.


While we're nit-picking, this also doesn't account for a lot of problems which are inevitable on a 1,000 year scale, such as the lifetime of the computer's parts, dealing with power outages, staffing for the long-term upkeep of the system, etc.


That line of code is not beautiful, it's obscene.

At the very least, anything that's intended to last a long time should be written in the simplest, clearest, self-explanatory manner so as to at least give reasonable confidence it's correct.

Not to mention, 952 years is a lousy approximation of a millennium.

  const yearSeconds = 31556926

  for i = 1 to 1000
    sleep yearSeconds
Or, use some calendar library to get the exact number needed.


Why wait for a tropical year though? Surely most people will assume it waits for a calendar year?

Of course, even without leap seconds, this severely complicates the issue since you'd first need to figure out the number of leap days in the next 1000 years, which is unfortunately not fixed since 1000 is not a multiple of 400.


I reconsidered the spirit of the thing, which is obviously to use C and not to use large constants or external libraries. But I still think 95% accurate is terrible, so I posted a 99.99% solution in C.

Edit: I used the tropical year number without thinking about it, but (a) the difference is de minimus compared to being 5% off, and (b) I consider it undefined whether the Gregorian calendar year really is different, because who's to say we won't have an adjustment to the leap year cycle in the very long run to make them converge?


Not thread-safe. Also, from Alex in the comments: "Sounds good! Although probably we will run out of stack waay before that".


It won't run out of stack space with a high enough optimization level so that it uses tail recursion. https://en.wikipedia.org/wiki/Tail_call

You can try this yourself by compiling:

#include <stdio.h>

int i = 0; int x() {--i && x(printf("x"));} int main() {x();}

using gcc with and without '-02'.


You want obfuscated, I'll give you obfuscated:

    void
    f (int i, int j)
    {
        int k = j;
        
        k <<= 2;
        k += j;
        k <<= 3;

        if (--i)
            while (--k)
                f(i, j);
        else
            sleep(k);
    }

    int
    main ()
    {
      f (3, 'O'); /* Sleep for 1000 years */

      return 0;
    }
...this should solve your stack overflow problems and be 99.9% accurate.


(IMO enterprise grade C code should not have types other than int, use numbers larger than 2^15-1, or constants with more than one digit/character. This is, I'm sure, the best way to avoid undefined behavior and concomitant nasal demons)


Here's a more user-friendly version with self-explanatory parameters:

  f(i, j, k, l) { for (j = (j << 2) + j << 3; i + 1 && --j; f(i - 1, k, l, l)); sleep(j); }

  int
  main ()
  {
    f(1, 'O', 'O', 'O'); /* Sleep for 1000 years */
  }


Another problem is that it makes the assumption that an int is 32 bits. The C89 standard certainly doesn't promise that.


> With this, we have proven that this beautiful line of code is correct!

I wouldn't say 'correct', exactly. Not just int size, it depends on undefined behavior and a moderate level of compiler optimizations at the same time. Good luck there.


It relies on undefined behavior since signed integer overflow is undefined.


Apart from showing off syntax tricks, what exactly was the reason to write f(sleep(7)) instead of e.g. sleep(7);--i&&f()? Just minimizing the character count?


The original challenge [0] was submitted as a "code-golf" challenge, which means that the solution needed to solve the problem in the fewest bytes of source code.

There are a lot of tricks to minimize the character count, and replacing a();b() with b(a()) is one of them.

[0]: https://codegolf.stackexchange.com/q/196917/38454


Ah, that makes sense. Thanks.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: