JavaScript中级脚本算法编程练习(W3C学院)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39082031/article/details/81064611

JavaScript脚本算法编程实战课程

目录

JavaScript脚本算法编程实战课程

1、区间求值算法挑战

2、找出数组间差异算法挑战

3、数字转罗马数字

4、对象搜索算法挑战

5、字符串查询替换算法挑战

6、字符串移动插入算法挑战

7、字符配对算法挑战

8、字符串查询补充算法挑战

9、输入检查算法挑战

10、数组去重算法挑战

11、html符号转实体算法挑战

12、字符串连接算法挑战

13、斐波纳契奇数求和算法挑战

14、质素求和算法挑战

15、最小公倍数算法挑战

16、数组验证算法挑战

17、数组取值算法挑战

18、数组平铺算法挑战

18、二进制转字符算法挑战

19、数组元素判断算法挑战

20、函数迭代可选参数算法挑战


1、区间求值算法挑战

我们会传递给你一个包含两个数字的数组。返回这两个数字和它们之间所有数字的和。

最小的数字并非总在最前面。

function sumAll(arr) {
    var sum = 0;
    for (var i = Math.min(arr[0],arr[1]); i <= Math.max(arr[0],arr[1]); i++) {
        sum += i;
    }
    return sum;
}

sumAll([1, 4]);

运行结果:10

2、找出数组间差异算法挑战

比较两个数组,然后返回一个新数组,该数组的元素为两个给定数组中所有独有的数组元素。换言之,返回两个数组的差异。

function diff(arr1, arr2) {
    var newArr = [];
    // Same, same; but different.
    for (var i = 0; i < arr1.length; i++) {
        var flag1 = true;
        for (var j = 0; j < arr2.length; j++) {
            if (arr1[i] == arr2[j]) {
                flag1 = false;
                break;
            }
        }
        if(flag1){
            newArr = newArr.concat(arr1.slice(i,i+1));
        }
    }
    for (var m = 0; m < arr2.length; m++) {
        var flag2 = true;
        for (var n = 0; n < arr1.length; n++) {
            if (arr2[m] == arr1[n]) {
                flag2 = false;
                break;
            }
        }
        if(flag2){
            newArr = newArr.concat(arr2.slice(m,m+1));
        }
    }
    return newArr;
}

diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);

运行结果:[4]

3、数字转罗马数字

将给定的数字转换成罗马数字。

所有返回的 罗马数字 都应该是大写形式。

function convert(num) {
    var romanNum = [];
    switch (num % 10 / 1) {
        case 1:
            romanNum.splice(0,0,"I");
            break;
        case 2:
            romanNum.splice(0,0,"II");
            break;
        case 3:
            romanNum.splice(0,0,"III");
            break;
        case 4:
            romanNum.splice(0,0,"IV");
            break;
        case 5:
            romanNum.splice(0,0,"V");
            break;
        case 6:
            romanNum.splice(0,0,"VI");
            break;
        case 7:
            romanNum.splice(0,0,"VII");
            break;
        case 8:
            romanNum.splice(0,0,"VIII");
            break;
        case 9:
            romanNum.splice(0,0,"IX");
            break;
    }
    switch (Math.floor(num % 100 / 10)) {
        case 1:
            romanNum.splice(0,0,"X");
            break;
        case 2:
            romanNum.splice(0,0,"XX");
            break;
        case 3:
            romanNum.splice(0,0,"XXX");
            break;
        case 4:
            romanNum.splice(0,0,"XL");
            break;
        case 5:
            romanNum.splice(0,0,"L");
            break;
        case 6:
            romanNum.splice(0,0,"LX");
            break;
        case 7:
            romanNum.splice(0,0,"LXX");
            break;
        case 8:
            romanNum.splice(0,0,"LXXX");
            break;
        case 9:
            romanNum.splice(0,0,"XC");
            break;
    }
    switch (Math.floor(num % 1000 / 100)) {
        case 1:
            romanNum.splice(0,0,"C");
            break;
        case 2:
            romanNum.splice(0,0,"CC");
            break;
        case 3:
            romanNum.splice(0,0,"CCC");
            break;
        case 4:
            romanNum.splice(0,0,"CD");
            break;
        case 5:
            romanNum.splice(0,0,"D");
            break;
        case 6:
            romanNum.splice(0,0,"DC");
            break;
        case 7:
            romanNum.splice(0,0,"DCC");
            break;
        case 8:
            romanNum.splice(0,0,"DCCC");
            break;
        case 9:
            romanNum.splice(0,0,"CM");
            break;
    }
    switch (Math.floor(num % 10000 / 1000)) {
        case 1:
            romanNum.splice(0,0,"M");
            break;
        case 2:
            romanNum.splice(0,0,"MM");
            break;
        case 3:
            romanNum.splice(0,0,"MMM");
            break;
       /* case 4:
            romanNum.splice(0,0,"MV");
            break;
        case 5:
            romanNum.splice(0,0,"D");
            break;
        case 6:
            romanNum.splice(0,0,"DC");
            break;
        case 7:
            romanNum.splice(0,0,"DCC");
            break;
        case 8:
            romanNum.splice(0,0,"DCCC");
            break;
        case 9:
            romanNum.splice(0,0,"CM");
            break;*/
    }
 return romanNum.join("");
}

convert(12);

运行结果:XII

此方法用到过多的switch语句,不建议过多使用switch,此题只是提供一种思维方式,推荐读者寻找新的方法

4、对象搜索算法挑战

写一个 function方法,它遍历一个对象数组(第一个参数)并返回一个包含相匹配的属性-值对(第二个参数)的所有对象的数组。如果返回的数组中包含 source 对象的属性-值对,那么此对象的每一个属性-值对都必须存在于 collection 的对象中。

例如,如果第一个参数是 [{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }],第二个参数是 { last: "Capulet" },那么你必须从数组(第一个参数)返回其中的第三个对象,因为它包含了作为第二个参数传递的属性-值对。

function where(collection, source) {
    var arr = [];
    // What's in a name?
    var sourceKeys = [];
    var key;
    for(key in source){
        sourceKeys.push(key);
    }
    for (var i = 0; i < collection.length; i++) {
        var collectionKeys =[];
        for(key in collection[i]){
            collectionKeys.push(key);
        }
        var flag = true;
        for(key in sourceKeys){
            if (collectionKeys.join("").indexOf(sourceKeys[key]) == -1 || source[sourceKeys[key]] != collection[i][sourceKeys[key]]) {
                flag = false;
                break;
            }
        }
        if(flag){
            arr.push(collection[i]);
        }
    }
    return arr;
}

where([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });

运行结果:[{"first":"Tybalt","last":"Capulet"}]

5、字符串查询替换算法挑战

使用给定的参数对字符串执行一次查找和替换,然后返回新字符串。
第一个参数是将要对其执行查找和替换的字符串。
第二个参数是将被替换掉的单词(替换前的单词)。
第三个参数用于替换第二个参数(替换后的单词)。

注意:替换时保持原单词的大小写。例如,如果你想用单词 "dog" 替换单词 "Book" ,你应该替换成 "Dog"。

function myReplace(str, before, after) {
    var strArr = str.split(before);
    var afterArr = after.split("");
    var codeNum = afterArr[0].charCodeAt();
    if (before.charCodeAt(0) >= 65 && before.charCodeAt(0) <= 90 && codeNum >= 97 && codeNum <= 122) {
        afterArr[0] = String.fromCharCode(codeNum - 32);
    } else if (before.charCodeAt(0) >= 97 && before.charCodeAt(0) <= 122 && codeNum >= 65 && codeNum <= 90){
        afterArr[0] = String.fromCharCode(codeNum + 32);
    }
    after = afterArr.join("");
    str = strArr.join(after);
return str;
}

myReplace("A quick brown fox jumped over the lazy dog", "jumped", "leaped");
运行结果:A quick brown fox leaped over the lazy dog

6、字符串移动插入算法挑战

把指定的字符串翻译成 pig latin。
Pig Latin 把一个英文单词的第一个辅音或辅音丛(consonant cluster)移到词尾,然后加上后缀 "ay"。
如果单词以元音开始,你只需要在词尾添加 "way" 就可以了。

输入字符串保证是英文单词全部小写。

function translate(str) {
    var strArr = str.split("");
    var expression = /[aeiou]/;
    var index;
    for (var i = 0; i < strArr.length; i++) {
        if(strArr[i].match(expression)){
            index = i;
            break;
        }
    }
    if(index === 0){
        strArr.push("way");
    }else{
        for (var j = 0; j < index; j++) {
            strArr.push(strArr.shift());
        }
        strArr.push("ay");
    }
    str = strArr.join("");
    return str;
}

translate("consonant");

运行结果:onsonantcay

7、字符配对算法挑战

DNA 链缺少配对的碱基。依据每一个碱基,为其找到配对的碱基,然后将结果作为第二个数组返回。
Base pairs(碱基对) 是一对 AT 和 CG,为给定的字母匹配缺失的碱基。
在每一个数组中将给定的字母作为第一个碱基返回。
例如,对于输入的 GCG,相应地返回 [["G", "C"], ["C","G"],["G", "C"]]

字母和与之配对的字母在一个数组内,然后所有数组再被组织起来封装进一个数组。

function pair(str) {
    var strArr = str.split("");
    var parentArr = [];
    for (var i = 0; i < str.length; i++) {
        var childArr = [];
        childArr.push(str.slice(i,i+1));
        switch (str.slice(i,i+1)) {
            case 'G':
                childArr.push("C");
                break;
            case 'C':
                childArr.push("G");
                break;
            case 'T':
                childArr.push("A");
                break;
                case 'A':
            childArr.push("T");
                break;
            default:
                break;
        }
        parentArr.push(childArr);
    }
return parentArr;
}

pair("GCG");

运行结果:[["G","C"],["C","G"],["G","C"]]

8、字符串查询补充算法挑战

从传递进来的字母序列中找到缺失的字母并返回它。

如果所有字母都在序列中,返回 undefined。

function fearNotLetter(str) {
    var _return;
    for (var i = 0; i < str.length - 1; i++) {
        if (str[i+1].charCodeAt() - str[i].charCodeAt() > 1) {
            _return = String.fromCharCode(str[i].charCodeAt() + 1);
            break;
        }else{
            _return = undefined;
        }
    }
    return _return;
}

fearNotLetter("abcdefghjklmno");

运行结果:i

9、输入检查算法挑战

检查一个值是否是基本布尔类型,并返回 true 或 false。

基本布尔类型即 true 和 false。

function boo(bool) {
    // What is the new fad diet for ghost developers? The Boolean.
    var flag = false;
    if(typeof bool == "boolean"){
        flag = true;
    }
    return flag;
}

boo(null);

运行结果:false

10、数组去重算法挑战

写一个 function,传入两个或两个以上的数组,返回一个以给定的原始数组排序的不包含重复值的新数组。
换句话说,所有数组中的所有值都应该以原始顺序被包含在内,但是在最终的数组中不包含重复值。

非重复的数字应该以它们原始的顺序排序,但最终的数组不应该以数字顺序排序

function unite(arr1, arr2, arr3) {
    var arg = arguments;
    for (var i = 0; i < arguments[0].length - 1; i++) {
        for (var j = i + 1; j < arguments[0].length; j++) {
            if(arguments[0][i] == arguments[0][j]){
                arguments[0].splice(i,1);
            }
        }
    }
    for (var k = 1; k < arguments.length; k++) {
        for (var l = 0; l < arguments[k].length; l++) {
            if(arguments[0].indexOf(arguments[k][l]) == -1){
                arguments[0].push(arguments[k][l]);
            }
        }
    }
return arguments[0];
}

unite([1, 3, 2], [5, 2, 1, 4], [2, 1]);

运行结果:[1,3,2,5,4]

11、html符号转实体算法挑战

将字符串中的字符 &、<、>、" (双引号), 以及 ' (单引号)转换为它们对应的 HTML 实体。

function convert(str) {
    // :)
    var strArr = str.split("");
    var newArr = {};
    for(var i in strArr){
        var ele = /[\&\<|\>|\]|\"|\']/.exec(str[i]);
        // console.log(ele);
        if (ele !== null) {
            switch (ele[0]) {
                case '\&':
                    ele[0] = "&";
                    break;
                case '\<':
                    ele[0] = "<";
                    break;
                case '\>':
                    ele[0] = ">";
                    break;
                case '\"':
                    ele[0] = """;
                    break;
                case '\'':
                    ele[0] = "'";
                    break;
                
                default:
                    // code
            }
            newArr[i] = ele[0];
        }
    }
    for(var j in newArr){
        strArr.splice(j,1,newArr[j])
    }
    return strArr.join("");
}

convert("Dolce & Gabbana");

运行结果:Dolce &amp; Gabbana

12、字符串连接算法挑战

将字符串转换为 spinal case。Spinal case 是 all-lowercase-words-joined-by-dashes 这种形式的,也就是以连字符连接所有小写单词。

function spinalCase(str) {
    // "It's such a fine line between stupid, and clever."
    // --David St. Hubbins
    var strArr = str.split(/[\ |_]/g);
    if(strArr.length == 1){
        strArr = str.replace(str[0],str[0].toLowerCase()).replace(/([A-Z])/g,"-$1").split(/[\ |_]/g);
    }
    console.log(strArr);
    return strArr.join("-").toLowerCase();
}

spinalCase('This Is Spinal Tap');

运行结果:this-is-spinal-tap

13、斐波纳契奇数求和算法挑战

给一个正整数num,返回小于或等于num的斐波纳契奇数之和。
斐波纳契序列中的前两个数字是1和1.序列中的每个附加数字是前面两个数字的和。斐波纳契序列的前六个数字是1,1,2,3,5和8。
例如,sumFibs(4)应该返回 5,因为斐波纳契数列中所有小于4的奇数是 1、1、3。
提示:此题不能用递归来实现斐波纳契数列。因为当num较大时,内存会溢出,推荐用数组来实现。

function sumFibs(num) {
    var a1 = 1, a2 = 1;
    var arr = [];
    var sum = 0;
    if (num === 0) {
        arr.push(0);
    } else if (num == 1) {
        arr.push(a1);
    } else if (num > 1){
        arr.push(a1);
        while(sum <= num) {
            arr.push(a2);
            sum = a2 + a1;
            a1 = a2;
            a2 = sum;
        }
    }
    num = 0;
    for(var i in arr){
        if(arr[i] % 2 !== 0){
            num += Number(arr[i]);
        }
    }
    return num;
}

sumFibs(4);

运行结果:5

14、质素求和算法挑战

求小于等于给定数值的质数之和。
只有 1 和它本身两个约数的数叫质数。例如,2 是质数,因为它只能被 1 和 2 整除。1 不是质数,因为它只能被自身整除。

给定的数不一定是质数。

function sumPrimes(num) {
    var sum = 0;
    var arr = [];
    var i;
    for (i = 2; i <= num; i++){
        var flag = true;
        if(i != 2 && i!= 3){
            for (var k = 2; k <= Math.sqrt(i); k++) {
                if(i % k === 0){
                    flag = false;
                    break;
                }
            }
        }
        if(flag){
            arr.push(i);
        }
    }
    for(var j in arr){
        sum += arr[j];
    }
    return sum;
}


sumPrimes(10);

运行结果:17

15、最小公倍数算法挑战

找到所提供参数的最小公倍数,这两个参数可以均匀分配,以及这些参数之间范围内的所有最小公倍数。
范围是两个数字构成的数组,两个数字不一定按数字顺序排序。

例如对 1 和 3 —— 找出能被 1 和 3 和它们之间所有数字整除的最小公倍数。

function smallestCommons(arr) {
    var num = Math.min(arr[0],arr[1]);
    for (var i = num; i <= Math.max(arr[0],arr[1]); i++) {
        num = minimumCommonMultiple(num,i);
    }
    console.log(num);
return num;
}

//穷举法求两个数的最大公约数
function greatestCommonDivisor1(a,b){
    var num = null;
    if(Math.min(a,b) !== 0){
        for (var i = Math.min(a,b); i > 0; i--) {
            if(a % i === 0 && b % i ===0){
                num = i;
                break;
            }
        }
    }else{
        num = 0;
    }
    return num;
}

//相减法求两个数的最大公约数
function greatestCommonDivisor2(a,b){
    var maxNum = Math.max(a,b);
    var minNum = Math.min(a,b);
    if(minNum === 0){
        return 0;
    }
    while(maxNum - minNum !== 0){
        if(maxNum > minNum){
            maxNum = maxNum - minNum;
        }else{
            minNum = minNum - maxNum;
        }
    }
    return maxNum;
}

//辗转求余法求两个数的最大公约数
function greatestCommonDivisor3(a,b){
    var maxNum = Math.max(a,b);
    var minNum = Math.min(a,b);
    var num;
    if(minNum===0){
        num = 0;
    }
    if(minNum !== 0){
        while(minNum !==0){
            num = maxNum % minNum;
            maxNum = minNum;
            minNum = num;
        }
        num = maxNum;
    }
    return num;
}

//两个数的最小公倍数
function minimumCommonMultiple(a,b){
    var num;
    if(a === 0 || b === 0){
        num = 0;
    }else{
        num = a * b / greatestCommonDivisor1(a,b);
    }
    return num;
}

smallestCommons([1,5]);

运行结果:60

此题运用的是目标转换的思维方式:两个数的最小公倍数=这两个数的乘积 / 这两个数的最大公约数,所以先求出两个数的最大公约数,转而再求最小公倍数。

16、数组验证算法挑战

写一个 function,它查找数组(第一个参数)并返回数组中第一个通过某种方法(第二个参数)验证的元素。

function find(arr, func) {
    var num = 0;
    for(var i in arr){
        if (func(arr[i])) {
            num = arr[i];
            break;
        }
        num = undefined;
    }
    return num;
}

find([1, 2, 3, 4], function(num){ return num % 2 === 0; });

运行结果:2

17、数组取值算法挑战

删除数组(第一个参数)的元素,从左边开始,直到回调函数(第二个参数)return true就停止。
第二个参数,func,是一个函数。用来测试数组的第一个元素,如果返回fasle,就从数组中抛出该元素(注意:此时数组已被改变),继续测试数组的第一个元素,如果返回fasle,继续抛出,直到返回true。

最后返回数组的剩余部分,如果没有剩余,就返回一个空数组。

function drop(arr, func) {
    // Drop them elements.
    var newArr = [];
    for(var i in arr){
        if (func(arr[i])) {
            newArr = arr.slice(i);
            break;
        }
    }
    return newArr;
}

drop([1, 2, 3], function(n) {return n < 3; });

运行结果:[1,2,3]

18、数组平铺算法挑战

对嵌套的数组进行平铺嵌套数组。你必须考虑到不同层级的嵌套。

var newArr = [];
function steamroller(arr) {
    // I'm a steamroller, baby
    for(var i in arr){
        if (!Array.isArray(arr[i])) {
            newArr.push(arr[i]);
        } else {
            steamroller(arr[i]);
        }
    }
    return newArr;
}

steamroller([[["a"]], [["b"]]]);
运行结果:["a","b"]

这种方法返回结果是正确的,但是在W3Cschool通不过测试,我就很郁闷了。

function steamroller(arr) {
    // I'm a steamroller, baby
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            newArr.push.apply(newArr, steamroller(arr[i]));
        } else {
            newArr.push(arr[i]);
        }
    }
    return newArr;
}

steamroller([[["a"]], [["b"]]]);

第二种方法结果也是没问题,能通过测试。这种方法中用到Function.prototype.apply()

18、二进制转字符算法挑战

传入二进制字符串,翻译成英语句子并返回。

二进制字符串是以空格分隔的。

方法一:

function binaryAgent(str) {
    var arr = str.split(" ");
    for(var i in arr){
        var num = 0;
        for (var j = 0; j < arr[i].length; j++) {
            num += Math.pow(2,7 - j) * Number(arr[i][j]);
        }
        arr.splice(i,1,String.fromCharCode(num));
    }
return arr.join("");
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");

方法二:

function binaryAgent(str) {
    var arr = str.split(" ");
    for(var i in arr){
        var num = 0;
        num = parseInt(arr[i],2);
        arr.splice(i,1,String.fromCharCode(num));
    }
return arr.join("");
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");

运行结果:Aren't bonfires fun!?

19、数组元素判断算法挑战

所有的东西都是真的!
完善编辑器中的every函数,如果集合(collection)中的所有对象都存在对应的属性(第二个参数),并且属性(第二个参数)对应的值为真。函数返回ture。反之,返回false。

记住:您可以通过点符号或[]符号来访问对象属性。

function every(collection, pre) {
    // Is everyone being true?
    var flag = true;
    for(var i in collection){
        if (!collection[i][pre]){
            flag = false;
            break;
        }
    }
    return flag;
}

every([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}, {"user": "Laa-Laa", "sex": "female"}, {"user": "Po", "sex": "female"}], "sex");

运行结果:true

20、函数迭代可选参数算法挑战

创建一个计算两个参数之和的 function。如果只有一个参数,则返回一个 function,该 function 请求一个参数然后返回求和的结果。
例如,add(2, 3) 应该返回 5,而 add(2) 应该返回一个 function。
调用这个有一个参数的返回的 function,返回求和的结果:
var sumTwoAnd = add(2);
sumTwoAnd(3) 返回 5。

如果两个参数都不是有效的数字,则返回 undefined。

function add() {
    if (arguments.length == 1 && typeof(arguments[0]) != "number") {
        return undefined;
    } else if (arguments.length == 1 && typeof(arguments[0]) == "number") {
        var arg = arguments[0];
        return function(num){
            console.log(num);
            if(typeof(num) == "number"){
                return arg + num;
            }else{
                return undefined;
            }
        }
    }else{
        if(arguments.length){
            var sum = 0;
            for (var i = 0; i < arguments.length; i++) {
                if (typeof(arguments[i]) == "number") {
                    sum += arguments[i];
                } else {
                    sum = undefined;
                }
            }
            return sum;
        }
    }
}

add(2,3);
运行结果:5

猜你喜欢

转载自blog.csdn.net/weixin_39082031/article/details/81064611
w3c