9
\$\begingroup\$

Yesterday, as part of a IQ-style test, I got this interesting question:

The time on a 24-hour clock is 11:43. What is the least number of minutes I should wait before the same digits are on the screen again (in any valid 24-hour time order)?

The answer's 91 minutes, if you were wondering!

This stuck in my mind, and it finds its way... here. In an adapted form, however... Your task is, given a 24-hour time string in the format HH:MM (or in any other way as long as it provides HH and MM), shift the digits around until you find 24-hour time strings that would be in the same day counting forwards, and pick the one whose distance to the input is the shortest. Then return the number of minutes to the picked time string as an integer, using default output rules.

Method:

See above.

Input:

Allow facilities for input such that 2 digits of hours and 2 digits of minutes are provided. Do not worry about invalid input (example: 25:12, 1:34 [01:34 will be correct, however], and 05:89).

You cannot use 12-hour system.

Output:

An integer. Note that it should be in minutes, not seconds or any other unit (this is fixed)

Return a distinct value (like 1440, an error, etc. I'm using "Nil" in the test-cases) when no valid shifted 24-hour time string can be created until 23:59.

Test cases:

Input (HH:MM) -> Output (Int or "Nil")
11:43 -> 91
01:01 -> 9
17:38 -> 59
14:21 -> 413
13:20 -> 413
23:41 -> Nil
00:00 -> Nil

Scoring:

This is , so shortest answer wins!

Greg Martin
16.7k4 gold badges23 silver badges73 bronze badges
asked Feb 10, 2023 at 9:05
\$\endgroup\$
13
  • 8
    \$\begingroup\$ You still didn't explain why 21:14 can't come from 14:21 \$\endgroup\$ Commented Feb 10, 2023 at 9:08
  • 1
    \$\begingroup\$ Can I pass time to my function as two numbers i.e. f(hours,minutes) or it must be a string f('hh:mm')? \$\endgroup\$ Commented Feb 10, 2023 at 10:04
  • 1
    \$\begingroup\$ You can, as long as 03 does not get parsed as 3. \$\endgroup\$ Commented Feb 10, 2023 at 10:07
  • 2
    \$\begingroup\$ But there is no number 03. You can write f(03,08) but it will be the same as f(3,8) but it doesn't affect to the algorithm or result. Passing numbers instead of string(s) just allow me to not use split method and/or not convert strings to numbers so it saves me some bytes \$\endgroup\$ Commented Feb 10, 2023 at 10:14
  • 6
    \$\begingroup\$ Suggested edge case: 00:00 -> Nil \$\endgroup\$ Commented Feb 10, 2023 at 11:59

14 Answers 14

6
\$\begingroup\$

Wolfram Language (Mathematica), 135 bytes

Min@(s=Select)[(x@#~f~60-a~f~60)&/@s[Permutations[p=#],(w=x@#;24>w[[1]]>=#&@@(a=x@p)&&w[[2]]<60)&],#>0&]&
x=BlockMap[f=FromDigits,#,2]&

Try it online!

-6 bytes from @att

answered Feb 10, 2023 at 10:21
\$\endgroup\$
2
  • \$\begingroup\$ Finally a non builtin answer :P \$\endgroup\$ Commented Feb 10, 2023 at 16:12
  • \$\begingroup\$ x=BlockMap[f=FromDigits,#,2]& \$\endgroup\$ Commented Feb 11, 2023 at 1:02
4
\$\begingroup\$

05AB1E, 24 bytes

œ2δôʒŽ9¦2ô‹P}60δβć-ʒ0›}ß

Input as a single 4-digit string in the format HHmm. Outputs an empty string if there is no result available.

Try it online or verify all test cases.

Explanation:

œ # Get all permutations of the (implicit) input-string
 δ # Map over each permutation:
 2 ô # Split it into parts of size 2 (to split HH and mm)
 ʒ # Filter this list of [HH,mm] by:
 Ž9¦ # Push compressed integer 2460
 2ô # Split it into parts of size 2 as well: [24,60]
 ‹ # Check [HH<24,mm<60]
 P # And check if both are truthy by taking the product
 } δ # After the filter: map over the remaining [HH,mm]:
 60 β # Convert it from a base-60 list to a base-10 integer
ć # Extract head; pop and push remainder-list and first item separately
 - # Subtract this head (the input) from all other valid permutations
 ʒ0›} # Only keep all positive integers from the list with a filter on 0>
 # (a.k.a. keep all integers for times later than the input-time)
 ß # After the filter: pop and leave the minimum
 # (which is output implicitly as result)

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

answered Feb 10, 2023 at 10:51
\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js), 84 bytes

x=>(g=y=>++y>2399?+g:y%100<60?(e=t=>[...1e4+t+g].sort()+0)(x)==e(y)||g(y)+1:g(y))(x)

Try it online!

answered Feb 10, 2023 at 12:13
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Input must be 2 digits for each part. \$\endgroup\$ Commented Feb 10, 2023 at 18:48
  • \$\begingroup\$ @Shaggy The challenge doesn't say that? \$\endgroup\$ Commented Feb 11, 2023 at 13:57
  • \$\begingroup\$ @Etheryte, see the "input" section of the spec which specifies that they must be 2 digits each and provides the example that 1:34 is invalid while 01:34 is valid. \$\endgroup\$ Commented Feb 11, 2023 at 16:51
  • \$\begingroup\$ @Shaggy I feel like you might be misreading the sentence, it explicitly says that you don't have to worry about invalid input. \$\endgroup\$ Commented Feb 11, 2023 at 19:01
4
\$\begingroup\$

JavaScript (ES6), 96 bytes

Expects ("HH")("MM"). Returns NaN for Nil.

h=>F=(m,s=h+m)=>(m=-~m%60)||++h<24?(g=s=>[...s].sort().slice(-4)+0)(s)==g("00"+h+m)||1+F(m,s):+F

Try it online!

Commented

h => // outer function taking h = hours
F = ( // inner recursive function taking
 m, // m = minutes
 s = h + m // s = concatenation of the original hours and minutes
) => //
(m = -~m % 60) // increment the minutes modulo 60
|| // ignore the next statement if the result is not 0
++h < 24 // otherwise, increment the hours and make sure they are
? // less than 24; if successful:
 ( g = s => // g is a helper function taking a string s
 [...s] // split s into a list of characters
 .sort() // sort them lexicographically
 .slice(-4) // take the last 4 characters
 + 0 // coerce back to a string with a trailing '0'
 )(s) == // invoke g with s and compare the result with
 g( // the same operation applied to ...
 "00" + // two leading zeros
 h + m // followed by h, followed by m
 ) //
 || // stop if it matches; otherwise,
 1 + // increment the final result
 F(m, s) // and do a recursive call
: // else:
 +F // force the result to NaN and stop
answered Feb 10, 2023 at 11:51
\$\endgroup\$
1
  • 1
    \$\begingroup\$ 89 \$\endgroup\$ Commented Feb 10, 2023 at 12:29
3
\$\begingroup\$

Vyxal g, (削除) 24 23 (削除ここまで) 22 bytes

Ṗ1⁄2'‛0xC1⁄2<Π;ƛE60β;ḣ$-'Ṡ

Try it Online!

Port of Kevin Cruijssen's 05AB1E answer. Input as a string, "HHmm".

-1 thanks to AndrovT in chat
-1 thanks to lyxal

Explanation

Ṗ1⁄2'‛0xC1⁄2<Π;ƛE60β;ḣ$-'Ṡ # Implicit input
Ṗ # Permutations
 1⁄2 # Split each in half
 ' ; # Filter:
 ‛0xC1⁄2 # Push [24, 60]
 < # Less than [24, 60]?
 Π # Both are true?
 ƛ ; # Map:
 E # Convert to integer
 60β # Convert from base-60
 ḣ$ # Extract head and swap
 - # Subtract head from rest
 ' # Filter:
 Ṡ # Positive integers only
 # g flag gets minimum
 # Implicit output
answered Feb 11, 2023 at 17:20
\$\endgroup\$
2
3
\$\begingroup\$

Python, 132 bytes

lambda x:(a:=x.split(':'),b:=int(a[0])*60+int(a[1]),*[i for i in range(b+1,1440)if sorted(f"{i%60:02}:{i//60:02}")==sorted(x)])[2]-b

Attempt This Online!

Throws a error if there is no valid output.

Python, 113 bytes

lambda x,y:(b:=x*60+y,*[i for i in range(b+1,1440)if sorted((e:="%02d%02d")%divmod(i,60))==sorted(e%(x,y))])[1]-b

Attempt This Online!

Takes input as 2 numbers

answered Feb 10, 2023 at 9:31
\$\endgroup\$
2
  • \$\begingroup\$ My rules allow you to take 2 digits of hour and minute without having to provide it as HH:MM; I suppose you could shave off a few bytes with that (by taking input as a list or something) \$\endgroup\$ Commented Feb 10, 2023 at 9:53
  • 3
    \$\begingroup\$ Why not use "%02d"*2 for the string in the second solution? Edit: can also set the signature to lambda x,y,z=sorted: and replace two sorted() calls with z() \$\endgroup\$ Commented Feb 12, 2023 at 8:49
3
\$\begingroup\$

Charcoal, 42 bytes

≔↨I⪪θ:60ηI⌊Φ...1−1440η⬤I...1χ=NoθλNoI↨100↨+ηι60λ

Try it online! Link is to verbose version of code. Outputs None if there is no solution. Explanation:

≔↨I⪪θ:60η

Calculate the number of minutes since midnight.

I⌊Φ...1−1440η⬤I...1χ=NoθλNoI↨100↨+ηι60λ

Create a range from 1 until the number of minutes until the next midnight, filter on those that, when formatted as a time, contain identical counts of digits, and output the minimum. Note that I don't count 0 digits as all times have four digits so if the counts of the other digits are correct then so will the counts of the zero digits be; this avoids having to actually format the time.

answered Feb 10, 2023 at 10:26
\$\endgroup\$
3
\$\begingroup\$

JavaScript, 109 bytes

Without recursion:

(h,m)=>{for(k=1,t=h*60+m;t++<1440;++k)if((a=(h,m)=>+[...''+h+m].sort().join``)(h,m)==a(t/60|0,t%60))return k}

Try it

f=(h,m)=>{for(k=1,t=h*60+m;t++<1440;++k)if((a=(h,m)=>+[...''+h+m].sort().join``)(h,m)==a(t/60|0,t%60))return k}
[
 '11:43', // -> 91
 '01:01', // -> 9
 '17:38', // -> 59
 '14:21', // -> 413
 '13:20', // -> 413
 '23:41', // -> undefined
].forEach(t => {
 const [hours, minutes] = t.split`:`.map(x=>+x);
 const additional = f(hours, minutes);
 if (additional === undefined) {
 console.log(undefined);
 return;
 }
 const getTime = (h,m) => {
 const now = new Date();
 now.setHours(h+1);
 now.setMinutes(m);
 
 const timeParts = now.toJSON().split`T`.flatMap(x=>x.split`:`);
 return [timeParts[1], timeParts[2]].join`:`
 }
 const oldTime = getTime(hours, minutes);
 const newTime = getTime(hours, minutes + additional);
 console.log(`${oldTime} + ${additional} minutes = ${newTime}`);
})

answered Feb 10, 2023 at 11:19
\$\endgroup\$
3
  • \$\begingroup\$ h & m must be taken as 2 digit strings so, unfortunately, this is invalid. \$\endgroup\$ Commented Feb 10, 2023 at 18:16
  • 1
    \$\begingroup\$ @Shaggy "or in any other way as long as it provides HH and MM" - you can pass 05 as h and 09 as m it just automatically be converted to 5 and 9 \$\endgroup\$ Commented Feb 10, 2023 at 18:36
  • \$\begingroup\$ @Shaggy The challenge doesn't say that the inputs need to be strings. \$\endgroup\$ Commented Feb 11, 2023 at 13:55
3
\$\begingroup\$

Perl 5, 99 bytes

sub{"@{[grep{s|1(..)([0-5].)|1ドル:2ドル@{[sort/./g]},|}1e4..12359]}"=~/$_[0]((.+),.*?)2円/&&1ドル=~y///c/16}

Try it online!

Creates a long string of all HH:MM in a day (all 24*60 of them) and adds the four digits sorted after each of those timestamps in the same long string. Searches the long string for the five char input HH:MM and collects the sorted digits behind it with (.+), and searches for those same sorted digits further down the long string with 2円. The number of chars jumped ahead to find them divided by 16 is the number of minutes.

answered Feb 10, 2023 at 12:14
\$\endgroup\$
0
2
\$\begingroup\$

Excel, (削除) 175 (削除ここまで) 171 bytes

=LET(
 a,A1,
 b,1440,
 c,{1;2;4;5},
 d,TEXT(SEQUENCE(,b)/b,"hh:mm"),
 e,BYCOL(MID(d,c,1),LAMBDA(x,CONCAT(SORT(x)))),
 f,0+IF(e=CONCAT(SORT(MID(a,c,1))),d),
 b*(XLOOKUP(a+1/b,f,f,,1)-a)
)

Input as string in format "hh:mm" in cell A1. Error returned if no valid output.

answered Feb 10, 2023 at 14:46
\$\endgroup\$
1
\$\begingroup\$

Thunno, \$ 42 \log_{256}(96) \approx \$ 34.57 bytes

DLzP.Je2APiEgAu60<s24<&ke60AdEDAJsZT_g0>km

Attempt This Online!

Port of Kevin Cruijssen's 05AB1E answer. Input as a string, "HHmm".

Explanation

DLzP # Get the permutations of the input string
 .J # Join each inner list into a single string
 e # Map over this list:
 2APi # Split into two pieces and convert to an integer
 E # (End map)
 g # Filter this list:
 Au # Dump onto the stack (last item of list on top of stack)
 60< # Is the last item less than 60?
 s24< # Is the first item less than 24?
& # Are both of the above true?
 k # (End filter)
 e # Map over this list:
 60Ad # Convert from base-60
 E # (End map)
 DAJ # Duplicate and get the first item
 sZT # Swap and remove the first item
 _ # Subtract the first item from the rest
 g # Filter this list:
 0> # Is the number greater than 0?
 k # (End filter)
 m # Push the minimum value of this list
 # Implicit output
answered Feb 11, 2023 at 17:06
\$\endgroup\$
1
\$\begingroup\$

Julia 1.0, (削除) 107 (削除ここまで) 102 bytes

using Dates
!x=(f=Minute;~q=sort(["$q"...]);t=Time(x);max(f(tonext(i->~i==~t,t,step=f(1))-t).value,0))

Try it online!

In Julia 1.8, the function will return 0 for inputs with no solution (example: !"23:41"). The TIO link only supports Julia 1.0, which fails for these inputs, since Dates.tonext doesn't stop at "23:59".

  • Renaming Dates.Minute a f saves a byte.
  • The subfunction ~ returns a sorted list of digits for comparison.
  • This solution relies on Dates.tonext, which I've used in another challenge. In Julia 1.8, it returns a negative value for inputs with no solution, so max is used to filter these out. A limit parameter also exists, but this would return an error instead of a NULL value.
  • -5 bytes thanks to MarcMush: replace string(q) with "$q"
answered Feb 10, 2023 at 22:45
\$\endgroup\$
1
  • 1
    \$\begingroup\$ -5 bytes: string(q) => "$q" \$\endgroup\$ Commented Feb 13, 2023 at 22:54
1
\$\begingroup\$

Nekomata, 24 bytes

↕a{¢b100B"<∩"e<60d}-_Paṁ

Attempt This Online!

Another port of Kevin Cruijssen's 05AB1E answer.

Take input as a list of four digits.

↕ Get a permutation of the input
 a Apply the following block to both the input and the permutation
 { Start the block
 ¢b Get a number from base 10 digits
 100B Convert the number to a list of digits in base 100
"<∩"e< Check that the two numbers are smaller than [24,60] respectively
 60d Get a number from base 60 digits
 } End the block
 -_ Subtract and negate
 P Check if the result is positive
 a Get a list of all possible results
 ṁ Get the minimum
answered Mar 2, 2023 at 13:52
\$\endgroup\$
0
\$\begingroup\$

J, 59 58 bytes

(e.*1+i.~)&([:/:~@,"%.10 10&#:)(+1+[:i.1440-])&.(24 60&#.)

Try it online!

  • (+1+[:i.1440-])&.(24 60&#.) Calculates every absolute minute of the day (0 to 1439 scale), starting at the current hour and up, and then converts back to hh:mm form.
  • ...&([:/:~@,"%.10 10&#:) Converting both the input and the candidate list from the previous step into sorted lists of digits...
  • (e.*1+i.~) Is the input an element of the candidate list (returns 0 or 1) times one plus its index within the candidate list. This returns 0 for no match, and the number of minutes we have to wait otherwise.
answered Feb 11, 2023 at 2:13
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.