Skip to content

Instantly share code, notes, and snippets.

@mather
Created July 7, 2015 04:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mather/d52259c7afe7a140b4f7 to your computer and use it in GitHub Desktop.
Save mather/d52259c7afe7a140b4f7 to your computer and use it in GitHub Desktop.
CodeIQ問題のHaskell解答 ref: http://qiita.com/mather314/items/8a9b2ff8b3b143950320
import Data.List
main = do
l <- fmap toInt $ getLine -- 標準入力からLを読み込む
n <- fmap toInt $ getLine -- 標準入力からNを読み込む(使わない
bars <- fmap (fmap toInt . lines) $ getContents -- 残りのリストを取得
print (sum $ fmap (findTripleSum l) $ tails bars) -- tails で部分リストを順番に調べる
-- Int化
toInt :: [Char] -> Int
toInt xs = read xs :: Int
-- リストの先頭をピックアップして、 和がL-xになる組み合わせを後方のリストから探す
findTripleSum :: Int -> [Int] -> Int
findTripleSum _ [] = 0
findTripleSum _ (_:[]) = 0
findTripleSum i (x:xs) = sum $ fmap (findDoubleSum (i-x)) $ tails xs
-- リストの先頭をピックアップして、L-x-yに等しい物を探す
findDoubleSum :: Int -> [Int] -> Int
findDoubleSum _ [] = 0
findDoubleSum i (x:xs) = if elem (i-x) xs then 1 else 0
Prelude> import Data.List
Prelude Data.List> tails [1,2,3]
[[1,2,3],[2,3],[3],[]]
import Data.List
main :: IO ()
main = do
l <- fmap toInt $ getLine
n <- fmap toInt $ getLine
sortedBars <- fmap (sort . fmap toInt . lines) $ getContents -- ソートしておく
print (countFixedLengthTripleBars l sortedBars)
toInt :: [Char] -> Int
toInt xs = read xs :: Int
-- tailsで部分リストを作って処理して、結果をsum
countFixedLengthTripleBars :: Int -> [Int] -> Int
countFixedLengthTripleBars length = sum . fmap (countTripleSum length) . tails
-- 先頭の値 x を使って、残りのリストを(L-x)/2を基準に分割して走査する
countTripleSum :: Int -> [Int] -> Int
countTripleSum _ [] = 0
countTripleSum l (x:xs) = countDoubleSum 0 s (filter (< h) xs) (reverse $ filter (>= h) xs) -- 大きい方のリストは reverse しておく
where s = l - x
h = ceiling ((fromIntegral s)/2)
-- s (= L-x) に一致するペアを大小のリストを走査しながら探す
-- countで見つけた数を更新して末尾再帰にする
countDoubleSum :: Int -> Int -> [Int] -> [Int] -> Int
countDoubleSum count _ [] _ = count
countDoubleSum count _ _ [] = count
countDoubleSum count s (low:lows) (high:highs)
| sum == s = countDoubleSum (count+1) s lows highs
| sum < s = countDoubleSum count s lows (high:highs)
| sum > s = countDoubleSum count s (low:lows) highs
where sum = low + high
inputs = STDIN.read.lines.map{|l| l.chomp.to_i }
L = inputs.shift
N = inputs.shift
D = inputs.sort # ソートしておく
count = 0
(0..(N-2)).each do |i|
remain = L - D[i]
# カーソルの初期位置
low_cursor = i + 1
high_cursor = N - 1
# カーソルが中央で合流するまで
while low_cursor < high_cursor do
s = D[low_cursor] + D[high_cursor]
if remain == s
count += 1
low_cursor += 1
high_cursor -= 1
elsif remain > s
low_cursor += 1
else
high_cursor -= 1
end
end
end
puts count
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment