Skip to content

Instantly share code, notes, and snippets.

@kiris
Created July 6, 2013 02:30
Show Gist options
  • Save kiris/5938391 to your computer and use it in GitHub Desktop.
Save kiris/5938391 to your computer and use it in GitHub Desktop.
http://www.itmedia.co.jp/enterprise/articles/1004/03/news002_2.html が会社で流行ってたのでScalaで解いてみた。 枝切りとかは面倒なのでしてない。
object Mahjong {
type Hands = Seq[(Int, Int)]
type State = (List[Mentsu], Option[Int], Option[Mati])
abstract class Mentsu
case class Zyuntsu(n: Int) extends Mentsu
case class Kotsu(n: Int) extends Mentsu
abstract class Mati
case class ZyuntsuMati(n1: Int, n2:Int) extends Mati
case class KotsuMati(n1: Int) extends Mati
case class AtamaMati(n1: Int) extends Mati
def collectGoal(hands:Hands, state:State):List[State] = {
hands.filter(_._2 > 0) match {
case Nil =>
List(state)
case xs =>
kotsu(xs, state) ++ zyuntsu(xs, state) ++ atama(xs, state) ++ mati(xs, state)
}
}
def kotsu(hands:Hands, state:State):List[State] = {
hands match {
case (n, i) :: tail if i >= 3 =>
collectGoal((n, i - 3) :: tail, state.copy(_1 = state._1 :+ Kotsu(n)))
case _ =>
Nil
}
}
def zyuntsu(hands:Hands, state:State):List[State] = {
hands.splitAt(3) match {
case (xs @ List((n1, i1), (n2, i2), (n3, i3)), tail) if n2 - n1 == 1 && n3 - n2 == 1 =>
collectGoal(xs.map({case (n, i) => (n, i - 1)}) ++ tail, state.copy(_1 = state._1 :+ Zyuntsu(n1)))
case _ =>
Nil
}
}
def atama(hands:Hands, state:State):List[State] = {
(hands, state) match {
case ((n, i) :: tail, (_, None, mati)) if i >= 2 && mati.filter(_.isInstanceOf[AtamaMati]).isEmpty =>
collectGoal((n, i - 2) :: tail, state.copy(_2 = Some(n)))
case _ =>
Nil
}
}
def mati(hands:Hands, state:State):List[State] = {
state match {
case (_, _, None) =>
zyuntsuMati(hands, state) ++ kotsuMati(hands, state) ++ atamaMati(hands, state)
case _ =>
Nil
}
}
def zyuntsuMati(hands:Hands, state:State):List[State] = {
hands.splitAt(2) match {
case (xs @ List(n1, n2), tail) if n2._1 - n1._1 <= 2 =>
collectGoal(xs.map({case (n, i) => (n, i - 1)}) ++ tail, state.copy(_3 = Some(ZyuntsuMati(n1._1, n2._1))))
case _ =>
Nil
}
}
def kotsuMati(hands:Hands, state:State):List[State] = {
hands match {
case (n, i) :: tail if i >= 2 =>
collectGoal((n, i - 2) :: tail, state.copy(_3 = Some(KotsuMati(n))))
case _ =>
Nil
}
}
def atamaMati(hands:Hands, state:State):List[State] = {
(hands, state) match {
case ((n, i) :: tail, (_, None, _)) =>
collectGoal((n, i - 1) :: tail, state.copy(_3 = Some(AtamaMati(n))))
case _ =>
Nil
}
}
def main(args:Array[String]): Unit = {
val in = args(0)
val hands = (1 to 9).map(i => (i, in.count(i.toString == _.toString))).toList
val result = collectGoal(hands, (Nil, None, None)).distinct.map({ case (mentsu, atama, mati) =>
val atamaStr = atama.map(n => s"${n}${n}")
val mentsuStr = mentsu.map {
case Zyuntsu(n) => Some(s"${n}${n+1}${n+2}")
case Kotsu(n) => Some(s"${n}${n}${n}")
}
val matiStr = mati.get match {
case ZyuntsuMati(n1, n2:Int) => s"${n1}${n2}"
case KotsuMati(n: Int) => s"${n}${n}"
case AtamaMati(n: Int) => s"${n}"
}
((mentsuStr :+ atamaStr).flatten.map(n => s"(${n})") :+ s"[${matiStr}]").mkString("")
})
println(result.mkString("\n"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment