« Apache 用 mod_auth_fb (Firebird用認証モジュール)新版公開 | Main | Scala で書いた麻雀役判定のプログラムを Haskell で書き直してみた »

Scala で麻雀の役判定の基本処理の部分を書いてみた

半年以上前の話だが、Scala とか勉強するのに数学の課題とかを解く気が個人的に起きないので、麻雀の役判定の基礎部分を Scala で書いてみた。
出先仕事も今月で終わりであとは今の所ないので暇だし、後で自分で見たりするかも?ということであげておく。
関数型プログラミングも含めてこれがほとんど初めて書いた Scala のプログラムなので、それらしいとかまったく不明。
あんまり意味もないことも多少やっていたり。
しかし、関数型言語のプログラムは、昔 ImPP というパイプライン処理プロセッサのプログラムや、awk、yacc の定義ファイルを書いてる気分になってくるな。

大雑把には以下のような手順。

  • 計算しやすいように、牌毎の数リストに再構成
  • 対子の候補を全部抽出
  • 各対子を仮定したときに、刻子の候補を全抽出
  • 刻子のすべての組み合わせを仮定したときに、残りが順子に分解できるか処理
  • 余りがなければ成功、余ったら失敗
  • 成功例のみを集積
ちなみに、槓子はプレイ中に意識的に分離しているはずなので、事前に抽出済みな前提。

yakuhantei.scala ファイル
// 牌の種別を表す列挙型のようなもの
class paiGroup(val code: Int) {
  // 比較関数実装
  def <(arg: paiGroup): Boolean = code < arg.code
  // 順子になれる牌か判定
  def isJyun: Boolean = this < paiGroup.tu
}

object paiGroup {
  case object sz extends paiGroup(1)
  case object pz extends paiGroup(2)
  case object wz extends paiGroup(3)
  case object tu extends paiGroup(4)

  // 整数から生成。異常時はマッチング例外になる
  def fromInt(n: Int) = n match {
    case 1 => this.sz
    case 2 => this.pz
    case 3 => this.wz
    case 4 => this.tu
  }
}

// 牌1枚を表すケースクラス (idx = 1~9)
case class pai(grp: paiGroup, idx: Int) {
  // 基本コンストラクタ
  if (idx <= 0 || idx > 9) throw new Exception("pai.idx is error value ! (" + idx.toString + ")")

  // 拡張コンストラクタ
  def this(n: Int) = this(paiGroup.fromInt(n / 10), n % 10)
  def this(n: String) = this(n.toInt)

  // 比較関数実装
  def <(arg: pai): Boolean = grp < arg.grp || (grp == arg.grp && idx < arg.idx)
  // 順子になれる牌か判定
  def isJyun: Boolean = grp.isJyun

  override def toString = grp.toString.substring(0, 1) + idx.toString
}

// 役評価処理
object yakuhyouka {
  // 牌のリストの型
  type PL = List[pai] // 牌リスト。手牌や、対子、刻子、順子一つなど
  type TSU = List[pai] // 分類後の牌セット。対子、刻子、順子一つなど
  type GRPTSU = List[TSU] // 1つの分析結果セット。牌リストの集合

  // ソートしたものを取得
  def sortList(src: PL) = src.sortWith { _ < _ }

  // 対子になる牌種すべてを取得 (同じ牌は折りたたまれる)
  def toiList(src: PL) = src.filter(n => src.count(n == _) >= 2).distinct

  // 刻子になる牌種すべてを取得
  def kouList(src: PL) = src.filter(n => src.count(n == _) >= 3).distinct

  // 対子刻子を抜いた牌リストを生成
  // 意味はまったくないが、ためしに関数リテラル+クロージャーで書いてみた
  val partitionRemove = (src: PL) => (p: pai) => {
    val (lmy, lother) = src.partition(p == _)
    (n: Int) => if (lmy.size <= n) lother else sortList(lother ++ lmy.drop(n)): PL
  }

  def removeToi(src: PL)(p: pai) = partitionRemove(src)(p)(2)
  def removeKou(src: PL)(p: pai) = partitionRemove(src)(p)(3)

  // 刻子/槓子のリストを全削除
  def pListRemove(F: (PL) => (pai) => PL, src: PL, klist: PL): PL = if (klist.isEmpty) src else pListRemove(F, F(src)(klist.head), klist.drop(1))

  // 牌リストを種類ごとに分解する
  def grpGrouping(src: PL) = src.groupBy(_.grp)

  // 牌リストをインデックスごとに分解する
  def idxGrouping(src: PL) = src.groupBy(_.idx)

  // セット(2~3枚)を1つ作成
  def makeToi(p: pai): TSU = List.fill(2)(p)
  def makeKou(p: pai): TSU = List.fill(3)(p)
  def makeJun(p: pai): TSU = List(p, pai(p.grp, p.idx + 1), pai(p.grp, p.idx + 2))

  // 牌リストをセットリストに変換
  def makeKouList(pl: PL): GRPTSU = pl.map { makeKou }

  // 七対子を生成
  def makeChitoi(pl: PL): GRPTSU = pl.map { makeToi }

  // 数値のみで順子に分解。全分解出来なければ None。牌の種類は選り抜いてあること
  def junDivide(s: List[(Int, Int)])(j: List[Int]): Option[List[Int]] = {
    def f(p0: (Int, Int), p1: (Int, Int), p2: (Int, Int), oth: Seq[(Int, Int)]) = {
      // 分離したものを除いたリストを再生成 (残数0は含まれないし除去される)
      val c0 = p0._1
      val cl = List(p0, p1, p2).collect { case (x, n) if (n > 1 && (x == c0 || x == c0 + 1 || x == c0 + 2)) => (x, n - 1) } ++ oth
      // さらに分解
      junDivide(cl)(j :+ c0)
    }
    s match {
      case List() => Some(j)
      case List(p0, p1, p2, other @ _*) if p1._1 == p0._1 + 1 && p2._1 == p0._1 + 2 => f(p0, p1, p2, other)
      case _ => None
    }
  }

  // 牌リストを順子として分類する(字牌は事前に抜いてあること)
  def junList(src: PL): Option[GRPTSU] = {
    // 牌種ごとにグループ分け
    val typl = grpGrouping(src)
    // 牌種ごとにインデックスごとの牌数リストに分解後、順序判定のためにソート
    val igmap = typl.mapValues(n => idxGrouping(n).map { m => (m._1, m._2.length) }.toList.sortWith { _._1 < _._1 })
    // 牌種ごとに順子への分解
    val resultmap = igmap.mapValues(junDivide(_)(List[Int]()))
    // 与えられた全てを順子に分解できたか判定し、分解出来ていた場合のみ結果を生成
    if (resultmap.values.exists(_.isEmpty)) None else Option(resultmap.transform { (grp, v) => v.get.map { idx => makeJun(pai(grp, idx)) } }.values.toList.flatten)
  }

  // 全組み合わせ生成関数
  def mkFullList(l: PL)(res: List[PL])(idx: Int): List[PL] = if (idx == 0) res else mkFullList(l)(res ++ l.combinations(idx))(idx - 1)

  // 刻子の全組み合わせケースで評価実行(槓子は分離されてるはずなので、事前抜出済みな前提)
  def evalSetKou(src: PL)(t: pai): List[GRPTSU] = {
    // 字牌(tsrc)とそれ以外(jsrc)に分離
    val (jsrc, tsrc) = src.partition(_.isJyun)
    // 字牌は刻子以外にはならないので、刻子以外が残ったらすでに評価できないこと確定
    val tkl = kouList(tsrc)
    if (tkl.length * 3 != tsrc.length) List()
    else {
      // 対子と字牌の刻子は決定物なのであらかじめ生成しておく
      val tlresult = List(makeToi(t)) ++ makeKouList(tkl)
      // 字牌のみの場合は確定
      if (jsrc.length == 0) List(tlresult)
      else {
        // 刻子のリストを取得
        val jkl = kouList(jsrc)
        // 全チェックパターン生成 (先頭は刻子として評価しないパターン)し順子割り当て
        mkFullList(jkl)(List(List()))(jkl.length).map {
          n =>
            {
              // 刻子を省いた残りを順子に分解
              val yl = junList(pListRemove(removeKou, jsrc, n))
              // 分解出来たらここでの評価は成功とする
              if (yl.isEmpty) List() else tlresult ++ makeKouList(n) ++ yl.get
            }
        }.filter { !_.isEmpty }.toList
      }
    }
  }

  // 役基本評価実行
  def evaluate(src: PL): List[GRPTSU] = {
    // 対子候補のリストを生成
    val toilist = toiList(src)
    // 七対子は特殊なのでここで処理
    val t7: List[GRPTSU] = if (toilist.length == 7) List(makeChitoi(toilist)) else List()
    // 対子を仮定した評価を実行 (+七対子の処理)
    (t7 ++ toilist.map { t => evalSetKou(removeToi(src)(t))(t) }.flatten).filter { !_.isEmpty }
  }

}

// テスト用のメインオブジェクト
object testmain {

  def input: Option[String] = {
    val in = readLine
    if (in.length == 0) None else Some(in)
  }

  def main(args: Array[String]) = {
    println("START!");
    println("paiid = type * 10 + index");
    var s: Option[String] = Some("");
    while (s.isDefined) {
      print("Input pailist :");
      s = input
      if (s.isDefined) {
        val sp = s.get.trim.split(' ').toList.map { new pai(_) }
        val start = System.currentTimeMillis
        val result = yakuhyouka.evaluate(sp).toList
        println ((System.currentTimeMillis - start) + " msec")
        // 結果表示
        result.foreach {
          one =>
            {
              one.foreach {
                k =>
                  {
                    print("[")
                    k.foreach {
                      print
                    }
                    print("]")
                  }
              }
              print("\n")
            }
        }
      }
    }
    println("END!");
  }
}
コンパイル (sjisでファイルを書いたのでエンコードを指定してる)
C:\scala\yakuhantei>scalac yakuhantei.scala -encoding sjis
実行例 (ちなみに、41~ は字牌)
C:\scala\yakuhantei>scala testmain
START!
paiid = type * 10 + index
Input pailist :11 11 12 12 13 13 14 14 15 15 16 16 17 17
16 msec
[s1s1][s2s2][s3s3][s4s4][s5s5][s6s6][s7s7]
[s1s1][s2s3s4][s2s3s4][s5s6s7][s5s6s7]
[s4s4][s1s2s3][s1s2s3][s5s6s7][s5s6s7]
[s7s7][s1s2s3][s1s2s3][s4s5s6][s4s5s6]
Input pailist :11 11 11 12 12 12 13 13 13 14 14 14 15 15
63 msec
[s2s2][s1s1s1][s2s3s4][s3s4s5][s3s4s5]
[s5s5][s1s1s1][s2s2s2][s3s3s3][s4s4s4]
[s5s5][s1s1s1][s2s3s4][s2s3s4][s2s3s4]
[s5s5][s4s4s4][s1s2s3][s1s2s3][s1s2s3]
Input pailist :11 12 13 12 13 14 41 41 41 42 42
15 msec
[t2t2][t1t1t1][s1s2s3][s2s3s4]
Input pailist :41 42 43 44 44
0 msec
Input pailist :
END!

|

« Apache 用 mod_auth_fb (Firebird用認証モジュール)新版公開 | Main | Scala で書いた麻雀役判定のプログラムを Haskell で書き直してみた »

プログラム」カテゴリの記事

Comments

ugg 激安 楽天 一度私は取得1 つのデザイナー ハンドバッグなる夢中します。多くポケット前面と背面、マイナーな個人的なアイテムの収納に便利なスナップ閉鎖との完全なを飾っています。 ugg 手入れ

Posted by: ugg 激安 楽天 | 2013.11.24 05:05 AM

AnytҺing about аny ߋf іt story resemble ɑnyone? Haѵе you ever imagined օr aгe yoս cߋnsidering јust ɦow can ɑ tҺin person bulk սp? Well, tto obtaіn the ball rolling let's start ԝith the fundamentals. To ensure tҺat a thin guy tto ccreate muscles, уou will nded seѵeral pointѕ. o Proper diet o Correct education ӏ steer cleɑr οf muscle towels for developing muscle - (keеp reading to learn whʏ.) Thе human body ոeeds the energy that foopd gіves as a way to gain weight anɗ continue to perform at аn optimum level. Νevertheless The gass eeds to be premium fօr the equipment to achieve tҺat function. Оtherwise it woulkd be thhe identical tօ trying tο ցet yoսr caг bʏ filling սp thee reservoir աith pudding. Ѕure it miught twste scrumptious but whst range ϲaո it run սsing tɦat type of fuel? Thіnk complex carbs. Α key issue foor ɑ skinnyy guy tto constrct muscle volume, undeniably іs proper education. Ύou've to elevate tɦе proper level оff times applying tҺe proper form constantly in ߋrder to the proper quantity оf weight tto geet benefits. Trained іn this way, makes mee conѕider throwing іn a locked door. Ƴou'll neеd to apply the right force annd apрropriate type ffor ɑ specific quantity οf ries allowing үou to actuallү force the entrancewaay oρen. (ІЕ: Ԍetting effects.) Ƅеst lean muscle supplement Thhe 3rd product; avoid, toss, throw аway, walk away oor bettеr yet гun away from muscle magazines ɑոd anyone աho is attempting to gіve training about building muscle ѡhen they never emerged froom tthe spot ƅy աhich ʏou arе comig freom to you. In ɑ nutshell, publications arе simply ttrying tߋ sell you products, (count the ոumber of webpages tɦat аre basically advertisements іn almost аny among those mags, you'd be amazed!), and many if nott еach of tɦe he-guys raising those huge weights weгe alгeady born աith tɦat genetic ability and probably sed some type of steroid to assist hiis ѡork...ɑnԁ appearance which cahses some sigոificant bad issues. Вesides, еxactly whazt dߋes he understand аbout yoou and your genetics? An improved bet іs to learn fгom a thin gentleman who haѕ understood muscle-building success. ңe's the օne wwho knοws the trruth abiut ɦow to build muscle accoгding to hiѕ orr Һer own persona quest.

Posted by: best lean muscle supplement | 2014.03.28 09:20 PM

Wow, amazing blog format! How long have you been running a blog for? you made running a blog look easy. The full glance of your site is fantastic, let alone the content!

Posted by: minecraft games | 2015.09.09 02:35 PM

[url=http://www.funcipro-virtual.org/gallery/liuy.php?page=23-Levitra-20-Prix,Acheter-Levitra-10-Mg,Kamagra-Oral-Jelly-Suisse]Levitra 20 Prix[/url]
Give up smoking to quit heavy snoring. Once you inhale cigarettes light up to your lungs, irritants are designed that affect your air passage and nose membranes. The producing swelling brings about your tonsils to thin and plays a role in your loud snoring. Do not smoke cigarettes before going to bed, or much better have up together.
[url=http://www.laferiaamericana.com/css/defines.asp?page=47-Cialis-Farmacia-Online-Cialis-Originale-Miglior-Prezzo-Cialis-Prezzo-In-Farmacia-2016]Cialis Farmacia Online[/url]
Try lower-levels laserlight therapies. After a number of classes, this type of therapy can lead to labeled improvement in back pain. The therapies should go right to the deepest mobile levels, reducing constant back discomfort in ways that is quick and efficient. Ask your medical professional if laser treatment method is wonderful for you.
[url=http://www.anppharma.in/themes/6/images.asp?division=126]Cialis Shop Schweiz[/url]
Look at the fine print for all the vouchers that you employ. You may not should be humiliated in range while you are seeking to use vouchers. An easy read will help you find out if you have anything at all you should consider when you might buy anything having a voucher.
[url=http://www.claesdirk.be/images/cache.asp?list=29-Cialis-5-Mg-Opiniones-Kamagra-Gel-Oral-Generico-Levitra-Brasil]Cialis 5 Mg Opiniones[/url]

Posted by: Eugenewem | 2018.03.22 06:03 PM

[url=http://www.funcipro-virtual.org/gallery/liuy.php?page=23-Levitra-20-Prix,Acheter-Levitra-10-Mg,Kamagra-Oral-Jelly-Suisse]Levitra 20 Prix[/url]
Give up smoking to quit heavy snoring. Once you inhale cigarettes light up to your lungs, irritants are designed that affect your air passage and nose membranes. The producing swelling brings about your tonsils to thin and plays a role in your loud snoring. Do not smoke cigarettes before going to bed, or much better have up together.
[url=http://www.laferiaamericana.com/css/defines.asp?page=47-Cialis-Farmacia-Online-Cialis-Originale-Miglior-Prezzo-Cialis-Prezzo-In-Farmacia-2016]Cialis Farmacia Online[/url]
Try lower-levels laserlight therapies. After a number of classes, this type of therapy can lead to labeled improvement in back pain. The therapies should go right to the deepest mobile levels, reducing constant back discomfort in ways that is quick and efficient. Ask your

Posted by: Eugenewem | 2018.03.22 06:04 PM

[url=http://www.parakco.com/footer/button.php?put=Clomid-Pills-Methandienone-China-Oxymetholone-Manufacturer-391/]Clomid Pills[/url]
In case you are new to making use of blush, use this way of implementing this simple booster. Produce a huge, absurd grin inside the mirror. The apples your cheeks make with this concept are in which the initial swipe of blush need to terrain. Use the cheekbone to steer the rest of your swipe. Using this method, you will understand your blush is correctly used on the face design!
[url=http://www.atlasmaden.com/language/zare.php?s=97-Boldenone-Cypionate-Reviews,Nandrolone-New-Zealand,Testosterone-Phenylpropionate-Vs-Propionate]Boldenone Cypionate Reviews[/url]
If you realise your self very thinking about expensive jewelry or if you are searching to buy or sell one of your products, take time to look into the distinct manufacturers, varieties of rocks and precious metals, value of parts and also the very best sites in which to buy or sell things so that you will are equipped and knowledgeable.
[url=http://www.beachbreakbliss.com/wp-admin/page.php?we=708-Methenolone-Enanthate-Steroidology,Clomiphene-Citrate-Australia,Methandienone-Wholesale.html]Methenolone Enanthate Steroidology[/url]
When you are getting a liposuction surgery, or perhaps a comparable procedure, question your surgeon when there is anything you could do once the functioning, to keep your body weight down. You will likely have to obtain some exercise every single day. Implement a balanced diet to the outcomes of your surgical treatment to previous.
[url=http://www.atlantiquegites.com/old/list.php?id=335-China-Steroid-Laws,Anabolic-Steroid-Names,Testosterone-Injections-Ireland]China Steroid Laws[/url]

Posted by: Curtisgide | 2018.04.19 11:58 AM

[url=http://www.parakco.com/footer/button.php?put=Clomid-Pills-Methandienone-China-Oxymetholone-Manufacturer-391/]Clomid Pills[/url]
In case you are new to making use of blush, use this way of implementing this simple booster. Produce a huge, absurd grin inside the mirror. The apples your cheeks make with this concept are in which the initial swipe of blush need to terrain. Use the cheekbone to steer the rest of your swipe. Using this method, you will understand your blush is correctly used on the face design!
[url=http://www.atlasmaden.com/language/zare.php?s=97-Boldenone-Cypionate-Reviews,Nandrolone-New-Zealand,Testosterone-Phenylpropionate-Vs-Propionate]Boldenone Cypionate Reviews[/url]
If you realise your self very thinking about expensive jewelry or if you are searching to buy or sell one of your products, take time to look into the distinct manufacturers, varieties of rocks and precious metals, value of parts and also the very best sites in which to buy or sell things so that you will are equipped and knowledgeable.
[url=http://www.beachbreakbliss.com/wp-admin/page.php?we=708-Methenolone-Enanthate-Steroidology,Clomiphene-Citrate-Australia,Methandienone-Wholesale.html]Methenolone Enanthate Steroidology[/url]
When you are getting a liposuction surgery, or perhaps a comparable procedure, question your surgeon when there is anything you could do once the functioning, to keep your body weight down. You will likely have to obtain some exercise every single day. Implement a balanced diet to the outcomes of your surgical treatment to previous.
[url=http://www.atlantiquegites.com/old/list.php?id=335-China-Steroid-Laws,Anabolic-Steroid-Names,Testosterone-Injections-Ireland]China Steroid Laws[/url]

Posted by: Curtisgide | 2018.04.19 11:59 AM

[url=http://www.parakco.com/footer/button.php?put=Clomid-Pills-Methandienone-China-Oxymetholone-Manufacturer-391/]Clomid Pills[/url]
In case you are new to making use of blush, use this way of implementing this simple booster. Produce a huge, absurd grin inside the mirror. The apples your cheeks make with this concept are in which the initial swipe of blush need to terrain. Use the cheekbone to steer the rest of your swipe. Using this method, you will understand your blush is correctly used on the face design!
[url=http://www.atlasmaden.com/language/zare.php?s=97-Boldenone-Cypionate-Reviews,Nandrolone-New-Zealand,Testosterone-Phenylpropionate-Vs-Propionate]Boldenone Cypionate Reviews[/url]
If you realise your self very thinking about expensive jewelry or if you are searching to buy or sell one of your products, take time to look into the distinct manufacturers, varieties of rocks and precious metals, value of parts and also the very best sites in which to buy or sell things so that you will are equipped and knowledgeable.
[url=http://www.beachbreakbliss.com/wp-admin/page.php?we=708-Methenolone-Enanthate-Steroidology,Clomiphene-Citrate-Australia,Methandienone-Wholesale.html]Methenolone Enanthate Steroidology[/url]
When you are getting a liposuction surgery, or perhaps a comparable procedure, question your surgeon when there is anything you could do once the functioning, to keep your body weight down. You will likely have to obtain some exercise every single day. Implement a balanced diet to the outcomes of your surgical treatment to previous.
[url=http://www.atlantiquegites.com/old/list.php?id=335-China-Steroid-Laws,Anabolic-Steroid-Names,Testosterone-Injections-Ireland]China Steroid Laws[/url]

Posted by: Curtisgide | 2018.04.19 12:00 PM

Posted by: PrestonDiurl | 2018.04.26 11:29 AM

Tune in for some of the most rated and most needed sex movies online by simply surfing [url=https://www.pornmd.pro]www.pornmd.pro[/url], the number one place where you can see any type of free porn videos your mind desires in seconds. The horny porn stars, the finest milfs and many more, all available to rock your sexual imagination with mind blowing xxx sex videos. Only most rated adult content in HD image and with the best options you can get, all for free at [url=https://www.pornmd.pro]www.pornmd.pro[/url], the only place to finalize your dreams in proper modes.

Posted by: Michaelevism | 2018.04.26 04:33 PM

Tune in for some of the most rated and most needed sex movies online by simply surfing [url=https://www.pornmd.pro]www.pornmd.pro[/url], the number one place where you can see any type of free porn videos your mind desires in seconds. The horny porn stars, the finest milfs and many more, all available to rock your sexual imagination with mind blowing xxx sex videos. Only most rated adult content in HD image and with the best options you can get, all for free at [url=https://www.pornmd.pro]www.pornmd.pro[/url], the only place to finalize your dreams in proper modes.

Posted by: Michaelevism | 2018.04.26 04:33 PM

[url=http://www.efrances.org/sitemap/images.php?white=503]Dianabol Methandienone Usa[/url]
Be sure you shell out your bank card transaction by the due date each month. This can help you keep a good credit status with this business as well as assist you to steer clear of higher attention fees. Even when you can't pay back the complete balance monthly, at the very least have the minimum repayment.
[url=http://www.newartfurniture.in/img/filter.php?p_id=938]Oxymetholone Tablets Uk[/url]
Comprehend house owner's insurance policy terminology. As an example, the exact funds importance of a product may be the item's true value much less its devaluation. As an example, should you paid out $500 for one thing a couple of years in the past and features an predicted helpful life of ten years, then you already have exhausted about 20 % of your item's worth, prior to it had been misplaced or destroyed. Since the insurance policies is founded on the actual money value (ACV), it can only pay the staying 80 % from the item's worth.
[url=http://www.livingstoncommunityacupuncture.com/wp-content/cabecalho.php?you=1619-Trenbolone-Powder-Conversion,Nandrolone-Steroids,Trenbolone-Acetate-Powder-Suppliers/]Trenbolone Powder Conversion[/url]
To conclude, nobody desires to pick up your pet dog start barking. There are numerous factors why your dog barks, and it is very important know the real

Posted by: AngelLed | 2018.04.28 04:39 AM

Ищешь доступную и сексуальную девочку на вечер? Заходи на сайт, лучшие проститутки Питера ждут тебя. Выбирай понравившуюся анкету шлюхи СПб и сексуальная девочка окажется возле тебя.
[url=https://prostitutkipitera.pw/]проститутки Питера![/url]

Posted by: GordgGiz | 2018.06.23 11:03 AM

Ищешь доступную и сексуальную девочку на вечер? Заходи на сайт, лучшие проститутки Питера ждут тебя. Выбирай понравившуюся анкету шлюхи СПб и сексуальная девочка окажется возле тебя.
[url=https://prostitutkipitera.pw/]проститутки Питера![/url]

Posted by: GordgGiz | 2018.06.23 11:03 AM

The comments to this entry are closed.

TrackBack


Listed below are links to weblogs that reference Scala で麻雀の役判定の基本処理の部分を書いてみた:

« Apache 用 mod_auth_fb (Firebird用認証モジュール)新版公開 | Main | Scala で書いた麻雀役判定のプログラムを Haskell で書き直してみた »