Help us understand the problem. What is going on with this article?

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で。

ytanto
札幌のエンジニアです。 主にフロントエンドをやってます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away