呪文を唱えられますか?


22

マジック:ザギャザリングでは、メイジ(「プレインズウォーカー」として知られる)は呪文を唱えることによって互いに戦います。呪文のコストはマナです。マナには、白、青、黒、赤、緑の5色があり、それぞれ{W}、{U}、{B}、{R}、{G}として表されます。

呪文のコストはやや複雑です。コストは、次の任意の組み合わせにすることができます。

  • 1つまたは複数の色
  • {X}として表される1つ以上の無色、Xは正の整数
  • {Y / Z}で表される1つ以上のハイブリッド。YとZは色(5文字のいずれかで表される)または無色で、正の整数で表されます。

呪文を唱えようとするとき、次の規則が適用されます。

  • コスト内の色は、その色の1マナで満たされる必要があります
  • 無色のコスト{X}は、どの色のXマナでも満たすことができます
  • ハイブリッドコスト{Y / Z}は、YまたはZのいずれかを満たすことで満たされます。
    • ブレースはネストされないことに注意してください
    • YとZはハイブリッドではありません

マナのプールとコストが与えられると、そのプール内のマナがコストを満たすことができる場合にのみtrue(または何らかの真理値)を出力または返すプログラムまたは関数を作成します。

マナプールは、次の形式の空でない文字列です。

Color1,Color2,Color3,...,Colorn-1,Colorn

コストは、次の形式の空でない文字列です。

Cost1,Cost2,Cost3,...,Costn-1,Costn

フォーマットPool Cost -> ExpectedOutput(プールとコストの間にスペースがあります):

{R},{R},{G},{B},{R} {4},{R} -> True
{G},{G},{G},{G},{W},{W},{W} {2/W},{2/U},{2/B},{2/R},{2/G} -> False
{G},{G},{R} {R/G},{G/B},{B/R} -> True
{R},{R},{R},{G} {1},{G},{2/G}-> True
{R} {R},{R},{R},{R},{R} -> False
{W},{R},{R} {2/W},{W/B} -> True
{U},{U} {1} -> True
{W},{R},{G} {1},{2} -> True

プールに無色のマナを持つことは可能ですか?
-nutki

@nutki実際のゲームでは、はい。チャレンジでは、いいえ。チャレンジでは、チャレンジで定義された5色のみが存在します。
レインボルト

私はあまりにも長い間魔法から離れていました。ハイブリッドコスト?!?
スパー

2
@Sparr 2005年に戻ったラヴニカで紹介されました
murgatroid99

@ murgatroid99 6Eが出たときに終了しました。私の友人は誰も新しいルールに順応する

回答:


7

Pyth、55 53 52 50バイト

FN*Fmsm?k}kG^Gvkcd\/ceKc-rz0`Hd\,#=sN)I!.-NhK1B)E0

オンラインで試す:デモンストレーションまたはテストハーネス

時間とメモリの複雑さが本当に悪いことに注意してください。したがって、2番目の例は機能しません。マシンでクラッシュする前に、約1.6 GBのRamを割り当てます。

説明

説明は53ソリューションについてです。唯一の違いは、最初の解析が最初ではなく中央で行われることです。

Kc-rz0"{}"dFN*Fmsm?k}kG^Gvkcd\/ceKc-rz0`H\,#=sN)I!.-NhK1B)E0

だから、ここに最初の解析があります。

Kc-rz0`Hd
   rz0     convert input() to lowercase
  -   `H   remove all curly brackets (`H = "{}")
 c      d  split at the space
K          assign to K

したがって、入力"{W},{R},{R} {2/W},{W/B}"はに変換され['w,r,r', '2/w,w/b']ます。

m               ceK\,    map each cost d of the costs split by "," to:
 s                         the sum of
  m         cd\/           map each value k of cost split by "/" to:
    k                        k
   ? }kG                     if k in "abcdef...xyz" else
        ^Gvk                 Cartesian product with "abc...yz" of int(k) repeats

それでこれは何をするのでしょうか?コスト入力'2/w,w/b'は次のように変換されます:

[['aa', 'ab', 'ac', ..., 'zx', 'zy', 'zz', 'w'], 'wb']

のすべての文字列が['aa', 'ab', 'ac', ..., 'zx', 'zy', 'zz', 'w']満たされ{2/W}、のすべての文字が'wb'満たされ{w/b}ます。

ここで、これらのリスト(または文字列)のデカルト積を生成し、mana-poolで組み合わせを生成できるかどうかを確認します。

FN*F...              )      for N in Cartesian product of ...:
       #   )                   while 1:
        =sN                      N = sum(N)
                               this flattens N
            I!.-NhK            if not (subtract mana pool from N):
                   1             print 1 (True)
                    B            break
                      E      else:
                       0       print 0 (False)

1
truthyとfalsy値だけではなく、許可されているTrueFalse
isaacg

に割り当てをインリングすると、キャラクターを保存できますKKc-rz0"{}")どこに置くK最初に使用され、そして初期割り当てを削除K
isaacg

@isaacgああ、それを見るべきだった。ありがとう。
ジャクベ

@Rainbolt動作しないソリューションを受け入れました。まあそれを投稿したときはうまくいきましたが、Pythは大きく変わりました。それを更新し、さらに2バイト節約しました。
寂部

@Jakubeありがとう。ただし、この回答は、新しい更新された通訳ではなく、チャレンジが投稿された時点で利用可能であった通訳を使用して動作する必要があります。
レインボルト

2

Python 2.7、412文字

import re,collections as C
r,C=re.findall,C.Counter
def g(m,h,c,v):
 try:return t(m,h,c+int(v))
 except:
  if m[v]:return t(m-C({v:1}),h,c)
def t(m,h,c):return any(g(m,h[1:],c,v)for v in h[0].split('/'))if h else sum(m.values())>=c
def f(m,c):m=C(r(r'\w',m));c=[filter(None, x)for x in zip(*r(r'(\w+/\w+)|(\d+)|(\w)',c))];m.subtract(C(c[2]));print all(x>=0 for x in m.values())*t(m,c[0],sum(int(x)for x in c[1]))

関数fはチェックを行うものです。マナプールとコストを文字列引数として受け取り、マナ1がコストを満たした場合などに出力し0ます。たとえば、f('{R},{R},{G},{B},{R}', '{4},{R}')prints 1です。

Ungolfed、それは基本的にこのように見えます

import re
from collections import Counter
def helper(mana, hybrids, colorless, option):
  try:
    option = int(option) # See if option is an integer
    # For colorless hybrid, just add the value to the colorless amount
    # to check at the end.
    return check_hybrids(mana, hybrids, colorless + option)
  except ValueError: # Option is a mana letter
    # For colored hybrid costs, check if any of that color is
    # available, then try to pay the rest of the cost with 1 less
    # of that color.
    if mana[option] >= 0:
      return check_hybrids(mana - Counter({option: 1}), hybrids, colorless)
    else:
      return False
def check_hybrids(mana, hybrids, colorless):
  '''Check whether the given mana pool can pay the given hybrid costs and colorless costs'''
  if hybrids:
    # For each option in the first hybrid cost, check whether the
    # rest of the cost can be paid after paying that cost
    return any(helper(mana, hybrids[1:], colorless, option) for option in hybrids[0].split('/'))
  else:
    # When there are no remaining hybrid costs, if there is enough
    # remaining mana to pay the colorless costs, we have success
    return sum(m.values()) > colorless
def can_cast(mana_str, cost_str):
  mana = Counter(re.findall(r'\w', mana_str))
  # transpose to get separate lists of hybrid, colorless, and colored symbols
  cost = zip(*re.findall(r'(\w+/\w+)|(\d+)|(\w)',cost_str))
  cost = [filter(None, sublist) for sublist in cost] # Remove unfound symbols
  mana.subtract(Counter(cost[2]))
  # After subtracting the single-colored cost from the mana pool, if
  # anything in the mana pool is negative, we didn't have enough to
  # pay for that color.
  if any(x <=0 for x in mana.values()):
    return False
  return check_hybrids(mana, cost[0], sum(int(x)for x in cost[1]))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.