emson / elixirgolf

Elixir Golf web site
MIT License
3 stars 1 forks source link

New Year Countdown in Elixir #5

Open emson opened 8 years ago

emson commented 8 years ago

The puzzle is to create a countdown timer that displays the number of Days:Hours:Minutes:Seconds until the next New Year. This countdown timer will decrease every cond until 000:00:00:00.
See the website for more details : http://elixirgolf.com/articles/new-year-countdown-in-elixir/

As a bit of fun and a side project maybe consider the following flourishes:

padde commented 8 years ago

213 chars (214 bytes)

:timer.send_interval ?Ϩ,0
f=fn f->receive do 0->t=1451606400-:erlang.system_time 1
s=rem t,60
t=div t,60
m=rem t,60
t=div t,60
:io.format'\r~3..0B:~2..0B:~2..0B:~2..0B',[div(t,24),rem(t,24),m,s]
end
f.(f)end
f.(f)

Twitter: @der_padde

henrik commented 8 years ago

176 characters (counting newlines):

for x<-1451606400-:erlang.system_time(1)..0do
m=div x,60
s=rem x,60
h=div m,60
m=rem m,60
:io.fwrite"~3..0B:~2..0B:~2..0B:~2..0B\r",[div(h,24),rem(h,24),m,s]
:timer.sleep ?Ϩend

(Stole the shorter :erlang.system_time(1) from @padde, who also suggested inlining the div and rem – thank you!)

An important difference to @padde's solution is that this one is likely to drift. See notes below.

What it does:

Notes:

Some abandoned ideas:

My Gist is here if you want to see a bit of the progression: https://gist.github.com/henrik/856b02213fddb7829fdd

Twitter: @henrik

padde commented 8 years ago

@henrik quick win: by inlining the div/rem as I did, you can shave off another 10 chars or so. I tried hard to extract a function for this but it was always much longer than writing it directly.

If you would allow me to criticise your solution: it will run slow rather quickly because doing the computations and printing, then sleeping for a second will actually take longer than a second.

henrik commented 8 years ago

@padde Good call on the div/rem. Never tried the non-abbreviated version there :) Thank you!

Yeah, I realized pretty quickly that it is prone to drift (put it in my notes above). I might make a stab at a drift-safe one, though you've done a good job of that already :)

henrik commented 8 years ago

@padde Looked for ways to abbreviate yours; not easy… If one doesn't care about performance, seems it can be shortened to skip the whole interval thing and just have a very CPU-wasteful loop:

f=fn f->t=1451606400-:erlang.system_time 1
s=rem t,60
t=div t,60
m=rem t,60
t=div t,60
:io.format'\r~3..0B:~2..0B:~2..0B:~2..0B',[div(t,24),rem(t,24),m,s]
f.(f)end
f.(f)
emson commented 8 years ago

Oh wow... very interesting. It's amazing what these puzzles bring out. Well done @padde and @henrik

padde commented 8 years ago

@henrik nice idea! However it seems to be stuck at the first second. I guess the massive amount of printing takes way too long for this to work.

Maybe one could combine that approach with sleeping for some time. According to the sampling theorem we need a total cycle time that is below 500ms in order not to miss a second. So we should be safe with a sleep time < (500ms - max(time for other computations)). In theory we cannot predict how long it will take, but in practice we should be safe with a sleep time of say 100ms (or ?d).

f=fn f->t=1451606400-:erlang.system_time 1
s=rem t,60
t=div t,60
m=rem t,60
t=div t,60
:io.format'\r~3..0B:~2..0B:~2..0B:~2..0B',[div(t,24),rem(t,24),m,s]
:timer.sleep ?d
f.(f)end
f.(f)

For the record: this joint effort takes 185 chars (and an equal amount of bytes since there are no multi byte characters involved).

henrik commented 8 years ago

@padde Hm, stuck at the first second? Seems to run fine for me, though it spikes the CPU. Haven't left it running for a long time, maybe it degrades.

padde commented 8 years ago

@henrik checked again, still does not work for me. Very strange. Are you running the latest versions of Erlang and Elixir?

henrik commented 8 years ago

@padde Yeah, now running Elixir 1.2 and Erlang/OTP 18. On OS X.

Bumped the timestamp since it's past new year's:

countdown

padde commented 8 years ago

@henrik me too. It seems to update the time once as soon as I send Ctrl-C to iex though:

ezgif com-video-to-gif

henrik commented 8 years ago

I use iTerm - maybe it has a problem in Terminal.app? Will try that tomorrow.

padde commented 8 years ago

I think I found it. This seems to be a tmux problem, don't really understand why this happens though.