39
\$\begingroup\$

Introduction

code golf explanation

Imagine that line of chars is in fact two rows. Upper row - dots - represents hours (24 hour system), while lower - commas - represents minutes. One character can represent hour, minute or both - whenever it's possible.

At first probably you'd have to convert minutes since midnight to hours and minutes.

The result is the string showing current time in "dot format". The dot count (apostrophe counts here as a dot and will be called so!) is the hour count since midnight and comma count is minutes count. I'll show a few examples to make it clear.

  • (Remark) hh:mm - result
  • (Only hours) 05:00 - '''''
  • (Only minutes) 00:08 - ,,,,,,,,
  • (hours < minutes) 03:07 - ;;;,,,,
  • (hours > minutes) 08:02 - ;;''''''
  • (hours = minutes) 07:07 - ;;;;;;;
  • (the start of the day) 00:00 - (empty result)

Notice that "both" character can be used max 23 times - for 23:xx, where xx is 23 or more.

Symbols

If character have to (see rule 5.) be escaped in your language, you could changed it to one of alternatives. If said alternatives aren't enough, you may use other symbols - but keep it reasonable. I just don't want escaping to be a barrier.

  • ; (semicolon) - marker for both hours and minutes (alt: :)
  • ' (apostrophe) - marker for hours (alt: '``°)
  • , (comma) - marker for minutes (alt: .)

Additional rules

  1. The code with the least amount of bytes wins!
  2. You have to use both symbol whenever it's possible. For 02:04 the result can't be '',,,,, nor ;',,,. It have to be ;;,,
  3. Input - can be script/app parameter, user input (like readline) or variable inside code
    3.1. If the variable inside code is used, then its lenght have to be the longest possible. It's 1439 (23:59), so it would look like t=1439
  4. The common part which is symbolized by "both" character (12 in 12:05, 3 in 03:10) must be placed on the beginning of the string
  5. Symbols can be replaced to alternatives only if they would have to be escaped in your code.
  6. Input is given in minutes after 00:00. You can assume that this is a non-negative integer.

Test cases

Input: 300
Output: '''''

Input: 8
Output: ,,,,,,,,

Input: 187
Output: ;;;,,,,

Input: 482
Output: ;;''''''

Input: 427
Output: ;;;;;;;

Input: 0
Output:  (empty)
\$\endgroup\$
  • \$\begingroup\$ Thank you, Adnan for editing my post! This way I'll learn by comparison of my, newbie golf to yours :) \$\endgroup\$ – Krzysiu Dec 23 '15 at 2:28
  • 3
    \$\begingroup\$ No problem! It is a very good first post and a nice challenge :) \$\endgroup\$ – Adnan Dec 23 '15 at 2:45
  • 1
    \$\begingroup\$ this looks so good with just semicolons and commas, but apostrophes muck it all up :( \$\endgroup\$ – Sparr Dec 23 '15 at 2:55
  • \$\begingroup\$ Actually 1439 is 23:59 and not 1339. (23 x 60 + 59). \$\endgroup\$ – insertusernamehere Dec 23 '15 at 9:04
  • \$\begingroup\$ Thank all of you for good words! :) @Sparr, yeah, that's the bad point :( Have you idea how it could be replaced? insertusernamehere, of course that's right! Fixed :) \$\endgroup\$ – Krzysiu Dec 23 '15 at 18:33

24 Answers 24

10
\$\begingroup\$

Pyth, 19 bytes

:.iF*V.DQ60J"',"J\;

Test suite

:.iF*V.DQ60J"',"J\;
      .DQ60            Divmod the input by 60, giving [hours, minutes].
           J"',"       Set J equal to the string "',".
    *V                 Perform vectorized multiplication, giving H "'" and M ','.
 .iF                   Interleave the two lists into a single string.
:               J\;    Perform a substitution, replacing J with ';'.
\$\endgroup\$
8
\$\begingroup\$

CJam, 22 20 19 bytes

Takes input from STDIN:

ri60md]',`.*:.{;K+}

Test it here.

Explanation

ri     e# Read input and convert to integer.
60md   e# Divmod 60, pushes hours H and minutes M on the stack.
]      e# Wrap in an array.
',`    e# Push the string representation of the comma character which is "',".
.*     e# Repeat apostrophe H times and comma M times.
:.{    e# Apply this block between every pair of characters. This will only applied to
       e# first N characters where N = min(hours,minutes). The others will remain
       e# untouched. So we want the block to turn that pair into a semicolon...
  ;    e#   Discard the comma.
  K+   e#   Add 20 to the apostrophe to turn it into a semicolon.
}

It was really lucky how well things worked together here, in particular the assignment of hours to ' and minutes to , such that the order of hours and minutes on the stack matched up with the string representation of the character.

This is the only 3-byte block I've found so far. There were tons of 4-character solutions though:

{;;';}
{';\?}
{^'0+}
{^'F-}
{-'@+}
{-'6-}
...
\$\endgroup\$
6
\$\begingroup\$

GNU Sed, 37

Score includes +1 for -E option to sed.

I wasn't particularly impressed with the golfiness of my bash answer, so I thought I'd try with sed for the fun.

Input is in unary, as per this meta-answer.

y/1/,/          # Convert unary 1's to commas (minutes)
s/,{60}/'/g     # divmod by 60.  "'" are hours
:               # unnamed label
s/(.*)',/;\1/   # replace an apostrophe and comma with a semicolon
t               # jump back to unnamed label until no more replacements

Try it online

\$\endgroup\$
  • \$\begingroup\$ unnamed label?? \$\endgroup\$ – mikeserv Dec 23 '15 at 7:32
  • \$\begingroup\$ @mikeserv, see Digital Trauma's related tip in Tips for golfing in sed. \$\endgroup\$ – manatwork Dec 23 '15 at 12:26
  • \$\begingroup\$ @manatwork - i think it must be a GNU bug. \$\endgroup\$ – mikeserv Dec 23 '15 at 18:12
  • \$\begingroup\$ @mikeserv - but using bugs is OK as well, right? I'm not asking to mock you, I just don't know :) \$\endgroup\$ – Krzysiu Dec 23 '15 at 18:40
  • \$\begingroup\$ @Krzysiu - ok? hmm. on this site i think it would be a mark of excellence. otherwise, almost definitely no. when programmers stray from API and use implementation details programs become version/implementation dependent - which is a bad thing. \$\endgroup\$ – mikeserv Dec 23 '15 at 18:59
6
\$\begingroup\$

Python 2, 56 bytes

def g(t):d=t%60-t/60;print(t/60*";")[:t%60]+","*d+"'"*-d

A function that prints (one char shorter than t=input();).

The method is similar to Loovjo's. The number of , is the different between minutes and hours, with an implicit minimim of 0. For ', it's the negation. For ;, computes the min implicitly by taking as many ; as hours, then truncating to the number of minutes.

It saves chars to save d, but not the number of hours and minutes here. The analogue with lambda was two chars longer (58), so the variable assignments are worth it.

lambda t:(t%60*";")[:t/60]+","*(t%60-t/60)+"'"*(t/60-t%60)

Processing the input directly didn't save chars either (58):

h,m=divmod(input(),60);d=m-h;print(";"*m)[:h]+","*d+"'"*-d

Another strategy with slicing, much longer (64):

def g(t):m=t%60;h=t/60;return(";"*m)[:h]+(","*m)[h:]+("'"*h)[m:]
\$\endgroup\$
3
\$\begingroup\$

Retina, 24

Trivial port of my sed answer.

Input is in unary, as per this meta-answer.

1
,
,{60}
'
+`(.*)',
;$1

Try it online.

\$\endgroup\$
3
\$\begingroup\$

Pure Bash (no external utilities), 103

p()(printf -vt %$2s;printf "${t// /$1}")
p \; $[h=$1/60,m=$1%60,m>h?c=m-h,h:m]
p , $c
p \' $[m<h?h-m:0]

Thanks to @F.Hauri for saving 2 bytes.

\$\endgroup\$
  • \$\begingroup\$ Nice! But you could save 2 chars by swapping $1 and $2 in p() and write p , $c at line 3. \$\endgroup\$ – F. Hauri Dec 23 '15 at 21:03
  • \$\begingroup\$ Yes, but as it's used only in a printf "%s", having c empty will work fine (while not reused) \$\endgroup\$ – F. Hauri Dec 24 '15 at 7:35
  • \$\begingroup\$ @F.Hauri Now I get it - thanks! \$\endgroup\$ – Digital Trauma Dec 24 '15 at 22:43
3
\$\begingroup\$

C, 119 bytes

#define p(a,b) while(a--)putchar(b);
main(h,m,n){scanf("%d",&m);h=m/60;m%=60;n=h<m?h:m;h-=n;m-=n;p(n,59)p(h,39)p(m,44)}

Detailed

// macro: print b, a times
#define p(a,b) while(a--)putchar(b)

int main(void)
{
    int h,m,n;
    scanf("%d",&m);  // read input

    h=m/60;m%=60;    // get hours:minutes
    n=h<m?h:m;       // get common count
    h-=n;m-=n;       // get remaining hours:minutes

    p(n,59);        // print common
    p(h,39);        // print remaining hours
    p(m,44);        // print remaining minutes

    return 0;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Using putchar & integer literals as characters saves one byte, pulling the semicolons inside the macro saves two more :) \$\endgroup\$ – Quentin Dec 23 '15 at 22:35
  • \$\begingroup\$ @Quentin note taken, saved 5 bytes \$\endgroup\$ – Khaled.K Dec 24 '15 at 7:09
  • \$\begingroup\$ You can lose the space before your while in your #define macro. -1 byte \$\endgroup\$ – Albert Renshaw Mar 2 '17 at 8:41
  • 1
    \$\begingroup\$ You can also save some more bytes by just making p(a,b) a function instead of a macro. (And sprinkling a few more semi-colons to your main function) \$\endgroup\$ – Albert Renshaw Mar 2 '17 at 8:48
3
\$\begingroup\$

Haskell, 68 66 Bytes

g(h,m)=id=<<zipWith replicate[min h m,h-m,m-h]";',"
g.(`divMod`60)

Usage example:

(g.(`divMod`60)) 482

The clever bit here is that replicate will return the empty string if the length given is negative or zero so I can apply it to both differences and only the positive one will show up. The first part is easy, since the number of semicolons is just the minimum of the two. Then zipWith applies the function to the corresponding items.

EDIT: Realized I was using the wrong char for minutes

EDIT 2: Saved 2 bytes thanks to @Laikoni

\$\endgroup\$
  • \$\begingroup\$ You can save two bytes by replacing concat$ with id=<<. \$\endgroup\$ – Laikoni Mar 2 '17 at 8:38
2
\$\begingroup\$

JavaScript (ES6) 69

m=>";".repeat((h=m/60|0)>(m%=60)?m:h)+",'"[h>m|0].repeat(h>m?h-m:m-h)
\$\endgroup\$
2
\$\begingroup\$

Powershell, 99 85 bytes

param($n)";"*(($m=$n%60),($h=$n/60))[($b=$m-gt$h)]+"'"*(($h-$m)*!$b)+","*(($m-$h)*$b)

Using Loovjo's method, this is my powershell implementation.

ungolfed

param($n) 
# set the number of minutes and hours, and a boolean which one is bigger
# and also output the correct number of ;s
";"*(($m=$n%60),($h=$n/60))[($b=$m-gt$h)]+ 
# add the difference between h and m as 's but only if h > m
"'"*(($h-$m)*!$b)+
# add the difference between m and h as ,s but only if m > h
","*(($m-$h)*$b)

Saved 14 bytes thanks to AdmBorkBork

\$\endgroup\$
  • \$\begingroup\$ You can save by using a pseudo-ternary for the first one, moving the $m and $h declarations into it, and then using Boolean multiplication. Like so -- param($n)';'*(($m=$n%60),($h=$n/60))[($b=$m-gt$h)]+'°'*(($h-$m)*!$b)+','*(($m-$h)*$b) \$\endgroup\$ – AdmBorkBork Mar 2 '17 at 14:01
1
\$\begingroup\$

Python 3, 98 bytes

d=int(input());m=d%60;h=int((d-m)/60)
if m>=h:print(";"*h+","*(m-h))
else:print(";"*(m)+"'"*(h-m))

Probably not the best answer, but it was a lot of fun!

\$\endgroup\$
1
\$\begingroup\$

Python 2, 61 bytes

t=input();m,h=t%60,t/60
print";"*min(h,m)+","*(m-h)+"'"*(h-m)

Explaination:

t=input();              # Read input
          m,  t%60,     # Do a divmod, h = div, m = mod
            h=     t/60

print";"*min(h,m)+                    # Print the minimum of the h and m, but in ";"s
                  ","*(m-h)+          # Print (m-h) ","s (if m-h is negative, print nothing)
                            "'"*(h-m) # Print (h-m) "'"s (if h-m is negative, print nothing)
\$\endgroup\$
1
\$\begingroup\$

PHP, 81 bytes

I went for the variable input as it is shorter than reading from STDIN or taking command line arguments.

for($_=1439;$i<max($h=0|$_/60,$m=$_%60);++$i)echo$i<$h?$i<min($h,$m)?';':"'":",";
\$\endgroup\$
  • \$\begingroup\$ I thought that I know PHP rather well, but I see | for the first time. I think I'll use it to exercise a bit - I'll analyze it :) \$\endgroup\$ – Krzysiu Dec 23 '15 at 18:38
  • \$\begingroup\$ Fails for 240. Try $i>=min($h,$m)?$h<$m?",":"'":";" (+1 byte). Or use for($_=1439;$i<max($h=0|$_/60,$m=$_%60);)echo"',;"[$i++<min($h,$m)?2:$h<$m]; (76 bytes). Btw: single quote renders -r impossible; so you should use backtick for hours if in a string or ° standalone (needs no quotes -> -1 byte). \$\endgroup\$ – Titus Mar 1 '17 at 16:10
1
\$\begingroup\$

JavaScript (ES6), 77 71 bytes

x=>';'[r='repeat'](y=Math.min(h=x/60|0,m=x%60))+"'"[r](h-y)+','[r](m-y)
\$\endgroup\$
  • \$\begingroup\$ Great use of assignments in attribute access/function arguments. +1 \$\endgroup\$ – Cyoce Mar 2 '17 at 1:48
1
\$\begingroup\$

Perl 6, 103 101 98 97 69 bytes

$_=get;say ";"x min($!=($_-$_%60)/60,$_=$_%60)~"'"x $!-$_~","x $_-$!;

Outputs several arrays, but fuck it, enjoy. As usual, any golfing oppertunities are appericated.

Edit: -2 bytes: got brave and removed some casts.

Edit2: -3 bytes by removing the arrays.

Edit3: -1 byte to print in right format, using "lambdas" and removing parantheses.

Edit4: (sorry guys) abusing that hours - minutes should return 0 and the opposite. Removed if statements. Then removing brackets, then realising i didnt need the lambda at all. -28 bytes :)

Woah im getting better at this.

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

C, 141 bytes

main(h,m){scanf("%d",&m);h=(m/60)%24;m%=60;while(h||m){if(h&&m){printf(";");h--;m--;}else if(h&&!m){printf("'");h--;}else{printf(",");m--;}}}
\$\endgroup\$
  • \$\begingroup\$ I think you could save a few bytes by using h>0||m>0. Then you need to h--;m--; only once in every iteration and the {} for if/else would get obsolete. \$\endgroup\$ – insertusernamehere Dec 23 '15 at 8:57
  • \$\begingroup\$ You can also save a few bytes on your second conditional: instead of else if(h&&!m) you can just have else if(h) \$\endgroup\$ – Hellion Dec 23 '15 at 19:57
  • \$\begingroup\$ And finally try to use the ternary operator, it will save you from using "long" words like if and else. \$\endgroup\$ – insertusernamehere Dec 23 '15 at 21:14
  • \$\begingroup\$ Consider refactoring as a function that takes the input as an int parameter - that should at least save you the scanf(). \$\endgroup\$ – Digital Trauma Dec 25 '15 at 0:57
  • \$\begingroup\$ I don't think the %24 is necessary - max input is 23:59. \$\endgroup\$ – Digital Trauma Dec 25 '15 at 0:58
0
\$\begingroup\$

Gema, 119 characters

<D>=@set{h;@div{$0;60}}@set{m;@mod{$0;60}}@repeat{@cmpn{$h;$m;$h;$h;$m};\;}@repeat{@sub{$h;$m};'}@repeat{@sub{$m;$h};,}

Sample run:

bash-4.3$ gema '<D>=@set{h;@div{$0;60}}@set{m;@mod{$0;60}}@repeat{@cmpn{$h;$m;$h;$h;$m};\;}@repeat{@sub{$h;$m};`}@repeat{@sub{$m;$h};,}' <<< '252'
;;;;,,,,,,,,
\$\endgroup\$
0
\$\begingroup\$

Matlab: 89 bytes

i=input('');m=mod(i,60);h=(i-m)/60;[repmat(';',1,min(h,m)),repmat(39+5*(m>h),1,abs(h-m))]

Test:

310
ans =
;;;;;,,,,,
\$\endgroup\$
0
\$\begingroup\$

SmileBASIC, 59 bytes

INPUT M
H%=M/60M=M-H%*60?";"*MIN(H%,M);",'"[M<H%]*ABS(H%-M)

Explained:

INPUT MINUTES 'input
HOURS=MINUTES DIV 60 'separate the hours and minutes
MINUTES=MINUTES MOD 60
PRINT ";"*MIN(HOURS,MINUTES); 'print ;s for all positions with both
PRINT ",'"[MINUTES<HOURS]*ABS(HOURS-MINUTES) 'print extra ' or ,

It looks pretty terrible, since the bottom part of ; is not even the same as , in SmileBASIC's font

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

PHP, 81 bytes

some more solutions:

echo($r=str_repeat)(";",min($h=$argn/60,$m=$argn%60)),$r(",`"[$h>$m],abs($h-$m));
// or
echo($p=str_pad)($p("",min($h=$argn/60,$m=$argn%60),";"),max($h,$m),",`"[$h>$m]);

Run with echo <time> | php -R '<code>'.

<?=($r=str_repeat)(";",min($h=($_=1439)/60,$m=$_%60)),$r(",`"[$h>$m],abs($h-$m));
// or
<?=($r=str_repeat)(";",min($h=.1/6*$_=1439,$m=$_%60)),$r(",`"[$h>$m],abs($h-$m));
// or
<?=str_pad(str_pad("",min($h=($_=1439)/60,$m=$_%60),";"),max($h,$m),",`"[$h>$m]);

Replace 1439 with input, save to file, run.

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

Ruby, 50 characters

->t{(?;*h=t/60)[0,m=t%60]+",',"[0<=>m-=h]*m.abs}

Thanks to:

  • G B for
    • reminding me that I can't take more characters from a string than it has (-1 character)
    • reorganizing my calculation (-1 character)

Waited so long to use Numeric.divmod, just to realize that its horribly long.

Sample run:

2.1.5 :001 > puts ->t{(?;*h=t/60)[0,m=t%60]+",',"[0<=>m-=h]*m.abs}[252]
;;;;,,,,,,,,
\$\endgroup\$
  • 1
    \$\begingroup\$ Save 1 character by truncating the string instead of using min: (?;*h=t/60)[0,m=t%60] \$\endgroup\$ – G B Mar 2 '17 at 12:23
  • 1
    \$\begingroup\$ And another byte by subtracting h from m: ",',"[0<=>m-=h]*m.abs \$\endgroup\$ – G B Mar 2 '17 at 12:40
0
\$\begingroup\$

05AB1E, 25 bytes

60‰vy„'.Nè×}‚.BøJ„'.';:ðK

Try it online!

60‰vy„'.Nè×} can definitely be shortened, I just couldn't figure it out, and doubt I'll be able to shave off 7 bytes to win with this approach unless there's a vectored version of ×.


Example (With input equal to 63):

60‰                       # Divmod by 60.
                          # STACK: [[1,3]]
   vy      }              # For each element (probably don't need the loop)...
                          # STACK: []
     „'.Nè×               # Push n apostrophe's for hours, periods for minutes.
                          # STACK: ["'","..."]
            ‚             # Group a and b.
                          # STACK: [["'","..."]]
             .B           # Boxify.
                          # STACK: [["'  ","..."]]
               ø          # Zip it (Transpose).
                          # STACK: [["'."," ."," ."]
                J         # Join stack.
                          # STACK: ["'. . ."]
                 „'.';:   # Replace runs of "'." with ";".
                          # STACK: ["; . ."]
                       ðK # Remove all spaces.
                          # OUTPUT: ;..

D60÷''×s60%'.ׂ.BøJ„'.';:ðK was my original version, but that's even MORE costly than divmod.

60‰WDµ';ˆ¼}-¬0Qi'.ë''}ZׯìJ yet another method I tried...

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

dc, 95 bytes

[60~sdsp39sj]sd[60~spsd44sj]se?ddd60~<d60~!<e[59Plp1-spld1-dsd0<y]syld0<y[ljPlp1-dsp0<y]sylp0<y

Try it online!

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

Java 8, 101 99 86 bytes

n->{String r="";for(int m=n%60,h=n/60;h>0|m>0;r+=h--*m-->0?";":h<0?",":"'");return r;}

Explanation:

Try it here.

n->{                      // Method with integer parameter and String return-type
  String r="";            //  Result-String (starting empty)
  for(int m=n%60,h=n/60;  //   Get the minutes and hours from the input integer
      h>0|m>0;            //   Loop as long as either the hours or minutes is above 0
    r+=                   //   Append the result-String with:
       h--*m-->0?         //    If both hours and minutes are above 0
                          //    (and decrease both after this check):
        ";"               //     Use ";"
       :h<0?              //    Else-if only minutes is above 0 (hours is below 0)
        ","               //     Use ","
       :                  //    Else:
        "'"               //     Use "'"
  );                      //  End loop
  return r;               //  Return the result
}                         // End of method
\$\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.