18
\$\begingroup\$

The shortest code to generate the correct times on the clocks wins.

You are a seasoned time traveler and have been known to stop at many planets during your journies. Each planet rotates at a different rate and because of this, the length of a day is different than our usual 24-hour day. As a result, the planets use clocks with different numbers of hours. The hours on a clock with x hours are arranged similar to ours (1, 2, 3, ... , x) with the number rotating clockwise and x being at the top.

Additionally, each planet has a different amount of minutes in an hour, and a different number of seconds in a minute. You will be given a starting time and a number of elapsed seconds from which you must determine the ending time.

Input can be taken directly from a file passed as an argument, or as standard input. The first line of input will be the number of clocks you need to process. After that, each clock has three lines of input that contains integers in the following format:

x y z
h m s
t

The meaning of each letter is below.

x = The number of hours in a day (2 <= x <= 99)
y = The number of minutes in an hour (2 <= y <= 100)
z = The number of seconds in a minute (2 <= z <= 100)
h = The hour of the starting time (1 <= h <= x)
m = The minute of the starting time (0 <= m < y)
s = The second of the starting time (0 <= s < z)
t = The number of seconds that have elapsed

The output must be the ending time for each clock after t seconds have passed since the starting time. Your output must be formatted as standard clock time (HH:MM:SS). Numbers should be padded, when necessary, to ensure that all numbers are two-digits.

Test Cases


Input

2
5 20 10
1 10 5
2633
6 25 5
6 0 3
290

Output

04:13:08
02:08:03

Input

1
14 17 11
12 16 10
1530

Output

07:03:00

Input

2
8 40 25
3 1 15
10620
14 15 20
1 14 0
-580

Output

05:26:10
14:00:00
\$\endgroup\$
  • 8
    \$\begingroup\$ I wonder if all the planets are inhabited by Englishmen? \$\endgroup\$ – aaaaaaaaaaaa Mar 19 '11 at 22:03
  • 4
    \$\begingroup\$ @eBusiness Better give them a nice cup of not entirely unlike tea. \$\endgroup\$ – Mateen Ulhaq Mar 20 '11 at 4:47
  • \$\begingroup\$ I think I don't understand the examples/the input format. x is the number of hours in a day - hours in that planets time, or human/earth hours? And h, the starting time is the time in that planets time, or again, human/earth time? Because: If in input 1, example 2, the planet only has 6 hours - how should the starting time be 6? That would be an invalid time. \$\endgroup\$ – user unknown May 4 '12 at 4:24
  • \$\begingroup\$ If I understand correctly, Hours go from 1 to n. Minutes and seconds go from 0 to n-1. But is midnight n:00:00 or 1:00:00. That is where I get confused. \$\endgroup\$ – captncraig May 4 '12 at 13:57
  • \$\begingroup\$ @CMP: As the last test case shows, the time for midnight is n:00:00. \$\endgroup\$ – Kevin Brown May 11 '12 at 19:56

15 Answers 15

8
\$\begingroup\$

GolfScript - 50 chars

~](;7/{{~+.4$/\4$%])\}3*3<)@\or\+{100+`(;}%':'*n}%

The values (H/M/S) are collected by moving them to the front of the stack (])\). The hour 'underflow' at 0 is handled with or. Zero padding is handled with 100+`(;, although I suppose 0`\+-2> is the same length.

\$\endgroup\$
  • \$\begingroup\$ Ooooh, the 100 thing makes me mad. I wish I'd thought of it. (It would only save me 3 characters, but would have saved me much more brain time.) \$\endgroup\$ – Jesse Millikan Mar 24 '11 at 2:37
9
\$\begingroup\$

Python, 142 characters

R=raw_input
for i in' '*input():x,y,z,h,m,s=map(int,(R()+i+R()).split());t=input()+h*y*z+m*z+s;print'%02d:%02d:%02d'%((t/y/z-1)%x+1,t/z%y,t%z)
\$\endgroup\$
  • \$\begingroup\$ If I'm not mistaken, since you use for i in ' '*input() you could actually use i instead of ' ' in R()+' '+R(), saving two characters. \$\endgroup\$ – Dan Burton Mar 19 '11 at 18:19
  • \$\begingroup\$ Indeed, thanks. \$\endgroup\$ – Keith Randall Mar 19 '11 at 18:27
  • \$\begingroup\$ You can replace the second line by this exec"x,y,z,h,m,s=map(int,(R()+' '+R()).split());t=input()+h*y*z+m*z+s;print'%02d:%02d:%02d'%((t/y/z-1)%x+1,t/z%y,t%z);"*input() \$\endgroup\$ – fR0DDY Mar 20 '11 at 3:37
  • \$\begingroup\$ t/y/z%x or x is a character shorter. \$\endgroup\$ – Nabb Mar 20 '11 at 7:24
5
\$\begingroup\$

GolfScript 62 60 characters

Edit: I managed to get the array formerly stored in a to reside on the stack, it takes a little extra switching that way though so no major improvement.

~](\7/\{(~+[]\{.5$/@@5$%\+@@+}3*;\;(@or\+{'0'\+-2>}%':'*n@}*

62 version:

~](\7/\{[]:a;(~{+.4$/\4$%a+:a;}3*;;;a(@or\+{'0'\+-2>}%':'*n@}*
1______a2____3_b4_5___6__7____8__9__10_____11_________12____13

I'm sure it can be done a lot better, I just couldn't think of anything better.

1: Make an array of all input, pick off the first element, group the rest into blocks of 7.
a/13: Consume the first number from the input to run the loop that number of times.
2: Store an empty array in a.
3: Pick a block of 7 and expand it to 7 individual numbers.
b/8: Run a loop 3 times, once for each of seconds, minutes and hours.
4: Add the last two numbers together, for the first iteration that is seconds and time to shift, for the following it is minutes and hour with the overflow from the previous cycle. Make a second copy of the result.
5: Divide the copy by it's limit to produce the overflow and shift the result back one space.
6: Calculate the modulo of the previous division to produce a part of the result.
7: Add this part to the a array.
9: Remove the hour overflow and the second and minute limits from the stack.
10: Take the hour part of a, if it's zero replace it with the hour limit, put it back in the array.
11: For each element in a, place '0' in front, thus converting to string, and throw away everything but the last 2 characters.
12: Collapse the array into a single string delimited by ':', place a newline and shift the array containing the remaining jobs to the front of the stack, thus preparing for the next iteration.

\$\endgroup\$
  • \$\begingroup\$ And what is 13? Good explanation! +1 \$\endgroup\$ – FUZxxl Mar 20 '11 at 9:33
  • \$\begingroup\$ @FUZxxl: 13 and 8 are end markers of blocks a and b. \$\endgroup\$ – schnaader Mar 20 '11 at 13:49
5
\$\begingroup\$

J (172/35) 137 99 107

Now passes all given test cases.

4(1!:2)~LF,~"1([,':',])/"2,"2":"0(10 10#:1 0 0+{.#:{.&{:+{.#.1 0 0-~1&{)"2&(,&}.$~,&3 3&{.&{.)".;._2(1!:1)3

172 is the whole thing; 35 is the number of characters I would give if I was really snooty and refused to do the IO as indicated. (I still modified it a little bit; clocks is a function taking a filename meant to be used interactively within J.)

I sure hope this is a lot easier in J than I make it look.

Edit: Figured out how to do better input parsing in J, eliminated charsub, switched to command line invocation & output.

Edit 2: Changed input of central function to 3x3 matrix, eliminated many pesky parentheses, eliminated names

Edit 3: 0-o'clock handled.

Explanation:

My J still isn't great, and IO is a pain as always. So bits of this are loony.

  • The verb 1 0 0+{.#:{.&{:+{.#.1 0 0-~1&{ takes a three by three matrix (consisting of the input lines, the last two elements are garbage)
  • The h/m/s is gotten with {. (head), the actual time with 1&{ (second element), and the second count with {.&{: (head of tail).
  • The verb uses #. to transform the clock time to seconds. (See documenation.)
  • It adds the second count and then uses #: to get the 3 element answer.
  • The 0 o'clock case is handled by subtracting 1 from the hour before the base change and adding 1 back after. (the two bits with 1 0 0)
  • The rest is input and output, which is really grubby (as always).
  • ".;._2(1!:1)3 gets a 3 'column' matrix of the input with 0s in unfilled positions.
  • ,&}.$~,&3 3&{.&{. cuts the first row off the input and shapes the remaining rows into Nx3x3.
  • The "2 modifies the central verb to take the 3x3 cases.
  • 10 10&#: gives 2 decimal digits for each number giving an Nx3x2 matrix. (Getting 0s for padding was a pain.)
  • ,"2":"0 converts the digits to ASCII (Nx3x2x1) and ravels the last column, giving Nx3x2 again as ASCII.
  • LF,~"1([,':',])/"2 inserts : between each element and appends them (Nx7) and adds a line feed per for (Nx8).
  • 4(1!:2)~ prints each row.
\$\endgroup\$
4
\$\begingroup\$

Haskell, 159 characters

v(_:x:y:z:h:m:s:t:r)=(w%x+1)&":"$z%y&":"$1%z&"\n"$v$t:r where w=y*z;(%)=mod.div(t+h*w-w+m*z+s)
v _=""
d&c=tail.(shows(d+100)c++)
main=interact$v.map read.words

  • Edit: (207 -> 200) sometimes divMod isn't worth it!
  • Edit: (200 -> 178) succumbed to not using the elegant foldr approach (which works for time systems with any number of components!)
  • Edit: (178 -> 164) inlined f
  • Edit: (164 -> 158) removed unnecessary parentheses
  • Edit: (158 -> 160) fixed a bit introduced three edits ago: hours are now correct again
  • Edit: (160 -> 159) dropped a call to tail
\$\endgroup\$
  • \$\begingroup\$ The hour is offset by one in all outputs. \$\endgroup\$ – Joey Adams Mar 20 '11 at 17:00
  • \$\begingroup\$ @Joey: Good catch! Fixed. \$\endgroup\$ – MtnViewMark Mar 20 '11 at 17:38
3
\$\begingroup\$

Ruby, 128 chars

Shamelessly copies from the python one:

d=$<.read.split.map(&:to_i);d[0].times{|o|x,y,z,h,m,s,t=d[o*7+1,7];t+=z*(y*h+m)+s;puts ["%02d"]*3*':'%[(t/y/z-1)%x+1,t/z%y,t%z]}
\$\endgroup\$
3
\$\begingroup\$

Haskell - 219 necessary characters

import Text.Printf
(#)=div
(%)=mod
n?d=(n-1)%d+1
e a n=mapM(\_->a)[1..n]
main=readLn>>=(e$do{
 a<-e getLine 3;
 let[x,y,z,h,m,s,t]=map read.words=<<a;
    w=y*z;e=h*w+m*z+s+t::Int
  in printf"%02d:%02d:%02d\n"(e#w?x)(e#z%y)(e%z)})
\$\endgroup\$
2
\$\begingroup\$

PHP (241 chars)

Takes input from a file passed as an argument.

foreach(array_chunk(array_slice(file($argv[1]),1),3)as$v){list($x,$y,$z)=split(" ",$v[0]);list($h,$m,$s)=split(" ",$v[1]);$e=($v[2]+$s+$z*($m+$h*$y))%($x*$y*$z);$s=$e%$z;$e/=$z;$m=$e%$y;$h=($e/$y)%$x;printf("%02d:%02d:%02d\n",$h?:$x,$m,$s);}

And ungolfed:

$input = array_chunk(array_slice(file($argv[1]),1),3);
foreach($input as $v){
    list($x,$y,$z)=split(" ",$v[0]);
    list($h,$m,$s)=split(" ",$v[1]);
    $t = $v[2];
    $seconds_in_day = $x * $y * $z;
    $total_elapsed = $t + $s + $m*$z + $h*$y*$z;
    $elapsed = $total_elapsed % $seconds_in_day;

    $sec = $elapsed % $z;
    $elapsed /= $z;

    $min = $elapsed % $y;
    $elapsed /= $y;

    $hours = $elapsed % $x;
    if ($hours == 0) $hours = $x;

    printf("%02d:%02d:%02d\n",$hours,$min,$sec);
}

And just to note, without sigils (the dollar sign), this comes out to 205 characters.

\$\endgroup\$
2
\$\begingroup\$

Java, 486 371 characters

Ungolfed version: http://pastebin.com/6LiTdGyi

This gives the same output as in the provided examples.

But I disagree on that behavior: a clock does not have as many numbers as there are hours in a day: it has half of them.

Meaning that if you add 3600 seconds to 12:50:12, it should print 01:50:12, not 13:50:12 (in our standard 24/60/60 system).

I handled that in my code but commented it out in my solution for it to match the examples. Of course if you consider this, then the input times could be considered ambiguous unless you add some AM/PM marker.

But in any case, the puzzle has an inconsistency: if 00 hours should be replaced by x, then hours > (x/2) should be replaced by hours - (x/2).

Edit: Golfed version:

import java.io.File;import java.util.Scanner;public class U{static int i(Scanner s){return
s.nextInt();}public static void main(String[]g)throws Exception{Scanner s=new Scanner(new File(g[0
]));int n=i(s);while(0!=n--){int J=i(s),K=i(s),L=i(s),P=(i(s)*K*L+i(s)*L+i(s)+i(s))%(J*K*L);System.
out.println(String.format("%02d:%02d:%02d",(0==P/L/K%J)?J:P/L/K%J,P/L%K,P%L));}}}
\$\endgroup\$
  • \$\begingroup\$ Hi there, a [code-golf] question requires the shortest answer in the total number of characters. This means a golfed entry should, at least: 1. not use package declarations; 2. not use final; 3. use single-character variable names and class names; 4. generally use the cleverest ways to make the shortest code possible. \$\endgroup\$ – Chris Jester-Young Mar 20 '11 at 1:06
  • \$\begingroup\$ It doesn't matter if your code is unreadable or not; therefore, your "unreadable" version is not useful for a code golf contest if it's not otherwise short. To be honest, Java is a poor language for entering a golf contest with, because compared to most languages, Java is so verbose. :-( \$\endgroup\$ – Chris Jester-Young Mar 20 '11 at 1:07
  • \$\begingroup\$ In the near future, I'll be doing a cleanup exercise where non-golfed entries will be removed from [code-golf] questions. So, if you can make a golfed version (see my first comment), please do; otherwise, your answer will be removed at the next cleanup. \$\endgroup\$ – Chris Jester-Young Mar 20 '11 at 1:10
  • \$\begingroup\$ Hi. Sorry for it all. I got confused... I ended up understanding what golfing meant. I kept the ungolfed version as a link only. I hope that is fine especially because of my doubts regarding the input and expected result. I put then a better golfed version. Right Java ain't the best but I think I did well enough for this golfed version to be kept here. Sorry again. \$\endgroup\$ – tisek Mar 20 '11 at 3:29
  • \$\begingroup\$ @tisek: Thanks for your new version. Here's a suggestion for shortening the code even further: instead of int[]c={i(s),i(s),i(s),i(s),i(s),i(s),i(s)}, you may want to use int a=i(s),b=i(s),c=i(s),d=i(s),e=i(s),f=i(s),g=i(s). Yes, you add 11 characters here, but you save three characters each time you use c[x], which means after 4 such instances, it's paid for itself. I counted 13 such instances, which means you save 28 characters overall! \$\endgroup\$ – Chris Jester-Young Mar 20 '11 at 4:44
2
\$\begingroup\$

Bash - 189 characters:

read n
for((i=0;i<n;i++));do
read x y z
read h m s
read t
R=$(((s+m*z+h*y*z+t)%(x*y*z)))
H=$((R/y/z))
R=$((R-H*y*z))
M=$((R/z))
printf"%02d:%02d:%02d\n"$((((H-1)%x+x)%x+1))$M$((R-M*z))
done
\$\endgroup\$
  • \$\begingroup\$ As I recall the second mod is there for negative elapsed seconds. \$\endgroup\$ – user1099 Apr 1 '11 at 10:34
  • \$\begingroup\$ That printf line doesn't work. Spaces are required between printf and its arguments and between those arguments... \$\endgroup\$ – Mark Reed May 3 '12 at 18:44
1
\$\begingroup\$

PHP, 229 228 characters

<?$v=file($argv[1]);while(++$i<$v[0]*3){list($x,$y,$z)=split(" ",$v[$i++]);list($h,$m,$s)=split(" ",$v[$i++]);$s=($e=($v[$i]+$s+$m*$z+$h*$y*$z)%($x*$y*$z))%$z;$m=($e/=$z)%$y;printf("%02d:%02d:%02d\n",($e/$y)%$x?$e%$x:$x,$m,$s);}

File must be passed into the script as an argument

Ungolfed:

<?php

$v = file($argv[1]); // Automatically break the file into an array by line

while(++$i < $v[0]*3){ // Loop for every three lines
  list($x, $y, $z) = explode(" ", $v[$i++]); // Break apart the first line by space
  list($h, $m, $s) = explode(" ", $v[$i++]); // Break apart the second line

  /*
    Add the starting time to the total number of seconds that have passed
    Divide by total amount of seconds in a day
  */

  $time = ($v[$i] + $s + $m * $z + $h * $y * $z) % ($x * $y * $z);

  $seconds = $time % $z;  // Get the number of seconds
  $minutes = ($time /= $z) % $y; // Remove the end amount of seconds, then get the minutes

  /*
    Remove the end amount of hours
    Determine how many hours there would be
    If the number is zero, then output the max hours
    If the number is not zero, output the amount of hours left
  */

  $hours = ($time / $y) % $x? $e % $x : $x;

  // Display the time in the correct format
  printf("%02d:%02d:%02d\n", $hours, $minutes, $seconds);
}

Changelog:

229 -> 228: No need to set time remaining while performing division on the hours

\$\endgroup\$
1
\$\begingroup\$

Bash, 139 characters

read n
while((n--));do
read x y z;read h m s;read t
((t+=z*(y*h+m)+s,a=(t/y/z-1)%x+1,b=t/z%y,c=t%z))
printf %02d:%02d:%02d\\n $a $b $c
done
\$\endgroup\$
1
\$\begingroup\$

Scala 184 chars:

object C extends App{val r=new java.util.Scanner(System.in)
def n=r.nextInt
for(j<-1 to n;h=n;m=n;s=n;x=n;y=n;z=n;t=n;d=(x*m+y)*s+z+t){printf("%02d:%02d:%02d\n",d/(m*s)%h,d/s%m,d%s)}
}

In conflict to the rules, I claim, that for

14 15 20
1 14 0
-580

The output shouldn't be

14:00:00

but

00:00:00

and that's what my code produces. Please show me a clock which displays 24:00:00 on earth instead of 00:00:00 - maybe 24:59:59. Or do you expect the sequence:

23:59:59
24:00:00
00:00:01

instead of

23:59:59
00:00:00
00:00:01
\$\endgroup\$
  • \$\begingroup\$ On Earth, you won't see 24:00:01, but you do occasionally see 'day N at 24:00:00' used as a synonym for 'day N+1 at 00:00:00'. It's the same time but a different focus - 'midnight tonight' vs 'midnight tomorrow morning'. \$\endgroup\$ – Mark Reed Dec 16 '13 at 14:45
1
\$\begingroup\$

Python 2, 137 bytes

lambda T:["%02d:%02d:%02d"%((s/z/y%x,x)[s%x<1],s/z%y,s%z)for x,y,z,h,m,s,t in[T[i:i+7]for i in range(1,len(T),7)]for s in[s+m*z+h*y*z+t]]

Try it online!

Only slightly shorter than the other Python answer, but takes a different route to get there.

Ungolfed Explanation:

def f(T):
    # ignore first list element, split list into even chunks of length 7
    for i in range(1, len(T), 7):
        # get variables for sublist
        for x, y, z, h, m, s, t in [T[i:i + 7]]:
            # get total time in seconds, inside a list so that we can use list comprehension
            for s in [s + m*z + h*y*z + t]:
                # split total time into parts
                # seconds: convert seconds to minute, take remainder
                sec = s % z
                # minutes: convert seconds to minutes (discard remainder), convert minutes to hours, take remainder
                min = s / z % y
                # hours: convert seconds to minutes (discard remainder),
                #        convert minutes to hours (discard remainder),
                #        convert hours to days, take remainder
                # if seconds are evenly divisible by total hours, use number of hours in day instead ("midnight")
                hr = (s / z / y % x, x)[s % x < 1]

                print "%02d:%02d:%02d"%(hr, min, sec)
\$\endgroup\$
0
\$\begingroup\$

Haskell (815 624 chars non-golfed, blank lines excluded)

Mine prints 00:00:00 instead of 12:00:00 or similar for "midnight"-like times. Edit: changed that.

main = readFile "in.txt" >> mapM_ print . times . map (map read . words) . tail . lines

times [] = []
times ([x,y,z]:[h,m,s]:[t]:xs) = Time x y z h m s +++ t : times xs

data Time = Time {x,y,z,h,m,s :: Int}
hr t | h t == 0 = x t | otherwise = h t

instance Show Time where show t = pad2 (hr t) ++ ':':pad2 (m t) ++ ':':pad2 (s t)

pad2 x | x < 10 = '0':show x | otherwise = show x

t +++ ss | ss < 0  = t +++ (ss + x'*y'*z') | otherwise = Time x' y' z' h' m' s'
  where (x',y',z') = (x t, y t, z t)
        (ms, s') = (s t + ss) `quotRem` z'
        (hs, m') = (m t + ms) `quotRem` y'
        (_,  h') = (h t + hs) `quotRem` x'

Could've abstracted a few things more, but w/e. It completely ignores the first line of the input file, and generally screams at you for improperly-formatted files.

\$\endgroup\$
  • \$\begingroup\$ Note it would be easy to manipulate this solution to allow for more than two digits for hours, minutes, and seconds. \$\endgroup\$ – Dan Burton Mar 19 '11 at 18:16
  • \$\begingroup\$ "The hours on a clock with x hours are arranged similar to ours (1, 2, 3, ... , x)", so 00:00:00 isn't valid. Shouldn't be difficult to adjust for that though. \$\endgroup\$ – Kevin Brown Mar 19 '11 at 18:37
  • \$\begingroup\$ @Bass5098 fixed, and shortened a bit. I still don't have the heart to gut it out into an unreadable form, though. \$\endgroup\$ – Dan Burton Mar 19 '11 at 22:07

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.