以前にF#で書いたコードをNemerleに移植した。なので解き方は同じ。ただしテストケース部分は省略した。
using Nemerle.Collections;
using Nemerle.Utility;
using System.Collections.Generic;
using System.Console;
module Program
{
Main() : void
{
WriteLine(Test("Qs9s3dJd10h"));
_ = ReadLine();
}
enum Suit { | Spade | Heart | Diamond | Club }
enum Rank { | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | R10 | RJ | RQ | RK | RA }
type Card = Suit * Rank;
type Hand = list[Card];
DirectProduct[T](xss : list[list[T]]) : list[list[T]]
{
xss.FoldRight([[]], (xs, xss) => xs.Map(y => xss.Map(ys => [y :: ys]).Flatten()).Flatten())
}
CardToNumbers(c : Card) : list[int]
{
def (_, r) = c;
match (r)
{
| R2 => [2]
| R3 => [3]
| R4 => [4]
| R5 => [5]
| R6 => [6]
| R7 => [7]
| R8 => [8]
| R9 => [9]
| R10 => [10]
| RJ => [11]
| RQ => [12]
| RK => [13]
| RA => [1, 14]
}
}
AreSequential(list : list[int]) : bool
{
match (list.Sort(Comparer.Default.Compare))
{
| [] => true
| [_] => true
| x0::x1::_ => if (x0 + 1 == x1) AreSequential(list.Tail) else false
}
}
IsStraight(h : Hand) : bool
{
DirectProduct(h.Map(CardToNumbers)).Exists(AreSequential)
}
IsFlush(h : Hand) : bool
{
def (headNum, _) :: tail = h;
tail.ForAll((num, _) => num == headNum)
}
IsStraightFlush(h : Hand) : bool
{
IsStraight(h) && IsFlush(h)
}
IsRoyal(h : Hand) : bool
{
def list = h.Map(Pair.Second).Sort(Comparer.Default.Compare);
match (list)
{
| [Rank.R10, Rank.RJ, Rank.RQ, Rank.RK, Rank.RA] => true
| _ => false
}
}
IsRoyalFlush(h : Hand) : bool
{
IsRoyal(h) && IsFlush(h)
}
RemoveOne[T](list : list[T]) : list[list[T]]
{
def removeOne(former, acc, list)
{
match (list)
{
| [] => acc.Rev()
| (head : T) :: tail =>
{
def former' = head :: former;
def acc' = former.RevAppend(tail) :: acc;
removeOne(former', acc', tail)
}
}
}
removeOne([], [], list)
}
ForAllExceptOne[T](list : list[T], pred : list[T] -> bool) : bool
{
RemoveOne(list).Exists(pred)
}
IsFourFlush(h : Hand) : bool
{
ForAllExceptOne(h, IsFlush)
}
IsFourStraight(h : Hand) : bool
{
ForAllExceptOne(h, IsStraight)
}
IsFourStraightFlush(h : Hand) : bool
{
ForAllExceptOne(h, IsStraightFlush)
}
Show (h : Hand): string
{
match (h)
{
| _ when IsRoyalFlush(h) => "RF"
| _ when IsStraightFlush(h) => "SF"
| _ when IsFlush(h) => "FL"
| _ when IsStraight(h) => "ST"
| _ when IsFourStraightFlush(h) => "4SF"
| _ when IsFourFlush(h) => "4F"
| _ when IsFourStraight(h) => "4S"
| _ => "-"
}
}
Parse(s : string) : option[Hand]
{
def parseSuit(cs)
{
match (cs)
{
| 's' :: cs' => Some (Suit.Spade, cs')
| 'h' :: cs' => Some (Suit.Heart, cs')
| 'd' :: cs' => Some (Suit.Diamond, cs')
| 'c' :: cs' => Some (Suit.Club, cs')
| _ => None ()
}
}
def parseRank(cs)
{
match (cs)
{
| '2' :: cs' => Some (Rank.R2, cs')
| '3' :: cs' => Some (Rank.R3, cs')
| '4' :: cs' => Some (Rank.R4, cs')
| '5' :: cs' => Some (Rank.R5, cs')
| '6' :: cs' => Some (Rank.R6, cs')
| '7' :: cs' => Some (Rank.R7, cs')
| '8' :: cs' => Some (Rank.R8, cs')
| '9' :: cs' => Some (Rank.R9, cs')
| '1' :: '0' :: cs' => Some (Rank.R10, cs')
| 'J' :: cs' => Some (Rank.RJ, cs')
| 'Q' :: cs' => Some (Rank.RQ, cs')
| 'K' :: cs' => Some (Rank.RK, cs')
| 'A' :: cs' => Some (Rank.RA, cs')
| _ => None ()
}
}
def parseCards(acc, cs)
{
match (cs)
{
| [] => acc.Rev()
| _ => match (parseRank(cs))
{
| Some ((r, cs')) => match (parseSuit(cs'))
{
| Some ((s, cs'')) => parseCards ((s, r) :: acc, cs'')
| _ => []
}
| _ => []
}
}
}
def cards = parseCards([], s.NToList());
match (cards)
{
| [_, _, _, _, _] => Some (cards)
| _ => None ()
}
}
Test(s : string) : string
{
match (Parse(s))
{
| Some (h) => Show (h)
| _ => ""
}
}
}