HaskellでCodeforcesに参戦してきた

Codeforces初参戦。

昨夜あったCodeforces Div2 #79に参戦してきました。使用言語はHaskell
SRMではC++なので、案の定いろいろと苦労しました。

基本的にこれから、SRMC++で、CodeforcesHaskellで参戦しようと思ってます。



A:Accepted
B:Accepted
C,D,E:(未送信)

954 pts
Non-rated -> 1453



まあ、初参加なんでこんなもんでいいかなと。
でも次はA,B,C通しての1200ptsくらい狙いたいですね。


以下、解いた問題について軽く方針を。

Aは
(1)衣服の番号をインデックスとし、それとマッチする衣服のリストを値として持つ配列を作成。
(2)衣服iについて、iにマッチする服jと、jにマッチする服kを上で作った配列を用いて取得し、kにiがマッチしたらそれら3つの価格の和を求める。
(3)全ての衣服の全ての(i,j,k)の組み合わせに対し価格を求め、最安値を返す。

割と早く思いつけたけど実装に手間取りました。
入れ替えた対応関係も考慮に入れないといけないということに気づかず一回プレテストで落とされました。



Bは
(1)数字を文字列として頭から読み込み、1桁読みこむごとに足していく
(2)1ケタになるまで(1)をくりかえす。

こっちのがはるかにAより簡単でした。
TLEが心配でしたが無事通りました。



以下コード。

A:

import Array

getIntPairs :: IO (Int,Int)
getIntPairs = do ns <- getLine
                 return (make_pair [(read n::Int)|n<-(words ns)])
                        where
                          make_pair (x:y:_) = (x,y)
                          make_pair _ = (0,0)

getInts :: IO [Int]
getInts = do ns <- getLine
             return [(read n::Int)|n<-(words ns)]

getPairLines :: Int -> IO [(Int,Int)]
getPairLines n = if n > 0 then
                     do l <- getIntPairs
                        ls <- getPairLines (n-1)
                        return (l:ls)
                 else
                     return []

putAnsLn :: (Show a) => a -> IO ()
putAnsLn ans = putStrLn (show ans)

include x [] = False
include x (l:ls) = if x==l then True else include x ls

mins m [] = m
mins m (x:xs) = if m>x then mins x xs else mins m xs

loop_find n ms = filter (\(j,k) -> include n (ms!k)&&n/=j&&n/=k ) [(j,k)|j<-(ms!n),k<-(ms!j)]

solve n m a uv = solve_rec 100000000 [1..n]
    where
      solve_rec ans [] = if ans==100000000 then -1 else ans
      solve_rec ans (i:is) = solve_rec (mins ans [prices!i + prices!j + prices!k|(j,k)<-loops]) is
          where
            loops = loop_find i matchings
            prices = array (1,n) (zip [1..n] a)
            matchings = make_matching (array (1,n) [(i,[])|i<-[1..n]]) uv
                where
                  make_matching ary [] = ary
                  make_matching ary ((u,v):uvs) = make_matching ((ary//[(u,v:(ary!u))])//[(v,u:(ary!v))]) uvs
                         

main = do (n,m) <- getIntPairs
          a <- getInts
          uv <- getPairLines m
          putAnsLn (solve n m a uv)


B:

import Char
import List

putAnsLn :: (Show a) => a -> IO ()
putAnsLn ans = putStrLn (show ans)

digitsum [] s = s
digitsum (n:ns) s = digitsum ns (s + (ord n) - 48)

solve n ans = if (length n) == 1 then
                  ans
              else
                  solve (show (digitsum n 0)) (ans+1)

main = do n <- getLine
          putAnsLn (solve n 0)


こうして見比べてもやっぱBのほうが簡単……というよりAの実装にモタつきすぎました。
これからもうちょっと頑張ってみようと思ってます。

それではノシ