Re[5]: Статья "Введение в Nemerle" - по критикуйте
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 03.10.09 15:04
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, так он создан для быстрого нахождения фичь. Ты же взял совсем другой материал.

VD>В прочем, было бы ОЧЕНЬ интересно узнать в чем были проблемы, как ты их решил и саму задачу.

Задача примерно такая: генерация таблиц для того, чтобы выполнять оценивание руки из пяти карт в покере. Схема примерно такая: у карты есть номинал (тез, шестерка) и масть. Каждому номиналу карты сопоставляется простое число. Таким образом зная произведение этих простых числе в карточной комбинации, а также флеш это или нет, мы можем однозначно определить силу руки. Естественно, что вначале нам надо силу всех этих рук посчитать. В общем стоит задача построения примерно такого


  class Info
  {
    public int Product;
    public int FlushRank;
    public int NormalRank;
  }

  static public Dictionary<int, Info> Data;


объекта, который пригодится для построения талицы. Ключ это произведение простых чисел, соответствующих номиналу карт. Flush это сила комбинации при условии, что все карты одной масти. Normal это сила комбинации при условии, что не все карты одной масти.

Также я решил карту представлять списками, хоть это не совсем удобно в C#, но хотелось поучиться. Ну и в общем за несколько часов наступания на грабли родилось нечто такое, что считает только StraightFlush. После чего я устал и сделал большой перерыв.

using System.Console;
using System.Collections.Generic;

class Info
{
  public mutable Product: int;
  public mutable FlushValue: int;
  public mutable NormalValue: int;
}

def GlobalTable = Dictionary();

def Primary = array[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41];

mutable rank = 1;

def AddFlushHand(hand)
{
  mutable Product = 1;
  foreach(card in hand)
    Product *= Primary[card];

  mutable info = Info();
  info.Product = Product;
  info.FlushValue = rank;
  info.NormalValue = -1;

  WriteLine(hand);
  WriteLine(info.Product);
  WriteLine();
  GlobalTable.Add(Product, info);
  rank = rank + 1;
}

mutable StraightFlush = [8, 9, 10, 11, 12];

AddFlushHand(StraightFlush);

foreach(card in [7, 6, 5, 4, 3, 2, 1, 0])
{
  StraightFlush = StraightFlush.Remove(card + 5);
  StraightFlush = StraightFlush + [card];
  AddFlushHand(StraightFlush);
}

AddFlushHand([3, 2, 1, 0, 12]);


WriteLine("Hello, World: " + GlobalTable.Count.ToString());


Для сравнения исходник на C#, который пишется без особого напряга за половину часа с отладкой:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PokerTable
{
  class Info
  {
    public int Product;
    public int FlushRank;
    public int NormalRank;
  }

  class Program
  {
    static readonly int[] Primary = new int[] { 41, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 };

    static public int rank = 1;
    static public Dictionary<int, Info> Data = new Dictionary<int, Info>();
    
    static public void AddFlush(int Product)
    {
      Info info = new Info();
      info.Product = Product;
      info.FlushRank = rank;
      info.NormalRank = -1;
      Data.Add(Product, info);
      rank = rank + 1;
    }

    static public void AddNormal(int Product)
    {
      Info info;
      if (!Data.TryGetValue(Product, out info))
      {
        info = new Info();
        info.Product = Product;
        info.FlushRank = -1;
      }
      info.NormalRank = rank;
      rank = rank + 1;
    }

    static public void Straight(bool isFlush)
    {
      int Product = Primary[13] * Primary[12] * Primary[11] * Primary[10] * Primary[9];
      if (isFlush) AddFlush(Product); else AddNormal(Product);
      for (int i = 8; i >= 0; --i)
      {
        Product /= Primary[i + 5];
        Product *= Primary[i];
        if (isFlush) AddFlush(Product); else AddNormal(Product);
      }
    }

    static public void Quads()
    {
      for (int Base = 13; Base >= 1; --Base)
      for (int Kicker = 13; Kicker >= 1; --Kicker)
      {
        if (Base == Kicker) continue;
        int BasePrimary = Primary[Base];
        int KickerPrimary = Primary[Kicker];
        AddNormal(BasePrimary * BasePrimary * BasePrimary * BasePrimary * KickerPrimary);
      }
    }

    static public void FullHouse()
    {
      for (int Base = 13; Base >= 1; --Base)
      for (int Pair = 13; Pair >= 1; --Pair)
      {
        if (Base == Pair) continue;
        int BasePrimary = Primary[Base];
        int PairPrimary = Primary[Pair];
        AddNormal(BasePrimary * BasePrimary * BasePrimary * BasePrimary * PairPrimary);
      }
    }

    static public void Chanse(bool isFlush)
    {
      for (int card1 = 13; card1 >= 1; --card1)
      for (int card2 = card1 - 1; card2 >= 1; --card2)
      for (int card3 = card2 - 1; card3 >= 1; --card3)
      for (int card4 = card3 - 1; card4 >= 1; --card4)
      for (int card5 = card4 - 1; card5 >= 1; --card5)
      {
        if (card1 == 13 && card2 == 4) continue;

        bool isStraight = true  
          && card1 == card2 + 1 
          && card2 == card3 + 1 
          && card3 == card4 + 1 
          && card4 == card5 + 1
        ;
        
        if (!isStraight)
        {
          int Product = Primary[card1] * Primary[card2] * Primary[card3] * Primary[card4] * Primary[card5];
          if (isFlush) AddFlush(Product); else AddNormal(Product);
        }  
          
      }
    }
    
    static public void ThreeCards()
    {
      for (int Base=13; Base >= 1; --Base)
      for (int Kicker1 = 13; Kicker1 >= 1; --Kicker1)
      for (int Kicker2 = Kicker1 - 1; Kicker2 >= 1; --Kicker2)
      {
        if (Base == Kicker1) continue;
        if (Base == Kicker2) continue;
        AddNormal(Primary[Base] * Primary[Base] * Primary[Base] * Primary[Kicker1] * Primary[Kicker2]);
      }
    }

    static public void TwoPair()
    {
      for (int Base1 = 13; Base1 >= 1; --Base1)
      for (int Base2 = Base1 - 1; Base2 >= 1; --Base2)
      for (int Kicker = 13; Kicker >= 1; --Kicker)
      {
        if (Base1 == Kicker) continue;
        if (Base2 == Kicker) continue;
        AddNormal(Primary[Base1] * Primary[Base1] * Primary[Base2] * Primary[Base2] * Primary[Kicker]);
      }
    }

    static public void Pair()
    {
      for (int Base = 13; Base >= 1; --Base)
      for (int Kicker1 = 13; Kicker1 >= 1; --Kicker1)
      for (int Kicker2 = Kicker1 - 1; Kicker2 >= 1; --Kicker2)
      for (int Kicker3 = Kicker2 - 1; Kicker3 >= 1; --Kicker3)
      {
        if (Base == Kicker1) continue;
        if (Base == Kicker2) continue;
        if (Base == Kicker3) continue;
        AddNormal(Primary[Base] * Primary[Base] * Primary[Kicker1] * Primary[Kicker2] * Primary[Kicker3]);
      }
    }
  
    static void Main(string[] args)
    {
      Straight(true);
      Quads();
      FullHouse();
      Chanse(true);
      Straight(false);
      ThreeCards();
      TwoPair();
      Pair();
      Chanse(false);
      System.Console.WriteLine(rank);
    }
  }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.