0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【全探索 3】+1, -1, ‘1’+, +’1′

Posted at

今回は paiza 「【全探索 3】+1, -1, ‘1’+, +’1’」の問題に挑戦!

全探索ってことでシンプルに全部書いたなら長くなりすぎた(´;ω;`)


問題概要

◯ 入力

  • N 個の自然数 X1,X2,…,XN​ が与えられる。

◯ 操作ルール

  • 任意の2つの数を選ぶ。
  • それぞれの数に対して「次の操作のいずれかを1回だけ行える(行わなくても良い)」:
    • +1 する
    • -1 する
    • 先頭に「1」をつける
    • 末尾に「1」をつける
  • これで得られた2つの数の差の絶対値を計算。

◯ 出力

  • 操作後の 2 つの数の差の絶対値の "最小値" を出力。



入力例:

3
111
222
333

出力例:

109






✅ 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]);
    const X = lines.slice(1).map(Number);
    
    
    let minDiff = Infinity;
    
    for (let i = 0; i < N; i++) {
        const A = X[i];
        const A1 = A + 1;
        const A2 = A - 1;
        const A3 = '1' + A
        const A4 = A + '1';
        
        for (let j = 0; j < N; j++) {
            if (i === j) continue;
            
            const B = X[j];
            const B1 = B + 1;
            const B2 = B - 1;
            const B3 = '1' + B;
            const B4 = B + '1';
            
            if (Math.abs(A - B) < minDiff) minDiff = Math.abs(A - B);
            if (Math.abs(A - B1) < minDiff) minDiff = Math.abs(A - B1);
            if (Math.abs(A - B2) < minDiff) minDiff = Math.abs(A - B2);
            if (Math.abs(A - B3) < minDiff) minDiff = Math.abs(A - B3);
            if (Math.abs(A - B4) < minDiff) minDiff = Math.abs(A - B4);
            if (Math.abs(A1 - B) < minDiff) minDiff = Math.abs(A1 - B);
            if (Math.abs(A1 - B1) < minDiff) minDiff = Math.abs(A1 - B1);
            if (Math.abs(A1 - B2) < minDiff) minDiff = Math.abs(A1 - B2);
            if (Math.abs(A1 - B3) < minDiff) minDiff = Math.abs(A1 - B3);
            if (Math.abs(A1 - B4) < minDiff) minDiff = Math.abs(A1 - B4);
            if (Math.abs(A2- B) < minDiff) minDiff = Math.abs(A2 - B);
            if (Math.abs(A2 - B1) < minDiff) minDiff = Math.abs(A2 - B1);
            if (Math.abs(A2 - B2) < minDiff) minDiff = Math.abs(A2 - B2);
            if (Math.abs(A2 - B3) < minDiff) minDiff = Math.abs(A2 - B3);
            if (Math.abs(A2 - B4) < minDiff) minDiff = Math.abs(A2 - B4);
            if (Math.abs(A3 - B) < minDiff) minDiff = Math.abs(A3 - B);
            if (Math.abs(A3 - B1) < minDiff) minDiff = Math.abs(A3 - B1);
            if (Math.abs(A3 - B2) < minDiff) minDiff = Math.abs(A3 - B2);
            if (Math.abs(A3 - B3) < minDiff) minDiff = Math.abs(A3 - B3);
            if (Math.abs(A3 - B4) < minDiff) minDiff = Math.abs(A3 - B4);
            if (Math.abs(A4 - B) < minDiff) minDiff = Math.abs(A4 - B);
            if (Math.abs(A4 - B1) < minDiff) minDiff = Math.abs(A4 - B1);
            if (Math.abs(A4 - B2) < minDiff) minDiff = Math.abs(A4 - B2);
            if (Math.abs(A4 - B3) < minDiff) minDiff = Math.abs(A4 - B3);
            if (Math.abs(A4 - B4) < minDiff) minDiff = Math.abs(A4 - B4);
        }
    }
    
    console.log(minDiff);
});

◯ コードの流れ

  1. 入力の読み込み
    • N を読み込み、続く X の配列を作る。
  2. 最小差を管理する変数 minDiff を初期化
    • 初期値は Infinity にしておく。
  3. 2重ループで2つの数字を選ぶ
    • 外側ループで数字 A を選び、内側ループで数字 B を選ぶ(ただし i === j の場合はスキップ)。
  4. A, B それぞれの操作後の値を4つずつ生成
    • A: A+1, A-1, '1'+A, A+'1'
    • B: B+1, B-1, '1'+B, B+'1'
  5. 差の絶対値をひたすらチェック
    • 25パターン (5×5) の組み合わせをすべて if で書き出している。
    • その都度 minDiff を更新。
  6. 結果を出力
    • 最終的に一番小さかった差を出力する。

◯ 特徴

  • 動きは単純でわかりやすい。
  • ただし if 文が25個も並んでいるため、冗長で「ゴリ押し」感が強い。
  • 小規模問題だから成立するが、スッキリはしていない。






✨ OK例: 二次元配列 + 4重ループ(全探索)

const rl = require('readline').createInterface({ input: process.stdin });

const lines = [];
rl.on('line', (line) => lines.push(line));

rl.on('close', () => {
    const N = Number(lines[0]);
    const X = Array.from({ length: N }, () => Array(5).fill(0));

    // 各数の5パターンを作成
    for (let i = 0; i < N; i++) {
        const val = Number(lines[i + 1]);
        X[i][0] = val;
        X[i][1] = val + 1;
        X[i][2] = val - 1;
        X[i][3] = Number("1" + val.toString());
        X[i][4] = Number(val.toString() + "1");
    }

    let ans = Infinity;

    // すべての組み合わせを調べる
    for (let i = 0; i < N; i++) {
        for (let j = i + 1; j < N; j++) {
            for (let k = 0; k < 5; k++) {
                for (let l = 0; l < 5; l++) {
                    ans = Math.min(ans, Math.abs(X[i][k] - X[j][l]));
                }
            }
        }
    }

    console.log(ans);
});

◯ コードの流れ
  1. 入力の読み込み
    • N を読み込み、長さ N × 5 の二次元配列 X を用意。
  2. 候補値を格納する
    • 各数について 5パターンを X[i] に入れる:
      • 0番目: 元の値
      • 1番目: +1
      • 2番目: -1
      • 3番目: 先頭に1をつける
      • 4番目: 末尾に1をつける
  3. 最小差を管理する変数 ans を初期化
    • 初期値は Infinity
  4. 4重ループで全組み合わせを調べる
    • 外側2重ループ: 2つの異なる数字のペア (i, j) を選ぶ。
    • 内側2重ループ: それぞれの候補値 (k, l) を選ぶ。
    • Math.abs(X[i][k] - X[j][l]) を計算し、ans を更新。
  5. 結果を出力
    • 最終的に一番小さい差を出力する。

◯ 特徴

  • 25パターンの if を書かず、ループでまとめて処理。
  • 二次元配列に候補を保存しておくため、操作がシンプル。
  • スッキリしていて、拡張性もある。






🗒️ まとめ

◯ 問題

  • 「2つの数を選び、操作後の差の絶対値を最小化する」→ 全探索で解ける問題。

◯ 実装方針

  • 各数について「元の数+4種類の操作結果」を列挙 → 計5パターンを作る。
  • すべての組み合わせ(2つの数 → 5パターン × 5パターン)を比較し、最小差を求める。

◯ 解法の2パターン

  • シンプル版
    • 25通りの差を if 文で直接比較。
    • 初学者でも動作が追いやすい。
    • ただし冗長で保守性が低い。
  • 二次元配列+4重ループ版
    • 各数の候補を二次元配列にまとめて、ループで網羅。
    • コードがスッキリし、拡張性も高い。

◯ 学びのポイント

  • 制約が小さいときは「全探索」でシンプルに解ける。
  • 冗長な書き方(if を25回書く)と、整理された書き方(二次元配列+ループ)の両方を比較すると、
    • コードの冗長さ・保守性・見通しの違い が理解できる。
  • 数字の操作に「文字列変換」を使うテクニック("1"+val, val+"1" → Number(...))も重要。




僕の失敗談(´;ω;`)と解決法🐈

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?