Pythonで解く「壊れた電卓」問題 ― 最小操作回数を求める逆算アルゴリズム
問題の概要
ある「壊れた電卓」があるとします。ディスプレイには何らかの数字が表示されていますが、私たちが実行できる操作は次の2つだけです。
- 2倍(Double) … ディスプレイに表示されている数字を2倍にする
- 1減らす(Decrement) … ディスプレイに表示されている数字から1を引く
初期状態では、電卓には数字 X が表示されています。ここで、数字 Y を表示させるために必要な最小の操作回数を求めてください。
例えば、入力が X = 5、Y = 8 の場合、答えは 2 になります。これは「1減らして4にする」→「2倍して8にする」という2回の操作で目的の値に到達できるためです。
解法のアプローチ:逆算で考える
XからYへ向かって順に操作を試す方法も考えられますが、組み合わせが膨大になり非効率です。そこで有効なのが逆算(バックワード)の発想です。目標値Yから出発し、Xに近づくまで操作を巻き戻していきます。
逆算時のルールは次の通りです。
- Yが偶数の場合:2倍の逆操作である「半分にする」(Y ÷ 2)が最短経路になります。
- Yが奇数の場合:2倍した結果は必ず偶数になるため、奇数Yは「1減らす」操作の結果と考えるしかありません。つまり逆操作は「1足す」(Y + 1)となります。
そして、YがX以下になった段階で、残りは「1減らす」操作を (X − Y) 回繰り返すだけで到達できます。
アルゴリズムの手順
- 操作回数を記録する変数
resを0で初期化します。 Y > Xの間、以下を繰り返します。res += Y % 2 + 1を実行(奇数なら2回分、偶数なら1回分としてカウント)- Yが偶数なら
Y // 2、奇数なら(Y + 1) // 2で更新
- 最後に
res + X - Yを返します。
Pythonでの実装例
以下の実装を見ると、理解がより深まるでしょう。
class Solution(object):
def brokenCalc(self, X, Y):
res = 0
while Y > X:
res += Y % 2 + 1
Y = Y // 2 if Y % 2 == 0 else (Y + 1) // 2
return res + X - Y
ob = Solution()
print(ob.brokenCalc(5, 8))
入力例
5
8
出力例
2
計算量について
このアルゴリズムの時間計算量は O(log Y)、空間計算量は O(1) です。Yを繰り返し半分に近づけていくため、必要な操作回数は対数オーダーに収まり、大きな数に対しても非常に効率的に動作します。
-
PythonとTkinterで作る!初心者向けシンプルGUI計算機の作り方
このチュートリアルでは、Pythonの標準モジュールTkinterを使用して、シンプルなGUI計算機を作成します。TkinterはPythonに組み込まれているGUIアプリケーション開発用のモジュールで、追加インストールが不要で手軽に使えるのが魅力です。GUIアプリケーションを活用すれば、データや計算結果を視覚的にわかりやすく操作できます。 それでは、シンプルなGUI計算機の作り方を見ていきましょう。 作成の手順 Tkinterからすべての機能を「*」でインポートします。 計算機のインターフェース(ウィンドウ)を作成します。 入力フィールドに数字を入力する関数(input_number)を作
-
【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説
はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが