# Setting the time

Imagine the following 24-hour clock that can be controlled by arrow keys:

╔══╗ ┌──┐
║00║:│00│
╚══╝ └──┘
HH   mm


Pressing the up arrow twice (↑↑) will increase the currently focused hour input:

╔══╗ ┌──┐
║02║:│00│
╚══╝ └──┘
HH   mm


Pressing the right arrow (→) will focus the other input.

┌──┐ ╔══╗
│02│:║00║
└──┘ ╚══╝
HH   mm


Pressing the down arrow thrice (↓↓↓) will now decrease this input.

┌──┐ ╔══╗
│02│:║57║
└──┘ ╚══╝
HH   mm


Shortly put:

• The up arrow (↑) will increase the currently active input.
• The down arrow (↓) will decrease the active input.
• The right arrow (→) will move focus to the right input.
• The left arrow (←) will move focus to the left input.
• Up and down movement will loop around as expected for a time input.
• Left and right movement don't loop around.

## The challenge

The clock starts out at 00:00 with the hour input active (see first schematic). Given a list of input commands, output the resulting time in HH:mm format.
Input can be either a string or a list (or your language equivalent), where the different input directions can be one of the below options:

• ↑↓←→
• udlr
• ^v<>
• actual arrow key presses if your program has a GUI

Standard loopholes apply.

## Test cases

↑↑→↓↓↓ = 02:57
↓→↑←↑→↓ = 00:00
↓→→↓ = 23:59
←←←←→↑ = 00:01
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓→↓ = 23:59

• @JonathanFrech One of the given options, choosing any four unique values (for example 0123) would make the challenge a lot easier in certain languages while not benefitting others. – Nit Jul 18 '18 at 11:21
• @LuisfelipeDejesusMunoz Yes, that's actually written out under the input rules. – Nit Jul 18 '18 at 11:45
• I think this would have been more challenging if it included seconds. This would have more logic behind which one is currently in focus – Jo King Jul 18 '18 at 12:40
• Missing a special rule to handle Konami code. – coredump Jul 20 '18 at 14:02
• @coredump Considered it, but it would probably take more space than the core of the answer in most languages. – Nit Jul 20 '18 at 18:51

# HTML on Google Chrome 67 in Chinese (Simplified), 39 bytes

<input type=time value=00:00 autofocus>

Chrome show different UI component in different language. Even a simple time input: AM/PM will be shown if you are using English (US). If you want test this by changing your Chrome's language. Do not mass up how to change it back.

• dudee!! hahah I think is not valid tho – Luis felipe De jesus Munoz Jul 18 '18 at 12:35
• Hitting right twice goes to AM/PM for me – Jo King Jul 18 '18 at 12:35
• @JoKing I think it's locale/settings dependent? – Nit Jul 18 '18 at 12:36
• @JoKing That's locale dependent. Maybe have a try by changing your Chrome's language to Chinese Simplify? (Do not mass up how to change it back.) – tsh Jul 18 '18 at 12:44
• It works on firefox 61.0.1 – Francisco Hahn Jul 18 '18 at 14:10

# C (gcc), 117 107 bytes

• Saved ten bytes thanks to l4m2.
t,i,m[8];e(char*_){for(*m=i=2[m]=0;t=*_++;t<63?i=t%4:(i[m]+=t&8?1:'w'));printf("%02d:%02d",*m%24,2[m]%60);}


Try it online!

• Nice variable naming. – Nit Jul 18 '18 at 11:44
• # C (gcc), 107 bytes <!-- language-all: lang-c --> t,i,m[8];e(char*_){for(*m=i=2[m]=0;t=*_++;t<63?i=t%4:(i[m]+=t&8?1:119));printf("%02d:%02d",*m%24,2[m]%60);} Try it online! – l4m2 Jul 18 '18 at 12:06

# Stax, 363533 32 bytes

áXò↑─↨√▓|êóÇiU&≡Q#┤Æ⌡⌠╟C▐╜√⌡∟▄╩╠


Run and debug it

Uses lrud.

Explanation:

'l/{'r/Bs$2lmM{${:14-m|+i36*24+%2|zm':* Full program,
'l/                                     Split the string on "l"
{        m                           Map over the resulting array
'r/                                   Split at "r"
B                                  Uncons left, first on TOS (top of stack)
s                                 Swap to get tail to top
$Flatten; this removes multiple 'r's 2l Listify two items, BOS (bottom of stack) is first element M Transpose: get [hour commands, minute commands] { m Map:$                          Flatten
{    m                    Map over single commands:
:1                         Number of set bits: 5 for 'u', 3 for 'd'
4-                       Subtract 4: u -> 1, d -> -1
|+                  Sum
i                 Iteration index: hours -> 0, minutes -> 1
36*24+           Multiply by 36, add 24: 0 -> 24, 1 -> 60
%          Modulo, this does -5 % 60 = 55
2|z       Stringify, left-padding with "0" to length 2
':* Join on ":"
Implicit output


# Python 2, 105 bytes

h=m=p=0
for c in map(' ^<>'.find,input()):w=1/c;m+=w*p;h+=w-w*p;p=[c-2,p][w]
print'%02d:%02d'%(h%24,m%60)


Try it online!

# JavaScript (Node.js), 103 bytes

Takes input as a string, using udlr.

s=>(Buffer(s).map(n=>n%6?s%4?m+=n%2||59:h+=n%2||23:s=n,h=m=0),g=n=>('0'+n).slice(-2))(h%24)+':'+g(m%60)


Try it online!

# C# (.NET Core), 149 132 bytes

s=>{var p=0;int[]h={0,0};foreach(var c in s)h[p=c<63?c/2%2:p]+=c>62?c>95?-1:1:0;return$"{(h[0]%24+24)%24:D2}:{(h[1]%60+60)%60:D2}";}  Try it online! Using ^v<>. This one made me realize that the modulo operator in C# does not work as expected, because in C# -1 % 60 = -1, so I need to do that weird operation at the end. • Can't (h[1]%60+60)%60 be replaced with (h[1]+60)%60 ? – IanF1 Jul 18 '18 at 18:31 • @IanF1 no you can't. What if the user presses the down button 100 times? Or 1000 times? – Charlie Jul 18 '18 at 19:07 • thanks for clarifying :) it's surprising to me that this way is shorter than applying the modulo on the fly (with 59 in place of -1). – IanF1 Jul 18 '18 at 19:12 Lua (love2d framework),311 308 bytes l,b,d,t,f,a=love,{24,60},{1,-1},{0,0},1,{"left","right","up","down"}function c(n,i)t[f]=(n+d[i])%b[f]end function l.draw()h,m=t[1],t[2]l.graphics.print((h<10 and 0 ..h or h)..":"..(m<10 and 0 ..m or m),0,0)end function l.keypressed(k)for i,n in pairs(a)do f=k==n and(i>2 and(c(t[f],i-2)or f)or i)or f end end  Unscrumbeled version: --initialize all needed values l,b,d,t,f,a=love,{24,60},{1,-1},{0,0},1,{"left","right","up","down"} --increase the numbers depending on the focus and up or down function c(n,i) t[f]=(n+d[i])%b[f] end --draw the time to the screen function l.draw() h,m=t[1],t[2] l.graphics.print((h<10 and 0 ..h or h)..":"..(m<10 and 0 ..m or m),0,0) end --get the keys and check if it is an arrow key function l.keypressed(k) for i,n in pairs(a)do f=k==n and(i>2 and(c(t[f],i-2)or f)or i)or f end end  Probably still not 100% easy to read because all the ifs are interchanged with an trinary statement ( ..and ..or) :) if started in an main.lua with love then it will pop up a window and you can press the arrowkeys to change the numbers • could you also post expanded version for readability – aaaaa says reinstate Monica Jul 18 '18 at 18:20 • sure, I added a expanded version no problem :) – Lycea Jul 19 '18 at 7:24 # MATL, 5756 55 bytes 1Oi9\"@5<?y@3-ZS*+}wx7@-X^w]]wx&Zjh24 60h\'%02d:%02d'YD  Try it online! Represents hour and minutes using complex numbers, with the real part being hours and the imaginary part minutes. ### With comments: 1 % Push 1 on the stack % represents which timer box we're in, starts at hour box % imaginary number j would represent minutes box O % Push initial hour and minutes 0+0j i9\ % Fetch input, mod each character's ASCII value by 9. % Gives 4 1 8 6 for ^ v > < respectively " % iterate through (modded) input @5<? % Push current input, see if it's < 5 % if so, it's an up or down time change y % so copy out the box indicator (1 or j) @3- % Subtract 3 from the current input ZS % Take the result's sign (-1 for v, 1 for ^) * % Multiply indicator with that + % Add the result to the time value } % else, it's a right or left arrow wx % so bring out the box indicator and delete it 7@- % Subtract current input from 7. 1 for < and -1 for > X^ % Take the square root of that. 1 for < and j for > w % switch stack to bring time value on top again ] % end if ] % end loop wx % bring box indicator out, delete it &Zj % split the complex time value to real and imaginary h % then concatenate them into an array 24 60h\ % mod hour and minute values by 24 and 60 respectively '%02d:%02d'YD % sprintf the time array with 0-padding  # PHP, 145134 133 bytes (-11 bytes by more golfing) (-1 byte by using Davіd's loop method) <?for($h=$m=0,$a=h;$c=$argv[++$i];)$c<l?$$a--:(c>r?$$a++:$a=$c<r?h:m);$h%=24;$m%=60;printf('%02d:%02d',$h<0?$h+24:$h,$m<0?$m+60:$m);


To run it:

php -n -d error_reporting=0 <filename> <command_1> <command_2> ... <command_n>


Example:

php -n -d error_reporting=0 time_setter.php u u r d d d l d


Notes:

• To save some bytes, I have used strings without single/double quotations as the string wrapper. Thus, the error_reporting=0 option is used to not output warnings.
• Input commands: u d l r
• 128 bytes, -6: Try it online! (Nice solution, btw :) – Ethan Jul 19 '18 at 6:13
• @Davіd: Thanks, but your update has two issues. First on is that $h is not set, so decreasing it on start fails: Try it online! – Night2 Jul 19 '18 at 8:30 • @David: And the second issue happens when we switch hour/minute up or down more than 24/60 times: Try it online! – Night2 Jul 19 '18 at 8:30 • @Davіd: But thanks to your loop method, I could reduce 1 more byte: Try it online! – Night2 Jul 19 '18 at 8:33 • ah, alright, sorry it didn't completely work :) – Ethan Jul 19 '18 at 9:03 # JavaScript, 104 103 bytes Takes input as an array of characters, using <>^v. a=>(a.map(z=>z<"^"?a=z<">":a?x+=z<"v"||23:y+=z<"v"||59,x=y=0),g=n=>0${n}.slice(-2))(x%24)+:+g(y%60)


Try it online

f=u 0 0
k _ _ _ _ _ h m[]=z h++':':z m
k a b c d e h m(q:s)=case q of{'^'->e(a h)(b m)s;'v'->e(c h)(d m)s;'>'->v h m s;'<'->u h m s}
u=k(o(+)24)id(o(-)24)id u
v=k id(o(+)60)id(o(-)60)v
o f m x=mod(f x 1)m
z n|n<10='0':show n
z n=show n


f is the main function, and has type String -> String:

*Main> f "^^>vvv"
"02:57"
*Main> f "v>^<^>v"
"00:00"
*Main> f "v>>v"
"23:59"
*Main> f "<<<<>^"
"00:01"
*Main> f "vvvvvvvvvvvvvvvvvvvvvvvvv>v"
"23:59"


Essentially u and v are mutually recursive functions of type Integer -> Integer -> String -> String. They take the hour, the minute and a list of characters over the set {v,^,<,>}, and return the time string. u acts as if the hour dial is highlighted, recursively calling u if the head of the list is in {v,^}, and v if the head of the list is in {<,>}. v is similar but for the minute dial.

Everything else is just saving characters.

# Lua, 132 bytes

loadstring's,t,m=1,{0,0},{24,60}for c in(...):gmatch"."do t[s]=(t[s]+(("d u"):find(c)or 2)-2)%m[s]s=("lr"):find(c)or s end return t'


Try it online!

### Explanation

This is an anonymous function (a way to use it is shown on the link).

s=1 -- s will control the selection (1 is hour and 2 min)
t={0,0} -- is the time itself
m={24,60} -- is the maximum for each 'box' (hour or min)
-- I've actually used Lua's multiple variable assignment: s,t,m=1,{0,0},{24,60}

for c in (...):gmatch(".") do -- go through each character of the input
t[s] = (t[s] + (("d u"):find(c) or 2)-2) % m[s] -- set the current 'box' as
t[s] +   -- itself plus ...
("d u"):find(c) or 2   -- it's index on the string "d u" (that means it's going to be 1 or 3)
-- or 2 if it wasn't found (if the current character doesn't sum or subtract from the box)
-2   -- this adjusts the result 1, 2 or 3 to being -1, 0 or 1
-- making the inputs 'd' and 'u' as -1 and +1 respectively, and an input different from both as 0
(                               ) % m[s]   -- modulo of the maximum of the selected 'box'

s=("lr"):find(c) or s
("lr"):find(c)   -- if the current input character is l or r, then set 's' (the 'box' selection) to being 1 or 2.
or s   -- else let it as is
end
return t -- returns 't', a table with hour and minutes respectively

• The output should be in the HH:mm format, rather than a table – Jo King Jul 29 '18 at 10:40

# Java 8, 121 bytes

c->{int i=0,m[]={0,0,0};for(int t:c)if(t<63)i=t%4;else m[i]+=(t&8)>0?1:119;return"".format("%02d:%02d",m[0]%24,m[2]%60);}


Port of Jonathan Frech's C answer. Accepts ^v<>. Try it online here.

# Jelly, 36 bytes

I believe O%5;4ṣ3œṡ€4Z%3’§§%"“ð<‘DŻ€ṫ€-j”: should work for 32, but œṡ seems to currently have a bug.

O%5;4ṣ3i€4$œṖ"$Z%3’§§%"“ð<‘DŻ€ṫ€-j”:


A full program printing the result to STDOUT (as a monadic link it actually returns a mixed list of integers (albeit single digit ones) and characters (the :).

Uses the udlr option for input.

Try it online! Or see a test-suite.

### How?

O%5;4ṣ3i€4$œṖ"$Z%3’§§%"“ð<‘DŻ€ṫ€-j”: - Link: list of characters (in 'udlr')
O                                    - to ordinals
%5                                  - modulo five  ...maps u:2, d:0, l:3, r:4
;4                                - concatenate a 4 (to always end up with both hrs & mins - even when no r is ever pressed)
ṣ3                              - split at threes (the l presses)
i€4$œṖ"$                      - a replacement for œṡ€4 (split each at first occurrence of)...
$- | last two links as a monad:$                          - |   last two links as a monad:
4                           - |     literal four
i€                            - |     for €ach get first index of (4) else yield 0
"                       - |   zip with:
œṖ                        - |     partition at indices
Z                     - transpose (to get a list of two lists of lists)
%3                   - modulo by three. To replace any 4(r) with 1
-  ...while keeping any 0(d) as 0, or 2(u) as 2
’                  - decrement. All r are now 0, d are -1 and u are 1
§                 - sum each
§                - sum each. Now we have the total increase value as
-    ...integers for each of hrs and mins
“ð<‘          - code-page indices list = [24,60]
"              - zip with:
%               -   modulo
D         - to decimal lists
Ż€       - prepend each with a zero (to cater for values less than ten)
ṫ€-    - tail each from index -1. Keeps rightmost two digits of each only)
”: - literal character ':'
j   - join
- as full program implicit print (smashes the digits and characters together)


# APL (Dyalog Classic), 97 84 bytes

5↑∊{¯3↑'0',':',⍨⍕⍵}¨24 60|A⊣⍎¨'⎕IO←1' '⎕IO←0' 'A[1]+←1' 'A[1]-←1'['←→↑'⍳⍞,'←']⊣A←0 0


Try it online!

Requires ⎕IO←1

# QBasic, 229 bytes

A script that takes input as keystrokes and outputs to the console.

Note: terminal " are included for syntax highlighting only, and do not contribute to the bytecount

z$=CHR$(0)
DO
x=0
y=0
SELECT CASE INKEY$CASE z$+"K"
r=0
CASE z$+"M" r=1 CASE z$+"H"
x=1
y=1
CASE z$+"P" x=23 y=59 END SELECT IF r THEN m=(m+y)MOD 60ELSE h=(h+x)MOD 24 CLS ?RIGHT$("00000"+LTRIM$(STR$(h*1000+m)),5)
LOCATE 1,3
?":"
LOOP


### Commented

z$=CHR$(0)                                      ''  Set var to null char
DO                                              ''
x=0                                         ''  Set Hours Shift to 0
y=0                                         ''  Set Minutes Shift to 0
SELECT CASE INKEY$'' Take keystroke input CASE z$+"K"                             ''  If is Left Arrow
r=0                                 ''    Bool to modify right (minutes)
CASE z$+"M" '' If is Right Arrow r=1 '' Bool to modify left (hours) CASE z$+"H"                             ''  If is Up Arrow
x=1                                 ''    Set Hours Shift to 1
y=1                                 ''    Set Minutes Shift to 1
CASE z$+"P" '' If is Down Arrow x=23 '' Set Hours Shift to 23 y=59 '' Set Minutes Shift to 23 END SELECT '' IF r THEN m=(m+y)MOD 60ELSE h=(h+x)MOD 24 '' Shift Minutes If r=1 Else Shift Hours CLS '' Clear Screen ?RIGHT$("00000"+LTRIM$(STR$(h*1000+m)),5)   ''  Use math to concat Hours and Minutes
''  then Convert to String and prepend 0s
''  to a length of 5
LOCATE 1,3                                  ''  Cursor to the the third digit
?":"                                        ''  Overwrite that digit with a :
LOOP                                            ''  Loop

• Shouldn't that be (m+y)? – Neil Jul 18 '18 at 15:15
• In the note, should not does be do? – Jonathan Frech Jul 18 '18 at 15:40
• @JonathanFrech - Yep it should be. Thanks for keeping my grammar in check – Taylor Scott Jul 18 '18 at 16:26
• Sorry, I thought m was for minutes for some reason... I see your commented version is more readable. – Neil Jul 18 '18 at 18:49

# Powershell, 109 103 bytes

$t=0,0$args|%{$t[+$i]+=. @{l={$i=0};r={$i=1};u={1};d={119}}.$_} "{0:00}:{1:00}"-f($t[0]%24),($t[1]%60)  Test script: $f = {

$t=0,0$args|%{$t[+$i]+=. @{l={$i=0};r={$i=1};u={1};d={119}}.$_} "{0:00}:{1:00}"-f($t[0]%24),($t[1]%60) } @( ,('02:57',('u','u','r','d','d','d')) ,('00:00',('d','r','u','l','u','r','d')) ,('23:59',('d','r','r','d')) ,('00:01',('l','l','l','l','r','u')) ,('23:59',('d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','d','r','d')) ) | % {$e, $c =$_
$r = &$f @c
"$($r-eq$e):$r"
}


Output:

True: 02:57
True: 00:00
True: 23:59
True: 00:01
True: 23:59


## Explanation

Basic idea is to use a [hashtable], which keys are control commands and values are scriptblocks. The code execute the scriptblock for each command from arguments.

f t i('v':r)=f(i#t$-1)i r f t i(x:r)=f t x r f(h,m)_ _=s h++':':s m ('<'#(h,m))n=(mod(24+n+h)24,m) (_#(h,m))n=(h,mod(60+n+m)60) s n=['0'|n<10]++show n  Try it online! # R, 368 355 bytes f=function(){C=as.character i=ifelse p=paste0 r=1:10 h=C(0:23);m=C(0:59) h[r]=p(0,h[r]) m[r]=p(0,m[r]) x=y=z=1 while(T){print(p(h[x],":",m[y])) v=1 n="[UDLRS]" while(!grepl(n,v))v=toupper(readline(n)) if(v=="L")z=1 else if(v=="R")z=0 if(v=="S")T=F if(v=="U")if(z)x=i(x==24,1,x+1)else y=i(y==60,1,y+1) if(v=="D")if(z)x=i(x==1,24,x-1)else y=i(y==1,60,y-1)}}  Definitely not the best approach, but works. Functionality: Run function, type each letter to (in/de)crease or move left/right, typing "s" ends the "game". The catch is that it will accept one and only one letter at a time. -13 bytes Consolidated some values into one row, overwrote T as F instead of using break, found several spaces to eliminate, and a string stored in a variable instead f=function(){C=as.character # Abbreviate functions i=ifelse p=paste0 r=1:10 # Initialize and format values h=C(0:23);m=C(0:59) h[r]=p(0,h[r]) m[r]=p(0,m[r]) x=y=z=1 while(T){print(p(h[x],":",m[y])) # Begin while loop and print time v=1 # Initial value reset each iteration to retrieve a new direction n="[UDLRS]" # Used for verification and request while(!grepl(n,v))v=toupper(readline(n)) # Will only accept proper directions or stopping rule if(v=="L")z=1 else if(v=="R")z=0 # Evaluate for hour or minute if(v=="S")T=F # Stopping rule, overwrite True to False if(v=="U")if(z)x=i(x==24,1,x+1)else y=i(y==60,1,y+1) # Rules for Up if(v=="D")if(z)x=i(x==1,24,x-1)else y=i(y==1,60,y-1)}} # Rules for Down  I am also editing an alternate format to accept an R string and/or vector, will post next week. # SmileBASIC, 123 bytes @L B=BUTTON(2)D=(B==1)-(B==2)S=S+!S*(B>7)-S*(B==4)H=(H+D*!S+24)MOD 24WAIT M=(M+D*S+60)MOD 60?FORMAT$("%02D:%02D",H,M)GOTO@L


BUTTON() returns an integer where each bit represents a button

1 = up
2 = down
4 = left
8 = right
...


BUTTON(2) returns only the buttons that were just pressed (not being held)

WAIT is required because BUTTON only updates once per frame (1/60 of a second). Otherwise the same button press would be detected multiple times.

This can definitely be shorter

# 05AB1E, 38 37 bytes

'l¡ε'r¡}0ζćs˜‚€S„udS1®‚:OŽ9¦2ä%T‰J':ý


Uses udlr for the directions, but could also use ^v<> for the same byte-count (the characters ↑↓←→ are not part of 05AB1E's codepage, so using those would increase the byte-count by a lot, since the encoding should be changed to ASCII).

Explanation:

'l¡            '# Split the (implicit) input on "l"
#  i.e. "lllrurulddd" → ["","","","ruru","ddd"]
ε   }        # Map each item to:
'r¡        '#  Split the item on "r"
#   i.e. ["","","","ruru","ddd"] → [[""],[""],[""],["","u","u"],["ddd"]]
0ζ      # Zip/transpose; swapping rows/columns, with "0" as filler
#  i.e. [[""],[""],[""],["","u","u"],["ddd"]]
#   → [["","","","","ddd"],["0","0","0","u","0"],["0","0","0","u","0"]]
ć               # Head extracted: pop and push the remainder and head-item to the stack
#  i.e. [["","","","","ddd"],["0","0","0","u","0"],["0","0","0","u","0"]]
#   → [["0","0","0","u","0"],["0","0","0","u","0"]] and ["","","","","ddd"]
s              # Swap to get the remainder
˜             # Flatten it
#  i.e. [["0","0","0","u","0"],["0","0","0","u","0"]]
#   → ["0","0","0","u","0","0","0","0","u","0"]
‚            # Pair the head and remainder back together
#  i.e. ["","","","","ddd"] and ["0","0","0","u","0","0","0","0","u","0"]
#   → [["","","","","ddd"],["0","0","0","u","0","0","0","0","u","0"]]
€S          # Convert each item to a list of characters
# (implicitly flattens and removes empty strings)
#  i.e. [["","","","","ddd"],["0","0","0","u","0","0","0","0","u","0"]]
#   → [["d","d","d"],["0","0","0","u","0","0","0","0","u","0"]]
„udS1®‚:  # Replace all "u" with "1" and all "d" with "-1"
#  i.e. [["d","d","d"],["0","0","0","u","0","0","0","0","u","0"]]
#   → [["-1","-1","-1"],["0","0","0","1","0","0","0","0","1","0"]]
O # Then take the sum of each inner list
#  i.e. [["-1","-1","-1"],["0","0","0","1","0","0","0","0","1","0"]]
#   → [-3,2]
Ž9¦             # Push compressed integer 2460
2ä           # Split into two parts: [24,60]
%          # Modulo the two lists
#  i.e. [-3,2] and [24,60] → [21,2]
T‰        # Divmod each with 10
#  i.e. [21,2] → [[2,1],[0,2]]
J       # Join each inner list together
#  i.e. [[2,1],[0,2]] → ["21","02"]
':ý   '# Join the list with ":" delimiter
#  i.e. ["21","02"] → "21:02"
# (and output the result implicitly)


See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ž9¦ is 2460.