読者です 読者をやめる 読者になる 読者になる

@numa08 猫耳帽子の女の子

明日目が覚めたら俺達の業界が夢のような世界になっているとイイナ。

#新宿Scala座 で新入女子社員を救ってきた

この海に沈む雷ちゃんに思いを馳せるf:id:numanuma08:20131207230506p:plain

新宿Scala座 第6回をやってきました。

今回はライブコーディングに挑戦してみようと思い、最近話題の新入女子社員のコードを直すやつをScalaを利用して実践してきました。

事前にコードを書いていって、解説をしながら改めてコーディングを行いましたが、説明って結構難しいですね。設計の説明と、どうやって実装をしているのか、Scalaの関数の役割説明etc...。Scalaを知らない人でも分かるように、と心がけたつもりでしたがまだまだですね。

以下コードです。Listの最大値を得るmaxの存在はid:white-azaleaさんに教えてもらいました。List系の関数は沢山あって、把握するのが大変ですね。

//readlineで標準入力から1行える。" "で区切った配列を作り、各要素をIntとした配列に変換する
val line = readLine.split(" ").map(_.toInt) 

//配列の先頭要素を商品数、末尾要素をキャンペーン日数とする
val (products, days) = (line.head, line.last)

//商品数分だけ標準入力から数値を得て配列とする
val prices = for( i <- 1 to products) yield {
    readInt
}

//キャンペーン日数分だけ標準入力から数値をえて配列とする
val settingPrices = for( i <- 1 to days) yield {
    readInt
}

//商品価格リストから2つの要素を選ぶ組み合わせを全て生成し、
//各組み合わせの合計値を求め、リストを作る
val sums = prices.combinations(2)
                 .map(_.sum)
                 .toList

//キャンペーンの設定値リストを、求めるリストへ変換する
val ansers = settingPrices.map{ sPrice =>
    //商品合計値のリストから、設定値を上回るものを消す
    val filterdPrice = sums.filter(_ <= sPrice)

    //フィルターしたリストから最大の要素を得る
    //フィルターした結果、リストが空なら0とする
    val retval = filterdPrice match {
        case Nil => 0
        case _ => {
            //filterdPrice.sortBy(sPrice - _).head
            filterdPrice.max
        }
    }
    retval
}

//出力用に整形する
val ans = ansers.mkString("\n")
println(ans)

さすがScalaですね!コメントを除いて30行程度で書けました。問題は、新入女子社員のコードを直すやつはScalaの提出を受け付けてないことですね!!

Scalaじゃ新入女子社員を救えなかったよ・・・。

ちょっと解説

今回の肝はcombinationsです。引数に渡した要素数の組み合わせをリストから取得し、全ての組み合わせを求めてリストとして返してくれます。他の言語でも、combinationsに該当するものの実装が完了すれば簡単に解ける問題ですね。

ちなみに、Rubyにも同様の実装があるそうです。Javaは多分無いので自前で用意しました。C#Linqとか使えばいけそうな気がします。

新入女子社員へ

Scalaはリストなどのデータ構造に対する処理を完結に記述できるのでお勧めです。