30
\$\begingroup\$

The Program

You are given two strings, A and B. A is the current position at which your timer is at, and B is the position at which your timer will stop. Both strings are in the format m:ss. You must write a program that determines the amount of time left which should also be formatted as m:ss or mm:ss.

Example

0:00 0:01 -> 0:01 0:55 1:00 -> 0:05 1:45 3:15 -> 1:30 
\$\endgroup\$
9
  • 1
    \$\begingroup\$ In dc the input is read incorrectly, since : is a command (data as code philosophy). Am I allowed to use spaces instead or do I need to find other language to answer this? \$\endgroup\$ Commented Mar 28, 2017 at 21:10
  • 1
    \$\begingroup\$ is 01:30 valid output? (leading zero) \$\endgroup\$ Commented Mar 28, 2017 at 21:18
  • 2
    \$\begingroup\$ Yes, I'll accept that as valid. I'll edit the description. \$\endgroup\$ Commented Mar 28, 2017 at 21:35
  • 1
    \$\begingroup\$ @seshoumara The input must contain a colon. \$\endgroup\$ Commented Mar 28, 2017 at 21:41
  • \$\begingroup\$ What is the maximum value expected for m? \$\endgroup\$ Commented Mar 28, 2017 at 22:06

26 Answers 26

91
\$\begingroup\$

Excel, 6 Bytes

=B1-A1 

Assuming A is in cell A1 and B is in cell B1

\$\endgroup\$
11
  • 37
    \$\begingroup\$ No... NO... I WILL NOT LET EXCEL WIN. +1 you devious individual. \$\endgroup\$ Commented Mar 28, 2017 at 20:42
  • 2
    \$\begingroup\$ Cancel that, |vy':¡ bootstrapped in 05AB1E, nothing I can do... I think Excel may honestly win this, nothing else automatically parses that format that I know of. \$\endgroup\$ Commented Mar 28, 2017 at 20:49
  • 7
    \$\begingroup\$ HOW? HOW? How is Excel winning? My brain must now explo... \$\endgroup\$ Commented Mar 28, 2017 at 22:07
  • 2
    \$\begingroup\$ If m is greater than 23, then the formatting doesn't seem to work. For example if I type 45:45 in A1 and 22:22 in B1, then the result is 23:23:00 Edit Nevermind - max expected value for m is 9. \$\endgroup\$ Commented Mar 28, 2017 at 22:08
  • 4
    \$\begingroup\$ @EngineerToast Whatever the default formatting is worked for me. I just typed in the input, moved to a different cell, typed the formula and hit enter. \$\endgroup\$ Commented Mar 29, 2017 at 13:12
15
\$\begingroup\$

MATL, 17 7 bytes

YOd15XO 

Input is a cell array of strings, in the form {'1:45' '3:15'} or {'1:45', '3:15'}.

Try it online!

Explanation

YO % Input cell array of strings (implicit). Convert to serial date numbers d % Difference 15XO % Convert to format 15, i.e. 'HH:MM'. Display (implicit) 
\$\endgroup\$
1
  • \$\begingroup\$ Oh nice! Carry on! \$\endgroup\$ Commented Mar 28, 2017 at 23:56
8
\$\begingroup\$

Bash + coreutils, 44 39 bytes

tr : \ |dc -e?r60*+r-r60*-60~rn58PA~rnn 

Try it online!

Explanation: using "1:45 3:15" as test case (last example). I show intermediary steps in quotes.

tr : \ | # replace colons with spaces: "1 45 3 15" dc -e? # start dc script, push input to LIFO stack: "15 3 45 1" r60*+ # turn time B to total seconds: "195 45 1" r-r60*- # turn time A to total seconds and get difference: "90" 60~r # turn difference (time left) to minutes and seconds: "1 30" n58P # pop and print minutes, print colon (ASCII code 58): "30" A~rnn # print seconds. Padding with zeroes is done by dividing by #10 (A), and printing the quotient and the remainder. 

Note that I don't check if the minute value needs zero padding, because the OP stated that the maximum value for m is 9.


Below is my original 44 bytes answer, that used the date command to turn the total time left in seconds to the m:ss format.

date -d@`tr : \ |dc -e?r60*+r-r60*-p` +%M:%S 
\$\endgroup\$
4
  • 2
    \$\begingroup\$ @DigitalTrauma Thank you. But in the end, I managed to remove the date command and do the format printing in dc as well. \$\endgroup\$ Commented Mar 29, 2017 at 0:07
  • 1
    \$\begingroup\$ Crossed out 44 looks like regular 44. \$\endgroup\$ Commented Mar 30, 2017 at 22:40
  • 1
    \$\begingroup\$ @Riley I crossed out the spaces surrounding 44 as well, to get the effect that should have been there in the first place. \$\endgroup\$ Commented Mar 31, 2017 at 2:15
  • 1
    \$\begingroup\$ codegolf.meta.stackexchange.com/a/7427/57100 \$\endgroup\$ Commented Mar 31, 2017 at 2:19
6
\$\begingroup\$

Python 2, 90 87 83 80 bytes

Takes input like "2:45","5:01".

a,b=[60*int(s[-5:-3])+int(s[-2:])for s in input()] print'%d:%02d'%divmod(b-a,60) 

Try it online

\$\endgroup\$
3
  • \$\begingroup\$ you can use map on input to save 3 bytes \$\endgroup\$ Commented Mar 28, 2017 at 21:27
  • \$\begingroup\$ you can use list comprehension to save several bytes: a,b=[60*int(s[-5:-3])+int(s[-2:])for s in input()] \$\endgroup\$ Commented Mar 31, 2017 at 14:01
  • \$\begingroup\$ If I'm not mistaken, you can save three additional characters replacing the two last lines by print'%d:%02d'%divmod(b-a,60) :) \$\endgroup\$ Commented Apr 3, 2017 at 18:21
5
\$\begingroup\$

c, 86

f(a,b,c,d){scanf("%d:%d%d:%d",&a,&b,&c,&d);d+=(c-a)*60-b;printf("%d:%02d",d/60,d%60);} 

Reads space-separated times from STDIN.

Try it online.

\$\endgroup\$
5
\$\begingroup\$

Batch, 74 bytes

@set t=%2-(%1) @set/as=%t::=*60+1%,m=s/60,t=s/10%%6 @echo %m%:%t%%s:~-1% 

Replacing the : in the time with *60+1 converts it into an expression that calculates the number of seconds. Batch interprets leading zeros as octal so I prepend a 1 to the seconds to ensure decimal conversion; fortunately the two 1s cancel out.

\$\endgroup\$
5
\$\begingroup\$

C, 112 100 bytes

Thanks to @betseg for saving 11 bytes and thanks to @Johan du Toit for saving one byte!

i,j;f(char*a,char*b){i=atoi(b)-atoi(a);j=atoi(b+2)-atoi(a+2);j<0?i--,j+=60:0;printf("%d:%02d",i,j);} 

Try it online!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can change %s%d with %02d and remove the ?:. Try it online! \$\endgroup\$ Commented Mar 28, 2017 at 22:00
  • 1
    \$\begingroup\$ scanf() is your friend for reading multiple integers. \$\endgroup\$ Commented Mar 28, 2017 at 23:40
  • 1
    \$\begingroup\$ You can also save 1 byte by using: j<0?i++,j+=60:0; \$\endgroup\$ Commented Mar 29, 2017 at 11:01
  • \$\begingroup\$ @DigitalTrauma Nononono, It's usually shorter to use arguments which he did. \$\endgroup\$ Commented Mar 29, 2017 at 13:05
5
\$\begingroup\$

MySQL, 13 22 bytes

select right(timediff(B,A),5) 

expects the times in A and B.

\$\endgroup\$
4
\$\begingroup\$

Bash + GNU utilities, 43

date -d@`date -f- +%s|dc -e??r-60/p` +%M:%S 

Try it online.

Explanation

 date -f- +%s # read in 2 line-delimited dates and output as number of seconds since the epoch |dc -e # pipe to dc expression: ?? # - read 2 input numbers r- # - reverse and subtract 60/ # - divide by 60 p # - output ` ` # evaluate date|dc command date -d@ +%M:%S # format seconds difference and output 

Note the dc expression divides by 60, because date reads the input as H:MM instead of M:SS.

\$\endgroup\$
4
\$\begingroup\$

ECMAScript 6, 99 91 85 bytes

Single Line:

f=s=>s.split`:`.reduce((a,e,i)=>a+e*(!i?60:1),0);t=n=>~~(n/60)+":"+n%60;t(f(b)-f(a)); 

Slightly formatted:

f=s=>s.split`:`.reduce((a,e,i)=>a+e*(!i?60:1),0); t=n=>~~(n/60)+":"+n%60; t(f(b)-f(a)); 

I feel there could be some some savings in there.. but I am not seeing them at present.

Edit - excellent suggestions in the comments.

\$\endgroup\$
2
  • \$\begingroup\$ You can remove the parentheses around the s. \$\endgroup\$ Commented Mar 29, 2017 at 1:38
  • \$\begingroup\$ And instead of s.split(":"), you can use the newer syntax : s.split<backtick>:<backtick>. \$\endgroup\$ Commented Mar 29, 2017 at 1:39
4
\$\begingroup\$

PHP, 55 53 bytes

<?=date('i:s',($s=strtotime)($argv[2])-$s($argv[1])); 

takes input from command line arguments

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 53 bytes: <?=date('i:s',($x=strtotime)($argv[2])-$x($argv[1])); \$\endgroup\$ Commented Mar 31, 2017 at 1:02
4
\$\begingroup\$

Rebol, 5 bytes

b - a 

Assuming I didn't miss any rules..

Rebol has arithmetic built-in for a number of literal data types. This also applies to its descendants such as Red

\$\endgroup\$
2
  • \$\begingroup\$ I know little to nothing about this language. \$\endgroup\$ Commented Apr 19, 2017 at 17:59
  • \$\begingroup\$ @carusocomputing chat.stackoverflow.com/rooms/291/rebol \$\endgroup\$ Commented Apr 19, 2017 at 20:21
3
\$\begingroup\$

C#, 72 bytes

using System;a=>b=>((DateTime.Parse(b)-DateTime.Parse(a))+"").Remove(5); 

Takes input as strings. b="3:15" a="1:45".

Explanation:

Because DateTime.Parse() returns a Date in hh:mm:ss format, I am able to parse the result into a string using +"", then trim the trailing :00.

This works with hh:mm because there are both 60 seconds in a minute and 60 minutes in an hour.

0:01 0:00 returns 0:01

1:00 0:55 returns 0:05

3:15 1:45 returns 1:30

\$\endgroup\$
3
  • 3
    \$\begingroup\$ Unfortunately, the DateTime.Parse() is taking the input -- for example, 1:45 -- as hh:mm and not mm:ss, resulting in the follow output -- for A 1:45 and B 3:15 -- [01:30:00] ( hh:mm:ss ) ( even with CultureInfo.InvariantCulture specified ). You might have to add a "0:" + a/b when parsing. \$\endgroup\$ Commented Mar 29, 2017 at 10:37
  • \$\begingroup\$ @auhmaan Ah, nice catch. I ended up trimming the trailing :00. \$\endgroup\$ Commented Mar 29, 2017 at 14:05
  • \$\begingroup\$ I believe you need a ; on the end, you can use currying i.e. a=>b=>, you need to fully qualify DateTime or include using System;. \$\endgroup\$ Commented Mar 30, 2017 at 16:24
2
\$\begingroup\$

Pyth, 47 45 44 40 Bytes

J.U-Zbm+*60hdedmmvkcd\:.z%"%d:%02d".DJ60 

Takes the input separated by newlines.

Pyth had no time built-ins useful for this. I tried some fancy eval() stuff but apparantly Pyth can't eval stuff with * or any leading zeroes whatsoever. This got much longer than i hoped. Quite some bytes are spent on adding a leading zero to the output. At least I'm shorter than bash. Will add explanation if asked.

Try this!

alternative solution, 48 Bytes

J.U-Zbm+*60hdh_dmmvkcd\:.z K%J60 s[/J60\:*<KT\0K 
\$\endgroup\$
2
\$\begingroup\$

Haskell, 98 127 86 Bytes

r(m:_:s)=60*read[m]+read s a#b|(d,m)<-divMod(r b-r a)60=show d++':':['0'|m<=9]++show m 

Try it online!

But I wonder if there are some library functions for this

EDIT: Removed import, also fixed an error where it showed m:s instead of m:ss

Also, well-formatted version:

convert :: String -> Integer convert (a:_:b) = (read [a])*60+(read b) diffTime :: String -> String -> String diffTime s1 s2 = let (d,m) = divMod (c b-c a) 60 in show d ++ ":" ++ pad2d m pad2d :: Int -> String pad2d n = ['0'|n<=9]++show n 

EDIT2: Golfed off (30?) bytes thanks to Laikoni! Also golfed some other misc. bytes.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You should tell us what language this is and how many bytes it uses. \$\endgroup\$ Commented Mar 28, 2017 at 21:38
  • 2
    \$\begingroup\$ Yeah, I didn't mean to press post (who knew tab+enter from the text box posts your answer?) \$\endgroup\$ Commented Mar 28, 2017 at 21:48
  • \$\begingroup\$ Same approach, 86 bytes: Try it online! \$\endgroup\$ Commented Mar 28, 2017 at 22:30
  • \$\begingroup\$ I didn't think of using a list comprehension. Thanks :) \$\endgroup\$ Commented Mar 28, 2017 at 22:32
2
\$\begingroup\$

T-SQL, 238 bytes

CREATE PROCEDURE d @a time,@b time AS BEGIN DECLARE @d int DECLARE @s varchar(2) SET @d=datediff(s,@a,@b);SET @s=CAST(@d%3600/60 AS VARCHAR(3)) SELECT CAST(@d/3600 AS VARCHAR(3))+':'+(SELECT CASE WHEN LEN(@s)=1 THEN '0'+@s ELSE @s END)END 

Usage:

EXEC d '00:55','01:00' 

Seeing the PostGres example earlier I realised I hadn't seen many golfing attempts in SQL so I had a go at it in T-SQL. Now I know why you don't see much golfing in SQL :D

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

CJam, 34 33 25 bytes

Saved 8 bytes thanks to Martin Ender!

{r':/60b}2*\m60mds2Te[':\ 

Try it online!

Explanation

{ e# Start of block r e# Read one time from input ':/ e# Split on colons, gives [minutes seconds] 60b e# Convert from base 60 }2* e# Run this block 2 times e# At this point, we have the two times in seconds on the stack \ e# Swap top elements m e# Subtract 60md e# Divmod the result by 60, to convert back to minutes and seconds s e# Convert the seconds to a string 2Te[ e# Pad it to 2 characters by adding 0s to the left (T = 0) ': e# Push a colon character \ e# Swap top elements, bringing seconds back to the top 
\$\endgroup\$
0
2
\$\begingroup\$

T-SQL, 82 Bytes

select left(cast(dateadd(minute, datediff(S,'0:00','0:01')/60,114) as time(0)), 5) 
\$\endgroup\$
2
\$\begingroup\$

Python, 160 bytes

I am still new to code golf so if anyone has any suggestions, I would appreciate it.

a, b = input() def z(x): x = x.split(":") return int(x[0])*60+int(x[1]) a, b = z(a),z(b) s, m = b-a,0 while s >= 60: s -= 60 m += 1 print(str(m)+":"+str(s)) 
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Hello and welcome to our site. It seems that you are taking input for your program from preinitialized variables. However this is not permitted under out defaults for IO. I would recommend for this specific case to take input via raw_input(). \$\endgroup\$ Commented Mar 30, 2017 at 0:07
1
\$\begingroup\$

REXX, 79 bytes

arg t q say right(time(,f(q)-f(t),s),5) f:return time(s,'00:'right(arg(1),5,0)) 
\$\endgroup\$
1
\$\begingroup\$

Pyth, 28

%"%d:%02d".Dh.+misMcd\:60Q60 

Try it.

Explanation

 cd\: # lambda to split c on ":" sM # map to convert string to int mi 60Q # convert from base-60 list to give seconds .+ # delta of the two seconds values h # single-item list to int .D 60 # divmod by 60 %"%d:%02d" # format output 
\$\endgroup\$
1
\$\begingroup\$

Java 7, 164 bytes

String c(String a,String b){long s=x(b,1)-x(a,1)+(x(b,0)-x(a,0))*60,m=s%60;return(s/60)+":"+(m>9?m:"0"+m);}long x(String s,int i){return new Long(s.split(":")[i]);} 

Explanation:

String c(String a, String b){ // Method with two String parameters and String return-type long s = x(b,1) - x(a,1) // Get difference in seconds from input times + (x(b,0) - x(a,0)*60, // plus the difference in minutes times 60 to get the seconds m = s%60; // Temp variable of seconds after we've subtracted the minutes (used multiple times) return (s/60) // Return minutes +":" // plus ":" +(m>9?m:"0"+m); // plus seconds (with a leading 0 if necessary) } // End of method long x(String s,int i){ // Separate ethod with String and Integer parameters and long return-type return new Long(s.split(":")[i]; // Return either minutes or seconds of String parameter based on the index } // End of method 

Test code:

Try it here.

class M{ String c(String a,String b){long s=x(b,1)-x(a,1)+(x(b,0)-x(a,0))*60,m=s%60;return(s/60)+":"+(m>9?m:"0"+m);}long x(String s,int i){return new Long(s.split(":")[i]);} public static void main(String[] a){ M m = new M(); System.out.println(m.c("0:00", "0:01")); System.out.println(m.c("0:55", "1:00")); System.out.println(m.c("1:45", "3:15")); } } 

Output:

0:01 0:05 1:30 
\$\endgroup\$
1
\$\begingroup\$

TXR Lisp, 101 bytes

$ txr -e '(awk (:let (s "%M:%S")) ((mf (time-parse s)) (prn (time-string-local (- [f 1].(time-utc) [f 0].(time-utc)) s))))' 13:49 14:49 01:00 0:13 1:47 01:34 5:01 5:59 00:58 6:00 6:00 00:00 6:00 5:00 59:00 

Condensed: (awk(:let(s"%M:%S"))((mf(time-parse s))(prn(time-string-local(-[f 1].(time-utc)[f 0].(time-utc))s))))

\$\endgroup\$
1
  • \$\begingroup\$ You need a bytecount, and I don't think this is fully golfed. \$\endgroup\$ Commented Mar 30, 2017 at 1:58
1
\$\begingroup\$

Ruby, 91 bytes

require'time';t=Time;d=t.parse($*[1])-t.parse($*[0]);puts t.at(d.to_i).utc.strftime '%H:%M' 

Try it online!

Takes input from command line arguments.

Invocation:

ruby outatime.rb $A $B 

Example:

ruby outatime.rb 1:45 3:15 

Output:

01:30

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to the site! \$\endgroup\$ Commented Mar 30, 2017 at 20:08
1
\$\begingroup\$

PowerShell 47 Bytes

param($s,[timespan]$f)($f-$s).ToString("h\:mm") 

Simple timespan math and coverting to hour and seconds string.

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

JavaScript, 88 bytes

a=>b=>{c=a.split`:`,d=b.split`:`;return +c[0]-d[0]-d[1]>c[1]?1:0+":"+(+c[1]+60-d[1])%60} 

Try it online!

Explanation:

Splits the inputs on the colon

c=a.split`:`,d=b.split`:`; 

Converts string to int

+c[0] 

Gets the minute value

+c[0]-d[0]-d[1]>c[1]?1:0 

Gets the second value

(+c[1]+60-d[1])%60 

Returns the string minutes:seconds

return +c[0]-d[0]-d[1]>c[1]?1:0+":"+(+c[1]+60-d[1])%60 
\$\endgroup\$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.