1時間以内に解けなければプログラマ失格となってしまう5つの問題

1時間以内に解けなければプログラマ失格となってしまう5つの問題が話題に」で紹介されている問題に挑戦してみました。といっても、一時間なんてとんでもなくて2週間くらいかけてますけどね...

問題4

正の整数のリストを与えられたとき、数を並び替えて可能な最大数を返す関数を記述せよ。例えば、[50, 2, 1, 9]が与えられた時、95021が答えとなる。

def makeBiggestNumber(ns: List[Int]): Int =
  ns.permutations.toList.map(_.foldLeft("")((a, x) => a + x).toInt).max

これはこんな感じでいいですかね。

問題5

1,2,…,9の数をこの順序で、”+”、”-“、またはななにもせず結果が100となるあらゆる組合せを出力するプログラムを記述せよ。例えば、1 + 2 + 34 – 5 + 67 – 8 + 9 = 100となる。

def makeList(ns: List[Int]): Set[List[Int]] = {
  def makeList(ns: List[Int], ms: List[Int], rs: Set[List[Int]]): Set[List[Int]] =
    if (ns.isEmpty) rs + ms
    else if (ms.isEmpty) makeList(ns.tail, List(ns.head), rs)
    else makeList(ns.tail, ns.head :: ms,
           makeList(ns.tail, ms.head * 10 + ns.head :: ms.tail, rs))
  makeList(ns, List[Int](), Set[List[Int]]()).map(_.reverse)
}
def makeListsWithNegative(ns: List[Int]): Set[List[Int]] = {
  def makeListsWithNegative(ns: List[Int], ms: List[Int], rs: Set[List[Int]]): Set[List[Int]] =
    if (ns.isEmpty) rs + ms
    else makeListsWithNegative(ns.tail, ns.head :: ms,
           makeListsWithNegative(ns.tail, -ns.head :: ms, rs))
  makeListsWithNegative(ns, List[Int](), Set[List[Int]]()).map(_.reverse)
}
def resolve: Set[List[Int]] = 
  makeList(Range(1, 10).toList).flatMap(ns => makeListsWithNegative(ns).filter(ms => ms.sum == 100))

こちらは、えー、深さ優先探索っていうんですか、初めて書きました。関数名がイマイチですが勘弁してください。問題を解くとはリストを作ること、っていう基本に忠実にやってみたつもりです。

問題5の別解

def solve: List[List[Int]] =
  Range(1, 10).foldLeft(List[List[Int]]()) {
    case (_, 1) => List(List(1))
    case (a, n) => a.flatMap(ls => List(n :: ls, ls.head * 10 + n :: ls.tail))
  }.flatMap(ls => ls.foldLeft(List(List[Int]()))((a, n) => 
    a.flatMap(ms => List(n :: ms, -n :: ms))
  )).filter(ls => ls.sum == 100)

foldでaccを処理すると可能性広がるなってことと、flatMap超便利!ってことが学びです。