プログラミング初学者の壁(JavaScript編)

## はじめに

* プログラミング初学者にAtCoderを紹介し
* 突き当たった壁を百本ノックでこなす

---
## AtCoder 概要

競技プログラミング大手

- C++, Python, Rust, Java, C#, JavaScript, Ruby, Elixir[など](https://img.atcoder.jp/file/language-update/language-list.html)いろんな言語で参加できる
- **Algorithm Contest**と**Heuristic Contest**の2種類
  - **Algorithm Contest**
    - [AtCoder Beginners Selection](https://atcoder.jp/contests/abs?_gl=1*pn71tn*_ga*ODEwMjMwMjE0LjE3MjUyNTgxMTM.*_ga_RC512FD18N*MTcyNTI1ODExMy4xLjEuMTcyNTI1ODU5MC4wLjAuMA..): まず第一にこれをこなす
        - [「AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～」](https://qiita.com/drken/items/fd4e5e3630d0f5859067)
    - [**AtCoder Daily Training**](https://atcoder.jp/contests/adt_top): 過去問に取り組む(本戦と同じく時間制限あり)
        - **AtCoder Daily Training EASY**: 灰色（Rating1から399）
        - **AtCoder Daily Training MEDIUM**: 主に茶色・緑色（Rating400から1199）        
        - **AtCoder Daily Training HARD**: 主に水色と青色（Rating1200から1999）        
        - **AtCoder Daily Training ALL**: 主に水色と青色（Rating1200から1999）
    - 本戦
        - **AtCoder Beginner Contest**: 初心者～中級者向け/土曜日夜9時から/毎週
        - **AtCoder Regular Contest**: 中級者～上級者向け/日曜日夜9時から/ 月1回ほど
        - **AtCoder Grand Contest**: 上級者～世界ランカー向け/日曜日夜9時から/年6回ほど
  - **Heuristic Contest**

---

## 壁No.1: 入力データをプログラムに取り込めない

* 障害: 標準入力を理解していない
* 回答: 初学者時点で理解できないので呪文として覚える
* ポイント
    * 「標準入力」という言葉を習得する
    * わからないときに調べる手段が必要: Google、ChatGPT、Perplexityなど
    
### 同期式
```JavaScript
function main(input) {
  const lines = input.split("\n");  // 入力

  // コードを入れる

  console.log(lines); // 出力
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));
```

### 非同期式

```JavaScript
process.stdin.resume();
process.stdin.setEncoding('utf8');

var lines = [];
var reader = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});
reader.on('line', (line) => {
    // ここで入力を処理する
    lines.push(line);
});
reader.on('close', () => {
    // ここで出力する

    console.log(lines);
});
```

---

## 壁No.2: テキストファイルを行単位に分けたり、文字列を分割することができない

* 障害: 基本的なデータ変換のうち、文字列=>配列の変換がわからない
* 回答: 文字列操作の基本
* ポイント
    * 改行文字が"\n"であること、"\r?\n"であることは後回しでよい
    * 公式を紹介: [String - JavaScript \| MDN]( https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String)

---

## 壁No.3: 足し算したつもりで＋は連結

* 現象: `console.log(a+b+c) => 123`
* 障害: 数値データと文字列データの区別がついていない
* 回答: 文字列データを数値データに変換する
  * `let a = parseInt(lines[0])`
  * `let a = lines[0] - 0`
* ポイント: 数値 + 文字列 または 文字列 + 数値は、「+」は連結の意味になり数値は文字列化される

---

## 壁No.4: + 連結のつもりで空白もれ

* 現象: `console.log(a+b+c+s) => 6test`
* 障害: 文字列連結と標準出力様式の混同
* 回答: 文字列連結するなら、明示的に" "空白文字をいれる。そうでなければ、文字列中の変数展開を行うかconsole.logの引数を分ける
    * `console.log(a+b+c +" "+ s)`
    * `console.log("%i %s", a+b+c, s)`
    * ``console.log(`${a+b+c} ${s}`)``
    * `console.log(a+b+c, s)`
* ポイント:
    * [console.log() - Web API \| MDN](https://developer.mozilla.org/ja/docs/Web/API/console/log_static) 
    * [JavaScriptでconsole.logを使うのはやめよう](https://qiita.com/baby-degu/items/1046763163bc794870ea)

---

## 壁No.5: 条件を立式できない 

* 現象: 演算子は理解できても、立式に至れない
* 障害: 立式のための**日本語の読み取り方**が確立していない
* 回答: 「AがBであるならばC」＝「if(A == B) C」
* ポイント:
    * 比較演算子のうち、等号 == は、日本語としては「**である**」
    * 不等号 != は、日本語としては「**でない**」
---

## 壁No.6: 文字列中の1文字1文字へのアクセス方法を知らない

* 現象: 文字列を対象とした繰り返し処理が書けない
* 障害: 文字列も配列と同じ構造である認識がなく、文字列の要素への参照方法が、配列要素への参照方法と一緒である認識がない 
* 回答: 配列arrのi番目の要素がarr[i]であるように、文字列sssのi番目の文字はsss[i]


---

## 壁No.7: 整数の各桁の数値を求められない

* 現象: 与えられた数値の十の位だけを求めるところ、100で割ると答えてしまう
* 障害: 切り捨て、剰余などの**組み合わせ**に思い至らない
* 回答: 一度、10で割って求めた商を10で割った余りが十の位
    * 百の位なら、100で割って求めた商を10で割った余り

どうも、Aの次にB、Bの次にCをするといった順序でなく、一度の処理で解が得られる式を想像したようである

---

## 壁No.8: constで宣言された変数を再度宣言してしまう

* 現象: Uncaught SyntaxError: Identifier 'found' has already been declared って何ですか？
* 障害: 専門用語からエラーの意味がわからない
* 回答: すでに、宣言されているconst変数を再度、変数宣言しようとしたから

syntax、indentifier、declareは、いずれも専門用語。ちゃんと理解しようとするなら、コンパイラの単位が必要。

---

* 順次、改稿していきます