24
\$\begingroup\$

Whenever I search for the running length of a movie in IMDb, it is displayed in minutes. Immediately I would try to convert it into hour(s) and minute(s). It would be better if we could automate this.

Input:

150 min

Output:

2 hours 30 minutes

Input:

90 min

Output:

1 hour 30 minutes

Input:

61 min

Output:

1 hour 1 minute

Input:

60 min

Output:

1 hour 0 minute or 1 hour 0 minutes

Following are the conditions:

  1. Input and Output should be in this exact format.

  2. Input minutes will between 0 and 240.

  3. Your answer can accept command line arguments or read input from the user or a function.

  4. Output should not be enclosed within quotes.

  5. Output must be printed, not returned.

Leaderboard:

    var QUESTION_ID=65106,OVERRIDE_USER=16196;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/65106/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
    body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}#answer-list{padding-right: 100px}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

Result:

Its a tie between CJam and Pyth. Accepting CJam's answer as it was submitted before Pyth's 35 bytes code. However, please continue encouraging new submissions.

\$\endgroup\$
  • 2
    \$\begingroup\$ @quintopia According to site rules, no. You can use a function if you want to. \$\endgroup\$ – Doorknob Nov 28 '15 at 17:34
  • 1
    \$\begingroup\$ Technically, I (and I bet other humans) can read "150 minutes". \$\endgroup\$ – PyRulez Nov 28 '15 at 21:55
  • 1
    \$\begingroup\$ Why restrict to >59 minutes? Also, I prefer 61 minutes to 1 hour 1 minute and really would hate seeing 1 hour 0 minutes \$\endgroup\$ – markshancock Nov 29 '15 at 0:28
  • 6
    \$\begingroup\$ You changed the input range to be 0-240 but haven't included any test cases less than 60. I recommend sticking with the original range given that 28 answers have already been posted. \$\endgroup\$ – Alex A. Nov 29 '15 at 7:03
  • 2
    \$\begingroup\$ It appears you also changed the acceptable output for whole hours. Unless a challenge has blaring issues that need to be fixed, please do not make changes to a challenge that invalidate existing answers. \$\endgroup\$ – Alex A. Nov 29 '15 at 7:12

50 Answers 50

10
+100
\$\begingroup\$

CJam, 39 35 bytes

ri60md]"hour minute"S/.{1$1>'s*+}S*

Try it online

Latest version includes improvements suggested by @MartinBüttner, particularly using the element-wise vector operator instead of transposing the two lists.

Explanation:

ri    Get input and convert to integer.
60md  Split into hours and minutes by calculating moddiv of input.
]     Wrap hours and minutes in a list.
"hour minute"
      String with units.
S/    Split it at spaces, giving ["hour" "minute"]
.{    Apply block element-wise to pair of vectors.
  1$    Copy number to top.
  1>    Check for greater than 1.
  's    Push 's.
  *     Multiply with comparison result, giving 's if greater 1, nothing otherwise.
  +     Concatenate optional 's with rest of string.
}     End block applied to both parts.
S*    Join with spaces.
|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ 35: ri60md]r"utehour"+6/W%.{1$1>'s*+}S* (Looks like this gives you a pretty solid lead on this challenge :)) \$\endgroup\$ – Martin Ender Nov 29 '15 at 19:23
  • \$\begingroup\$ @MartinBüttner r"utehour"+6/W% is actually the same length as "hour minute"S/, so that part ends up not helping. I think I had seen . used with a block before, but I had forgotten again that it was supported. \$\endgroup\$ – Reto Koradi Nov 29 '15 at 20:12
  • \$\begingroup\$ Ah, right, I had first posted a 36-byte version where it actually helped (but then deleted the comment and replaced it by the 35-byte version where it doesn't matter any more). \$\endgroup\$ – Martin Ender Nov 29 '15 at 20:14
19
\$\begingroup\$

Python 3, 50 67 119 116 112 111 104 94 bytes

I'm not fond of going back to %-style string formatting, but it saves 6 bytes on .format.

Edit: Forgot to parse input.

Edit: Forgot to handle plurals.

Edit: Yay lambdas!

Edit: Added ungolfing

Edit: Darn it. Lambdas didn't help.

Edit: Since the minutes have maximum three digits, and int() doesn't mind spaces in the string, I can save a few bytes by using input()[:3].

i,j=divmod(int(input()[:3]),60);print(str(i),"hour"+("s"[:i!=1]),str(j),"minute"+("s"[:i!=1]))

Ungolfed:

string = input()[:3]
hours, minutes = divmod(int(string), 60)
a = string(div)
b = "hour" + ("s" if hours == 1 else "")
c = string(mod)
d = "minute" + ("s" if minutes == 1 else "")
print(a, b, c, d)
|improve this answer|||||
\$\endgroup\$
  • 22
    \$\begingroup\$ Ah! Increasing bytecount! +1 for not giving up ;-) \$\endgroup\$ – agtoever Nov 28 '15 at 17:52
9
\$\begingroup\$

JavaScript, 78 bytes

n=>(h=(n=parseInt(n))/60|0)+` hour${h-1?"s":""} ${m=n%60} minute`+(m-1?"s":"")
<!--                               Try the test suite below!                              --><strong id="bytecount" style="display:inline; font-size:32px; font-family:Helvetica"></strong><strong id="bytediff" style="display:inline; margin-left:10px; font-size:32px; font-family:Helvetica; color:lightgray"></strong><br><br><pre style="margin:0">Code:</pre><textarea id="textbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><pre style="margin:0">Input:</pre><textarea id="inputbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><button id="testbtn">Test!</button><button id="resetbtn">Reset</button><br><p><strong id="origheader" style="font-family:Helvetica; display:none">Original Code Output:</strong><p><div id="origoutput" style="margin-left:15px"></div><p><strong id="newheader" style="font-family:Helvetica; display:none">New Code Output:</strong><p><div id="newoutput" style="margin-left:15px"></div><script type="text/javascript" id="golfsnippet">var bytecount=document.getElementById("bytecount");var bytediff=document.getElementById("bytediff");var textbox=document.getElementById("textbox");var inputbox=document.getElementById("inputbox");var testbtn=document.getElementById("testbtn");var resetbtn=document.getElementById("resetbtn");var origheader=document.getElementById("origheader");var newheader=document.getElementById("newheader");var origoutput=document.getElementById("origoutput");var newoutput=document.getElementById("newoutput");textbox.style.width=inputbox.style.width=window.innerWidth-50+"px";var _originalCode=null;function getOriginalCode(){if(_originalCode!=null)return _originalCode;var allScripts=document.getElementsByTagName("script");for(var i=0;i<allScripts.length;i++){var script=allScripts[i];if(script.id!="golfsnippet"){originalCode=script.textContent.trim();return originalCode}}}function getNewCode(){return textbox.value.trim()}function getInput(){try{var inputText=inputbox.value.trim();var input=eval("["+inputText+"]");return input}catch(e){return null}}function setTextbox(s){textbox.value=s;onTextboxChange()}function setOutput(output,s){output.innerHTML=s}function addOutput(output,data){output.innerHTML+='<pre style="background-color:'+(data.type=="err"?"lightcoral":"lightgray")+'">'+escape(data.content)+"</pre>"}function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}function onTextboxChange(){var newLength=getByteCount(getNewCode());var oldLength=getByteCount(getOriginalCode());bytecount.innerHTML=newLength+" bytes";var diff=newLength-oldLength;if(diff>0){bytediff.innerHTML="(+"+diff+")";bytediff.style.color="lightcoral"}else if(diff<0){bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgreen"}else{bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgray"}}function onTestBtn(evt){origheader.style.display="inline";newheader.style.display="inline";setOutput(newoutput,"");setOutput(origoutput,"");var input=getInput();if(input===null){addOutput(origoutput,{type:"err",content:"Input is malformed. Using no input."});addOutput(newoutput,{type:"err",content:"Input is malformed. Using no input."});input=[]}doInterpret(getNewCode(),input,function(data){addOutput(newoutput,data)});doInterpret(getOriginalCode(),input,function(data){addOutput(origoutput,data)});evt.stopPropagation();return false}function onResetBtn(evt){setTextbox(getOriginalCode());origheader.style.display="none";newheader.style.display="none";setOutput(origoutput,"");setOutput(newoutput,"")}function escape(s){return s.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}window.alert=function(){};window.prompt=function(){};function doInterpret(code,input,cb){var workerCode=interpret.toString()+";function stdout(s){ self.postMessage( {'type': 'out', 'content': s} ); }"+" function stderr(s){ self.postMessage( {'type': 'err', 'content': s} ); }"+" function kill(){ self.close(); }"+" self.addEventListener('message', function(msg){ interpret(msg.data.code, msg.data.input); });";var interpreter=new Worker(URL.createObjectURL(new Blob([workerCode])));interpreter.addEventListener("message",function(msg){cb(msg.data)});interpreter.postMessage({"code":code,"input":input});setTimeout(function(){interpreter.terminate()},1E4)}setTimeout(function(){getOriginalCode();textbox.addEventListener("input",onTextboxChange);testbtn.addEventListener("click",onTestBtn);resetbtn.addEventListener("click",onResetBtn);setTextbox(getOriginalCode())},100);function interpret(code,input){window={};alert=function(s){stdout(s)};window.alert=alert;console.log=alert;prompt=function(s){if(input.length<1)stderr("not enough input");else{var nextInput=input[0];input=input.slice(1);return nextInput.toString()}};window.prompt=prompt;(function(){try{var evalResult=eval(code);if(typeof evalResult=="function"){var callResult=evalResult.apply(this,input);if(typeof callResult!="undefined")stdout(callResult)}}catch(e){stderr(e.message)}})()};</script>

For the test suite, enter input like "61 min" into the input box.


Explanation

n=>                 //Define anonymous function w/ parameter n
(h=                 //start building the string to return with h, the # of hours
(n=parseInt(n))     //parse input for n
/60|0)+             //set h to floor(n / 60)
` hour              //add ' hour' to the string to return
${h-1?"s":""}       //add 's' to the string to return if h != 1, else add ''
                    //<--(a single space) add ' ' to the string to return
${m=n%60}           //set m, the # of miuntes, to n % 60, and add it to the string to return
 minute`+           //add ' minute' to the string to return
(m-1?"s":"")        //add 's' to the string to return if m != 1, else add ''
                    //implicitly return
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Good one. Suggestion: reduce parseInt(n) to +n. \$\endgroup\$ – nicael Nov 28 '15 at 18:39
  • 1
    \$\begingroup\$ Input will not be just an integer. It fails when i provide input as 150 min. \$\endgroup\$ – Vasu Adari Nov 28 '15 at 19:12
  • 1
    \$\begingroup\$ @VasuAdari It's working for me, outputs 2 hours 30 minutes. May I ask how you tested it? \$\endgroup\$ – jrich Nov 28 '15 at 19:15
  • 3
    \$\begingroup\$ @ev3commander When using the test snippet, wrap the input in quotes so that it is recognized as a string. e.g. "61 min" or '61 min' \$\endgroup\$ – jrich Nov 28 '15 at 21:40
  • 1
    \$\begingroup\$ +1 For JavaScript. Now you just have to make it a bookmarlet ;) \$\endgroup\$ – MayorMonty Nov 30 '15 at 2:37
6
\$\begingroup\$

Pyth, 39 38 bytes

jd.iJ.Dv-zG60+Vc"hour minute")m*\s>d1J
|improve this answer|||||
\$\endgroup\$
5
\$\begingroup\$

Vitsy, 57 54 52 bytes

Oh, wow, I don't even have integers in my language. o-o

VVa6*Dv/D1M-D1m'ruoh 'Z' 'OVvM1m'etunim 'Z
N1-(['s']
VV                                      Capture the input as a final global 
                                        variable, and push it again.
  a6*Dv/1M-                             Get floor(input/60), capturing 60 as a 
                                        temp variable in the process.
           DN                           Duplicate and output it as a number.
             1-(['s']                   If it is only one, push 's'.

            'ruoh '                     Push ' hour'
                   Z                    Output everything.
                    ' 'O                Output a space.
V                                       Push the input.
 v                                      Get the temp variable (60).
  M                                     Modulo.
            N                           Output as a number.
             1-(['s']                   If it is only one, push 's'.

             'ruoh '                    Push ' hour'
                    Z                   Output everything.

Try it online!

|improve this answer|||||
\$\endgroup\$
4
\$\begingroup\$

K5, 55 51 bytes

" "/(" hour";" minute"){y,x,("s";"")1=.y}'$25 60\.*" "\

This is more general than it strictly has to be; might still golf it down further.

In action:

  f: " "/(" hour";" minute"){y,x,("s";"")1=.y}'$25 60\.*" "\;

  f'("61 min";"120 min";"150 min")
("1 hour 1 minute"
 "2 hours 0 minutes"
 "2 hours 30 minutes")

Edit:

This program went through several very different iterations in the course of development, and I thought that it might be more illuminating to show some of the intermediate steps.

Here was my first stab at the problem, before the pluralization requirement was introduced. There is clear repetition here:

{($_x%60)," hours ",($_60!x)," minutes"}@.*" "\

I realized that the general way to handle casting out of places was K5's "decode" form. To slot values into place in the string I used the "dot-apply" primitive, which applies an argument list to a function and unpacks the list into individual parameters:

{x," hours ",y," minutes"}.$25 60\.*" "\

Not much redundancy left here. When pluralization was added, I decomposed that leading anonymous function into a transformation I could apply to each number, like this:

{x,y,("s";"")1=.x}

Join x, y, and either s or nothing, depending on whether x is equal to "1". Ultimately it worked better to reverse the order of the arguments to this function.

Edit 2:

" "/(" hour";" minute"){y,x,("s";"")1=.y}'$25 60\.*" "\
" "/(" hour";" minute"){y,x,(~1=.y)#"s"}'$5 60\.-4_

Several small improvements here. A better way of selecting an "s" or an empty string, a shorter constant for "decode" which reflects the limited range of input, and a simpler way of discarding "min".

|improve this answer|||||
\$\endgroup\$
4
\$\begingroup\$

Pyth, 46 bytes

jKdm++J.v+++hd:z03K60K+td*\s>J1c"/hour %minute

Takes input as x min and outputs x hours y minutes

Try it Here

Explanation:

   m~~~~~~~~~~~~~~~~~~~~~~~~~~~c"/hour %minute - map(func, "/hour %minute".split(" "))
            hd                                 - Get the first character of the string (/ or %)
              :z03                             - Get the first 3 characters of input
         +++      K60                          - Join them together and add a space and 60 to the end
      J.v                                      - Evaluate it and set result to J
                       td                      - Get all the characters of the string but the first (hour, minute)
                      +  *\s>J1                - If the result of the evaluated expression is less than 1, add an 's' character to the string
    ++               K                         - Join the results seperated with a space
jKd                                            - Join the 2 halves together with a space
|improve this answer|||||
\$\endgroup\$
3
\$\begingroup\$

Perl 6, 80 73 bytes

80 byte original

{my$h=$_ div 60;my$m=$_%60;"$h hour{'s'x?($h-1)}"~" $m minute{'s'x?($m-1)}"x?$m}

Usage:

.say for (150,90,61,60).map:
  {my$h=$_ div 60;my$m=$_%60;"$h hour{'s'x?($h-1)}"~" $m minute{'s'x?($m-1)}"x?$m}
2 hours 30 minutes
1 hour 30 minutes
1 hour 1 minute
1 hour

Due to a change in the question I can remove x?$m from the end of the function, which allows me to reduce it by 3 more bytes.

{my$h=$_ div 60;my$m=$_%60;"$h hour{'s'x?($h-1)} $m minute{'s'x?($m-1)}"}
2 hours 30 minutes
1 hour 30 minutes
1 hour 1 minute
1 hour 0 minutes
|improve this answer|||||
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 100 94 89 81 bytes

t=>(h=0|(t=parseInt(t))/60)+' hour'+(h>1?'s ':' ')+t%60+' minute'+(t%60>1?'s':'')

De-golfed demo (converted to ES5, as not all the browsers support ES6 yet)

function s(t) {
  return (h = 0 | (t = parseInt(t)) / 60) + ' hour' + (h > 1 ? 's ' : ' ') + t % 60 + ' minute' + (t % 60 > 1 ? 's' : '');
}

alert(s(prompt()))

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ You could wrap t=parseInt(t) and parenthesis, and then put that where ever you first use t so: (h=0|(t=parseInt(t))/60). This way, you can remove the return and the {} \$\endgroup\$ – Downgoat Nov 28 '15 at 19:41
  • \$\begingroup\$ @Downgoat I've already tried but it didn't work for some reason. Will try again. \$\endgroup\$ – nicael Nov 28 '15 at 19:42
  • 1
    \$\begingroup\$ @Downgoat Apparently I've made a mistake previously, now it works properly. Thanks :) \$\endgroup\$ – nicael Nov 28 '15 at 19:45
  • \$\begingroup\$ USE TEMPLATE STRINGS. ${}!!! \$\endgroup\$ – Mama Fun Roll Dec 1 '15 at 4:21
3
\$\begingroup\$

C#, 127 bytes

var i=int.Parse(Console.ReadLine().Split(' ')[0]);Console.Write(i/60+" hour"+(i/60>1?"s ":" ")+i%60+" minute"+(i%60>1?"s":""));

This can be put in a file and run via the C# interactive shell that comes with Mono, using the default configuration.

[This is my first attempt at code golf. I hope that my contribution is not violating any rules.]

|improve this answer|||||
\$\endgroup\$
3
\$\begingroup\$

C, 89 bytes

main(n){scanf("%d",&n);printf("%d hour%s %d minute%s",n/60,"s"+119/n,n%60,"s"+(n%60<2));}
|improve this answer|||||
\$\endgroup\$
3
\$\begingroup\$

Ruby, 75 bytes

a,b=gets.to_i.divmod 60;$><<"#{a} hour#{a>1??s:''} #{b} minute#{b>1??s:''}"
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Sometimes even an empty string is too long. ''p. \$\endgroup\$ – manatwork Dec 8 '15 at 7:55
2
\$\begingroup\$

MATLAB, 111 108 106 bytes

i=sscanf(input(''),'%d');h=fix(i/60);m=i-h*60;fprintf('%d hour%c %d minute%c\n',h,'s'*(h~=1),m,'s'*(m~=1))

This also works with Octave, and can be tried here. The link is to a workspace already containing the code in a file named runningLength.m. So to test it out simply enter runningLength at the prompt, then enter the input string, e.g. '123 mins' and it will display the output.

Takes the input as a string, e.g. '123 mins', converts it to a number (which implicitly ignores the mins bit).

i=sscanf(input(''),'%d');

Minutes and hours are then calculated

h=fix(i/60);m=i-h*60;

Then displays the output string

fprintf('%d hour%c %d minute%c',h,'s'*(h~=1),m,'s'*(m~=1));

The 's' bit of the output is calculated and handled correctly - an 's' is added whenever the number is not 1.

|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

Python 2, 96 bytes

i=int(raw_input().split()[0])
print"%d hour%s %d minute%s"%(i/60,"s"*(i>120),i%60,"s"*(i%60!=1))
|improve this answer|||||
\$\endgroup\$
  • 7
    \$\begingroup\$ This doesn't appear to correctly handle plurals. \$\endgroup\$ – Doorknob Nov 28 '15 at 17:34
  • \$\begingroup\$ @Doorknob This is what happens when the rules get changed after answers are posted :) \$\endgroup\$ – quintopia Nov 28 '15 at 22:26
2
\$\begingroup\$

Haskell, 117 109 bytes

f x|(d,m)<-divMod(read$take 3 x)60=putStr$u[d#"hour",m#"minute"];u=unwords;1#q=u["1",q];p#q=u[show p,q++"s"]

Less golfed version:

f :: String -> IO ()
f x = putStr (unwords [(n`div`60)#"hour",(n`mod`60)#"minute"])
  where
  n :: Int
  n = take 3 (read x)

  (#) :: Int -> String -> String
  1#q = unwords ["1",q]
  p#q = unwords [show p,q++"s"]

f is a function which takes the first 3 characters of its input and converts them to an integer. p#q is a function which pluralises q if p is not equal to 1. In order to return the result without surrounding quotes, I used putStr to print the result to STDOUT.

Thanks to nimi for the help!

|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

Python 2, 79 77 bytes

m=int(raw_input()[:3])
print m/60,"hours"[:4+m/120],m%60,"minutes"[:6+m/2%30]

The first 3 characters of the input are simply parsed as an integer. This only works because the third character in a 2 digit input is a space, which int will ignore during conversion.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ I think you can just do "hour"+m/120*"s" and likewise for minutes. \$\endgroup\$ – xnor Nov 29 '15 at 6:29
  • \$\begingroup\$ It'll fail for m=240, unfortunately. \$\endgroup\$ – xsot Nov 29 '15 at 6:59
2
\$\begingroup\$

LabVIEW, 50 Bytes

This is counted according to my suggestion on Meta.

The code is pretty straight forward, take number from input Modulo by 60 and add an s for minutes != 1. Other side of case just puts the string through.

enter image description here

|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

Scala, 135 bytes

var a=(i:String)=>{var (v,b)=(i.split(" ")(0).toInt,(i:Int)=>if(i<2)""else"s");printf(v/60+" hour"+b(v/60)+" "+v%60+" minute"+b(v%60))}

Usage:

a("120 min")
2 hours 0 minute
|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

Haskell, 107 101 bytes

g=putStr.f.read.take 3;s!1='1':s;s!n=show n++s++"s";f x|(a,b)<-divMod x 60=" hour"!a++' ':" minute"!b

Ungolfed:

g :: String -> String
g = putStr . f . read . take 3 
  where
    (!) :: String -> Int -> String
    s!1 = '1':s
    s!n = show n++s++"s"

    f :: Int -> String;
    f x
      | (a,b) <- divMod x 60 = " hour"!a ++ ' ':(" minute"!b)

s!n prepends n to s, adding a 's' to the end if n /= 1.

f x does the formatting after using divMod.

Since we can assume a max input of 240, take 3 is sufficient to take only the number.

(Had to try really hard to beat @Craig Roy's score...)

|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

R, 112 bytes

Edit: Fixed a scoping error and then addressed the quotation output issue.

g=function(x){h=floor(x/60);m=x%%60;cat(paste(h,ifelse(h==1,"hour","hours"),m,ifelse(m==1,"minute","minutes")))}

Test cases

> g(150)
2 hours 30 minutes
> g(90)
1 hour 30 minutes
> g(61)
1 hour 1 minute
> g(60)
1 hour 0 minutes

I tried to save space by trying to find a way to just add or subtract "s" as necessary but I had to mess with the sep = argument in the paste() function and it didn't really seem like it was going to save me very much space. Any suggestions?

Ungolfed

g=function(x){
    h=floor(x/60);
    m=x%%60;
    cat(paste(h,
              ifelse(h==1,"hour","hours"),
              m,
              ifelse(m==1,"minute","minutes")))
}

Rounding down with input/60 or input%%60 (mod) gives the hours and minutes respectively. Chain them together with an ifelse() statement that specifies whether or not the units are hour(s) or minute(s).

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Output should not be enclosed within quotes. \$\endgroup\$ – Vasu Adari Dec 4 '15 at 6:26
  • \$\begingroup\$ @Vasu Adari Fixed it using the cat() function. \$\endgroup\$ – syntonicC Dec 4 '15 at 15:44
  • 1
    \$\begingroup\$ You can save bytes by handling plural with just s and by changing your conditions. \$\endgroup\$ – Vasu Adari Dec 4 '15 at 15:51
1
\$\begingroup\$

Ruby, 97 100 99 88 bytes

Edit: Fixing output.

Edit: Removing braces from divmod.

Edit: Yay string interpolation! Thanks to Vasu Adari. Also, better ungolfing.

i,j=gets.split[0].to_i.divmod 60;puts"#{i} hour#{i==1?"":"s"} #{j} minute#{j==1?"":"s"}"

Ungolfed:

input = gets                            Input
number = input.split[0].to_i            Get number, convert to int
hours, minutes = number.divmod 60       hours == s / 60, minutes == s % 60
result = hours.to_s+" hour"             Start with the hours
result += {hours == 1 ? "" : "s"}       Put in the first "s" if plural
result += minutes.to_s+" minute"        Add the minutes
result += {minutes == 1 ? "" : "s"}     Put in the second "s" if plural
puts result                             Output
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ o/p should not be enclosed within quotes. \$\endgroup\$ – Vasu Adari Nov 28 '15 at 18:47
  • \$\begingroup\$ @VasuAdari Fixed \$\endgroup\$ – Sherlock9 Nov 28 '15 at 18:54
  • \$\begingroup\$ You can lose the braces for divmod method. Also by using string interpolation you can save few bytes. \$\endgroup\$ – Vasu Adari Nov 28 '15 at 19:03
  • \$\begingroup\$ @VasuAdari I am aware of that string iterpolation is a thing, but I'm not sure what it is or how it works. Thanks for the help \$\endgroup\$ – Sherlock9 Nov 28 '15 at 19:31
  • \$\begingroup\$ @VasuAdari Oop, wait. Google has taught me what I need to know. Let me get editing. \$\endgroup\$ – Sherlock9 Nov 28 '15 at 19:34
1
\$\begingroup\$

Go, 177 Bytes

(It includes only the function and the import statements)

import("fmt";c"strconv";t"strings")
func f(s string){p,_:=c.Atoi(t.Split(s," ")[0]);t:=fmt.Printf;h:=p/60;m:=p%60;t("%d Hour",h);if h>1{t("s")};t(" %d Minute",m);if m>1{t("s")}}

Pretty solution -

func f(s string) {
    p, _ := c.Atoi(t.Split(s, " ")[0])
    t := fmt.Printf
    h := p / 60;m := p % 60
    t("%d Hour", h)
    if h > 1 {
        t("s")
    }
    t(" %d Minute", m)
    if m > 1 {
        t("s")
    }
}

Testing it -

func main() {
    ip_list := []string{
        "120 min",
        "150 min",
        "60 min",
    }

    for _, ip_val := range ip_list {
        f(ip_val)
        fmt.Println("")
    }
}

/* OUTPUT
2 Hours 0 Minute
2 Hours 30 Minutes
1 Hour 0 Minute
*/
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 61 bytes

Print@ToString[Quantity@#~UnitConvert~MixedRadix["h","min"]]&
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

AutoHotkey, 174 170 160 bytes

x::Send,% !i?"x" i:=SubStr(clipboard,1,(Clipboard~="\s")):"{Backspace "StrLen(i)"}" i//60 " Hour"(i//60!=1?"s ":" ")Mod(i,60)" Minute"(Mod(i,60)!=1?"s":"")i:=""

Notes:

  1. Input from Clipboard
  2. Output prints to any form by pressing x
  3. Correctly handles plurals
  4. Could be smaller but I wanted a provide a One Liner.
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

PHP, 77 76 bytes

$m=($i=$argv[1])%60;echo$h=$i/60|0," hour","s"[$h<2]," $m minute","s"[$m<2];

horible, horible, horible!
PHP only issues a couple of Notices for "s"[$h<2]

To run: php -r 'CODE' '150 minutes'
and of course turn error reporting off/away from stdout!

Edit: -1byte assign in assign (credit: insertusernamehere)

It's so ugly I must give a run helper for linux users:

php -c /usr/share/php5/php.ini-production.cli -r 'CODE' '61 min'
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ 1 byte less: $m=($i=$argv[1])%60;echo$h=$i/60|0," hour","s"[$h<2]," $m minute","s"[$m<2];. \$\endgroup\$ – insertusernamehere Nov 29 '15 at 1:27
  • \$\begingroup\$ @insertusernamehere nice, thanks! crazy \$\endgroup\$ – CSᵠ Nov 29 '15 at 2:07
  • \$\begingroup\$ You're welcome. Even 4 bytes lesser (was too tired to notice yesterday): $m=($i=$argv[1])%60;echo$h=$i/60|0," hour",s[$h<2]," $m minute",s[$m<2];. \$\endgroup\$ – insertusernamehere Nov 29 '15 at 8:49
  • \$\begingroup\$ @insertusernamehere that's a really nasty old one, but can't believe it works for php 5.6-7 and not for 5.3-5.5 \$\endgroup\$ – CSᵠ Nov 29 '15 at 9:06
  • \$\begingroup\$ I've tested it with PHP 5.6.10 (OS X) and it works here. :) \$\endgroup\$ – insertusernamehere Nov 29 '15 at 9:50
1
\$\begingroup\$

Arcyóu (non-competitive), 93 bytes

This submission uses a version of the language that was created after this challenge.

(: x(#((v(l))0)))(: h(#/ x 60))(: m(% x 60))(% "%d hour%s %d minute%s"(' h(* s([ h))m(* s([ m

Yeesh! This language needs better string manipulation.

Explanation:

(: x              ; Set x
  (#              ; Cast to int
    ((v (l)) 0))) ; First element of input split on spaces
(: h (#/ x 60))   ; Set h to the hours
(: m (% x 60))    ; Set m to the minutes
(%                ; String format
  "%d hour%s %d minute%s"
  ('              ; List
    h             ; Hours
    (* s([ h))    ; Evaluates to 's' if h is not 1
    m             ; Minutes 
    (* s([ m      ; Evaluates to 's' is m is not 1
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Ruby, 74 73 71 bytes

->i{puts"#{i=i.to_i;h=i/60} hour#{h>1??s:''} #{m=i%60} minute#{m>1??s:''}"}

73 bytes

->i{puts"#{h,m=i.to_i.divmod 60;h} hour#{h>1??s:''} #{m} minute#{m>1??s:''}"}

74 bytes:

->i{h,m=i.to_i.divmod 60;puts "#{h} hour#{h>1??s:''} #{m} minute#{m>1??s:''}"}

Usage:

->i{puts"#{i=i.to_i;h=i/60} hour#{h>1??s:''} #{m=i%60} minute#{m>1??s:''}"}[61]

1 hour 1 minute
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Kotlin, 132 bytes

val m={s:String->val j=s.split(" ")[0].toInt();print("${j/60} hour${if(j/60==1)"" else "s"} ${j%60} minute"+if(j%60==1)"" else "s")}

Ungolfed Version:

val m = { s: String -> 
    val j = s.split(" ")[0].toInt();
    print("${j / 60} hour${if(j / 60 == 1) "" else "s"} ${j % 60} minute" + if(j % 60 == 1) "" else "s")
}

Test it with:

fun main(args: Array<String>) {
    for(i in arrayOf(150, 90, 61, 60)) {
        m("$i min")
        println()
    }
}

Example outputs:

2 hours 30 minutes
1 hour 30 minutes
1 hour 1 minute
1 hour 0 minutes
|improve this answer|||||
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to PPCG.SE! I have edited your post to make is look more aesthetically pleasing. Have fun! \$\endgroup\$ – GamrCorps Nov 29 '15 at 18:22
1
\$\begingroup\$

Seriously, 77 bytes

ε" min",Æ≈;:60:@\@:60:@%'sε(;)1≥I"%d hour"+(#@%'sε(;)1≥I"%d minute"+(#@%@k' j

Seriously is seriously not good at string manipulation. Try it online with full explanation (you will need to manually enter the input like "210 mins" because permalinks don't like quotes).

Quick and dirty explanation:

ε" min",Æ≈            get input, replace " min" with the empty string, convert to int
;:60:@\@:60:@%        calculate divmod
'sε(;)1≥I"%d hour"+   push "%d hour" or "%d hours", depending on whether pluralization is needed
(#@%                  format "%d hour(s)" with the # of hours calculated earlier
'sε(;)1≥I"%d minute"+ same as above, but with minutes
(#@%                  same as above, but with minutes
@k' j                 swap the order and join with a space to get "X hour(s) X minute(s)"
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Your link does not work \$\endgroup\$ – TanMath Jan 2 '16 at 15:07
1
\$\begingroup\$

Java 8, 148 Bytes

interface S{static void main(String[]b){int a=new Integer(b[0]),h=a/60,m=a%60;System.out.printf(h+" hour%s "+m+" minute%s",h>1?"s":"",m>1?"s":"");}}

I chose to post an alternative to @TheAustralianBirdEatingLouse as this is not only shorter by a good deal (~10%) but also more correct in printing hour(s) and minutes(s) instead of abbreviated hrs and mins. Method implementations in Interfaces are new to Java 8 - so this would be needed to compile/run

|improve this answer|||||
\$\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.