1. 程式人生 > >JavaScript高階指令碼演算法程式設計練習(W3C學院)

JavaScript高階指令碼演算法程式設計練習(W3C學院)

JavaScript指令碼演算法程式設計實戰課程

目錄

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.round(2 * Math.PI * Math.pow(Math.pow((earthRadius + arr[i].avgAlt), 3)/GM , 0.5));
        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}]

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