HaskellでABCを攻略していく ~ABC003C~

問題はこれ ABC003C

リストと数を入力し、ゴニョゴニョ計算した結果の最大を求める問題ですね。

入力

  • 動画講座の総数 : _
  • 見ることができる動画の数 : k
  • 動画配信者のレートのリスト : rs

出力

達成できる最大レート

実装

0からスタートしてk回自分と動画配信者との平均を取り最大値を求める

ソースコード

import Data.List (sort)

main :: IO ()
main = do
    [_, k] <- map read . words <$> getLine
    rs <- map read . words <$> getLine
    print $ ans rs k
ans :: [Double] -> Int -> Double
ans rs k     =
    let l    = length rs
        list = drop (l - k) $ sort rs
        in calc list

calc :: [Double] -> Double
calc list = foldl (\ a b -> (a + b) / 2) 0.0 list

関数

ans関数

答えを返却するための関数

ans :: [Double] -> Int -> Double
ans rs k     =
    let l    = length rs
        list = drop (l - k) $ sort rs
        in calc list

Double型のリストとInt型の値を受け取り、Doubleで本問題の回答を返却する。 let式ではリストの要素数を表す変数 l と視聴する動画配信者のレートを表すリスト list の二つを作成し、calc関数の結果を返却する。

import Data.List (sort)でsort関数をimportし、引数のrsを整列する。 drop (l - k) りすとの形になり、drop関数にて、先頭から(l - k)要素をリストから削除する。 最終的には要素数 k で整列されたリストができる。

calc関数

答えを計算する関数

calc :: [Double] -> Double
calc list = foldl (\ a b -> (a + b) / 2) 0.0 list

calc関数は整列したDouble型リストが送られてくる。 (\ a b -> (a + b) / 2)ラムダ式を使い2値の平均を求めている。以降 f と表す。 foldl f 0.0 listでは、引数で与えられたリストを初期値0.0で関数fを畳み込んでいる。 リストは昇順になっているため、小さい値から順に関数fに適用される。