Bạn còn chờ gì nữa? (Một người giải mạt chược)


13

Ý tưởng cảm ơn @ MartinBüttner từ một cuộc thảo luận trong trò chuyện

Mahjong là một trò chơi xếp gạch rất phổ biến ở châu Á. Nó thường được chơi với bốn người chơi và mục tiêu của trò chơi là trở thành người đầu tiên hoàn thành một ván bài hợp lệ bằng cách sử dụng các ô. Đối với thử thách này, chúng tôi sẽ xem xét một phiên bản đơn giản hóa của trò chơi - mạt chược PPCG.

Trong PPCG mạt chược, có ba bộ quần áo - m, ps- và gạch được đánh số từ 1đến 9. Có chính xác bốn bản của mỗi ngói và gạch được biểu thị bằng số của nó tiếp theo phù hợp với nó (ví dụ 3m, 9s).

Một tay chơi mạt chược PPCG hoàn thành bao gồm bốn bộ ba và một cặp, với tổng số 14 gạch.

Một bộ ba có thể là:

  • Ba của cùng một lát (ví dụ 4s 4s 4s, nhưng không 4m 4p 4s), hoặc
  • Một chuỗi ba gạch liên tiếp trong cùng một bộ đồ (ví dụ 1s 2s 3shoặc 6p 7p 8pkhông 3s 4m 5mhoặc 3p 5p 7p). Trình tự không bọc (vì vậy 9m 1m 2mlà không hợp lệ).

Một cặp chỉ đơn giản là hai gạch giống nhau (ví dụ 5s 5s).

Các thách thức

Chương trình của bạn sẽ nhận được một bàn tay cách nhau 13 ô, với mỗi ô xuất hiện không quá bốn lần. Bạn có thể viết một chương trình đầy đủ hoặc một hàm có trong một chuỗi.

Nhiệm vụ của bạn là tìm tất cả các ô thứ 14 có thể ("chờ"), khi được thêm vào tay, sẽ tạo thành một bàn tay mạt chược PPCG hoàn chỉnh. Các gạch đầu ra phải được phân tách không gian, nhưng có thể theo bất kỳ thứ tự nào. Khoảng trắng hàng đầu hoặc dấu được cho phép.

Chương trình của bạn nên chạy trong một khoảng thời gian hợp lý, không quá một phút.

Ví dụ

Input: 1m 1m 1m 4s 4s 4s 7p 7p 7p 3m 3m 3m 9s
Output: 9s

Input: 1m 1m 1m 3m 3m 3m 5m 5m 5m 2s 3s 7p 8p
Output:

Input: 1m 2m 2m 3m 3m 3m 3m 4m 1s 1s 9s 9s 9s
Output: 1s

Input: 1m 1m 1m 2m 3m 4m 5m 6m 7m 8m 9m 9m 9m
Output: 1m 2m 3m 4m 5m 6m 7m 8m 9m

Input: 1m 1m 1m 5p 2m 3m 5p 7s 8s 5p 9s 9s 9s
Output: 1m 4m 6s 9s 

Trong ví dụ đầu tiên, 1m 4s 7p 3mtất cả các hình thức bộ ba hiện có, để lại đơn độc 9sđể tạo thành một cặp.

Trong ví dụ thứ hai, các 2s 3s7p 8pchỉ có thể tạo thành các chuỗi và các ô còn lại chỉ có thể tạo thành các bộ ba. Do đó không có cặp nào có thể được hình thành, và không có đầu ra.

Trong ví dụ thứ ba, bàn tay tách ra 1m2m3m 2m3m4m 3m3m 1s1s 9s9s9s. Thông thường, điều này sẽ là chờ đợi 3m 1s, nhưng vì cả bốn 3mđã được sử dụng, nên chờ đợi duy nhất là có sẵn 1s.

Trong ví dụ thứ tư, tất cả các mgạch hoàn thành bàn tay. Ví dụ, đối với 1m, người ta có thể có 1m1m1m 1m2m3m 4m5m6m 7m8m9m 9m9mmột bàn tay hoàn thành.

Cố gắng tìm ra phần còn lại của ví dụ thứ tư và ví dụ thứ năm :)

Chấm điểm

Đây là , vì vậy giải pháp trong vài byte nhất sẽ thắng. Tiêu chuẩn áp dụng.


9
Cảm ơn bạn đã thực sự chơi Mahjong, thay vì trò chơi bài (IMO gây phiền nhiễu) bằng cách sử dụng gạch mà người phương tây dường như nghĩ đến bất cứ khi nào họ nghe thấy từ "Mahjong".
Justin

@Quincunx Sự thật thú vị: Thử thách này xuất hiện bởi vì tôi muốn thực hiện thử thách với một đại diện ASCII của Mahjong solitaire (điều mà tôi vẫn có thể làm vào một lúc nào đó ...). Tôi đã gọi nó là "Mahjong solitaire" mặc dù. ;)
Martin Ender

2
@Quincunx: Tôi không nghĩ đó là lỗi của họ. Đó là lỗi của các nhà phát triển trò chơi khi gọi các trò chơi "Mahjong solitaire" của họ là "Mahjong" và không có gì khác.
Joe Z.

Bảy cặp thì sao? mười ba trẻ mồ côi? bạn có thể làm một cái gì đó thậm chí còn phức tạp hơn với danh dự :) Bạn có nghĩ rằng nó không có mục đích nếu tôi tạo ra một codegolf yêu cầu tính toán shanten (số lượng gạch tối thiểu cần thiết trước khi có được tenpai - sẵn sàng giành chiến thắng)?
V. Courtois

@VCourtois Đã được một thời gian, nhưng tôi nhớ cụ thể loại trừ bảy cặp, mười ba trẻ mồ côi, danh dự và đã thực hiện các cuộc gọi để không vượt qua thử thách cho những người mới tham gia trò chơi. Tôi nghĩ rằng tôi đã cân nhắc thực hiện một thử thách shanten sau đó nhưng cuối cùng không bao giờ thực hiện - nếu bạn muốn đăng một bài tôi nghĩ rằng đó sẽ là một thử thách tốt.
Sp3000

Câu trả lời:


4

Con trăn 312 281 byte

def W(S):H=lambda C,n=0,t=1:sum([m<C[0]and H([c-s for c in C][:l]+C[l:],n+1,u)for m,s,l,u in(2,3,1,t),(t,2,1,4),(4-5*all(C[:3]),1,3,t)])|H(C[1:],n,t)if C[2:]and max(C)<5else n>4;T=[i+s for s in"mps"for i in"12345678900"];return" ".join(t for t in T if("1"<t)*H(map((S+t).count,T)))

W lấy một chuỗi làm đầu vào và trả về một chuỗi làm đầu ra.

Số lượng gạch nhỏ (27) làm cho nó đủ nhanh để kiểm tra nếu mỗi trong số chúng hoàn thành bàn tay. Vấn đề trở thành để kiểm tra nếu một bàn tay là hợp lệ. Hàm này sử dụng thuật toán quay lui đơn giản, xem xét tất cả các lựa chọn có thể có của các bộ và kiểm tra nếu bất kỳ trong số chúng thêm vào một bàn tay hoàn chỉnh.

Các bàn tay được biểu diễn dưới dạng biểu đồ ô vuông, tức là một danh sách đếm gạch (đối với tất cả các ô, không chỉ các ô có trong tay.) Điều này giúp dễ dàng kiểm tra xem chúng ta có một số lượng nhất định của một ô nhất định không và nếu chúng ta có một chuỗi các gạch liền kề (đệm giữa các gạch của các bộ quần áo khác nhau ngăn chặn các chuỗi đa bộ đồ.)


À, bạn đánh tôi: P Dù sao đi nữa, có vẻ như bạn có thể sử dụng mapở một vài nơi, như:H(map((S+t).count,T))
FryAmTheEggman

@FryAmTheEggman đã bỏ lỡ điều đó. Cảm ơn!
Ell

@ Sp3000 Đó là Python 2. Thật lạ; nó hoạt động tốt với tôi trên 2.7.8.
Ell

@Ell Hoạt động trong 2.7.8 - 2.7.5 không giống như 5else: P
Sp3000

2

JavaScript (E6) 306

F=h=>(
  R=(a,p,n=1)=>(a=[...a]).splice(p,n)&&a,
  K=(t,d=3)=>
    !t[0]
    |t.some(
      (v,p)=>
        v==t[p+1]&v==t[p+d-1]&&
        K(R(t,p,d))
      ||
        ~((r=t.indexOf((x=-~v[0])+v[1]))|(s=t.indexOf(-~x+v[1])))&&
        K(R(R(R(t,s),r),p))
    ),
  o=[],
  [for(s of'mps')for(i of'123456789')h.replace(t=i+s,s,'g')[34]
  &&K([t,...h.split(' ')].sort(),2)&&o.push(t)
  ],o
)

Giải thích

F=hand=>(
  Remove=(a,p,n=1)=>                // function to remove 1 or more element from an array, returning a new shorter array
    ((a=[...a]).splice(p,n), a),    // using array.splice on a new created array 

  Check=(ckHand, dim)=>  // recursive function to check hand. 
                         // removing pairs (at iteration 0) or sequence of three, if at last the hand remain empty then success
                         // parameter dim is 2 or 3 indicating how many equal elements are to be removed
    !ckHand[0]           // check if empty (element 0 does not exist)
    |ckHand.some(        // else traverse all array checking what can be removed
      (value, position)=> 
        value == ckHand[position + 1] 
        & value == ckHand[position + dim-1] &&   // look for 3 (or 2) equal elements
        Check(Remove(ckHand, position, dim), 3)   // if found, then remove elements and check again
      ||
        ~((r = ckHand.indexOf((x=-~value[0]) + value[1]))     // value[0] is number, value[1] is suit 
        |(s = ckHand.indexOf(-~x + value[1]))) &&              // look for an ascending sequence in following elements (the array is sorted)
        Check(Remove(Remove(Remove(ckHand, s), r), position),3) // if sequence found, remove elements and check again
    ),
  output=[], // start with an empty solution list
  [ // using array comprehension to implement a double loop
    for(s of'mps')        // loop for all suits
    for(i of'123456789')  // loop for all numbers
    (
       tile=i+s, // current tile 
       (hand.replace(tile,' ','g').length > 34)      // if tile is present 4 times in hand, the replaced length is 38-4 == 34
       && (                                       // else proceed with check
         ckHand = hand.split(' '), 
         ckHand.push(tile),    // in ckHand (as an array) the hand to be checked, that is base hand + current tile
         ckHand.sort(),        // sorting the array simplfy the checks
         Check(ckHand, 2)      // start checks looking for a pair
       )
       && 
         output.push(tile)   // if check ok, add tile to the solution list
    )   
  ],
  output // last expression in list is the function return value 
)

Thử nghiệm trong bảng điều khiển FireFox / FireBug

;["1m 1m 1m 4s 4s 4s 7p 7p 7p 3m 3m 3m 9s", "1m 1m 1m 3m 3m 3m 5m 5m 5m 2s 3s 7p 8p",
 "1m 2m 2m 3m 3m 3m 3m 4m 1s 1s 9s 9s 9s", "1m 1m 1m 2m 3m 4m 5m 6m 7m 8m 9m 9m 9m",
 "1m 1m 1m 5p 2m 3m 5p 7s 8s 5p 9s 9s 9s"].forEach(s=>console.log(s+' => '+F(s)))

Đầu ra

1m 1m 1m 4s 4s 4s 7p 7p 7p 3m 3m 3m 9s => 9s
1m 1m 1m 3m 3m 3m 5m 5m 5m 2s 3s 7p 8p =>
1m 2m 2m 3m 3m 3m 3m 4m 1s 1s 9s 9s 9s => 1s
1m 1m 1m 2m 3m 4m 5m 6m 7m 8m 9m 9m 9m => 1m,2m,3m,4m,5m,6m,7m,8m,9m
1m 1m 1m 5p 2m 3m 5p 7s 8s 5p 9s 9s 9s => 1m,4m,6s,9s
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.