• 【Edibat 算法 ★★★★★★】【吸血鬼数字】Vampire Numbers


    Vampire Numbers

    recursion permutation brute force

    A Vampire Number is a positive integer greater than 99, that rearranged in all of its possible digits permutations, with every permutation being split into two parts, is equal to the product of at least one of its permutations.

    • If the number has an even quantity of digits, left and right parts will have the same length in every permutation;
    • If the number has an odd quantity of digits and at least three digits, the left and right parts will present different lengths for every possible permutation, alternating between them in the range +1 and -1.

    Given a positive integer n, implement a function that returns the type of n as a string:

    • 'Normal Number' if n is lower than 100 or if no permutations return a product of their parts equal to n.
    • 'Pseudovampire' if n it is a Vampire with an odd quantity of digits.
    • 'True Vampire' if n it is a Vampire with an even quantity of digits.
    Examples
    isVampire(1260) // "True Vampire"
    // Has an even number of digits and is greater than 99)
    // Permutations:
    // 12 * 60 = 720
    // 16 * 20 = 320
    // 10 * 26 = 260
    // 21 * 60 = 1260
    
    isVampire(126) // "Pseudovampire"
    // Has an odd number of digits and is greater than 99
    // Permutations:
    // 12 * 6 = 72
    // 1 * 26 = 26
    // 21 * 6 = 126
    
    isVampire(67) // "Normal Number"
    // Is lower than 100
    // Permutations:
    // 6 * 7 = 7 * 6 = 42
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    Notes
    • Trivially, a number from 1 to 99 is a Normal Number by the definitions: a single-digit number can’t be split into two parts, and the product of the permutated two digits of a number will always be lower than the number itself.
    Solutions
    // solution1: recursion + permutation
    const isVampire = (n) => {
        if(n < 100){
            return 'Normal Number'
        }
        let t = n,d=[];
        while(t){
            d.unshift(t%10)
            t = Math.floor(t/10)
        }
        let o = d.length&0b1;
        let res = compute(d,0,n,o,d.length)
        return res?(!o?'True Vampire':'Pseudovampire'):'Normal Number';
    }
    const compute = (d,k,n,o,l)=>{
        if(k==l){
            k = l>>>1
            let pair = toIntPair(d,k);
            let res = pair[0]*pair[1] === n;
            if(o && !res){
                pair = toIntPair(d,k+1);
                res = pair[0]*pair[1] === n;
            }
            return res;
        }
        for(let i=k;i<l;i++){
            [d[i],d[k]] = [d[k],d[i]]
            let res = compute(d,k+1,n,o,l)
            if(res){
                return true;
            }
            [d[k],d[i]] = [d[i],d[k]]
        }
        return false;
    };
    const toIntPair=(d,k)=>{
        let res = [0,0];
        for(let i=0;i<k;i++){
            res[0] = res[0]*10 + d[i]
        }
        for(let i=k;i<d.length;i++){
            res[1] = res[1]*10 + d[i]
        }
        return res
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    // solution2: brute force
    const isVampire = (n) => {
        if(n < 100){
            return 'Normal Number'
        }
        let t = n,c=0;
        while(t){
            c++;
            t = Math.floor(t/10);
        }
        let o = c&0b1;
        c >>>= 1
        let max = 1 ;
        while(c-->0){
            max *= 10
        }
        let d=Array(10).fill(0);
        for(let i = Math.floor(max/10); i < max;i++){
                let j = Math.floor(n/i);
                let m = i*j;
                let [ii,jj,mm] = [i,j,m];
                while(mm){
                    d[mm%10]++;
                    mm = Math.floor(mm/10);
                }
                while(ii){
                    d[ii%10]--;
                    ii = Math.floor(ii/10);
                }
                while(jj){
                    d[jj%10]--;
                    jj = Math.floor(jj/10);
                }
                let is = true;
                for(let i=0;i<10;i++){
                    if(d[i]){
                        is = false;
                        d[i] = 0;
                    }
                }
                if(is && m === n){
                    return !o?'True Vampire':'Pseudovampire';
                }
        }
        return 'Normal Number';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    TestCases
    
    let Test = (function(){
        return {
            assertEquals:function(actual,expected){
                if(actual !== expected){
                    let errorMsg = `actual is ${actual},${expected} is expected`;
                    throw new Error(errorMsg);
                }
            }
        }
    })();
    
    Test.assertEquals(isVampire(1260), "True Vampire", "Example #1")
    Test.assertEquals(isVampire(126), "Pseudovampire", "Example #2")
    Test.assertEquals(isVampire(67), "Normal Number", "Example #3")
    Test.assertEquals(isVampire(1), "Normal Number")
    Test.assertEquals(isVampire(645), "Normal Number")
    Test.assertEquals(isVampire(688), "Pseudovampire")
    Test.assertEquals(isVampire(1345), "Normal Number")
    Test.assertEquals(isVampire(1395), "True Vampire")
    Test.assertEquals(isVampire(12964), "Pseudovampire")
    Test.assertEquals(isVampire(98765), "Normal Number")
    Test.assertEquals(isVampire(124421), "Normal Number")
    Test.assertEquals(isVampire(125460), "True Vampire")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    Python教学案例 - 三天打渔、两天晒网
    基础算法 - 常见算法模板题(最简洁写法)【上】
    论文翻译:多延迟块频域自适应滤波器
    浏览器输入url地址,到页面渲染发生了什么
    Android 多点触控
    HTML5和CSS3的一些重要特性
    中国人民大学与加拿大女王大学金融硕士——人生下半场,用实力为自己“撑腰”
    MySQL(5)
    基于javaweb的电力设备监测管理系统(servlet+jsp)
    Idefics2 简介: 为社区而生的强大 8B 视觉语言模型
  • 原文地址:https://blog.csdn.net/avenccssddnn/article/details/133895523