Try   HackMD

在競程用 JavaScript 讀取輸入資料

在 JavaScript 本身是網頁用的,由於網頁沒有 console,原本就沒有設計一個和 console 溝通的橋樑。而到了 Node.js 就有了 process.stdinprocess.stdout,不過他們都是資料流,沒有原生等待輸入的函式可以用。但不用傷心,內建有 readline module 可以幫我們控制讀取資料。

const readline = require('node:readline');

readline

要使用 readline 我們首先要創一個介面和 process.stdinprocess.stdout 溝通。

const readline = require('node:readline');
const { stdin: input, stdout: output } = require('node:process');

// 創建 readline 介面
const rl = readline.createInterface({ input, output });

之後我們就可以用介面提供的各種方式讀取資料。

rl.once('line', (line) => { /* code */ });
rl.question('', (line) => { /* code */ });

//  async 介面 (node:readline/promises)
const line = await rl.question('');

不過這樣寫會很亂,也會變成千層酥,這裡我們就可以用迭代器來搞定這些輸入。

// 迭代器
const read = rl[Symbol.asyncIterator]();

// 讀取一行
await read();

範例

這裡用 ICPC 2023 的 M. Triangle Construction

const readline = require("node:readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const it = rl[Symbol.asyncIterator](); (async () => { // js 用不到邊數 await it.next(); // 每個邊的頂點數量 const a = (await it.next()).value.split(" ").map(BigInt); // 所有頂點數量 const s = a.reduce((acc, v) => acc += v, 0n); // 最多頂點數量 const m = a.reduce((m, e) => e > m ? e : m); // 全部 - 最多 = 剩下的頂點數量 const r = s - m; if (m < 2n * r) { console.log((s / 3n).toString()); } else { console.log(r.toString()); } process.exit(0); })();

最後附上提交紀錄 238128106

總結

JavaScript 固然好用,打競程別用。