당신은 무엇을 기다리고 있습니까? (마작 해결사)


14

채팅 토론에서 @ MartinBüttner에게 감사드립니다.

마작 은 아시아에서 매우 인기있는 타일 게임입니다. 일반적으로 4 명의 플레이어와 함께 플레이하며 게임의 목표는 타일을 사용하여 먼저 유효한 핸드를 완성하는 것입니다. 이 과제를 위해 PPCG 마작이라는 간단한 버전의 게임을 고려할 것입니다.

- PPCG 마작에서, 세 가지 복이있다 m, p그리고 s- 그리고 타일에서 번호가 19. 이 각 타일의 네 개의 사본을 정확하게, 그리고 타일의 소송 다음의 번호 (예를 붙이고 3m, 9s).

완성 된 PPCG 마작 핸드는 총 14 개의 타일에 대해 3 세트와 4 세트로 구성됩니다.

세 세트는 다음 중 하나 일 수 있습니다.

  • 동일한 타일 중 3 개 (예 : 4s 4s 4s, 아님 4m 4p 4s) 또는
  • 동일한 소송에서 3 개의 연속 타일 시퀀스 (예 : 1s 2s 3s또는 6p 7p 8p그렇지 않은 3s 4m 5m또는 3p 5p 7p) 시퀀스는 랩핑되지 않습니다 (따라서 9m 1m 2m유효하지 않습니다).

한 쌍은 단순히 두 개의 동일한 타일입니다 (예 :) 5s 5s.

도전

프로그램은 공백으로 구분 된 13 개의 타일을 받게되며 각 타일은 4 번 이상 나타나지 않습니다. 전체 프로그램이나 문자열을받는 함수를 작성할 수 있습니다.

당신의 임무는 손에 추가 될 때 완성 된 PPCG 마작 핸드를 형성 할 수있는 가능한 모든 14 번째 타일 ( "대기")을 찾는 것입니다. 출력 된 타일은 공백으로 분리해야하지만 순서는 상관 없습니다. 선행 또는 후행 공백이 허용됩니다.

프로그램은 1 분을 넘지 않는 적당한 시간 내에 실행되어야합니다.

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 

첫 번째 예에서는 1m 4s 7p 3m모두 기존의 삼중 항 9s을 형성 하여 고독한 쌍을 형성합니다.

두 번째 예에서 2s 3s7p 8p은 시퀀스 만 형성 할 수 있으며 나머지 타일은 트리플렛 만 형성 할 수 있습니다. 따라서 쌍을 형성 할 수 없으며 출력이 없습니다.

세 번째 예에서 손은로 나뉩니다 1m2m3m 2m3m4m 3m3m 1s1s 9s9s9s. 일반적으로 이것은 대기 시간 3m 1s이지만 4 3m개가 모두 사용되었으므로 사용 가능한 유일한 대기 시간은 1s입니다.

네 번째 예에서는 모든 m타일이 손을 완성합니다. 예를 들어, 예를 들어 완성 된 핸드를 1m가질 수 있습니다 1m1m1m 1m2m3m 4m5m6m 7m8m9m 9m9m.

나머지 네 번째 예제와 다섯 번째 예제를 해결해보십시오. :)

채점

이것은 이므로 가장 적은 바이트의 솔루션이 이깁니다. 표준 허점이 적용됩니다.


9
서양인들이 "Mahjong"이라는 단어를들을 때마다 생각하는 타일을 사용하는 (IMO 성가신) 솔리테어보다는 실제로 Mahjong을 수행해 주셔서 감사합니다.
Justin 저스틴

@Quincunx 재미있는 사실 :이 도전은 마작 솔리테어의 ASCII 표현으로 도전하고 싶었 기 때문에 발생했습니다. 나는 그것을 "마작 솔리테어"라고 불렀습니다. ;)
Martin Ender

2
@Quincunx : 나는 그것이 그들의 잘못이라고 생각하지 않습니다. "Mahjong solitaire"게임을 "Mahjong"이라고 부르는 것은 게임 개발자의 잘못입니다.
Joe Z.

7 쌍은 어때요? 고아 13 명? 당신은 명예로 훨씬 더 복잡한 것을 할 수 있습니다 :) 당신이 손의 shanten ( 텐 페이 를 얻기 전에 필요한 최소한의 타일 수) 을 계산하도록 요청하는 codegolf를 만들면 그것이 목적이 없다고 생각 합니까?
V. Courtois

@VCourtois 오랜 시간이 지났지 만 게임에 익숙하지 않은 사람들을 위해 복잡하지 않도록 7 쌍, 13 명의 고아, 영예를 제외하고 이미 전화를 걸었습니다. 나는 나중에 그 후에 shanten 도전을하는 것을 고려했지만 결국 결코하지 않았다고 생각합니다.
Sp3000

답변:


4

파이썬, 312 281 바이트

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 문자열을 입력으로 사용하고 문자열을 출력으로 반환합니다.

적은 수의 타일 (27)은 각 타일이 손을 완성하는지 테스트하기에 충분히 빠릅니다. 문제는 손이 유효한지 확인하게됩니다. 이 기능은 간단한 역 추적 알고리즘을 사용하여 가능한 모든 세트 선택을 고려하고 그 중 하나가 완전한 핸드에 추가되는지 확인합니다.

손은 타일 히스토그램, 즉 타일 수 목록 (손에있는 타일뿐만 아니라 모든 타일에 대한 목록)으로 표시됩니다. 이렇게하면 특정 타일의 개수가 있는지 확인하고 특정 타일이 있는지 쉽게 확인할 수 있습니다 인접한 타일의 시퀀스를 갖습니다 (서로 다른 슈트 사이의 패딩은 멀티 슈트 시퀀스를 방지합니다).


아, 당신은 나를 이겼다 : P 어쨌든, 그것은 당신이 다음과 같은 map몇 곳에서 사용할 수있는 것 같습니다 :H(map((S+t).count,T))
FryAmTheEggman

@FryAmTheEggman보고 싶었습니다. 감사!
Ell

@ Sp3000 Python 2입니다. 이상합니다. 2.7.8에서 나에게 잘 작동합니다.
Ell

@Ell Works 2.7.8-2.7.5는 5else를 좋아하지 않았습니다 : P
Sp3000

2

자바 스크립트 (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
)

설명

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 
)

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

산출

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.