Find maximum possible time HH:MM by permuting four given digits

前端 未结 23 2094
执念已碎
执念已碎 2020-11-30 02:44

I recently took a coding test for a promotion at work. This was one of the tasks I really struggled with and was wondering what is the best way to do this. I used a load of

23条回答
  •  天命终不由人
    2020-11-30 02:56

    Here's my attempt. Added inline comments with explanations.

    // think of the result of the form {h1}{h2}:{ms}
    function generate(a, b, c, d) {
      const digits = [a, b, c, d];
    
      // extract possible starting digits
      const possibleH1s = [2, 1, 0].filter(digit => digits.includes(digit));
      
      // check result, starting from the highest possible h1 digit
      // if digits doesn't contains any of [2,1,0], we're done
      for (const h1 of possibleH1s) {
    
        // extract the remaining digits after h1
        const withoutH1 = removeFrom(digits, h1);
        
        // determine all possible h2 digits based on the h1 digit
        const possibleH2s = h1 === 2
          ? [3,2,1,0]
          : [9,8,7,6,5,4,3,2,1,0];
    
        // find the highest possible h2 digit (works because array of possible digits above is in descending order)
        // if none exist, loop iteration is done
        const h2 = possibleH2s.find(d => withoutH1.includes(d));
        if (typeof h2 !== 'number') {
          continue;
        }
        
        // remove h2 so we can search for the remaining ms digits
        const [possibleMS1, possibleMS2] = removeFrom(withoutH1, h2);
        
        // build the two possible combinations for ms    
        const possibleMs = [
          Number(`${possibleMS1}${possibleMS2}`),
          Number(`${possibleMS2}${possibleMS1}`)
        ];
        
        // determine the min and max ms value
        const maxMs = Math.max(...possibleMs);
        const minMs = Math.min(...possibleMs);
    
        // find the largest valid ms value
        // if none exist, loop iteration is done
        const ms = maxMs < 60 ? maxMs : minMs < 60 ? minMs : undefined;
        if (typeof ms !== 'number') {
          continue;
        }
    
        // yay, time
        return `${h1}${h2}:${padWithZero(ms)}`;
      }
      
      return 'NOT POSSIBLE';
    }
    
    // returns a new array by removing a single element 
    // that is equal to `val` from the given array
    // (performs better than splice cause if doesn't do array shift)
    function removeFrom(arr, val) {
      const newArr = [];
      for (let i = 0, l = arr.length, found = false; i < l; i++) {
        if (arr[i] !== val || found) {
          newArr.push(arr[i]);
        } else {
          found = true;
        }
      }
      return newArr;
    }
    
    function padWithZero(digit) {
      return digit < 10 ? `0${digit}` : `${digit}`;
    }
    
    /* --------------- Tests --------------------- */
    
    const speedTest = (times = 10000) => {
      let counter = times;
      const start = performance.now();
      while (counter--) {
        const A = randNum();
        const B = randNum();
        const C = randNum();
        const D = randNum();
        generate(A, B, C, D);
        if (counter == 0) {
          const ms = performance.now() - start;
          console.log(`${times} times to run generate took ${ms} ms`);
        }
      }
    }
    
    const randNum = () => Math.floor(Math.random() * (9 - 0 + 1)) + 0;
    
    const accuracyTest = () => {
      console.assert(generate(1,7,2,7) === '17:27');
      console.assert(generate(0,0,2,9) === '20:09');
      console.assert(generate(6,5,2,0) === '20:56');
      console.assert(generate(3,9,5,0) === '09:53');
      console.assert(generate(7,6,3,8) === 'NOT POSSIBLE');
      console.assert(generate(0,0,0,0) === '00:00');
      console.assert(generate(9,9,9,9) === 'NOT POSSIBLE');
      console.assert(generate(1,2,3,4) === '23:41');
      console.log('All good!');
    }
    
    speedTest();
    accuracyTest();

提交回复
热议问题