แก้ปัญหาเกมหีบเพลง


13

Accordionเป็นเกมไพ่เล่นไพ่คนเดียวที่ฉันเพิ่งเจอซึ่งเกือบทุกเลย์เอาท์สามารถแก้ไขได้ แต่ยากอย่างเหลือเชื่อ คุณสามารถเล่นได้ที่นี่

กฎระเบียบ

ไพ่หน้า 52 ใบหงายหน้าโดยสุ่ม ทุกเทิร์นคุณจะเปลี่ยนไพ่ด้วยการ์ดใหม่ซึ่งการ์ดทั้งสอง :

  • แบ่งปันสูทหรือหมายเลขและ
  • อยู่ที่ระยะ 1 (ติดกัน) หรือ 3 (ไพ่สองใบในระหว่าง)

เป็นเกมที่ได้รับรางวัลเมื่อมีเพียง 1 ใบที่เหลืออยู่ คุณสามารถสันนิษฐานได้ว่าแต่ละอินพุตนั้นสามารถแก้ไขได้ บัตรที่ถูกเปลี่ยนจะต้องนำหน้าบัตรที่เปลี่ยนใหม่เสมอ

ตัวอย่าง

เป็นตัวอย่างพิจารณาโครงร่างต่อไปนี้:

2H,2S,1S,2D  (H: Hearts, S: Spades, D: Diamonds)

มี 3 การเคลื่อนไหวที่เป็นไปได้ที่นี่:

  1. แทนที่2Hด้วยด้านที่อยู่ติดกัน2Sดังนั้นเราก็จบลงด้วย2S,1S,2D
  2. แทนที่2Sด้วยด้านที่อยู่ติดกัน1Sดังนั้นเราก็จบลงด้วย2H,1S,2D
  3. แทนที่2Hด้วย2D(ที่ระยะ 3) ดังนั้นเราจะได้2D,2S,1S

จากการเคลื่อนไหว 3 ครั้งนั้นมีเพียงด่านสุดท้ายเท่านั้นที่มีความเป็นไปได้ในการชนะ (คุณชนะโดยการแทนที่2D <- 2Sจากนั้น2S <- 1S)

Input / Output

งานของคุณคือการเขียนแก้หีบเพลง คุณถูกส่งผ่านรายการไพ่และคุณจำเป็นต้องส่งคืนรายการย้ายเพื่อแก้ไขเกม

คุณถูกส่งผ่านรายการของการ์ดเป็นสตริงที่คั่นด้วยเครื่องหมายจุลภาคซึ่งการ์ดแต่ละใบจะถูกส่งเป็นจำนวนเต็มแทนค่าตัวเลขของพวกเขาจากนั้นตัวละครที่เป็นตัวแทนของชุดของพวกเขา

คุณต้องส่งคืนรายการการแทนที่เป็นสตริงที่คั่นด้วยเครื่องหมายจุลภาคซึ่งการแทนที่แต่ละรายการอยู่ในรูปแบบCard <- Card(ตามรูปแบบการ์ดที่อธิบายไว้ด้านบน) ไพ่ใบแรกในแต่ละคู่คือไพ่ที่ถูกแทนที่

กรณีทดสอบ:

5H,1C,12S,9C,9H,2C,12C,11H,10C,13S,3D,8H,1H,12H,4S,1D,7H,1S,13D,13C,7D,12D,6H,10H,4H,8S,3H,5D,2D,11C,10S,7S,4C,2H,3C,11S,13H,3S,6C,6S,4D,11D,8D,8C,6D,5C,7C,5S,9D,10D,2S,9S
5H,9C,11H,7S,7D,12D,6H,10S,3H,4D,12C,2S,3C,5C,7H,6S,1H,8S,2H,11S,4C,10D,12H,9H,2D,4H,6C,13H,11C,2C,10H,8C,1S,11D,3S,12S,7C,5D,13S,8D,4S,6D,13C,3D,8H,13D,1D,9D,9S,1C,5S,10C
7H,11C,8C,7S,10D,13H,4S,10C,4D,2C,4H,13D,3C,2H,12C,6C,9H,4C,12H,11H,9S,5H,8S,13S,8H,6D,2S,5D,11D,10S,1H,2D,5C,1C,1S,5S,3H,6S,7C,11S,9C,6H,8D,12S,1D,13C,9D,12D,3D,7D,10H,3S

ในขณะที่การแข่งขันครั้งนี้เป็นฉันสนใจเป็นพิเศษในการแก้ปัญหาที่ประหยัดเวลาและมีแนวโน้มที่จะให้รางวัลกับการแก้ปัญหาที่ชาญฉลาดด้วยรางวัล ที่กล่าวว่าการแก้ปัญหาที่ใช้ระยะเวลาทางดาราศาสตร์ยังคงเป็นที่ยอมรับได้ (ฉันขอแนะนำให้ทดสอบด้วยสำรับขนาดเล็กเช่นการ์ด 16 ใบ, สำรับไพ่ 4 ใบ)


กฎของคุณพูดถึงว่าการเคลื่อนไหวสามารถทำได้ในทิศทางเดียวเท่านั้น?
feersum

6
ไพ่ทุกใบบนโต๊ะมีค่าเฉลี่ยประมาณ 0.25 + 0.25 = 0.5 การเคลื่อนไหวทางกฎหมาย ดังนั้นพื้นที่การค้นหาประมาณ 52! * 0.5 = 4E67 ความท้าทายตามที่เขียนไว้ (พร้อมรหัสแท็กกอล์ฟ) สามารถตีความได้ว่าจำเป็นต้องค้นหาพื้นที่ทั้งหมดนี้และรายงานวิธีแก้ปัญหาใด ๆ (หรือ "ไม่มี" ถ้าหมดแล้ว) ซึ่งออกจากห้องเล็ก ๆ เพื่อความเฉลียวฉลาดและต้องใช้เวลาทางดาราศาสตร์ ฉันขอแนะนำให้คุณทำสิ่งนี้ให้เป็นรหัสโดยพิจารณาจากอัตราความสำเร็จและเวลาและลดอิทธิพลของความยาวของรหัสที่มีต่อคะแนนหรือกำจัดออกไปโดยสิ้นเชิง
เลเวลริเวอร์เซนต์

1
@ Pietu1998 และในนั้นปัญหาอยู่ ฉันคิดว่าตัวช่วยจำกำลังคิดค่าใช้จ่ายเป็นจำนวนไบต์ดังนั้นคุณควรส่งรุ่นโดยไม่มีตัวช่วยจำเป็นรุ่น golfed แต่จากนั้นจะเป็นไปไม่ได้ที่จะทดสอบกับการ์ด 52 ใบ Codegolf ทำงานได้ไม่ดีเท่าระบบการให้คะแนนกับปัญหาในการค้นหาพื้นที่ขนาดใหญ่
ระดับแม่น้ำเซนต์

3
ฉันโอเคกับช่วงเวลาทางดาราศาสตร์สำหรับผู้ที่ต้องการแข่งขันกอล์ฟรหัส อย่างไรก็ตามผู้คนสามารถ (และสนับสนุน) ได้อย่างแน่นอนในการโพสต์คำตอบที่ไม่สามารถแข่งขันได้และเป็นเรื่องของเวลาทำงาน
นาธานเมอร์ริน

4
นอกจากนี้หากคุณต้องการทดสอบการแก้ปัญหาการเล่นกอล์ฟคุณไม่จำเป็นต้องมีการ์ด 52 ใบ สำรับไพ่ 16 ใบ (4 สูท) ควรจัดให้มีเวลาทำงานสั้นและตรวจสอบความถูกต้อง
นาธานเมอร์ริน

คำตอบ:


5

Python 3, 274 272 271 ไบต์

2 ไบต์บันทึกขอบคุณที่@orlp

def g(p):
 q=lambda a:[[i,a]for i in range(len(p)-a)if p[i][:-1]==p[i+a][:-1]or p[i][-1]in p[i+a]]
 for n in q(1)+q(3):
  s=sum(n);c=p[:s]+p[s+1:];c[n[0]]=p[s]
  if g(c):return p[n[0]]+' <- '+p[s]+','+g(c)
 return' 'if len(p)<2else[]
print(g(input().split(','))[:-2]or'')

ช้ามาก อย่างไรก็ตามคุณสามารถลองกับmemoize นี้มีไม่กี่พิเศษlist- tupleแปลง แต่เทียบเท่ามิฉะนั้น

import functools
@functools.lru_cache(maxsize=None)
def g(p):
 q=lambda a:[[i,a]for i in range(len(p)-a)if p[i][:-1]==p[i+a][:-1]or p[i][-1]in p[i+a]]
 for n in q(1)+q(3):
  s=sum(n);c=list(p[:s]+p[s+1:]);c[n[0]]=p[s]
  if g(tuple(c)):return p[n[0]]+' <- '+p[s]+','+g(tuple(c))
 return' 'if len(p)<2else[]
print(g(tuple(input().split(',')))[:-2]or'')

แม้อันนี้จะช้าในทางดาราศาสตร์ด้วยอินพุตบางอย่าง

รหัสใช้สตริงตัวเลขไม่ได้ดังนั้นจึงยังสนับสนุนสัญกรณ์เช่นแทนKH13H

ตัวอย่าง:

$ python accordion.py
5H,9C,11H,7S,7D,12D,6H,10S,3H,4D,12C,2S,3C,5C,7H,6S,1H,8S,2H,11S,4C,10D,12H,9H,2D,4H,6C,13H,11C,2C,10H,8C,1S,11D,3S,12S,7C,5D,13S,8D,4S,6D,13C,3D,8H,13D,1D,9D,9S,1C,5S,10C
7S <- 7D,7D <- 12D,3C <- 5C,12H <- 9H,11C <- 2C,3S <- 12S,13D <- 1D,1D <- 9D,9D <- 9S,2S <- 6S,7H <- 1H,6S <- 8S,1H <- 2H,8S <- 11S,2H <- 9H,10D <- 2D,9H <- 4H,4H <- 4C,5C <- 4C,4D <- 4C,4C <- 12C,10S <- 11S,11H <- 11S,6H <- 3H,12D <- 2D,12C <- 2C,2C <- 6C,6C <- 8C,12S <- 13S,5D <- 6D,6D <- 8D,8D <- 3D,4S <- 9S,13S <- 9S,11D <- 3D,7C <- 1C,1S <- 1C,1C <- 13C,8C <- 13C,13C <- 13H,13H <- 10H,2D <- 3D,3D <- 3H,3H <- 8H,8H <- 10H,11S <- 5S,5H <- 10H,5S <- 9S,10H <- 10C,10C <- 9C,9C <- 9S

ใช้functools.lru_cacheแทนการเขียนของคุณเอง
orlp

@ หรือฉันจะ แต่เป็นlistunhashable มันไม่ทำงาน
PurkkaKoodari

จากนั้นใช้สิ่งอันดับ
orlp

@ orlp ตกลง แต่นั่นจะต้องมีการเปลี่ยนแปลงรหัส (เช่นstr.splitผลตอบแทนlist) ฉันต้องการให้ทั้งสองโปรแกรมทำงานได้เทียบเท่ากัน
PurkkaKoodari

h=lambda p:lru_cache(None)(g)(''.join(p))คุณสามารถทำ
orlp
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.