Skip to content

Latest commit

 

History

History

week2

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

作業

備註:以下題目請看清楚題目要求,如果要你「印出」,代表你要在 function 內使用console.log印出正確答案,如果要你「回傳」,則是用return把正確的值傳回去。

在提交作業以前麻煩把自己份內的事情做好,確認我範例給的 input 你都輸出了正確的 output 才提交。

hw1:印出星星

給定 n(1<=n<=30),依照規律「印出」正確圖形

printStars(1)

正確輸出:
*
printStars(3)

正確輸出:
*
*
*
printStars(6)

正確輸出:
*
*
*
*
*
*

hw2:首字母大寫

給定一字串,把第一個字轉成大寫之後「回傳」,若第一個字不是英文字母則忽略。

capitalize('nick')
正確回傳值:Nick

capitalize('Nick')
正確回傳值:Nick

capitalize(',hello')
正確回傳值:,hello

hw3:反轉字串

給定一個字串,請「印出」反轉之後的樣子(不能使用內建的 reverse 函式)

reverse('yoyoyo')
正確輸出:oyoyoy

reverse('1abc2')
正確輸出:2cba1

reverse('1,2,3,2,1')
正確輸出:1,2,3,2,1

hw4:印出因數

先幫大家複習一下數學,給定一個數字 n,因數就是所有小於等於 n 又可以被 n 整除的數,所以最明顯的例子就是 1 跟 n,這兩個數一定是 n 的因數。現在請寫出一個函式來「印出」所有的因數

printFactor(10)

正確輸出:
1
2
5
10
printFactor(7)

正確輸出:
1
7

hw5:自己的函式自己寫

其實仔細思考的話,你會發現那些陣列內建的函式你其實都寫得出來,因此這一題就是要讓你自己動手實作那些函式!

我們要實作的函式有兩個:join 以及 repeat。(再次強調,這一題要你自己實作這些函式,所以你不會用到內建的join以及repeat

join 會接收兩個參數:一個陣列跟一個字串,會在陣列的每個元素中間插入一個字串,最後回傳合起來的字串。

repeat 的話就是回傳重複 n 次之後的字串。

join([1, 2, 3], ''),正確回傳值:123
join(["a", "b", "c"], "!"),正確回傳值:a!b!c
join(["a", 1, "b", 2, "c", 3], ','),正確回傳值:a,1,b,2,c,3

repeat('a', 5),正確回傳值:aaaaa
repeat('yoyo', 2)正確回傳值:yoyoyoyo

hw6:簡答題

在學程式的時候有一個能力很重要,你必須靜下心來一行一行看這個程式到底在幹嘛,並且在腦中模擬出這個程式執行的樣子,意思就是你要假裝自己就是 JS 引擎。

這是一個非常實用的技能,我來舉個例子。

for(var i=59; i<=61; i++) {
  if(i === 60) {
    console.log('剛好及格')
  } else if (i < 60) {
    console.log('不及格')
  } else {
    console.log('及格')
  }
}
  1. 執行第 1 行,設定變數 i 是 59,檢查 i 是否 <= 61,是,繼續執行,開始進入第一圈迴圈
  2. 執行第 2 行,判斷 i 是否等於 60,不是,繼續往下
  3. 執行第 4 行,判斷 i 是否小於 60,是
  4. 執行第 5 行,log 不及格
  5. 第一圈迴圈結束,跑回第一行,i++,i 變成 60,檢查是否 <= 61,是,繼續執行
  6. 執行第 2 行,判斷 i 是否等於 60,是
  7. 執行第 3 行,log 剛好及格
  8. 第二圈迴圈結束,跑回第一行,i++,i 變成 61,檢查是否 <= 61,是,繼續執行
  9. 執行第 2 行,判斷 i 是否等於 60,不是,繼續往下
  10. 執行第 4 行,判斷 i 是否小於 60,不是,繼續往下
  11. 執行第 6 行並進入到第 7 行,log 及格
  12. 第三圈迴圈結束,跑回第一行,i++,i 變成 62,檢查是否 <= 61,否
  13. 執行完畢

寫起來非常冗長,但每寫一步都會讓你對這個程式怎麼運作的變得更清晰,對程式思維非常有幫助。而且一但你習慣了這樣的方式,很快地對於一些簡單的情形你就不需要寫下來了,你可以直接用大腦模擬出程式執行的樣子。

現在,請假裝自己是電腦,像是上面示範的那樣,一步步寫下底下這個程式的執行流程,並且試著猜猜看它在做什麼:

function isValid(arr) {
  for(var i=0; i<arr.length; i++) {
    if (arr[i] <= 0) return 'invalid'
  }
  for(var i=2; i<arr.length; i++) {
    if (arr[i] !== arr[i-1] + arr[i-2]) return 'invalid'
  }
  return 'valid'
}

isValid([3, 5, 8, 13, 22, 35])

請將答案寫在 hw6.md

挑戰題

現在有一個排序好的陣列 arr,裡面的元素都是正整數而且保證不會重複。

給你一個數字 n,請寫出一個函式 search 回傳 n 在這個陣列裡面的 index,沒有的話請回傳 -1。

範例:

search([1, 3, 10, 14, 39], 14) => 3
search([1, 3, 10, 14, 39], 299) => -1

這題之所以放在挑戰題,是因為這一題的解法要比這個更快:

function search(arr, n) {
  for(var i=0; i<arr.length; i++) {
    if (arr[i] === n) return i
  }
  return -1
}

寫完如果想確認是否正確,可以到這邊來測試,只是輸出入要改一下,然後要學一下 LIOJ 的使用方法:LIOJ 1047

提示 #1 想想終極密碼怎麼做
提示 #2 二分搜尋法

超級挑戰題

在這次的課程中有教到位元運算,你知道位元運算可以達到什麼目標嗎?讓我來告訴你!只用位元運算,就可以寫出相加兩個數字的功能。所以這一週的超級挑戰題就是:「挑戰寫出一個 function,可以接收兩個正整數,而且回傳相加的結果,並且在 function 裡面不能出現 +-*/ 任何一個符號」

// 請實作以上函式,回傳 a+b 的結果
// 但是函式裡面不能出現 +-*/ 任何一個符號
function add(a, b) {

}
提示 #1 用二進位相加的方向去想,可以先試著把 2 個 bit 相加看看結果
提示 #1 關鍵字:加法器,full adder

超級超級挑戰題

在數字很大的時候,因為 JS 裡面數字上限的關係,一般的數學運算會出錯,例如說:

console.log(124902814902890825902840917490127902791247902479027210970941724092174091274902749012740921759037590347438758957283947234273942304239403274093275902375902374092410937290371093719023729103790123*1239128192048129048129021830918209318239018239018239018249082490182490182903182390128390128903182309812093812093820938190380192381029380192381092380192380123802913810381203) // Infinity

所以在最新的 JS 裡面多了一個資料型態,叫做 BigInt,只要在後面加個 n 就可以得到正確的結果:

console.log(124902814902890825902840917490127902791247902479027210970941724092174091274902749012740921759037590347438758957283947234273942304239403274093275902375902374092410937290371093719023729103790123n*1239128192048129048129021830918209318239018239018239018249082490182490182903182390128390128903182309812093812093820938190380192381029380192381092380192380123802913810381203n)



/*
15477059921234121826428557151741001505503078190287823812775974784617890980
41664961276263706619800328087900049616495708101329933970937581714628336484
30573931982820077357934138465500725654122355115431528560108824273624205622
43845728335428665892452211230138950874256724845100897209088600677816836907
8193075209592426056314957124024831139178307483030144703850736257969n
*/

問題來了,你有沒有辦法在不使用 BigInt 這個型別的前提之下,依舊完成兩個很大的數字的乘法?請你寫一個 function 叫做 multiply,會接收兩個格式是數字的「字串」,回傳兩個數字相乘之後的結果(一樣會是一個字串):

// 不能使用 BigInt 這個資料型態
function multiply(a, b) {

}

這邊 a 跟 b 之所以會是字串,是因為前面提過的,JS 的 number 型態沒辦法儲存這麼大的數字,所以要改用字串的型態來存。所以 multiply('3', '5') 應該要回傳 '15',而上面的超大數字相乘,也應該出現正確的數字。

提示 #1 想想看你在算乘法的時候是怎麼做運算的,直式乘法
提示 #2 關鍵字:大數乘法