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

Pythonで「数を減らすゲーム」の勝者を求めるプログラム

問題の概要

AmalとBimalが一つのゲームをプレイしているとします。2人はある整数nを持っており、まずそれが2の累乗であるかどうかを確認します。もし2の累乗であれば、その数を2で割ります。そうでなければ、nより小さい最も近い2の累乗の数だけ値を減らします。そして、数を1にまで減らした方が勝者となります。Amalが必ず先手であるとき、勝者の名前を求めるプログラムを作成しましょう。

例として、入力が n = 19 の場合を考えてみます。19は2の累乗ではないため、Amalは16まで減らします。次にBimalが8にし、Amalが4に、Bimalが2にし、最後にAmalが1にして勝利します。したがって出力は「Amal」となります。

解法のアプローチ

この問題を解くには、以下の手順に従います。

  • カウンタ res を0で初期化します。
  • n が1より大きい間、以下を繰り返します。
    • b を1で初期化します。
    • b × 2 が n 未満である限り、b を2倍していきます(これにより n 未満の最大の2の累乗が得られます)。
    • n から b を引きます。
    • res を1増やします。
  • ループ終了後、res が偶数であれば「Amal」を返します。
  • 奇数であれば「Bimal」を返します。

このアルゴリズムでは、各操作(割り算または減算)を1回のターンとしてカウントしています。操作回数の偶奇によって、どちらのプレイヤーが最後の「1」への到達を行うかが決まるという仕組みです。

実装例

理解を深めるために、以下のPythonコードを見てみましょう。

def solve(n):
   res = 0
   while(n > 1):
      b = 1
      while(b * 2 < n):
         b *= 2
      n -= b
      res += 1
   if res % 2 == 0:
      return 'Amal'
   else:
      return 'Bimal'

n = 19
print(solve(n))

入力

19

出力

Amal

計算量について

外側のwhileループは各反復で少なくとも半分以上の値を減らすため、全体の時間計算量は O(log² n) 程度となり、非常に効率的です。より高度な最適化としては、ビット演算を用いて n 未満の最大の2の累乗を求める方法や、n のビット長から直接操作回数を導出する方法もあります。

  1. Pythonでソート済みリストの重複を削除するゲームに必要なターン数を求めるプログラム

    問題の概要友人であるアマル(Amal)とビマル(Bimal)が、numsという名前のソート済み数値リストを使ってゲームを行っているとします。各ターンでは、まずアマルが任意の3つの数値を選び、次にビマルがそのうちの1つを削除し、続いてアマルがさらに1つを削除します。リストは最初、奇数個の要素で構成されています。ここで、アマルはリストから重複要素をなくすために必要なターン数を最小化したいと考え、一方ビマルはターン数を最大化しようとします。両者が最適な戦略で行動するとき、このゲームが完了するまでに必要なターン数を求めるのが課題です。入出力例例えば、入力が nums = [1, 1, 2, 3, 3,

  2. Pythonでリスト内の最大値を見つける方法|sort()とmax()の2つのアプローチ

    この記事では、リストの中から最大の数値を見つけるための解決策とアプローチについて詳しく解説します。問題の概要数値のリストが与えられたとき、その中から最大の要素を見つけ出す必要があります。Pythonでは、主に以下の2つの方法でこれを実現できます。ソート(並べ替え)を利用する方法組み込み関数 max() を利用する方法アプローチ1:sort() 関数を使う方法リストを sort() メソッドで昇順に並べ替えると、リストの最後の要素(インデックス -1)が必ず最大値になります。サンプルコードlist1 = [18, 65, 78, 89, 90] list1.sort() # メイン処理 prin