2016-11-03 5 views
0

하스켈을 배우고 있으며, problem 30 on project Euler을 해결하고 있습니다.정수를 숫자 목록으로 분리하십시오.

digits n = if n<10 then [n] else (digits (quot n 10)) ++ [(mod n 10)] 
isP30 n = (sum $ map (^5) $ digits n) == n 
sum $ filter isP30 [10^5..10^6-1] 

digits 기능을 구현하는 데 더 읽기 쉬운 방법이 있습니까?

digits n = fmap digitToInt $ show n 

난 당신이 @의 bheklilr의 대답처럼, Data.Char 처음부터 digitToInt를 가져올 필요가 있다고 언급하는 것을 잊었다 :에 대해 무엇

+1

[unfold] (http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-List.html#v:unfoldr)를 사용하는 것은 어떻습니까? –

+0

@ BenjaminHodgson, 정교하게 주시겠습니까? –

+1

'unfoldr'는 모든 단계에서 목록 요소를 생성하는 루프를 일반화합니다. 현재 루프 "state"가 주어지면 목록 값 (Nothing) 생성을 멈추거나 값 ('x')을 생성할지 여부를 결정하고 새 상태 ('s 예를 들어, 'unfoldr (\ n -> n == 10이면 Nothing else (n, n + 1)) 0'은'[0..9 ]'. 당신은 숫자를 거꾸로 생성하고 마지막에'역순으로'할 수 있습니다. – chi

답변

2

, 당신은 쓸 수있는 unfold 때문에 여기 역순으로 자리를 얻을 방법 unfoldr 작품, 그러나

import Data.Tuple (swap) 
import Data.List (unfoldr) 

digits = unfoldr go 
    where go 0 = Nothing 
      go n = Just (swap $ n `divMod` 10) 

있다. 또 다른 해결책은 전적으로이 도랑과

import Data.Char (digitToInt) 

digits = map digitToInt . show 

내 타이밍이 빠를 수와 최적화되지 않은 GHCi 세션에서 메모리의 약 25 %를 사용하는 그것을 발견로 이동하는 것입니다, 또한 숫자의 순서를 반대로하지 않습니다.

3

. BenjaminHodgson의 제안 @ 사용

1

먼저 항상 if-then-else 대신 가드가있는 코드를 작성하는 것이 더 읽기 쉽습니다. 관계없는 모든 괄호도 산만합니다.

당신의

digits n | n < 10 = [n] 
     | otherwise = digits (quot n 10) ++ [mod n 10] 

같은 비효율적 인 추기-에서 엔드 기능에 대한 표준 변환, 새로운 go n xs를 호출로 이전 digits n ++ xs를 호출하면 동일한 추가 인수를 소개하는 것입니다 :

digits n = go n [] -- digits_old n ++ [] == go n [] 
    where 
    go n next | n < 10 = n : next 
      | otherwise = go (quot n 10) (mod n 10 : next) 
관련 문제