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

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

JavaScript脚本算法编程实战课程


目录

JavaScript脚本算法编程实战课程

1、判断电话号码算法挑战

2、集合交集算法挑战

3、 收银系统算法挑战

4、库存更新算法挑战

5、排列组合去重算法挑战

6、日期改写算法挑战

7、类及对象构建算法挑战

8、 轨道周期算法挑战

9、数据组合求值算法挑战


1、判断电话号码算法挑战

如果传入字符串是一个有效的美国电话号码,则返回 true.用户可以在表单中填入一个任意有效美国电话号码. 下面是一些有效号码的例子(还有下面测试时用到的一些变体写法):

555-555-5555

(555)555-5555

(555) 555-5555

555 555 5555

5555555555

1 555 555 5555

在本节中你会看见如 800-692-7753 or 8oo-six427676;laskdjf这样的字符串. 你的任务就是验证前面给出的字符串是否是有效的美国电话号码. 区号是必须有的. 如果字符串中给出了国家代码, 你必须验证其是 1.如果号码有效就返回 true ; 否则返回 false.

function telephoneCheck(str) {
    // Good luck!
    var regExp1 = /^(1\s?)?\(\d{3}\)\s?\d{3}(\s|-)?\d{4}$/;
    var regExp2 = /^(1\s)?\d{3}(\s|-)?\d{3}(\s|-)?\d{4}$/;
    return (regExp1.test(str) || regExp2.test(str));
}

telephoneCheck("555-555-5555");

 运行结果:true

2、集合交集算法挑战

 创建一个函数,接受两个或多个数组,返回所给数组的 对等差分(symmetric difference) ( or )数组。

给出两个集合 (如集合 A = {1, 2, 3} 和集合 B = {2, 3, 4}), 而数学术语 "对等差分" 的集合就是指由所有只在两个集合其中之一的元素组成的集合(A △ B = C = {1, 4}). 对于传入的额外集合 (如 D = {2, 3}), 你应该安装前面原则求前两个集合的结果与新集合的对等差分集合 (C △ D = {1, 4} △ {2, 3} = {1, 2, 3, 4})。

function sym(args) {
    var arg = arguments;
    var newArgs = [];
    for(var i = 0; i < arguments.length; i++){
        var newArg = [];
        for(var j = 0; j < arguments[i].length; j++){
            if(arguments[i].indexOf(arguments[i][j]) == j){
                newArg.push(arguments[i][j]);
            }
        }
        newArgs.push(newArg);
    }
    
    var returnArg = [];
    for(var k in newArgs){
        for(var m in newArgs[k]){
            if(returnArg.indexOf(newArgs[k][m]) == -1){
                returnArg.push(newArgs[k][m]);
            }else{
                returnArg.splice(returnArg.indexOf(newArgs[k][m]),1);
            }
        }
    }
    return returnArg;
}

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

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

3、 收银系统算法挑战

设计一个收银程序 checkCashRegister() ,其把购买价格(price)作为第一个参数 , 付款金额 (cash)作为第二个参数, 和收银机中零钱 (cid) 作为第三个参数。

cid 是一个二维数组,存着当前可用的找零。

当收银机中的钱不够找零时返回字符串 "Insufficient Funds". 如果正好则返回字符串 "Closed"。

否者, 返回应找回的零钱列表,且由大到小存在二维数组中

function checkCashRegister(price, cash, cid) {
    var change = [];
    var changeMoney = cash - price;
    // console.log("要找回的总钱数:" + changeMoney);
    // Here is your change, ma'am.
    var cidDic = {
        "ONE HUNDRED":100.00,
        "TWENTY":20.00,
        "TEN":10.00,
        "FIVE":5.00,
        "ONE":1.00,
        "QUARTER":0.25,
        "DIME":0.10,
        "NICKEL":0.05,
        "PENNY":0.01
    };
    var someMoney;//能找回的数量
    for(var key in cidDic){
        someMoney = 0;
        while(changeMoney >= cidDic[key] && getSurplus(cid, key) >= cidDic[key]){
            changeMoney = changeMoney - cidDic[key];//修改总数
            someMoney += cidDic[key];
            changeSurplus(cid, key, cidDic[key]);//修改收银机中的零钱
        }
        if(someMoney !== 0){
            change.push([key,someMoney]);
        }
    }
    
    if(changeMoney === 0){
        var flag = true;
        for(var i in cid){
            if(cid[i][1] !== 0){
                flag = false;
                break;
            }
        }
        // console.log(flag);
        if(flag){
            return "Closed";
        }else{
            // console.log(change);
            return change;
        }
    }else{
        return "Insufficient Funds";
    }
}

//根据第二个参数返回第一个参数中的值
function getSurplus(arr, key){
    for(var i in arr){
        if(arr[i][0] == key){
            return arr[i][1];
        }
    }
}

//修改收银机中的钱数
function changeSurplus(arr, key, val){
    for(var i in arr){
        if(arr[i][0] == key){
            arr[i][1] =arr[i][1] - val;
        }
    }
}
// Example cash-in-drawer array:
// [["PENNY", 1.01],
// ["NICKEL", 2.05],
// ["DIME", 3.10],
// ["QUARTER", 4.25],
// ["ONE", 90.00],
// ["FIVE", 55.00],
// ["TEN", 20.00],
// ["TWENTY", 60.00],
// ["ONE HUNDRED", 100.00]]

checkCashRegister(19.50, 20.00, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.10], ["QUARTER", 4.25], ["ONE", 90.00], ["FIVE", 55.00], ["TEN", 20.00], ["TWENTY", 60.00], ["ONE HUNDRED", 100.00]]);

运行结果:[["QUARTER",0.5]]

此题目设计到浮点数修正的问题,此处未作小数修正,解题思路是正确的

4、库存更新算法挑战

 依照一个存着新进货物的二维数组,更新存着现有库存(在 arr1 中)的二维数组. 如果货物已存在则更新数量 . 如果没有对应货物则把其加入到数组中,更新最新的数量. 返回当前的库存数组,且按货物名称的字母顺序排列.

function updateInventory(arr1, arr2) {
    // All inventory must be accounted for or you're fired!
    var flag;
    for(var i in arr2){
        flag = false;
        for(var j in arr1){
            if (arr2[i][1] == arr1[j][1]) {
                flag = true;
                break;
            }
        }
        
        if(flag){
            for(var k in arr1){
                if(arr1[k][1] == arr2[i][1]){
                    arr1[k][0] += arr2[i][0];
                }
            }
        }else{
            arr1.push(arr2[i]);
        }
    }
    
    var temp = [];
    for(var m in arr1){
        temp.push(arr1[m][1]);
    }
    temp.sort();
    for(var n in temp){
        for(var t in arr1){
            if(temp[n] == arr1[t][1])
            temp.splice(n,1,arr1[t]);
        }
    }
    arr1 = temp;
    return arr1;
}

// Example inventory lists
var curInv = [
[21, "Bowling Ball"],
[2, "Dirty Sock"],
[1, "Hair Pin"],
[5, "Microphone"]
];

var newInv = [
[2, "Hair Pin"],
[3, "Half-Eaten Apple"],
[67, "Bowling Ball"],
[7, "Toothpaste"]
];

updateInventory(curInv, newInv);

 运行结果:[[88,"Bowling Ball"],[2,"Dirty Sock"],[3,"Hair Pin"],[3,"Half-Eaten Apple"],[5,"Microphone"],[7,"Toothpaste"]]

5、排列组合去重算法挑战

把一个字符串中的字符重新排列生成新的字符串,返回新生成的字符串里没有连续重复字符的字符串个数.连续重复只以单个字符为准

例如, aab 应该返回 2 因为它总共有6中排列 (aabaababaababaabaa), 但是只有两个 (abaand aba)没有连续重复的字符 (在本例中是 a).

评论区5楼的代码是本题的一种方法,可以借鉴。

6、日期改写算法挑战

让日期区间更友好!

把常见的日期格式如:YYYY-MM-DD 转换成一种更易读的格式。

易读格式应该是用月份名称代替月份数字,用序数词代替数字来表示天 (1st 代替 1).

记住不要显示那些可以被推测出来的信息: 如果一个日期区间里结束日期与开始日期相差小于一年,则结束日期就不用写年份了。月份开始和结束日期如果在同一个月,则结束日期月份就不用写了。

另外, 如果开始日期年份是当前年份,且结束日期与开始日期小于一年,则开始日期的年份也不用写。

例如:

makeFriendlyDates(["2016-07-01", "2016-07-04"]) 应该返回 ["July 1st, 2016","4th"]

makeFriendlyDates(["2016-07-01", "2018-07-04"]) 应该返回 ["July 1st, 2016", "July 4th, 2018"].

function makeFriendlyDates(arr) {
    var startDate;
    var endDate;
    var times = new Date(arr[1]).getTime() - new Date(arr[0]).getTime();
    // console.log(formatMonth(arr[0]));
    //开始日期
    if(new Date().getFullYear() == formatYear(arr[0]) && times > 0 && times < 365*24*60*60*1000){
        startDate = formatMonth(arr[0]) + " " + formatDay(arr[0]);
    }else{
        startDate = formatMonth(arr[0]) + " " + formatDay(arr[0]) + ", " + formatYear(arr[0]);
    }
    //结束日期
   if(formatMonth(arr[1]) == formatMonth(arr[0]) && formatYear(arr[0]) == formatYear(arr[1])){
        endDate = "" + formatDay(arr[1]);
    }else if((formatMonth(arr[1]) != formatMonth(arr[0]) || formatYear(arr[0]) != formatYear(arr[1])) && times > 0 && times < 365*24*60*60*1000){
        endDate = formatMonth(arr[1]) + " " + formatDay(arr[1]);
    }else{
        endDate = formatMonth(arr[1]) + " " + formatDay(arr[1]) + ", " + formatYear(arr[1]);
    }
    arr[0] = startDate;
    if(times === 0){
        arr.splice(1,1);
    }else{
        arr[1] = endDate;
    }
return arr;
}

function formatYear(_date){
    return (new Date(_date)).getFullYear();
}

function formatDay(_date){
    var _day = new Date(_date).getDate();
    if (_day % 10 == 1 && _day != 11) {
        _day = _day + "st";
    } else if (_day % 10 == 2 && _day != 12) {
        _day = _day + "nd";
    } else if (_day % 10 == 3 && _day != 13) {
        _day = _day + "rd";
    } else {
        _day = _day + "th";
    }
    return _day;
}

function formatMonth(_date){
    var _month;
    switch (new Date(_date).getMonth() + 1) {
        case 1:
            _month = "January";
            break;
        case 2:
            _month = "February";
            break;
        case 3:
            _month = "March";
            break;
        case 4:
            _month = "April";
            break;
        case 5:
            _month = "May";
            break;
        case 6:
            _month = "June";
            break;
        case 7:
            _month = "July";
            break;
        case 8:
            _month = "August";
            break;
        case 9:
            _month = "September";
            break;
        case 10:
            _month = "October";
            break;
        case 11:
            _month = "November";
            break;
        case 12:
            _month = "December";
            break;
    }
    return _month;
}

makeFriendlyDates(["2017-03-01", "2017-05-05"]);

运行结果:["March 1st, 2017","May 5th"]

7、类及对象构建算法挑战

用下面给定的方法构造一个对象.

方法有getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).

所有有参数的方法只接受一个字符串参数。

所有的方法只与实体对象交互。

var Person = function(firstAndLast) {
    this.getFirstName = function(){return firstAndLast.split(" ")[0]};
    this.getLastName = function(){return firstAndLast.split(" ")[1]};
    this.getFullName = function(){return firstAndLast};
    this.setFirstName = function(first){firstAndLast =  first + " " + firstAndLast.split(" ")[1]};
    this.setLastName = function(last){firstAndLast = firstAndLast.split(" ")[0] + " " + last};
    this.setFullName = function(fullName){firstAndLast = fullName};
};

var bob = new Person('Bob Ross');
bob.getFullName();

 运行结果:Bob Ross

8、 轨道周期算法挑战

 返回一个数组,其内容是把原数组中对应元素的平均海拔转换成其对应的轨道周期.

原数组中会包含格式化的对象内容,像这样 {name: 'name', avgAlt: avgAlt}.

至于轨道周期怎么求,戳这里 on wikipedia (不想看英文的话可以自行搜索以轨道高度计算轨道周期的公式).

求得的值应该是一个与其最接近的整数,轨道是以地球为基准的.

地球半径是 6367.4447 kilometers, 地球的GM值是 398600.4418, 圆周率为Math.PI

function orbitalPeriod(arr) {
    var GM = 398600.4418;
    var earthRadius = 6367.4447;
    var newArr = [];
    for(var i in arr){
        period = Math.floor(2 * Math.PI * Math.pow(Math.pow((earthRadius + arr[i].avgAlt) * 1000, 3)/GM , 0.5) / 3600);
        newArr.push({name : arr[i].name , orbitalPeriod : period});
    }
    return newArr;
}

orbitalPeriod([{name: "iss", avgAlt: 413.6}, {name: "hubble", avgAlt: 556.7}, {name: "moon", avgAlt: 378632.553}]);

 运行结果:

[{"name":"iss","orbitalPeriod":48815},{"name":"hubble","orbitalPeriod":50368},{"name":"moon","orbitalPeriod":20883321}]

此答案虽然通不过W3C的测试,但是周期计算公式是正确的。 

9、数据组合求值算法挑战

找到你的另一半

都说优秀的程序员擅长面向对象编程,但却经常找不到另一半,这是为什么呢?因为你总是把自己局限成为一个程序员,没有打开自己的思维。

这是一个社群的时代啊,在这里你应该找到与你有相同价值观但又互补的另一半。

譬如:你编程能力强,估值11分,如果以20分为最佳情侣来计算,你应该找一个设计能力强,估值为9分的女生。

那么当你遇到一个设计能力为9分的女生,千万别犹豫,大胆去表白。千万别以为后面的瓜比前面的甜哦。

举个例子:有一个能力数组[7,9,11,13,15],按照最佳组合值为20来计算,只有7+13和9+11两种组合。而7在数组的索引为0,13在数组的索引为3,9在数组的索引为1,11在数组的索引为2。

所以我们说函数:pairwise([7,9,11,13,15],20) 的返回值应该是0+3+1+2的和,即6。

我们可以通过表格来更直观地查看数组中索引和值的关系:

Index 0 1 2 3 4
Value 7 9 11 13 15

 任务:帮右边的pairwise函数实现上面的功能。

function pairwise(arr, arg) {
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
        var arrObj = {};
        arrObj.num = i;
        arrObj.value = arr[i];
        newArr.push(arrObj);
    }
    var count = 0;
    var arrLength = newArr.length;
    for (var j = 0; j < arrLength; j++) {
        for (var k = j + 1; k < arrLength; k++) {
            if (Number(newArr[j].value) + Number(newArr[k].value) == arg) {
                count  = count + newArr[j].num + newArr[k].num;
                // console.log(count);
                newArr.splice(k,1);
                arrLength--;
                newArr.splice(j,1);
                arrLength--;
                j--;
                k-=2;
                break;
            }
        }
    }
    return count;
}

pairwise([1, 3, 2, 4], 4);

 运行结果:1

猜你喜欢

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