[初心者向け] JavaScript で AtCoder の問題を解く

# はじめに
JavaScript で AtCoder の問題を解く方法を教える機会があり Notion にまとめたので、どうせなら公開しようと思って記事を書いています。

※ JavaScript の関数やメソッドを学んだくらいの方を想定しています。

# 目次
[1.AtCoderとは](#1-atcoderとは)
[2.標準入出力とは](#2-標準入出力とは)
[3.基本の型](#3-基本の型)
[4.受け取った値](#4-受け取った値)
[5.とりあえずこれだけは覚える](#5-とりあえずこれだけは覚える)
[6.値の扱い方](#6-値の扱い方)
[7.全体のコード](#7-全体のコード)
[8.さいごに](#8-さいごに)

# 1. AtCoderとは
AtCoder は、**競技プログラミングコンテストを開催している国内サイト**です。
詳しくは↓のサイトで詳しく説明されているので、こちらでは割愛します。

https://and-engineer.com/articles/YfPo9xAAAB8ATGLv

# 2. 標準入出力とは
AtCoder では、**何らかの入力値を受け取って**、それを問題の指定通りに計算等して、**答えとして出力**します。
その答えが正しければ正解です。


:::note warn
C問題以降になると、出力した値が正しくても、プログラム的に計算処理等の速度が遅いとタイムアウトの判定で不合格となるため、処理の効率も意識する必要が出てきます。
:::

標準入出力の操作が必須となるため、そもそも「標準入出力とは？」が分からない方は以下サイトをご参照ください。

https://products.sint.co.jp/topsic/blog/standard-input-output


# 3. 基本の型

```jsx
function Main(input) {

    // input(入力値)を使って何らかの処理をする

    // 答えの出力
    console.log(〇〇);
}

// 標準入力を引数として、 ↑ の関数を実行
Main(require("fs").readFileSync("/dev/stdin", "utf8"));
```

まず、全体の流れとして、標準入力を受け取って、答えを出力をする必要がある。

JavaScript で標準入力を受け取るためには、**fsモジュール** を利用する。

## fs モジュールとは

Node.js に組み込まれているモジュール。

:::note info
※ Node.js とは
本来ブラウザ上で動作する JavaScript の、PCでの実行環境。

※ モジュールとは
プログラムの一部として独立した機能を持つコードの集まり。
:::

コンピューター上のファイルやディレクトリを操作するための機能を提供する。

主な機能：
- ファイルの読み込み
- ファイルへの書き込み
- ファイルの作成や削除
- ディレクトリの作成や削除
- ファイル名の変更



この中の、`require("fs")` が該当部分。
```jsx
Main(require("fs").readFileSync("/dev/stdin", "utf8"));
```

`require` で、fs モジュールを読み込むための命令をしています。

続けて、読み込んだ fs モジュールの中の `readFileSync` メソッドを実行しています。

これは、引数で指定したファイルを読み込むメソッドです。

`readFileSync` メソッドには引数を２つ渡している。

- `"/dev/stdin"`：
    ファイルとして標準入力を指定している
    
- `"utf8”` ： 
    UTF-8という文字コードを指定している
    （UTF-8：一般的な文字コードで、ほとんどのテキストデータで使用されている）

→つまり、この部分では

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

Main 関数の引数として、「(一般的な文字コードを指定した)標準入力」を受け取るよということになります。

では、その Main 関数って何なんだ？ということですが、それをこれから定義します。

Main 関数が受け取るパラメーターを仮に `input` としましょう。

```jsx
function Main(input) {

}
```

つまり、この Main 関数を
```javascript
Main(require("fs").readFileSync("/dev/stdin", "utf8"));
```
として、`require("fs").readFileSync("/dev/stdin", "utf8")` を引数に渡して実行すると、`input` には(一般的な文字コードを指定した)標準入力が渡されるということです。

# 4. 受け取った値
実際の問題では、例えば以下の問題なら

https://atcoder.jp/contests/abs/tasks/practice_1

> 入力は以下の形式で与えられる。
> 
> 
> ```
> a
> b c
> s
> ```
> 

とあるので、

`require("fs").readFileSync("/dev/stdin", "utf8")`（= 標準入力）には、この入力値が入ってくることになります。

ただし、この場合は改行が入ってるので、↑の改行部分は**改行コード /n**に置き換えられるため、実際は以下のような値にます。

```jsx
"a\nb c\ns"
```

また、標準入力として受け取った値は、**文字列になる**ので注意が必要です。

:::note info
改行コードとは
参考：[JavaScriptでの改行の使い方。改行ができないときは？](https://job-support.ne.jp/blog/javascript/howto-new-line)
:::


つまり、
```
a(改行)
b c(改行)
s(改行)
```

↓

```jsx
"a\nb c\ns"
```
として受け取ります。
受け取った値をそのまま console.log すると

```jsx
function Main(input) {
  console.log(input);
}
```
改行コード \n は改行としての役割をするので
```jsx
a
b c
s
```

として出力されます。

# 5. とりあえずこれだけは覚える
ここまでが、Main 関数の基本でした。

「問題を解く」というのは、この `input` に入ってくる値( `string` 型であることに注意!!)を使って、指定の通りに計算したり配列の分割をしたりして、最後に答えとなる値を `console.log` で出力するということです。

理解するまで少し難しいと思うので、最初はこれ↓をコピペして、

```jsx
function Main(input) {

    // ここに処理を書く
    
    console.log();
}

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

`// ここに処理を書く` の部分に処理を、`console.log()` の引数に答えを書けばいいと思えば OK です！

# 6. 値の扱い方

https://atcoder.jp/contests/abs/tasks/practice_1 

↑ の問題文

> 整数 𝑎,𝑏,𝑐 と、文字列 *s* が与えられます。
> 
> 
> *a* + *b* + *c* の計算結果と、文字列 *s* を並べて表示しなさい。
> 

> 入力
入力は以下の形式で与えられる。
> ```
> a
> b c
> s
> ```

> 出力
> a+b+c と s を空白区切りで 1 行に出力せよ。

> 入力例 1（実際に渡される値）
> ```
> 1
> 2 3
> test
> ```
> 出力例 1
> ```
> 6 test
> ```
> 1+2+3 は 6 なので、上記のように出力します。


標準入力として受け取ると、

```
1
2 3
test
```
は前述のとおり `"1\n2 3\ntest"` という一つの文字列になりますが、一つの文字列ではなく、それぞれ 1, 2, 3, test という別の値として使いたいですよね。

そのために、まずは `split` メソッドを使って、 `\n` の部分で本来の入力の１行毎に文字列を分割して、配列に格納しましょう。
↓ では、`split` した値を `input` 変数に再代入しています。

```jsx
input = input.split("\n");
```

https://www.javadrive.jp/javascript/string/index1.html

そうすると、`input` はどうなっているかというと、

```jsx
function Main(input) {
  console.log(input); // "1\n2 3\ntest"
  
  input = input.split("\n");
  console.log(input); // 出力：["1", "2 3", "test"]
}
```

というように、元々の入力の一行ずつ、配列の要素に格納されているのが分かります。

さらに `"b c"` の部分も分割したいので、今度は空白で分割しましょう。

```jsx
let line2 = input[1].split(" "); // input[1]は "2 3"
console.log(line2) // 出力：["2", "3"]
```
※ ２行目なので line2 という変数名にしてみましたが、変数名はなんでもOKです。

これで、a, b, c, s をそれぞれ別の値として使える！と思いきや、もうひと工夫必要です。

問題文では、s は文字列だけど、**a, b, c は整数**だと言っています。

前述のとおり、標準入力で受け取ると勝手に文字列に変わってしまうので、整数に変換してあげないといけません。

```jsx
function Main(input) {
  console.log(input); // 出力："1\n2 3\ntest"
  
  input = input.split("\n");
  console.log(input); // 出力：["1", "2 3", "test"]
  
  let line2 = input[1].split(" ");
	console.log(line2) // 出力：["2", "3"]
  
  // 文字列から 10 進数に変換
  let a = parseInt(input[0], 10);
  console.log(a) // 出力：input[0]は "1" → 1(整数)
  let b = parseInt(line2[0], 10);
  console.log(b) // 出力：line2[0] は "2" → 2(整数)
  let c = parseInt(line2[1], 10);
  console.log(c) // 出力：line2[1] は "3" → 3(整数)
  let s = input[2];
  console.log(s) // 出力："test"(文字列)
}
```

そして、求められている答えは

> *a* + *b* + *c* の計算結果と、文字列 *s* を並べて表示しなさい。
> 

なので、

```jsx
console.log(a+b+c, s); // 出力： 6 test
```

これで答えが出せました！！

# 7. 全体のコード
提出する時は、途中の値を確認するために書いた `console.log` は消さないといけません。
（コメントアウトでも大丈夫です）

```jsx
function Main(input) {  
  input = input.split("\n");
  
  let line2 = input[1].split(" ");
  
  let a = parseInt(input[0], 10);
  let b = parseInt(line2[0], 10);
  let c = parseInt(line2[1], 10);
  let s = input[2];
	
  console.log(a+b+c, s);
}

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

# 8. さいごに
いかがだったでしょうか？
Main 関数の引数の標準入力の部分が少し難しかったかもしれませんが、そこはいわゆる"おまじない"としてコピペして使っていいと思います。

とはいえ、全く意味を知らないで使うのではなく、何をやっているのか知ろうとすることは大切だと思ったので、調べながらまとめてみました。

JavaScript で AtCoder デビューをする助けになれば嬉しいです。