31
\$\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\$
  • 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 Mar 28 '17 at 21:10
  • 1
    \$\begingroup\$ is 01:30 valid output? (leading zero) \$\endgroup\$ – Luis Mendo Mar 28 '17 at 21:18
  • 2
    \$\begingroup\$ Yes, I'll accept that as valid. I'll edit the description. \$\endgroup\$ – Josh Mar 28 '17 at 21:35
  • 1
    \$\begingroup\$ @seshoumara The input must contain a colon. \$\endgroup\$ – Josh Mar 28 '17 at 21:41
  • \$\begingroup\$ What is the maximum value expected for m? \$\endgroup\$ – Digital Trauma Mar 28 '17 at 22:06

26 Answers 26

92
\$\begingroup\$

Excel, 6 Bytes

=B1-A1

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

\$\endgroup\$
  • 37
    \$\begingroup\$ No... NO... I WILL NOT LET EXCEL WIN. +1 you devious individual. \$\endgroup\$ – Magic Octopus Urn Mar 28 '17 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\$ – Magic Octopus Urn Mar 28 '17 at 20:49
  • 7
    \$\begingroup\$ HOW? HOW? How is Excel winning? My brain must now explo... \$\endgroup\$ – caird coinheringaahing Mar 28 '17 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\$ – Digital Trauma Mar 28 '17 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 Mar 29 '17 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\$
  • \$\begingroup\$ Oh nice! Carry on! \$\endgroup\$ – Suever Mar 28 '17 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\$
  • 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 Mar 29 '17 at 0:07
  • 1
    \$\begingroup\$ Crossed out 44 looks like regular 44. \$\endgroup\$ – Riley Mar 30 '17 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 Mar 31 '17 at 2:15
  • 1
    \$\begingroup\$ codegolf.meta.stackexchange.com/a/7427/57100 \$\endgroup\$ – Riley Mar 31 '17 at 2:19
7
\$\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\$
  • \$\begingroup\$ you can use map on input to save 3 bytes \$\endgroup\$ – Rod Mar 28 '17 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\$ – Felipe Nardi Batista Mar 31 '17 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 Apr 3 '17 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\$
  • 1
    \$\begingroup\$ You can change %s%d with %02d and remove the ?:. Try it online! \$\endgroup\$ – betseg Mar 28 '17 at 22:00
  • 1
    \$\begingroup\$ scanf() is your friend for reading multiple integers. \$\endgroup\$ – Digital Trauma Mar 28 '17 at 23:40
  • 1
    \$\begingroup\$ You can also save 1 byte by using: j<0?i++,j+=60:0; \$\endgroup\$ – Johan du Toit Mar 29 '17 at 11:01
  • \$\begingroup\$ @DigitalTrauma Nononono, It's usually shorter to use arguments which he did. \$\endgroup\$ – Matthew Roh Mar 29 '17 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\$
  • \$\begingroup\$ You can remove the parentheses around the s. \$\endgroup\$ – Arjun Mar 29 '17 at 1:38
  • \$\begingroup\$ And instead of s.split(":"), you can use the newer syntax : s.split<backtick>:<backtick>. \$\endgroup\$ – Arjun Mar 29 '17 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
    \$\begingroup\$ 53 bytes: <?=date('i:s',($x=strtotime)($argv[2])-$x($argv[1])); \$\endgroup\$ – Ismael Miguel Mar 31 '17 at 1:02
4
\$\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
    \$\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 Mar 29 '17 at 10:37
  • \$\begingroup\$ @auhmaan Ah, nice catch. I ended up trimming the trailing :00. \$\endgroup\$ – Oliver Mar 29 '17 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\$ – TheLethalCoder Mar 30 '17 at 16:24
3
\$\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\$

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\$
  • 1
    \$\begingroup\$ You should tell us what language this is and how many bytes it uses. \$\endgroup\$ – Josh Mar 28 '17 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\$ – Generic Display Name Mar 28 '17 at 21:48
  • \$\begingroup\$ Same approach, 86 bytes: Try it online! \$\endgroup\$ – Laikoni Mar 28 '17 at 22:30
  • \$\begingroup\$ I didn't think of using a list comprehension. Thanks :) \$\endgroup\$ – Generic Display Name Mar 28 '17 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\$
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
    \$\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 Mar 30 '17 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\$
  • \$\begingroup\$ You need a bytecount, and I don't think this is fully golfed. \$\endgroup\$ – Rɪᴋᴇʀ Mar 30 '17 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\$
  • \$\begingroup\$ Welcome to the site! \$\endgroup\$ – DJMcMayhem Mar 30 '17 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, privacy policy and cookie policy

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