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