ユークリッドの互除法メニュー【分数・意地悪すごろく】
【分数】コード
reader.on('close', () => {
const gcd = (a, b) => {
if (!b) {
return a;
}
return gcd(b, a % b);
};
const [sA, sB, cal, sC, sD] = lines[0].split(' ');
const [A, B, C, D] = [sA, sB, sC, sD].map(Number);
let [n, d, x] = [0, 0, 1]; // n → 分子 d → 分母 x → n, d の最大公約数
switch (cal) { // A / B cal C / D の演算
case '+':
d = B * D;
n = A * D + C * B;
break;
case '-':
d = B * D;
n = A * D - C * B;
break;
case '*':
d = B * D;
n = A * C;
break;
case '/':
n = A * D;
d = B * C;
break;
}
if (n < 0 && d < 0) {
[n, d] = [n, d].map(e=>Math.abs(e));
}
[n2, d2] = [n, d].map(e=>Math.abs(e));
x = gcd(n2, d2); // n, d の絶対値を引数としてgcd()を呼び出し
console.log(n / x, d / x); // 約分して 出力
});
分数を通分して 式の計算を行い 分子と分母の最大公約数で約分した値を出力しました。
【意地悪すごろく】コード 1/2
reader.on('close', () => {
const gcd_s = (a, b, n) => {
const [A, B] = [a, b]; // 元の値をコピーして保存
while (b) {
[a, b] = [b, a % b];
}
if (n % a === 0 || a > Math.min(A, B) || B === A) {
return B;
}
};
const [N, A] = lines[0].split(' ').map(Number);
const S = new Set(); // サイコロの目
for (let i = 1; i <= 1000; i++) {
S.add(i); // 1〜1000の値(サイコロの目)を S に保存
}
for (let i = 1; i <= 1000; i++) {
const B = i;
S.delete(gcd_s(A, B, N)); // S から gcd_s() の戻り値を削除
}
if (S.size) { // S に値があれば
S.forEach(s => {
console.log(s); // S の各要素を表示
});
} else { // さもなくば
console.log(-1); // -1 を表示
}
});
N が A と i の 最大公約数 で割り切れない時は ゴールできない
ので 1 〜 1000 を S に保存してから gcd_s(A, B)
を実行して戻り値を削除しました。
【意地悪すごろく】コード 2/2《C++の実装例参照》
reader.on('close', () => {
const gcd = (a, b) => {
if (!b) {
return a;
}
return gcd(b, a % b);
};
const [N, A] = lines[0].split(' ').map(Number);
let none = true;
for (let i = 1; i <= 1000; i++) {
const min_move = gcd(A, i);
if (N % min_move !== 0 && i !== A) {
console.log(i);
none = false;
}
}
if (none) {
console.log(-1);
}
});
解答コード例・C++の場合を 書き換えるとこんな感じ…。
コメント