paizaラーニング レベルアップ問題集 ソートメニュー応用編 JavaScript タプルソート
タプルソート (paizaランク B 相当)
解いてみました。
解答コード例(JavaScript) C++ の場合(1)の模範解答参考
ソート前に、優先順位の高い順にしておきます。この問題では、
[ k 列目, 1 列目, 2 列目, ..., k - 1 列目, k + 1 列目, ..., m 列目 ]
の順にしてから、優先順位の低い末尾からソートを実行し、その後、元に戻します。
JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//n 行 m 列 の表 a , k 列目が昇順
const [n, m, _] = lines[0].split(" ").map(Number);
let [_, _, k] = lines[0].split(" ").map(Number);
k--;//表aのインデックスで扱うので-1する
//入力cin
const cin = lines.slice(1).map(line => line.split(" ").map(Number));
//表 a
const a = Array(n).fill(0).map(v => v = Array(m));
// k 番目の値を配列の先頭に入れる
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (j === k) {
a[i][0] = cin[i][j];
} else if (j < k) {
a[i][j + 1] = cin[i][j];
} else {
a[i][j] = cin[i][j];
}
}
}
//優先順位の低い末尾の列からソート実行
for (let i = m - 1; i >= 0; i--) {
a.sort((a, b) => a[i] - b[i]);
}
//戻し先の配列を作る
const sorted = Array(n).fill(0).map(row => row = []);
//先頭に入れた k 番目の値を元の位置に戻す
for (let i = 0; i < n; i++) {
//kの前
for (let j = 1; j < k + 1; j++) {
sorted[i].push(a[i][j]);
}
//kを元に戻す
sorted[i].push(a[i][0]);
//kの後
for (let j = k + 1; j < m; j++) {
sorted[i].push(a[i][j]);
}
}
//出力
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (j === 0) {
process.stdout.write(String(sorted[i][j]));
} else {
process.stdout.write(" " + String(sorted[i][j]));
}
}
process.stdout.write("\n");
}
表aを作るところは、メソッドを使って以下のようにも書けます。
JavaScript
//表 a
const a = [];
// k 番目の値を配列の先頭に入れる
for (let i = 0; i < n; i++) {
const a_i = lines[i + 1].split(" ").map(Number);//表aのi行目
const head = a_i.splice(k, 1);//k番目を抜く
a_i.unshift(...head);//抜いたk番目を先頭につける
a.push(a_i);//表aのi行目にpush
}
最後の出力のところは、以下のように1行でも書けます。
JavaScript
//出力
console.log(a.map(row => row.join(" ")).join("\n"));
解答コード例(JavaScript) C++ の場合(2)の模範解答参考
sort関数の中で、優先順位にしたがって、ifで場合分けをしても解くことができます。
ifは先に来る方が優先されます。
k 番目の値が等しくない場合はすぐに比較が完了します。k 番目の要素が最優先だからです。
k 番目の値が等しい場合は k 番目以外の値を先頭から順に見ていきます。
JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//n 行 m 列 の表 a , k 列目が昇順
let [n, m, k] = lines[0].split(" ").map(Number);
k--;//表aのインデックスで扱うので-1する
//表 a
const a = lines.slice(1).map(line => line.split(" ").map(Number));
//ソート実行
a.sort((a_l, a_r) => {
//ifは優先順位が高い方が先
if (a_l[k] !== a_r[k]) { // k 番目の要素の値が異なるとき
return a_l[k] - a_r[k]; //k 列目を昇順に
} else { //k 番目の要素の値が等しかったら、
for (let i = 0; i < a_l.length; i++) { //i番目の要素の値を調べる
if (i === k) { //k 番目の要素はスキップ
continue;
}
if (a_l[i] !== a_r[i]) { // i番目の要素の値が異なるとき
return a_l[i] - a_r[i]; // i 列目の値を昇順に
}
}
// すべての要素の値が等しいとき
return 0;
}
});
//出力
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (j === 0) {
process.stdout.write(String(a[i][j]));
} else {
process.stdout.write(" " + String(a[i][j]));
}
}
process.stdout.write("\n");
}
こちらも最後の出力のところは、以下のように1行でも書けます。
JavaScript
//出力
console.log(a.map(row => row.join(" ")).join("\n"));