JavaScript
Node.js
AtCoder
競技プログラミング

AtCoder に登録したら解くべき精選過去問 10 問を JavaScript で解いてみた

More than 1 year has passed since last update.

AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~

紹介されていた問題をJavaScript(Node.js)で解いてみました。

他言語で解いた記事はありますが、まだJavaScript版がない。

そして競技プログラミングだとJavaScriptはあまり使われない印象なので、

今回はあえてJavaScriptで挑みました。

競技プログラミングの問題を解くのが初なので、

最適解にはなっていないかもしれませんが、ご了承ください。

※問題の解説については、上記記事にわかりやすい解法が載っているので割愛します。


標準入出力

ここの「JavaScript(Node.js) での解答例」が非常にわかりやすいです。


こんな感じ

function main(input) {

console.log(input);
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


第1問: ABC 086 A - Product

二つの整数 a,bの積の偶奇を判定する。

function main(input) {

const args = input.split(' ');
const a = parseInt(args[0], 10);
const b = parseInt(args[1], 10);

if ((a * b) % 2 === 0) {
console.log('Even');
} else {
console.log('Odd');
}
}

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


第2問: ABC 081 A - Placing Marbles

文字列内の、1の個数をカウントする。

function main(input) {

console.log(input.split('1').length - 1);
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


第3問: ABC 081 B - Shift Only

N個の整数を同時に、割り切れなくなるまで割っていった場合、何回割ることができるかを求める。

function main(input) {

var nums = input.split('\n')[1].split(' ').map((n) => parseInt(n, 10));

var count = 0;
while(nums.every((n) => (n % 2) === 0)) {
count++;
nums = nums.map((n) => n / 2);
}

console.log(count);
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


第4問: ABC 087 B - Coins

500円玉、100円玉、50円玉を使ってX円を支払う方法が何通りあるかを求める。

function main(input) {

const args = input.split('\n');
const A = parseInt(args[0], 10),
B = parseInt(args[1], 10),
C = parseInt(args[2], 10),
X = parseInt(args[3], 10);

var count = 0;

for (var a = 0; a <= A; ++a) {
for (var b = 0; b <= B; ++b) {
for (var c = 0; c <= C; ++c) {
var sum = (a * 500) + (b * 100) + (c * 50);
if (sum === X) ++count;
}
}
}
console.log(count);
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


第5問: ABC 083 B - Some Sums

1以上N以下の整数のうち、各桁の和がA以上B以下であるものの総和を求める。

function main(input) {

const args = input.split(' ');
const N = parseInt(args[0], 10),
A = parseInt(args[1], 10),
B = parseInt(args[2], 10);

const nums = Array.from(new Array(N), (v, i) => ++i).filter((i) => {
var n = i.toString().split('').reduce((p, c) => p + parseInt(c), 0);
return (n >= A && n <= B);
});

console.log(nums.reduce((p, c) => p + c, 0));
}

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


第6問: ABC 088 B - Card Game for Two

N枚のカードを交互に自身の得点が最大になるように取っていった場合の、二人の得点の差分を求める。

function main(input) {

const args = input.split('\n');
const N = parseInt(args[0], 10),
cards = args[1].split(' ').map(n => parseInt(n, 10));

var aSum = 0,
bSum = 0;

cards.sort((a, b) => (a < b ? 1 : -1)).forEach((n, i) => {
(i % 2 === 0)? aSum += n : bSum += n;
});

console.log(aSum - bSum);
}

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


第7問: ABC 085 B - Kagami Mochi

N個の整数の重複しない値の数を求める。

function main(input) {

const args = input.split('\n');
const N = args[0],
nums = args.slice(1, args.length - 1);

console.log(nums.filter((n, i) => nums.indexOf(n) === i).length);
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


第8問: ABC 085 C - Otoshidama

10000円札、5000円札、1000円札がある前提で、合計がN枚、Y円になる組み合わせを求める。

function main(input) {

const args = input.split(' ');
const N = parseInt(args[0], 10),
Y = parseInt(args[1], 10);

var result = '-1 -1 -1';

for (var a = 0; a <= N; a++) {
for (var b = 0; b <= N; b++) {
if ((a + b) > N) {
continue;
}

var sum = (a * 10000) + (b * 5000) + ((N - a - b) * 1000);
if (sum === Y) {
result = `${a} ${b} ${N - a - b}`;
break;
}
}
}

console.log(result);

}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


第9問: ABC 049 C - Daydream

文字列Sが、"dream", "dreamer", "erase", "eraser"の組み合わせで作れるかどうかを判定する。

function main(input) {

const reverse = (s) => {
return s.split('').reverse().join('');
};

const WORDS = ['dream', 'dreamer', 'erase', 'eraser'].map(reverse);
const S = reverse(input.split('\n')[0]);

var index = 0;

while(true) {
var w = WORDS.find((w) => S.startsWith(w, index));
if (!w) break;
index += w.length;
}

if (S.length === index) {
console.log('YES');
} else {
console.log('NO');
}
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


第10問: ABC 086 C - Traveling

座標(0, 0)を出発地点とした場合、時刻ti時点で(xi, yi)にいることができるかどうかを判定する。

function main(input) {

const args = input.split('\n');
const N = parseInt(args[0], 10);
const nums = args.slice(1, N + 1);
const isValid = nums.every((n) => {
var ns = n.split(' ');
var t = parseInt(ns[0], 10),
x = parseInt(ns[1], 10),
y = parseInt(ns[2], 10);
var sum = x + y;

return (t >= sum) && ((t % 2) === (sum % 2));
});

if (isValid) {
console.log('Yes');
} else {
console.log('No');
}
}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));


おわりに

分割代入を使いたい場面が多々あるので、Node.jsのサポートバージョンがv5.12なのが少し残念。

このバージョンだとサポートされていない...。(近いうちにサポートバージョンが上がるはず!)

次はもう少し難しい問題にも挑戦してみようと思います。もちろんJavaScriptで。