Euler problems/151 to 160

From HaskellWiki
< Euler problems
Revision as of 13:57, 22 January 2008 by Lisp (talk | contribs)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Problem 151

Paper sheets of standard sizes: an expected-value problem.

Solution:

problem_151 = undefined

Problem 152

Writing 1/2 as a sum of inverse squares

Note that if p is an odd prime, the sum of inverse squares of all terms divisible by p must have reduced denominator not divisible by p.

Solution:

import Data.Ratio
import Data.List

invSq n = 1 % (n * n)
sumInvSq = sum . map invSq

subsets (x:xs) = let s = subsets xs in s ++ map (x :) s
subsets _      = [[]]

primes = 2 : 3 : 7 : [p | p <- [11, 13..79],
                          all (\q -> p `mod` q /= 0) [3, 5, 7]]

-- All subsets whose sum of inverse squares,
-- when added to x, does not contain a factor of p
pfree s x p = [(y, t) | t <- subsets s, let y =  x + sumInvSq t,
                        denominator y `mod` p /= 0]

-- Verify that we need not consider terms divisible by 11, or by any
-- prime greater than 13. Nor need we consider any term divisible
-- by 25, 27, 32, or 49.
verify = all (\p -> null $ tail $ pfree [p, 2*p..85] 0 p) $
         11 : dropWhile (< 17) primes ++ [25, 27, 32, 49]

-- All pairs (x, s) where x is a rational number whose reduced
-- denominator is not divisible by any prime greater than 3;
-- and s is all sets of numbers up to 80 divisible
-- by a prime greater than 3, whose sum of inverse squares is x.
only23 = foldl f [(0, [[]])] [13, 7, 5]
  where
    f a p = collect $ [(y, u ++ v) | (x, s) <- a,
                                     (y, v) <- pfree (terms p) x p,
                                     u <- s]
    terms p = [n * p | n <- [1..80`div`p],
                       all (\q -> n `mod` q /= 0) $
                           11 : takeWhile (>= p) [13, 7, 5]
              ]
    collect = map (\z -> (fst $ head z, map snd z)) .
              groupBy fstEq . sortBy cmpFst
    fstEq  (x, _) (y, _) = x == y
    cmpFst (x, _) (y, _) = compare x y

-- All subsets (of an ordered set) whose sum of inverse squares is x
findInvSq x y = f x $ zip3 y (map invSq y) (map sumInvSq $ init $ tails y)
  where
    f 0 _        = [[]]
    f x ((n, r, s):ns)
     | r > x     = f x ns
     | s < x     = []
     | otherwise = map (n :) (f (x - r) ns) ++ f x ns
    f _ _        = []

-- All numbers up to 80 that are divisible only by the primes
-- 2 and 3 and are not divisible by 32 or 27.
all23 = [n | a <- [0..4], b <- [0..2], let n = 2^a * 3^b, n <= 80]

solutions = if verify
              then [sort $ u ++ v | (x, s) <- only23,
                                    u <- findInvSq (1%2 - x) all23,
                                    v <- s]
              else undefined

problem_152 = length solutions

Problem 153

Investigating Gaussian Integers

Solution:

problem_153 = undefined

Problem 154

Exploring Pascal's pyramid.

Solution:

problem_154 = undefined

Problem 155

Counting Capacitor Circuits.

Solution:

problem_155 = undefined

Problem 156

Counting Digits

Solution:

problem_156 = undefined

Problem 157

Solving the diophantine equation 1/a+1/b= p/10n

Solution:

problem_157 = undefined

Problem 158

Exploring strings for which only one character comes lexicographically after its neighbour to the left.

Solution:

problem_158 = undefined

Problem 159

Digital root sums of factorisations.

Solution:

problem_159 = undefined

Problem 160

Factorial trailing digits

We use the following two facts:

Fact 1: (2^(d + 4*5^(d-1)) - 2^d) `mod` 10^d == 0

Fact 2: product [n | n <- [0..10^d], gcd n 10 == 1] `mod` 10^d == 1

We really only need these two facts for the special case of d == 5, and we can verify that directly by evaluating the above two Haskell expressions.

More generally:

Fact 1 follows from the fact that the group of invertible elements of the ring of integers modulo 5^d has 4*5^(d-1) elements.

Fact 2 follows from the fact that the group of invertible elements of the ring of integers modulo 10^d is isomorphic to the product of a cyclic group of order 2 and another cyclic group.

Solution:

problem_160 = trailingFactorialDigits 5 (10^12)

trailingFactorialDigits d n = twos `times` odds
  where
    base = 10 ^ d
    x `times` y = (x * y) `mod` base
    multiply = foldl' times 1
    x `toPower` k = multiply $ genericReplicate n x
    e = facFactors 2 n - facFactors 5 n
    twos
     | e <= d    = 2 `toPower` e
     | otherwise = 2 `toPower` (d + (e - d) `mod` (4 * 5 ^ (d - 1)))
    odds = multiply [odd | a <- takeWhile (<= n) $ iterate (* 2) 1,
                           b <- takeWhile (<= n) $ iterate (* 5) a,
                           odd <- [3, 5 .. n `div` b `mod` base],
                           odd `mod` 5 /= 0]

-- The number of factors of the prime p in n!
facFactors p = sum . zipWith (*) (iterate (\x -> p * x + 1) 1) .
               tail . radix p

-- The digits of n in base b representation
radix p = map snd . takeWhile (/= (0, 0)) .
          iterate ((`divMod` p) . fst) . (`divMod` p)

it have another fast way to do this .

Solution:

import Data.List
mulMod :: Integral a => a -> a -> a -> a
mulMod a b c= (b * c) `rem` a
squareMod :: Integral a => a -> a -> a
squareMod a b = (b * b) `rem` a
pow' :: (Num a, Integral b) => (a -> a -> a) -> (a -> a) -> a -> b -> a
pow' _ _ _ 0 = 1
pow' mul sq x' n' = f x' n' 1
    where
    f x n y
        | n == 1 = x `mul` y
        | r == 0 = f x2 q y
        | otherwise = f x2 q (x `mul` y)
        where
            (q,r) = quotRem n 2
            x2 = sq x
powMod :: Integral a => a -> a -> a -> a
powMod m = pow' (mulMod m) (squareMod m)
 
productMod =foldl (mulMod (10^5)) 1
hFacial 0=1
hFacial a
    |gcd a 5==1=mod (a*hFacial(a-1)) (5^5)
    |otherwise=hFacial(a-1)
fastFacial a= hFacial $mod a 6250
numPrime x p=takeWhile(>0) [div x (p^a)|a<-[1..]]
p160 x=mulMod t5 a b
    where
    t5=10^5
    lst=numPrime x 5
    a=powMod t5 1563 $mod c 2500
    b=productMod  c6 
    c=sum lst
    c6=map fastFacial $x:lst
problem_160 = p160 (10^12)