23
\$\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\$
16
  • 2
    \$\begingroup\$ @quintopia According to site rules, no. You can use a function if you want to. \$\endgroup\$
    – Doorknob
    Nov 28, 2015 at 17:34
  • 1
    \$\begingroup\$ Technically, I (and I bet other humans) can read "150 minutes". \$\endgroup\$
    – PyRulez
    Nov 28, 2015 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\$ Nov 29, 2015 at 0:28
  • 7
    \$\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, 2015 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, 2015 at 7:12

51 Answers 51

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)
\$\endgroup\$
1
  • 22
    \$\begingroup\$ Ah! Increasing bytecount! +1 for not giving up ;-) \$\endgroup\$
    – agtoever
    Nov 28, 2015 at 17:52
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.
\$\endgroup\$
3
  • 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\$ Nov 29, 2015 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\$ Nov 29, 2015 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\$ Nov 29, 2015 at 20:14
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
\$\endgroup\$
11
  • \$\begingroup\$ Good one. Suggestion: reduce parseInt(n) to +n. \$\endgroup\$
    – nicael
    Nov 28, 2015 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, 2015 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, 2015 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, 2015 at 21:40
  • 1
    \$\begingroup\$ +1 For JavaScript. Now you just have to make it a bookmarlet ;) \$\endgroup\$
    – bren
    Nov 30, 2015 at 2:37
6
\$\begingroup\$

Pyth, 39 38 bytes

jd.iJ.Dv-zG60+Vc"hour minute")m*\s>d1J
\$\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!

\$\endgroup\$
0
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".

\$\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
\$\endgroup\$
0
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
\$\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()))

\$\endgroup\$
4
  • \$\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, 2015 at 19:41
  • \$\begingroup\$ @Downgoat I've already tried but it didn't work for some reason. Will try again. \$\endgroup\$
    – nicael
    Nov 28, 2015 at 19:42
  • 1
    \$\begingroup\$ @Downgoat Apparently I've made a mistake previously, now it works properly. Thanks :) \$\endgroup\$
    – nicael
    Nov 28, 2015 at 19:45
  • \$\begingroup\$ USE TEMPLATE STRINGS. ${}!!! \$\endgroup\$ Dec 1, 2015 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.]

\$\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));}
\$\endgroup\$
1
3
\$\begingroup\$

Ruby, 75 bytes

a,b=gets.to_i.divmod 60;$><<"#{a} hour#{a>1??s:''} #{b} minute#{b>1??s:''}"
\$\endgroup\$
1
  • \$\begingroup\$ Sometimes even an empty string is too long. ''p. \$\endgroup\$
    – manatwork
    Dec 8, 2015 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.

\$\endgroup\$
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!

\$\endgroup\$
0
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.

\$\endgroup\$
2
  • \$\begingroup\$ I think you can just do "hour"+m/120*"s" and likewise for minutes. \$\endgroup\$
    – xnor
    Nov 29, 2015 at 6:29
  • \$\begingroup\$ It'll fail for m=240, unfortunately. \$\endgroup\$
    – xsot
    Nov 29, 2015 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

\$\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
\$\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...)

\$\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).

\$\endgroup\$
3
  • \$\begingroup\$ Output should not be enclosed within quotes. \$\endgroup\$
    – Vasu Adari
    Dec 4, 2015 at 6:26
  • \$\begingroup\$ @Vasu Adari Fixed it using the cat() function. \$\endgroup\$
    – syntonicC
    Dec 4, 2015 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, 2015 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
\$\endgroup\$
5
  • \$\begingroup\$ o/p should not be enclosed within quotes. \$\endgroup\$
    – Vasu Adari
    Nov 28, 2015 at 18:47
  • \$\begingroup\$ @VasuAdari Fixed \$\endgroup\$
    – Sherlock9
    Nov 28, 2015 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, 2015 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, 2015 at 19:31
  • \$\begingroup\$ @VasuAdari Oop, wait. Google has taught me what I need to know. Let me get editing. \$\endgroup\$
    – Sherlock9
    Nov 28, 2015 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
*/
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 61 bytes

Print@ToString[Quantity@#~UnitConvert~MixedRadix["h","min"]]&
\$\endgroup\$
0
1
\$\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))
\$\endgroup\$
2
  • 7
    \$\begingroup\$ This doesn't appear to correctly handle plurals. \$\endgroup\$
    – Doorknob
    Nov 28, 2015 at 17:34
  • \$\begingroup\$ @Doorknob This is what happens when the rules get changed after answers are posted :) \$\endgroup\$
    – quintopia
    Nov 28, 2015 at 22:26
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.
\$\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'
\$\endgroup\$
5
  • \$\begingroup\$ 1 byte less: $m=($i=$argv[1])%60;echo$h=$i/60|0," hour","s"[$h<2]," $m minute","s"[$m<2];. \$\endgroup\$ Nov 29, 2015 at 1:27
  • \$\begingroup\$ @insertusernamehere nice, thanks! crazy \$\endgroup\$
    – CSᵠ
    Nov 29, 2015 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\$ Nov 29, 2015 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, 2015 at 9:06
  • \$\begingroup\$ I've tested it with PHP 5.6.10 (OS X) and it works here. :) \$\endgroup\$ Nov 29, 2015 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
\$\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
\$\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
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to PPCG.SE! I have edited your post to make is look more aesthetically pleasing. Have fun! \$\endgroup\$
    – GamrCorps
    Nov 29, 2015 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)"
\$\endgroup\$
1
  • \$\begingroup\$ Your link does not work \$\endgroup\$
    – TanMath
    Jan 2, 2016 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

\$\endgroup\$

Your Answer

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

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