Open emson opened 8 years ago
0
every second to the current process, this will hopefully prevent timing issues (printing + sleep 1000 will actually take longer than a second and eventually results in a skipped second)1000
as ?Ϩ
from @henrikf = fn(f) -> f.(f) end
trick to be able to do recursion without having to define a module2016-01-01 00:00
is hard-coded as 1451606400
:erlang.system_time 1
to get the current unix time in seconds\r
to clear the line before printing the new values: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
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:
\r
(carriage return) to rewrite the same line. Since the line length never shrinks (thanks to the specified zero-padding), we don't need to clear out the line first.Notes:
?Ϩ
is 1000. Figured it out like so: to_string [1000]
Some abandoned ideas:
0x5685C180
):os.system_time(:seconds)
with something like :os.system_time/1.0e9
but with little luck since you get a float, not an int.My Gist is here if you want to see a bit of the progression: https://gist.github.com/henrik/856b02213fddb7829fdd
Twitter: @henrik
@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.
@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 :)
@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)
Oh wow... very interesting. It's amazing what these puzzles bring out. Well done @padde and @henrik
@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).
@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.
@henrik checked again, still does not work for me. Very strange. Are you running the latest versions of Erlang and Elixir?
@padde Yeah, now running Elixir 1.2 and Erlang/OTP 18. On OS X.
Bumped the timestamp since it's past new year's:
@henrik me too. It seems to update the time once as soon as I send Ctrl-C to iex though:
I use iTerm - maybe it has a problem in Terminal.app? Will try that tomorrow.
I think I found it. This seems to be a tmux problem, don't really understand why this happens though.
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 until000:00:00:00
.See the website for more details : http://elixirgolf.com/articles/new-year-countdown-in-elixir/
elixir countdown.exs
terminal command. We will manually copy all your solutions into this file, so just add comments below to submit your solutions.Days:Hours:Minutes:Seconds
000:00:00:00
As a bit of fun and a side project maybe consider the following flourishes:
000:00:00:00
.