第22回【JavaScript】お金の支払い、二重ループ:活用編 三角形の探索

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

はじめに

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

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

とてつもなく忙しい日、少しでも勉強を進めようと机の前に座るのですが、身が入りません。あれやったっけ、あれ終わらせたっけ、明日はあれやらないと、いつまでにあれ終わらせないと、と、頭がグルグルです。仕事を溜めるのがとにかく嫌な質なので、勉強よりも仕事を優先して進めてしまいます。

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

お金の支払い (paizaランク C 相当)

paiza国では、1 円と X 円と Y 円の 3 種類の硬貨しかありません。ちょうど Z 円を支払うとき、支払う硬貨の枚数が最小になるように支払ったときの硬貨の枚数を求めてください。ただし、支払う各硬貨の枚数に制限は無いものとします。


入力される値

X Y Z

・ あなたの持っている硬貨の金額 X , Y と、あなたが払う金額 Z が半角スペース区切りで 1 行で与えられます。

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


期待する出力

支払う硬貨の枚数の最小値を 1 行で出力してください。

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


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

・ 2 ≦ X , Y ≦ 1000
・ X != Y
・ 1 ≦ Z ≦ 3000


入力例

50 100 855

出力例

14

硬貨しかない国か。財布がとてつもなく重そうだ。

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 [x,y,z] = lines[0].split(/\s/).map(Number);
  let minNum = z;
  for (let i = 0; i <= Math.trunc(z / x); i++) {
      for (let j = 0; j <= Math.trunc(z / y); j++) {
          if (x * i + y * j <= z) {
              let one = z - x * i - y * j;
              if (minNum > i + j + one) minNum = i + j + one;
          }
      }
  }
  console.log(minNum);
});
Python
X,Y,Z = map(int, input().split())

ans = Z

for x in range(Z // X + 1):
    for y in range(Z // Y + 1):
        if x * X + y * Y <= Z:
            one = Z - x * X - y * Y
            if x + y + one < ans:
                ans = x + y + one
print(ans)

二重ループ:活用編 三角形の探索 (paizaランク C 相当)

整数 N が与えられるので、三角形の三辺の長さの和が N であり、全ての辺の長さが整数であるような直角三角形が存在するかどうかを判定してください。なお、直角三角形の斜辺 a と他の二辺 b , c の間には次のような三平方の定理が成り立ちます。

a ^ 2 = b ^ 2 + c ^ 2

・ ヒント
三辺の長さの和が N であるような全ての三角形の三辺 a , b , c の組み合わせのうち、三平方の定理を満たすものが 1 つでもあれば “YES" , それ以外の場合は “NO" が答えとなります。全ての三辺の場合を全列挙することができれば三平方の定理を満たすかの判定をすることで答えを求めることができます。


入力される値

N

・ 三角形の三辺の長さの和 N が 1 行で与えられます。

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


期待する出力

条件を満たすような直角三角形が存在する場合は “YES" を、存在しない場合は “NO" を 1 行で出力してください。

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


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

・ 3 ≦ N ≦ 1000


入力例

864

出力例

YES

どうやってループから抜けるかを考える。

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]);
  outside : for (let i = 1; i < n; i++) {
      for (let j = 1; j < n - i; j++) {
          const k = n - i - j;
          if (Math.pow(i,2) == Math.pow(j,2) + Math.pow(k,2)) {
              console.log('YES');
              break outside;
          }
      }
      if (i == n - 1) console.log('NO');
  }
});
Python
N = int(input())
for a in range(1,N):
    for b in range(1,N-a):
        c = N - a - b
        if a**2 == b**2 + c**2:
            print("YES")
            break
    else:
        continue
    break
else:
    print("NO")

最後に

もっとスマートな書き方がありそうだけど、今はまだ思いつかず。

プロの人が書くとどんな風になるんだろうか。素敵に function 化されたコードを見てみたいなぁ。console.log('NO’) を書き忘れて、何度やっても満点とれず、少しはまってしまった。ちょっと疲れているんですかね。

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

Python の第22回はこちら