---
# System prepended metadata

title: 程式導師 Week2 作業檢討
tags: [題目, 程式導師, JavaScript]

---

# 程式導師 Week2 作業檢討

###### tags: `程式導師` `JavaScript` `題目`

## hw1：印出星星

給定 n（1<=n<=30），依照規律「印出」正確圖形

```javascript=
function printStars(n) {
  var stars = "";
  for(var i=0; i<n; i++){
    stars = stars + "*";
  }
  console.log(stars);
}
```

```
printStars(1)

正確輸出：
*
```

```
printStars(3)

正確輸出：
*
*
*
```

```
printStars(6)

正確輸出：
*
*
*
*
*
*
```

## hw2：首字母大寫

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

```
capitalize('nick')
正確回傳值：Nick

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

capitalize(',hello')
正確回傳值：,hello
```

> :bulb: **想法**
> 
> 原本的寫法是：
> 1. 先設定一個空字串
> 2. 用 Ascii Code 判斷第一個字是否為英文小寫
> 3. 是的話，就轉成英文大寫，放到空字串內
> 4. 接著再從原字串的第二個字開始遍歷，依序將字塞入空字串內
> 
> 但這個寫法會導致第四步驟，將原字串的第二個字依序放入新字串內後，新字串就會變成 NaN。(如下方所示)
> 
```javascript=
function capitalize(str) {
  var newString = "";

  if (str.charCodeAt(0)>=97 && str.charCodeAt(0)<=122) {
    newString += String.fromCharCode(str.charCodeAt(0));  //這裡的 newString 確定成功轉為大寫英文字母

    for (var i=1; i<str.length; i++){    //這裡開始後的 newString 就變成 NaN
      newString =+ str[i];
    }
    return(newString);
  } else {
    return(str);
  }
};
```
> 所以解題想法改成先分類、再轉換：
> 1. 先設定一個空字串
> 2. 如果 Ascii code 判斷的第一個字是英文字，才進入判斷大小寫。
> 3. 如果 Ascii code 判斷的第一個字不是英文字，就直接輸出原字串。
> 4/ 如果是大寫，就直接輸出原字串。
> 5. 如果是小寫，就轉成大寫，再用 .slice(1)將字串第二個之後的字切出來，跟大寫字拼在一起。
> 

```javascript=
function capitalize(str) {
  var newString = "";

  if (str.charCodeAt(0)>=65 && str.charCodeAt(0)<=122) {
    if(str.charCodeAt(0)>=97 && str.charCodeAt(0)<=122) {
      var exchanged = String.fromCharCode(str.charCodeAt(0));
      var following = str.slice(1);
      newString = exchanged + following;

      return(newString);
    } else {
      return(str);
    }
  } else {
    return(str);
  }
};

console.log(capitalize('nick'));
console.log(capitalize('Nick'));
console.log(capitalize(',hello'));
```

## hw3：反轉字串

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

```
reverse('yoyoyo')
正確輸出：oyoyoy

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

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

> :bulb: **想法**
> 
> 採用與陣列相同的遍歷方式，遍歷字串。但這次需要反向遍歷字串，所以從原本正向的 i++ 改成 i--，且初始值是字串長度減一，才會剛好抓到最後一項。
> 
> 原本不想先設定一個空字串，改在圈內執行 `str += str[i]`，才發現不對，因為 str 會隨著再迴圈執行而變動，越後面的 str 會變得超長。
> 

```javascript=
function reverse(str) {
  var newString = "";
  for (var i=str.length - 1; i>=0; i--) {
    newString += str[i];
  }
  console.log(newString);
}

reverse('yoyoyo');
reverse('1abc2');
reverse('1,2,3,2,1');
```

## hw4：印出因數

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

```
printFactor(10)

正確輸出：
1
2
5
10


printFactor(7)

正確輸出：
1
7
```

```javascript=
function printFactor(n) {
  for (var i=1; i<=n; i++) {
    if (n%i===0) {
      console.log(i);
    }
  }
}

printFactor(10);
printFactor(7);
```

## hw5：自己的函式自己寫

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

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

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

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

```javascript=
function join(arr, concatStr) {
  var str = "";
  for (var i=0; i<arr.length; i++) {
    str = str + arr[i] + concatStr;
  }
  return(str);
}

function repeat(str, times) {
  var newStr = "";
  for (var i=1; i<=times; i++) {
    newStr += str;
  }
  return(newStr);
}



console.log(join(['a'], '!'));
console.log(join([1, 2, 3], ''))
console.log(join(["a", "b", "c"], "!"))
console.log(join(["a", 1, "b", 2, "c", 3], ','))

console.log(repeat('a', 5));
console.log(repeat('yoyo', 2));
```

## 挑戰題



> :bulb: 想法
> 
> 原本只想到用 for 迴圈，但用 for 迴圈的話，就必須確定`i++`或`i--`，然而這題的`i++`或`i--`，會隨著每次步驟而改變。
> 所以這題要用 `while` 條件是設定結束條件，結束條件就是當最小的搜尋位置等同最大搜尋位置，就結束迴圈。
> 

```javascript=
const search=(arr, n) => {
  var maxIndex = arr.length - 1
  var minIndex = 0
  
  while(minIndex <= maxIndex) {
    var centerIndex = Math.floor((maxIndex - minIndex) /2 + minIndex);

    if (n === arr[centerIndex]) {
      return(centerIndex);
    } else if (n > arr[centerIndex]) {
      minIndex += 1;
    } else {
      maxIndex -= 1;
    }
  }
  return(-1)
  
};

console.log(search([1, 3, 10, 14, 39], 14))  //3
console.log(search([1, 3, 10, 14, 39], 299))  //-1
```

第六行計算中間值的方式，不用 `(minIndex+maxIndex)/2` 而用 `(maxIndex-minIndex)/2 + minIndex` 是為了避免當數值很大時，可能產生的 overflow 狀況。