Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで方程式を成立させるために必要な最小の数字挿入回数を求めるプログラム

文字列 s が与えられ、これは x+y=z の形式で表される方程式を意味するとします。このとき、s に数字を挿入して等式が正しく成立するようにするために必要な、最小の挿入回数を求めるのがこの問題です。

例えば、入力が s = '2+6=7' の場合、出力は 2 になります。

これは、「1」と「2」を挿入することで方程式を「21+6=27」に書き換えられるためです。つまり、必要な修正回数は合計2回となります。

解法のアプローチ

この問題は、桁ごとの繰り上がりを考慮した動的計画法(DP)を用いて解くことができます。手順は以下の通りです。

  • 文字列 s を「+」記号で分割し、左側を A、右側を rest とします。

  • rest を「=」記号で分割し、左側を B、右側を C とします。

  • dp(サイズA - 1, サイズB - 1, サイズC - 1, 0) を返します。

関数 dp() の定義

引数として ijkcarry(繰り上がり)を受け取る関数 dp() を定義します。

  • i <= -1 かつ j <= -1 かつ k <= -1 の場合、carry が 0 なら 0 を、そうでなければ 1 を返します。

  • last1 := i >= 0 なら A[i]、それ以外は 0

  • last2 := j >= 0 なら B[j]、それ以外は 0

  • last3 := k >= 0 なら C[k]、それ以外は 0

  • prefix1 := i >= 0 なら A[0 から i+1 まで]、それ以外は 0

  • prefix2 := j >= 0 なら B[0 から j+1 まで]、それ以外は 0

  • prefix3 := k >= 0 なら C[0 から k+1 まで]、それ以外は 0

  • i <= -1 かつ j <= -1 の場合:

    • rhs := prefix3 - carry

    • rhs <= 0 であれば、|rhs| を返します。

    • i == -1 または j == -1 の場合、文字列 rhs の長さを返します。

    • それ以外の場合は False を返します。

  • k <= -1 の場合、str(prefix1 + prefix2 + carry) の長さを返します。

  • ans := 無限大 で初期化します。

  • carry2, lhs := divmod(carry + last1 + last2, 10) で商と余りを求めます。

  • lhs == last3 の場合、ans := dp(i - 1, j - 1, k - 1, carry2) とします。

  • req := last3 - carry - last2extra_zeros := max(0, -1 - i)carry2 := req < 0 なら 1、それ以外は 0 とし、ans := min(ans, 1 + extra_zeros + dp(max(-1, i), j - 1, k - 1, carry2)) を更新します。

  • 同様に req := last3 - carry - last1extra_zeros := max(0, -1 - j)carry2 := req < 0 なら 1、それ以外は 0 とし、ans := min(ans, 1 + extra_zeros + dp(i - 1, max(-1, j), k - 1, carry2)) を更新します。

  • carry2, lhs := divmod(last1 + last2 + carry, 10) を計算し、ans := min(ans, 1 + dp(i - 1, j - 1, k, carry2)) を更新します。

  • 最後に ans を返します。

メインメソッドからは dp(サイズA - 1, サイズB - 1, サイズC - 1, 0) を返します。

実装例

理解を深めるために、以下の実装を見てみましょう。

class Solution:
    def solve(self, s):
        A, rest = s.split("+")
        B, C = rest.split("=")
        def dp(i, j, k, carry):
            if i <= -1 and j <= -1 and k <= -1:
                return 0 if carry == 0 else 1
            last1 = int(A[i]) if i >= 0 else 0
            last2 = int(B[j]) if j >= 0 else 0
            last3 = int(C[k]) if k >= 0 else 0
            prefix1 = int(A[: i + 1]) if i >= 0 else 0
            prefix2 = int(B[: j + 1]) if j >= 0 else 0
            prefix3 = int(C[: k + 1]) if k >= 0 else 0
            if i <= -1 and j <= -1:
                rhs = prefix3 - carry
                if rhs <= 0:
                    return abs(rhs)
                if i == -1 or j == -1:
                    return len(str(rhs))
                else:
                    assert False
            if k <= -1:
                return len(str(prefix1 + prefix2 + carry))
            ans = float("inf")
            carry2, lhs = divmod(carry + last1 + last2, 10)
            if lhs == last3:
                ans = dp(i - 1, j - 1, k - 1, carry2)
            req = last3 - carry - last2
            extra_zeros = max(0, -1 - i)
            carry2 = 1 if req < 0 else 0
            ans = min(ans, 1 + extra_zeros + dp(max(-1, i), j - 1, k - 1, carry2))
            req = last3 - carry - last1
            extra_zeros = max(0, -1 - j)
            carry2 = 1 if req < 0 else 0
            ans = min(ans, 1 + extra_zeros + dp(i - 1, max(-1, j), k - 1, carry2))
            carry2, lhs = divmod(last1 + last2 + carry, 10)
            ans = min(ans, 1 + dp(i - 1, j - 1, k, carry2))
            return ans
        return dp(len(A) - 1, len(B) - 1, len(C) - 1, 0)

ob = Solution()
print (ob.solve('2+6=7'))

入力

'2+6=7'

出力

2
  1. Pythonで倉庫(godown)に押し込めるボックスの数を求めるプログラム

    問題の概要 2つの整数配列が与えられていると仮定しましょう。一方のリストには単位幅のボックスの高さが、もう一方の配列には倉庫(godown)内の各部屋の高さが格納されています。部屋には 0〜n の番号が付いており、各部屋の高さは godown 配列の対応するインデックスに記録されています。ここで、倉庫に押し込むことのできるボックスの数を求めます。 ただし、以下のルールを守る必要があります。 ボックスを積み重ねることはできません。 ボックスの順序は自由に入れ替えられます。 ボックスは必ず左から右へ向かって挿入します。 もしボックスの高さがある部屋の高さより大きい場合、そのボックスおよびそれよ

  2. Pythonでリスト内の最小値を見つける方法を解説

    この記事では、リストの中から最小の数値を見つける方法について、具体的なサンプルコードとともに詳しく解説します。問題の概要問題: 数値のリストが与えられたとき、その中に含まれる最も小さい数値を画面に表示すること。この問題を解くアプローチは主に2つあります。ひとつは sort() メソッドを使ってリストを昇順に並べ替え、先頭の要素(インデックス0)を取得する方法。もうひとつは、Pythonに標準で用意されている組み込み関数 min() を使う方法です。それぞれ順番に見ていきましょう。方法1:sort()メソッドで並べ替えて最小値を取得するまずはリストを昇順にソートし、先頭の要素を取り出す方法です。