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 code-golf, so shortest answer wins!
14 Answers 14
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]&
-6 bytes from @att
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.
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)
-
1\$\begingroup\$ Input must be 2 digits for each part. \$\endgroup\$Shaggy– Shaggy2023年02月10日 18:48:03 +00:00Commented Feb 10, 2023 at 18:48
-
\$\begingroup\$ @Shaggy The challenge doesn't say that? \$\endgroup\$Etheryte– Etheryte2023年02月11日 13:57:24 +00:00Commented 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:34is invalid while01:34is valid. \$\endgroup\$Shaggy– Shaggy2023年02月11日 16:51:46 +00:00Commented 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\$Etheryte– Etheryte2023年02月11日 19:01:17 +00:00Commented Feb 11, 2023 at 19:01
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
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
-
1
Vyxal g, (削除) 24 23 (削除ここまで) 22 bytes
Ṗ1⁄2'‛0xC1⁄2<Π;ƛE60β;ḣ$-'Ṡ
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
-
\$\begingroup\$
½vectorises by default, so thevinv½isn't needed \$\endgroup\$2023年03月02日 13:02:48 +00:00Commented Mar 2, 2023 at 13:02 -
\$\begingroup\$ Thanks, updated \$\endgroup\$The Thonnu– The Thonnu2023年03月02日 13:04:42 +00:00Commented Mar 2, 2023 at 13:04
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
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
Takes input as 2 numbers
-
\$\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\$Rhaixer– Rhaixer2023年02月10日 09:53:11 +00:00Commented Feb 10, 2023 at 9:53 -
3\$\begingroup\$ Why not use
"%02d"*2for the string in the second solution? Edit: can also set the signature tolambda x,y,z=sorted:and replace twosorted()calls withz()\$\endgroup\$musava_ribica– musava_ribica2023年02月12日 08:49:37 +00:00Commented Feb 12, 2023 at 8:49
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.
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}`);
})
-
\$\begingroup\$
h&mmust be taken as 2 digit strings so, unfortunately, this is invalid. \$\endgroup\$Shaggy– Shaggy2023年02月10日 18:16:00 +00:00Commented 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
05ashand09asmit just automatically be converted to5and9\$\endgroup\$EzioMercer– EzioMercer2023年02月10日 18:36:27 +00:00Commented Feb 10, 2023 at 18:36 -
\$\begingroup\$ @Shaggy The challenge doesn't say that the inputs need to be strings. \$\endgroup\$Etheryte– Etheryte2023年02月11日 13:55:49 +00:00Commented Feb 11, 2023 at 13:55
Perl 5, 99 bytes
sub{"@{[grep{s|1(..)([0-5].)|1ドル:2ドル@{[sort/./g]},|}1e4..12359]}"=~/$_[0]((.+),.*?)2円/&&1ドル=~y///c/16}
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.
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.
Thunno, \$ 42 \log_{256}(96) \approx \$ 34.57 bytes
DLzP.Je2APiEgAu60<s24<&ke60AdEDAJsZT_g0>km
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
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))
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.Minuteafsaves 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, somaxis used to filter these out. Alimitparameter also exists, but this would return an error instead of a NULL value. - -5 bytes thanks to MarcMush: replace
string(q)with"$q"
-
1\$\begingroup\$ -5 bytes:
string(q) => "$q"\$\endgroup\$MarcMush– MarcMush2023年02月13日 22:54:39 +00:00Commented Feb 13, 2023 at 22:54
Nekomata, 24 bytes
↕a{¢b100B"<∩"e<60d}-_Paṁ
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
J, 59 58 bytes
(e.*1+i.~)&([:/:~@,"%.10 10&#:)(+1+[:i.1440-])&.(24 60&#.)
(+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.
21:14can't come from14:21\$\endgroup\$f(hours,minutes)or it must be a stringf('hh:mm')? \$\endgroup\$03does not get parsed as3. \$\endgroup\$03. You can writef(03,08)but it will be the same asf(3,8)but it doesn't affect to the algorithm or result. Passing numbers instead of string(s) just allow me to not usesplitmethod and/or not convert strings to numbers so it saves me some bytes \$\endgroup\$00:00 -> Nil\$\endgroup\$