Bisakah kamu mengucapkan mantranya?

22

Dalam Magic: the Gathering, para penyihir (dikenal sebagai "planeswalkers") saling bertarung dengan melemparkan mantra. Mantra mana biaya. Ada lima warna mana: Putih, Biru, Hitam, Merah, dan Hijau, masing-masing direpresentasikan sebagai {W}, {U}, {B}, {R}, dan {G}.

Biaya mantra sedikit lebih kompleks. Biaya dapat berupa kombinasi dari yang berikut:

  • Satu atau lebih warna
  • Satu atau lebih tidak berwarna, direpresentasikan sebagai {X}, di mana X adalah bilangan bulat positif
  • Satu atau lebih hibrida, diwakili sebagai {Y / Z}, di mana Y dan Z adalah warna (diwakili oleh salah satu dari lima huruf) atau tidak berwarna, diwakili oleh bilangan bulat positif

Aturan berikut ini berlaku ketika mencoba membaca mantra:

  • Warna dalam biaya harus dipenuhi oleh satu mana dari warna itu
  • Biaya tak berwarna {X} dapat dipenuhi oleh X mana warna apa pun
  • Biaya hibrida {Y / Z} dapat dipenuhi dengan memenuhi Y atau Z
    • Perhatikan bahwa kawat gigi tidak bersarang
    • Y dan Z bukan hibrida

Tulis sebuah program atau fungsi yang, mengingat kumpulan mana dan biaya, mencetak atau mengembalikan true (atau nilai kebenaran) jika dan hanya jika mana dalam kumpulan itu dapat memenuhi biaya, yang lain salah (atau nilai falsy).

Pool mana adalah string yang tidak kosong dari format:

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

Biaya adalah string format yang tidak kosong:

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

Contohnya

Dalam format Pool Cost -> ExpectedOutput(dengan spasi antara Pool dan Biaya):

{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
Rainbolt
sumber
Apakah mungkin untuk memiliki mana yang tidak berwarna di kolam?
nutki
@nutki Dalam game sebenarnya, ya. Dalam tantangan itu, tidak. Hanya lima warna yang ditentukan dalam tantangan yang ada untuk tujuan tantangan.
Rainbolt
Aku sudah terlalu jauh dari sihir. Biaya hibrida?!?
Sparr
2
@Sparr Mereka diperkenalkan di Ravnica, kembali pada 2005
murgatroid99
@ murgatroid99 Saya berhenti ketika 6E keluar. Tidak ada teman saya yang mau beradaptasi dengan aturan baru :(
Sparr

Jawaban:

7

Pyth, 55 53 52 50 byte

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

Cobalah secara online: Demonstrasi atau Uji harness

Perhatikan bahwa kompleksitas waktu dan memori benar-benar buruk. Jadi contoh kedua tidak berhasil. Saya mengalokasikan sekitar 1,6 GB Ram sebelum crash di komputer saya.

Penjelasan

Penjelasannya adalah untuk solusi 53. Satu-satunya perbedaan adalah, bahwa penguraian awal terjadi di tengah dan bukan di awal.

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

Jadi, inilah uraian awal.

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

Jadi input "{W},{R},{R} {2/W},{W/B}"akan dikonversi menjadi ['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

Jadi apa fungsinya? Input biaya '2/w,w/b'dikonversi menjadi:

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

Setiap string dalam ['aa', 'ab', 'ac', ..., 'zx', 'zy', 'zz', 'w']memuaskan {2/W}dan setiap karakter dalam 'wb'memuaskan{w/b} .

Sekarang kita menghasilkan produk Cartesian dari daftar ini (atau string) dan lihat, apakah ada kombinasi yang dapat dihasilkan dengan pool-mana.

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)
Jakube
sumber
1
nilai-nilai kebenaran dan kepalsuan diizinkan, bukan adil Truedan False.
isaacg
Anda dapat menyimpan karakter dengan memasukkan tugas ke K. Letakkan di Kc-rz0"{}")mana Kpertama kali digunakan, dan hapus penugasan awal K.
isaacg
@isaacg Oh, seharusnya melihat itu. Terima kasih.
Jakube
@Rainbolt Anda menerima solusi yang tidak berfungsi. Yah itu berhasil ketika saya mempostingnya, tetapi Pyth banyak berubah. Saya memperbaruinya dan juga menyimpan 2 byte lagi.
Jakube
@ Jakube Terima kasih, tetapi jawaban ini perlu bekerja menggunakan penerjemah yang tersedia pada saat tantangan diposting, bukan penerjemah baru yang diperbarui.
Rainbolt
2

Python 2.7, 412 karakter

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]))

Fungsi fadalah fungsi yang melakukan pemeriksaan. Dibutuhkan pool dan biaya mana sebagai argumen string, dan dicetak 1ketika mana memenuhi biaya dan 0sebaliknya. Misalnya, f('{R},{R},{G},{B},{R}', '{4},{R}')cetak 1.

Tidak disatukan, pada dasarnya terlihat seperti ini

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]))
murgatroid99
sumber