5
\$\begingroup\$

Create a routine to calculate the position of each unit of a clock with an arbitrary number of units (minutes, hours, half-days, days, years, parsecs, quarter-quells, etc), where each unit can be equally sub-divided into an arbitrary number of sub-units; after n base units have elapsed.

Basically, figure out what a clock would show after n seconds given user defined lengths for minutes, hours, days, etc.

For example, after 86,400 seconds on a clock that has 60 seconds in a minute, 60 minutes in an hour, 12 hours per half day, 2 half days per day, and 365 days in a year; you get the following:

clockFunction(86400,[60,60,12,2,365]) = 0,0,0,0,1 (Standard Clock)

clockFunction(86400,[60,60,12,2]) = 0,0,0,0 (Standard Clock - Rolling Over)

clockFunction(7430201,[100,100,10,10,3,12]) = 1,2,3,4,1,2 (French Republican Calendar [sec / min, min / hr, hrs / day, days / wk, wks / mo, mo / yr])

clockFunction(2443332,[60,60,24,365]) = 12,42,6,28 (Standard Clock - Donnie Darko)

clockFunction(63570500940,[60,60,12,2,365,10000]) = 0, 29, 4, 1, 294, 2015 (Standard Clock - Back to the Future)

Shortest code that works wins!

Clarifications:

  • All Units are integer
  • All Units are greater than 0
\$\endgroup\$
  • 1
    \$\begingroup\$ In none of the test cases does the last conversion seem to matter at all (eg days/year on the standard clocks). Is this intentional? \$\endgroup\$ – Geobits Oct 20 '15 at 17:53
  • \$\begingroup\$ I think that's more how I designed the problems. I used that space as a catch all and made it really big so the biggest unit wouldn't roll over. Final unit does matter. I'll add another example. \$\endgroup\$ – JWally Oct 20 '15 at 18:01
  • \$\begingroup\$ Parsecs measure as much time as light-years...none. \$\endgroup\$ – intcreator Oct 20 '15 at 23:29
  • \$\begingroup\$ @brandaemon its a dorky tongue-in-cheek reference to Star Wars :-P \$\endgroup\$ – JWally Oct 21 '15 at 3:21
  • \$\begingroup\$ It's in Star Wars all right, but parsecs are a real thing. I'm very particular about my units. \$\endgroup\$ – intcreator Oct 21 '15 at 4:17
7
\$\begingroup\$

Dyalog APL, 9 7 5 bytes

⌽⊤⍨∘⌽

This is a dyadic function train that expects seconds and lengths as left and right arguments. It is equivalent to the following, train-less function:

{⌽⍺⊤⍨⌽⍵}

Verify all test cases at once on TryAPL.

How it works

    ⌽ Reverse the right argument...
   ∘    and...
 ⊤⍨     perform mixed base encoding on the left argument with those bases.
⌽     Reverse the order of the result.
\$\endgroup\$
  • \$\begingroup\$ Unless someone can get in under 5, winner! Can you explain what your code is doing? \$\endgroup\$ – JWally Oct 20 '15 at 18:07
  • \$\begingroup\$ What encoding does this use? \$\endgroup\$ – Mwr247 Oct 20 '15 at 19:39
  • 2
    \$\begingroup\$ @Mwr247 There are APL code pages (that predate Unicode by a few decades) where each character is a single byte. \$\endgroup\$ – Dennis Oct 20 '15 at 19:45
  • \$\begingroup\$ @Dennis I figured it was single byte, but for the life of me couldn't find any charset that fit them all. Thanks for clearing that up! \$\endgroup\$ – Mwr247 Oct 20 '15 at 19:48
3
\$\begingroup\$

Javascript ES6, 34 bytes

F=(q,a)=>a.map(u=>[q%u|0,q/=u][0])

Explanation:

F=(q,a)=>a.map(u=>
  // For each unit
  [
    q%u|0, // floored remainder of q / u
    q/=u // set q to quotient of q / u
  ][0] // return remainder
)
\$\endgroup\$
3
\$\begingroup\$

CJam, 10 bytes

{{md\}%W<}

Verify all test cases at once in the CJam interpreter.

How it works

{        }  Define a code block:
 {   }%     For each unit length:
  md          Perform modular division with the topmost integers on the stack.
    \         Swap quotient and residue.
            Collect the results in an array.
       W<   Discard the last quotient.
\$\endgroup\$
2
\$\begingroup\$

C – 166 176 bytes

The Back to the Future test case necessitated using long long types! The output format is not consistent in the specs, sometimes there are spaces after the comma, sometimes not, I assumed this meant the space was discretionary. Handles units of zero by outputting -1.

#include<stdlib.h>
#include<stdio.h>
int main(int c,char**v){long long x=atoll(*++v),m;while(--c>1){m=atoll(*++v);printf("%lld%c",x%m,c>2?',':'\n');x/=m;}return 0;}

To use, save as units.c, compile via gcc -o units units.c, and run on the command line as follows:

$ ./units 63570500940 60 60 12 2 365 10000
0,29,4,1,294,2015

Depending on compiler options, you may be able to remove int and return 0; for 153 bytes.

\$\endgroup\$
0
\$\begingroup\$

MATLAB, 66

function a=d(t,L);a=[];for s=L;a=[a mod(t,s)];t=floor(t/s);end;end

And an explanation

function a=d(t,L)
    a=[];
    for s=L %For each of the input blocks
       a=[a mod(t,s)]; %Append the number in this block
       t=floor(t/s); %And divide by the size of this block ignoring the remainder
    end
end

It's a pretty standard approach. I'll see if I can reduce the length.

It also works with Octave, so you can try it here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.