第103回【JavaScript】条件を満たす最小の自然数、シミュレーションの練習、シミュレーション

現在取り組んでいるのは、paiza ラーニング問題集「Cランクレベルアップメニュー」になります。

はじめに

猫とキャンプと野球観戦と AWS が大好きな旦那、LeoSaki です。モフモフしたい。

JavaScript をゼロから勉強してみよう、のコーナー 103 回目です。

普段の仕事の延長線で、自分としてはまったく難しいことをしていないつもりのことが、他の人からは凄い凄いと持ち上げられてしまうことがあります。これを技術料としてお金にするのが仕事なんでしょうけれど、何が凄いのかよく分からなくなってしまっています。

それでは、今日も頑張ってみようと思います。

条件を満たす最小の自然数 (paizaランク C 相当)

10000 以上かつ 13 で割り切れるような最小の自然数を求めてください。


入力される値

なし

入力値最終行の末尾に改行が1つ入ります。


期待する出力

答えを 1 行で出力してください。

また、末尾に改行を入れ、余計な文字、空行を含んではいけません。

模範解答では終了条件無しの for 文で書かれていたけれど、while の方が分かりやすい気がする・・・。

JavaScript
let n = 10000;
while (true) {
    if (n % 13 === 0) break;
    n++;
}
console.log(n);

JavaScript(模範解答)

for (let i = 10000; ; i++) {
  if (i % 13 === 0) {
    console.log(i);
    break;
  }
}
Python
N = 10000
while True:
    if N % 13 == 0:
        break
    N += 1
print(N)

シミュレーションの練習 (paizaランク C 相当)

パイザ君と霧島京子は最初どちらも数 1 をもっています。パイザ君は自分の番が来ると、自分のもっている数の a 倍を霧島京子の数に足してあげます。霧島京子は自分の番が来ると、自分のもっている数を b で割った余りをパイザ君の数に足してあげます。この手続きをパイザ君の番から始めて、霧島京子の数がnより大きくなるまで繰り返します。

手続きが終わったときのパイザ君の操作回数を求めてください。


入力される値

n
a b

1 行目には整数 n が与えられ、 2 行目には a, b が半角スペース区切りで与えられます。

入力値最終行の末尾に改行が1つ入ります。


期待する出力

答えを 1 行で出力してください。

また、末尾に改行を入れ、余計な文字、空行を含んではいけません。


すべてのテストケースにおいて、以下の条件をみたします。

・ 2 ≤ n ≤ 10000
・ 1 ≤ a , b ≤ 10


入力例

6
3 2

出力例

2

ゲームといっていいのかどうかよくわからないけれど、ちょっと面白そう。

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', () => {
  const n = Number(lines[0]);
  const [a,b] = lines[1].split(/\s/).map(Number);
  let [k,p] = [1,1];
  let count = 0;
  while (true) {
      k += p * a;
      count++;
      if (k > n) break;
      p += k % b;
  }
  console.log(count);
});
Python
n = int(input())
a,b = map(int,input().split())
p,k = 1,1
cnt = 0
while True:
    k += p * a
    cnt += 1
    if k > n:
        break
    p += k / b
print(cnt)

シミュレーション (paizaランク C 相当)

カウンター魔法を得意とするパイザ君は、同じくカウンター魔法を使うモンスターと戦っています。バトルはターン制で、パイザ君が先攻で、パイザ君とモンスターで交互に魔法を使い合います。パイザ君の魔法は 1 回目と 2 回目に使うときにはダメージ 1 ですが、 3 回目以降の n 回目には、(モンスターから受けた (n – 1) 回目の攻撃のダメージ) + (モンスターから受けた (n – 2) 回目の攻撃のダメージ) のダメージを与えます。モンスターの魔法はこれよりも強力で、 1 回目と 2 回目には同じくダメージ 1 ですが、 3 回目以降の n 回目には、 (パイザ君から受けた (n – 1) 回目の攻撃のダメージ) * 2 + (パイザ君から受けた (n – 2) 回目の攻撃のダメージ) のダメージを与えます。

パイザ君は自分がどれくらいモンスターの攻撃を耐えられるか知りたいと思っています。パイザ君の体力を H として、両者が同じ魔法を使い続けたとき、モンスターの何回目の攻撃でパイザ君の体力が 0 以下になるかを出力してください。


入力される値

H

1 行目にパイザ君の体力を表す整数 H が与えられます。

入力値最終行の末尾に改行が1つ入ります。


期待する出力

モンスターの何回目の攻撃でパイザ君の体力が 0 以下になるかを出力してください。

また、末尾に改行を入れ、余計な文字、空行を含んではいけません。


すべてのテストケースにおいて、以下の条件をみたします。

3 ≤ H ≤ 10^8


入力例

7

出力例

4

パイザくんが勝つことが出来ない前提なのだろうか。パイザくん頑張れ。

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', () => {
  const H = Number(lines[0]);
  const p = [0,1,1];
  const m = [0,1,1];
  let count = 2;
  let damage = 2;
  while (damage < H) {
      [p[0],p[1]] = [p[1],p[2]];
      [m[0],m[1]] = [m[1],m[2]];
      p[2] = m[1] + m[0];
      m[2] = p[1] * 2 + p[0];
      count++;
      damage += m[2];
  }
  console.log(count);
});
Python
H = int(input())
P = [0,1,1]
M = [0,1,1]
dmg = 2
cnt = 2
while dmg < H:
    P[0] = P[1]
    P[1] = P[2]
    M[0] = M[1]
    M[1] = M[2]
    P[2] = M[1] + M[0]
    M[2] = P[1] * 2 + P[0]
    dmg += M[2]
    cnt += 1
print(cnt)

最後に

スワップはこういうやり方も出来る、といつの日か学んだわけで、使わないと損かなぁと思いました。

問題文を読むと複雑そうに見えますが、必要な値だけ保存しておけばいいなら、これで十分なのかと。まぁ、過去のダメージをすべて記録しておかないといけないゲームでは通用しないですが。過去のダメージをすべて記録しておくとなると、あまり大きな体力値では大変なことになっちゃいそうですが。

引き続き、よろしくお願いいたします!

Python の第103回はこちら