Hatena::ブログ(Diary)

はすけるとぱいそん

2011-10-26

Project Euler 49

問題はこちら

これは個人的に素直にできたと思います。
でもネットを徘徊するとやたら複雑なコードなものが多くて、
はてにゃ?と思いました。なんで・・・。
まあ自分のコード、微妙に汎用性みたいなものないですが笑

import Data.List


--今回使う範囲の素数リスト
a :: [Integer]
a = takeWhile (<3340) $ dropWhile (<1000) primesList


--要素数3のリストが全部素数ならTrue。
f :: [Integer] -> Bool
f [x,y,z] = all isPrime [x,y,z]


--要素数3のリストの全要素ををshowしてsortして全て同じならTrue。
g :: [Integer] -> Bool
g [x,y,z] = (\[a,b,c] -> (a==b) && (b==c) && (c==a)) $ map (sort.show) [x,y,z]


--項差3300で項数3の数列のリストを作る。
h :: [Integer] -> [[Integer]]
h [] = []
h (x:xs) = [x,(x+3330),(x+6660)] : h xs

b :: [[Integer]]
b = h a


--要素数3のリストの要素を全てshowして連結させて数値に戻す。
i :: [Integer] -> Integer
i [x,y,z] = read (show x ++ show y ++ show z) :: Integer


--らすとおー。
main = print $ i $ last $ filter g (filter f b)



--素数の無限リスト。
primesList :: [Integer]
primesList = map fromIntegral primesList'
    where
      primesList' = [2, 3, 5] ++ f 5 7 (drop 2 primesList')
      f m s (p : ps) = [n | n <- ns, gcd m n == 1] ++ f (m * p) (p * p) ps
          where ns = [x + y | x <- [s, s + 6 .. p * p - 2], y <- [0, 4]]


--素数判定。
isPrime :: Integer -> Bool
isPrime n = (n > 1) && isPrime' primesList
    where
      isPrime' (x : xs)
          | x * x > n    = True
          | rem n x == 0 = False
          | otherwise    = isPrime' xs

集中的なHaskellリハビリ疲れたorz
でももうリハビリは終わり。このまま突っ走る!笑
 
 

Project Euler 46

問題はこちら

微妙にハマりました。
アプローチを変えたらできたので、まずそちらを。

--奇合成数の無限リスト
a :: [Integer]
a = [ x | x <- [3,5..] , (not.isPrime) x]


--2乗して2かけた数の無限リスト
b :: [Integer]
b = map (\n -> 2*n^2) [1..]


--ちょめちょめする。内包表記の中で内包表記を使ってうんちゃらと。
main = print $ head $  [ x | x <- a , all (not.isPrime) $ takeWhile (>0) [ x-y | y <- b ] ] 



--素数の無限リスト。
primesList :: [Integer]
primesList = map fromIntegral primesList'
    where
      primesList' = [2, 3, 5] ++ f 5 7 (drop 2 primesList')
      f m s (p : ps) = [n | n <- ns, gcd m n == 1] ++ f (m * p) (p * p) ps
          where ns = [x + y | x <- [s, s + 6 .. p * p - 2], y <- [0, 4]]


--素数判定。
isPrime :: Integer -> Bool
isPrime n = (n > 1) && isPrime' primesList
    where
      isPrime' (x : xs)
          | x * x > n    = True
          | rem n x == 0 = False
          | otherwise    = isPrime' xs

で、ハマったのが以下。未だによく解らない。
最後の行がprimesListになった途端だめになる。
他の普通のリストとかだと大丈夫なのになんで…。

--二乗数か判定するよ。
f :: (Floating a) => a -> Bool
f n = a !! ((length a)-2) == '.' && last a == '0'
	  where a = show (sqrt n)

--なんだかんだでこんな感じにやる。
g n (x:xs)
	| n < x = False
	| f ((n-x)/2) = True
	| otherwise = g n xs

h n = g n primesList

混乱してきたのでまた今度。
 
 

Project Euler 45

問題はこちら

これは結構簡単でした。
五角数と六角数だけでやれば良いので、
単純に同じものがあるかどうか調べました。

--まずは五角数、六角数の無限リストを作る。
p :: [Integer]
p = dropWhile (<= 40755) $ map (\n -> div (n*(3*n-1)) 2) [1..]

h :: [Integer]
h = dropWhile (<= 40755) $ map (\n -> n*(2*n-1)) [1..]


--地道にあるかどうか調べる。
f :: [Integer] -> [Integer] -> Integer
f (x:xs) (y:ys)
	| elem x (takeWhile (<=x) (y:ys)) = x
	| otherwise = f xs (dropWhile (<=x) (y:ys))

--もうおわり。
main = print $ f p h

でも余裕がないので、関数名とかできとーです。
すいませんorz
 
 

Project Euler 43

問題はこちら
結構死んだけどできたわあい!

でも余裕は全然ないので、解説というより完全に自分用メモです。
すいませんorz

import Data.List

--bはaで割り切れるか。
f :: Int -> Int -> Bool
f a b  = mod b a == 0


--[[17で割り切れる3桁の数リスト],[11で割り切れる3桁の数リスト]・・・]を作る。
g :: [Int] -> [Int] -> [[Int]]
g _ [] = []
g xs (y:ys) = filter (f y) xs : g xs ys

--ちょっとmapのmapに注意。
a :: [[String]]
a = map (map (show)) $ g [12..987] [17,13,11,7,5,3,2]


--2ケタは先頭に0つけないとだめだあー!
zero :: String -> String
zero c
	| length c == 2 = "0" ++ c
	| otherwise = c

--というわけでaの完成版b。
b :: [[String]]
b = map (map (zero)) a


--リストの要素が全て違うならTrue。
diff xs
	| (length ss == 1) = True
	| (head ss == ss !! 1) = False
	| otherwise = diff (tail ss)
		where ss = sort xs


--h [17で割り切れる3桁の数リスト] [11で割り切れる3桁の数リスト] みたいにしてちょめちょめ。
h :: [String] -> [String] -> [String]
h xs ys = [ [head y] ++ x | x <- xs , y <- ys , 
                            (tail y == take 2 x) && (diff $ ([head y] ++ x)) ]

--scanl1でさっき作ったbのリストにhを順々に適用(これで出るのかあ)。
c :: [String]
c = last $ scanl1 h b


--最後に足りない数字を見つけて先頭に足す(忘れてた)。
j' :: String -> String -> String
j' (x:xs) (y:ys)
	| (x == y) = j' xs ys
	| otherwise = [y]

j :: String -> String
j k = j' (sort k) "0123456789" ++ k


--これが最終的に欲しいリスト。
d :: [String]
d = map j c


--さいごなのっ!
main = print $ sum $ map (\n -> read n :: Integer) d


ほんと、これは自分としては結構ハマった問題でした(トホホ。