LoginSignup
0
0

More than 5 years have passed since last update.

第10回オフラインリアルタイムどう書くの参考問題をNemerleで

Last updated at Posted at 2017-09-06

第10回オフラインリアルタイムどう書くの参考問題

第10回オフラインリアルタイムどう書くの参考問題をF#で

以前に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)
            | _        => ""
        }
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0