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\$
    – seshoumara
    Commented Mar 28, 2017 at 21:10
  • 1
    \$\begingroup\$ is 01:30 valid output? (leading zero) \$\endgroup\$
    – Luis Mendo
    Commented Mar 28, 2017 at 21:18
  • 2
    \$\begingroup\$ Yes, I'll accept that as valid. I'll edit the description. \$\endgroup\$
    – Josh
    Commented Mar 28, 2017 at 21:35
  • 1
    \$\begingroup\$ @seshoumara The input must contain a colon. \$\endgroup\$
    – Josh
    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\$
    – Riley
    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\$
    – Suever
    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\$
    – seshoumara
    Commented Mar 29, 2017 at 0:07
  • 1
    \$\begingroup\$ Crossed out 44 looks like regular 44. \$\endgroup\$
    – Riley
    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\$
    – seshoumara
    Commented Mar 31, 2017 at 2:15
  • 1
    \$\begingroup\$ codegolf.meta.stackexchange.com/a/7427/57100 \$\endgroup\$
    – Riley
    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\$
    – Rod
    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\$
    – Morwenn
    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\$
    – betseg
    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\$
    – jdt
    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\$
    – Arjun
    Commented Mar 29, 2017 at 1:38
  • \$\begingroup\$ And instead of s.split(":"), you can use the newer syntax : s.split<backtick>:<backtick>. \$\endgroup\$
    – Arjun
    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
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\$
    – auhmaan
    Commented Mar 29, 2017 at 10:37
  • \$\begingroup\$ @auhmaan Ah, nice catch. I ended up trimming the trailing :00. \$\endgroup\$
    – Oliver
    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\$
    – Josh
    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\$
    – Laikoni
    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\$
    – Wheat Wizard
    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\$
    – Riker
    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\$
    – DJMcMayhem
    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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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