Find maximum possible time HH:MM by permuting four given digits
Here is a non brute force solution that I came up with. Check out the comments in the code to see how it works. If any of it is unclear I can help clarify.
function generate(A, B, C, D) {
vals = [A, B, C, D];
counts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < vals.length; i++) {
for (j = vals[i]; j < counts.length; j++) counts[j]++;
}
// counts is now populated with the number of values less than or equal to the index it belongs to
// so counts[2] is the total number of 0's, 1's and 2's
if (counts[2] === 0) return 'NOT POSSIBLE';
// if there are no 0's and 1's, then it must start with 2
mustStartWith2 = counts[1] === 0;
if (mustStartWith2 && counts[3] === 1) return 'NOT POSSIBLE';
// We want a count of the number of free digits that are 5 or less (for the minute digit)
numbersAvailableForMinute = counts[5] - (mustStartWith2 ? 2 : 1);
if (numbersAvailableForMinute === 0) return 'NOT POSSIBLE';
// we now know that it is a valid time
time = [0, 0, 0, 0];
// we also know if it starts with 2
startsWith2 = mustStartWith2 || (numbersAvailableForMinute >= 2 && counts[2] > counts[1]);
// knowing the starting digit, we know the maximum value for each digit
maxs = startsWith2 ? [2, 3, 5, 9] : [1, 9, 5, 9];
for (i = 0; i < maxs.length; i++) {
// find the first occurrence in counts that has the same count as the maximum
time[i] = counts.indexOf(counts[maxs[i]]);
// update counts after the value was removed
for (j = time[i]; j < counts.length; j++) counts[j]--;
}
// create the time
return time[0]+""+time[1]+":"+time[2]+""+time[3];
}
Added executable snippet and some test cases
function generate(A, B, C, D) {
var combinations = []
arguments = Array.from(arguments)
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (i !== j) {
var num = +(arguments[i] + '' + arguments[j])
if (num <= 59 && combinations.indexOf(num) === -1)
combinations.push(num)
}
}
}
combinations.sort((a, b) => a - b);
var hours = combinations.filter(hour => hour <= 23);
for (var i = hours.length - 1; i >= 0; i--) {
for (var j = combinations.length - 1; j >= 0; j--) {
if (computeMax(hours[i], combinations[j], arguments))
return hours[i] + ':' + combinations[j]
}
}
return 'not possible'
}
function computeMax(maxHour, maxMinute, args) {
var minute = String(maxMinute)
var hour = String(maxHour)
for (var k = 0; k < minute.length; k++)
if (hour.indexOf(minute[k]) > -1 && args.indexOf(+minute[k]) === args.lastIndexOf(+minute[k]))
return false
return true
}
console.log('generate(1,7,2,7)', generate(1,7,2,7))
console.log('generate(6,5,2,0)', generate(6,5,2,0))
console.log('generate(3,9,5,0)', generate(3,9,5,0))
console.log('generate(7,6,3,8)', generate(7,6,3,8))
console.log('generate(0,1,2,3)', generate(0,1,2,3))
console.log('generate(1,1,1,2)', generate(1,1,1,2))
console.log('generate(1,1,1,1)', generate(1,1,1,1))
console.log('generate(5,6,7,8)', generate(5,6,7,8))
console.log('generate(2,9,3,1)', generate(2,9,3,1))