今回は paiza の「「部外者をはじけ」を解くために:part3」の問題に挑戦!
問題概要
🎯 目的
-
N人の人物の座標 (x_i, y_i) が与えられる。 - 異なる2人を結んだ直線の方程式 「ax + by + c = 0」 をすべて求めて出力する。
ここで、任意の二点 (x_1, y_1), (x_2, y_2) を結ぶ直線の方程式 ax – by + c = 0 は次のように計算できる
(y_2-y_1) * x - (x_2-x_1) * y + {(x_2-x_1) * y_1 - (y_2-y_1) * x_1} = 0
⚙️ 出力形式
- 各ペア (i, j)(i < j)について 1 行ずつ出力。
- i 昇順、j 昇順で並べる。
- 誤差が 0.001 未満であれば正答とみなす。
入力例:
3
331.26 330.83
264.31 3.44
118.56 118.09
出力例:
-327.3900000000 66.9500000000 86302.1429000000
-212.7400000000 212.7000000000 104.7114000000
114.6500000000 145.7500000000 -30804.5215000000
✅OK例:
const rl = require('readline').createInterface({ input: process.stdin });
const lines = [];
rl.on('line', (input) => lines.push(input));
rl.on('close', () => {
const N = Number(lines[0]); // 人数 N を取得
const points = lines.slice(1).map(line => line.split(' ').map(Number)); // 各座標を配列に格納
// --- 全てのペア (i, j) を探索 ---
for (let i = 0; i < N; i++) {
const [x1, y1] = points[i];
for (let j = i + 1; j < N; j++) {
const [x2, y2] = points[j];
// --- 2点 (x1, y1), (x2, y2) から a, b, c を計算 ---
const a = y2 - y1;
const b = -(x2 - x1);
const c = (x2 - x1) * y1 - (y2 - y1) * x1;
// --- 結果出力 ---
console.log(a, b, c);
}
}
});
🧩 処理の流れ
- 入力を読み取り、最初の行から人数
Nを取得。 - 残りの行を読み取って (
x, y) の配列pointsに格納。 - 二重ループで 全ての点の組み合わせ (
i,j) を探索(i < j)。 - 各ペアについて、直線の係数 (
a,b,c) を次の式で求める:- a =
y₂ − y₁ - b =
−(x₂ − x₁) - c =
(x₂ − x₁)y₁ − (y₂ − y₁)x₁
- a =
- 各 (
a,b,c) を出力。
→ 出力順は自動的にi昇順・j昇順になる。
📝まとめ
- 直線の方程式:
- ax + by + c = 0
- 2点から直線を求める式:
- a =
y₂ − y₁ - b =
−(x₂ − x₁) - c =
(x₂ − x₁)y₁ − (y₂ − y₁)x₁
- a =
- 出力順:
- i 昇順・j 昇順(i < j)
- 構造の考え方:
- 外側ループで「基準の点」iを選ぶ
- 内側ループで「もう一方の点」jを選ぶ
- 2点 (i, j) から a, b, c を計算
- 出力