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

Λάδι Βιώσας

http://profile.hatena.ne.jp/kenkitii/

ふつうの haskellプログラミング読了&はじめてのhaskell

haskell

1週間ほど前に買ったふつけるを読み終えました。haskell 難しいと聞いてましたけど、かなりわかり易かったです。いや嘘つきましたすいません。後半、型クラスの説明のあたりからもうなにがなにやら、、、ややこしかった。けど、遅延評価がどんなもんかはわかりました。カリー化(部分適用)もわかったような気がします。モナドはよくわかりません。maybeモナドってたぶんモナドってこと?って感じ。

さてそんな状態のわたくしですが、金槌を持つ人にはなんでも釘に見える、という例え通り、さっそくhaskellでなんか書いてみたくなりました。で、ネットをさまよっていたところ、面白そうなネタを発見。

高校生以下を対象にしたプログラミングコンテストらしいです。問題をみてみたところ手頃な感じなのでやってみることに。問題は↓これ。

n 個の整数からなる数列 a1, a2, ..., anと正整数 k (1 ≦ k ≦ n) が与えられる.
このとき,連続して並ぶ k 個の整数の和 Si = ai+ai+1+...+ai+k−1 (1 ≦ i ≦ n−k+1) の最大値を出力するプログラムを作りなさい
http://www.ioi-jp.org/joi/2006/2007-ho-prob_and_sol/2007-ho.pdf

あとで haskell に書き換える事を意識しつつ、 とりあえず python で書いてみる。

def head(xs):
    return xs[0]

def last(xs):
    return xs[-1:]

def tail(xs):
    return xs[1:]

def drop(n, xs):
    return xs[n:]

def take(n, xs):
    return xs[:n]

lines = open("input.txt").read().strip().split("\n")
header = head(lines).split(" ")

length = int(head(header))
k = int(last(header))
ns = map(int, tail(lines))

f = lambda x: sum(take(k, drop(x, ns)))
print max(map(f, range(length - k + 1)))

さてこれを haskell で置き換えるわけですが、、、、。
なんかよくわからん意味不明なエラーと、型が違います、と言われまくって2時間かけてようやく動くものができました。かなり酷いコードな予感がしますが、初めて書いたhaskellのコードということでさらしておきます。

import Data.Char

main = do
  cs <- readFile "input.txt"
  let (length, k) = header cs
      ns          = map strToInt (tail $ lines cs)
  print $ maximum $ map (f ns k) [0..(length-k)]

f :: [Int] -> Int -> Int -> Int
f ns k x = sum $ take k $ drop x ns

header :: String -> (Int, Int)
header xs = let (ys, zs) = break (isSpace) $ head $ lines xs
       in (strToInt ys, strToInt $ tail zs)

strToInt :: String -> Int
strToInt s = read s :: Int

こういうことすると、あとで見直したとき恥ずかしさのあまり自殺したくなるんだよね、、、しないけど。