I am doing Project Euler question 55 on Lychrel numbers where the aim is to find the number of Lychrel numbers below 10,000 within 50 iterations. I came up with this:
revAdd n = (read $ reverse $ show n) + n
lychrel n | length xs == 50 = error "False"
| ((reverse $ show (revAdd n)) == (show (revAdd n))) = True
| otherwise = (lychrel (revadd n) ) : xs
answer = length [ x | x <- [1..10000] , lychrel x == True]
But I don't know how to define xs as the list of previous iterations upon n, which are when n is not a palindrome. How would I do this, and secondly would this work?
It becomes much easier if you separate your concerns into distinct steps.
Define a function that sums a number and its reverse.
Use iterate to repeat your number, starting from x.
Use take to limit your iteration to 50 steps.
Use all with a predicate to determine if any of these steps results in a palindrome.
You need to pass the list of iterations (or just the number of iterations) in as a parameter to lychrel, starting with [] in the call from answer and adding to it in the recursive call in the otherwise case. Look up "accumulating parameters" for more general background on this technique.
Related
How do I find two max value in a list and sum up, not using rec, only can use List.fold_left or right and List.map?
I used filter, but it's not allowed, anyways I can replace the filter?
let max a b =
if b = 0 then a
else if a > b then a
else b;;
let maxl2 lst =
match lst with
| [] -> 0
| h::t ->
let acc = h in
List.fold_left max acc lst +
List.fold_left
max acc
(List.filter (fun x -> (x mod List.fold_left max acc lst) != 0) lst);;
List.fold_left is very powerful and can be used to implement List.filter, List.map, List.rev and so on. So it's not much of a restriction. I would assume the purpose of the exercise is for you to learn about the folds and what they can do.
If your solution with List.filter actually works, you should be able to replace List.filter by one you wrote yourself using List.fold_left. The basic idea of a fold is that it builds up a result (of any type you choose) by looking at one element of the list at a time. For filter, you would add the current element to the result if it passes the test.
However I have to wonder whether your solution will work even with List.filter. I don't see why you're using mod. It doesn't make a lot of sense. You seem to need an equality test (= in OCaml). You can't use mod as an equality test. For example 28 mod 7 = 0 but 28 <> 7.
Also your idea of filtering out the largest value doesn't seem like it would work if the two largest values were equal.
My advice is to use List.fold_left to maintain the two largest values you've seen so far. Then add them up at the end.
To build on what Jeffrey has said, List.fold_left looks at one element in a list at a time and an accumulator. Let's consider a list [1; 3; 7; 0; 6; 2]. An accumulator that makes sense is a tuple with the first element being the largest and the second element representing the second largest. We can initially populate these with the first two elements.
The first two elements of this list are [1; 3]. Finding the max of that we can turn this into the tuple (3, 1). The remainder of the list is [7; 0; 6; 2].
First we consider 7. It's bigger than 3, so we change the accumulator to (7, 3). Next we consider 0. This is smaller than both elements of the accumulator, so we make no changes. Next: 6. This is bigger than 3 but smaller than 7, so we updated the accumulator to (7, 6). Next: 2 which is smaller than both, so no change. The resulting accumulator is (7, 6).
Actually writing the code for this is your job.
Often, functions called by fold use an accumulator that is simple enough to be stored as an anonymous tuple. But this can become hard to understand when you are dealing with complex behaviors: you have to consider different corner cases, like what is the initial accumulator value? what is the regular behavior of the function, ie. when the accumulator has encountered enough values? what happens before that?
For example here you have to keep track of two maximal values (the general case), but your code has a build-up phase where there is only one element being visited in the list, and starts with initially no known max value. This kind of intermediate states is IMO the hardest part of using fold (the more pleasant cases are when the accumulator and list elements are of the same type).
I'd recommend making it very clear what type the accumulator is, and write as many helper functions as possible to clear things up.
To that effect, let's define the accumulator type as follows, with all different cases treated explicitly:
type max_of_acc =
| SortedPair of int * int (* invariant: fst <= snd *)
| Single of int
| Empty
Note that this isn't the only way to do it, you could keep a list of maximum values, initially empty, always sorted, and of size at most N, for some N (and then you would solve a more general case, ie. a list of N highest values). But as an exercise, it helps to cover the different cases as above.
For example, at some point you will need to compute the sum of the max values.
let sum_max_of m = match m with
| Empty -> 0
| Single v -> v
| SortedPair (u,v) -> u+v;;
I would also define the following helper function:
let sorted_pair u v = if u <= v then SortedPair (u,v) else SortedPair (v, u)
Finally, your function would look like this:
let fold_max_of acc w = match acc with
| Empty -> ...
| Single v -> ...
| SortedPair (u, v) -> ...
And could be used in the following way:
# List.fold_left fold_max_of Empty [1;2;3;5;4];;
- : max_of = SortedPair (4, 5)
I am pretty new to Haskell and I have the data data Instruction = Add | Sub | Mul | Div | Dup | Pop deriving (Eq,Ord,Show,Generic) and I am generating lists with all possible combinations of Mul and Dup with mapM (const [Mul, Dup]) [1..n]) of size n.
I wanted only the lists starting with Dup and ending with Mul so I used filter((== Mul) . last)(filter((== Dup) . head) (mapM (const [Mul, Dup]) [1..n])) but I also want only the lists with the same number of Mul and Dup in them but I can't seem to come up with a way of doing this. How do I filter this and is there a more efficient way of doing this as there may be a huge amount of combinations as lists get bigger?
A sample list would look like this: [Dup,Mul,Dup,Mul] and [Dup,Dup,Mul,Mul] for lists of size 4.
While your approach is correct, I think it's not the most efficient one. You generate 2^N lists and then filter out many of them. Forgetting the other requirements to keep the counting simple, by requiring that we have as many Muls as Dups, we end up with only choose(N, N/2) lists (the number of subsets of size N/2 of 1..N), which is a much smaller figure.
We can instead try to avoid the filtering and generate the wanted lists, only, in the first place. I suggest the following approach, which you can modify as needed to satisfy the other requirements.
We define a function sameMulDup which takes two integers m and d and generates all the lists with m Muls and d Dups.
sameMulDup :: Int -> Int -> [[Instruction]]
sameMulDup 0 d = [replicate d Dup]
sameMulDup m 0 = [replicate d Mul]
sameMulDup m d = do
-- generate the first element
x <- [Dup, Mul]
-- compute how many m and d we have left
let (m', d') = case x of
Dup -> (m , d-1)
Mul -> (m-1, d )
-- generate the other elements
xs <- sameMulDup m' d'
return (x:xs)
Intuitively, if d=0 or m=0 there is only one possible list to include in out list-of-lists result. Otherwise, we non deterministically pick the first element, decrement the correponding counter d or m, and generate the rest.
Alternatively, the last equation can be replaced by the following more basic one:
sameMulDup m d =
map (Dup:) (sameMulDup m (d-1))
++
map (Mul:) (sameMulDup (m-1) d)
Anyway, given sameMuldup, you should be able to solve your full task.
It should be possible to define a function countPred :: a -> [a] -> Int, which counts the number of items in the list which are equal to the first argument; you can then do filter (\l -> countPred Mul l == countPred Dup l) (or alternately filter ((==) <$> countPred Mul <*> countPred Dup) if you prefer point-free form). Another approach I suppose might be to do (==0) . sum . map (\case { Mul -> 1, Dup -> (-1) }), but that strikes me as being slightly more complex than necessary.
I like chi's answer, but in a comment, I mentioned that it doesn't achieve as much sharing as it could. I speculated that the sharing would be beneficial if you iterate over the list of instructions multiple times, but worse if you iterate just once. Empirically, the sharing version appears to be faster no matter how many times you iterate, but the memory tradeoff is as predicted: worse for one iteration, better for multiple. So I thought it might be interesting to show it.
Here's how it looks. We're going to make an infinite list of answers. The first index will be how long the list of instructions will be; the second is how many Muls there are (though I'll use True and False instead of Mul and Dup). So:
bits :: [[[[Bool]]]]
bits = iterate extend [[[]]] where
extend bsss = zipWith (++)
(map (map (False:)) bsss ++ [[]])
([[]] ++ map (map (True:)) bsss)
For completeness, here's how you write a function with the same signature as chi's sameMulDup, and computing the same answer (up to the swap to Bool):
sameMulDup' :: Int -> Int -> [[Bool]]
sameMulDup' m d = bits !! (m+d) !! m
Some timings on my machine, for m=d=12, when compiled -O2:
sameMulDup , one iteration 1.35s 6480Kb
sameMulDup', one iteration 1.11s 226476Kb
sameMulDup , two iterations 4.26s 2135368Kb
sameMulDup', two iterations 1.97s 620880Kb
Here is the driver code I used for acquiring these numbers:
main :: IO ()
main = do
[sharing, twice, m, d] <- getArgs
let answer = (if read sharing then sameMulDup' else sameMulDup) (read m) (read d)
if read twice
then do
print . sum . map (sum . map fromEnum) $ answer
print . sum . map (sum . map (fromEnum . not)) $ answer
else print . sum . map (sum . map fromEnum) $ answer
There are some subtle points here:
To iterate over the list twice, we must have a way of referring to the same list in both iterations. This is answer in the above code.
We must use an iteration that actually forces all the values for it to be useful. I do this by counting up how many Trues there are, but there are other ways. (Just printing the whole list doesn't work well: the calculation's runtime is then dwarfed by the production of the String to print and the work done in transferring it to the terminal.)
Although the first iteration uses the same code in both branches of the if, it is important that this code not be shared and moved out of the if. We want the compiler to know in the else branch that answer will not be used again, so that it may garbage collect. If you write print answer >> if twice then print answer else pure (), it is not as obvious statically when the prefix of answer may be garbage collected.
In the then branch, I used two different calculations in the two loops, so that the compiler did not attempt to get clever and do the calculation just once and then print the calculated result twice.
I'll use a simple example for what I'm trying to do.
Say I have the list:
nums = []
Now I have the function:
allNums n = nums.append(n)
So if I run the function:
allNums 6
The list nums should have the values
[6]
I know nums.append doesn't work, but what code could replace that.
Simple Answer:
You can't do that. Haskell is a pure, functional language, that means:
A function does not have any side effect.
A function does always return the same result when called with the same parameters.
A function may or may not be called, but you don't have to care about that. If it wasn't called, it wasn't needed, but because the function does not have any side effects, you won't find out.
Complex answer:
You could use the State Monad to implement something that behaves a bit like this, but this is probably out of reach for you yet.
I'm suggesting to use an infinite list instead of appending to global variable.
It's true haskell is pure functional. But also it's lazy. Every part of data is not calculated until is really needed. It also applies to collections. So you could even define a collection with elements based on previous elements of same collection.
Consider following code:
isPrime n = all (\p -> (n `mod` p) /= 0 ) $ takeWhile (\p ->p * p <= n) primes
primes = 2 : ( filter isPrime $ iterate (+1) 3 )
main = putStrLn $ show $ take 100 primes
definition of isPrime is trivia when primes list is defined. It takes pack of primes which is less or equivalent to square root of examining number
takeWhile (\p ->p * p <= n) primes
then it checks if number have only non-zero remainders in division by all of these numbers
all (\p -> (n `mod` p) /= 0 )
the $ here is an application operator
Next using this definition we taking all numbers starting from 3:
iterate (+1) 3
And filtering primes from them.
filter isPrime
Then we just prepending the first prime to it:
primes = 2 : ( ... )
So primes becomes an infinite self-referred list.
You may ask: why we prepending 2 and just no starting filtering numbers from it like:
primes = filter isPrime $ iterate (+1) 2
You could check this leads to uncomputable expression because the isPrime function needs at least one known member of primes to apply the takeWhile to it.
As you can see primes is well defined and immutable while it could have as many elements as you'll need in your logic.
According to the book this is how its done, but I am not able to get this to work. It gives me an error Not in scope: 'ld'. I'm guessing I should be importing some package but not sure which one. Also the book uses GS module at the prompt but I'm using WinGHCi that has Prelude. What am I missing here?
factors :: Int -> [Int]
factors n | n < 1 = error "not positive"
| n == 1 = []
| otherwise = p : factors (div n p)
where p = ld n
I guess this can also be done using map and filter functions? How?
I suppose the aim of the assignment is to teach you about list comprehensions, filter and similar constructs, and not to have you write functions that test for primality or create the list of divisors in any sensible way. Therefore what you need is a predicate divides,
divides :: Int -> Int -> Bool
a `divides` b = ???
Then you use that predicate for the argument to filter or in a list comprehension to find the list of divisors, and use the divisors function for your isPrime test.
You want to inspect all numbers from 1 to n, and keep them only if they divide n. The filter function can help you:
divisors n = filter ??? [1..n]
So what condition you need to put in place of ??? ?
For the isPrime function you could reuse the divisors function, you already mentioned how.
Break it down into simpler steps.
Write a function, divides :: Int -> Int -> Bool such that
x `divides` n
is true when x is a divisor of n. So, first, think about what it means for x to be a divisor of n.
Now that you have a way to check if a single number x is a divisor of n, you need to check a certain range of numbers less than n to see which ones are divisors.
Hint: In Haskell, you can generate a list of numbers from 1 to n like so: [1..n]
This is where that filter function you mention would be useful. Check its type:
filter :: (a -> Bool) -> [a] -> [a]
Just replace the a above with Int.
As far as the isPrime function, just think about what it means for a number to be prime... if you've calculated your divisors correctly, you can check the list to make sure that it matches with that property.
If this is a homework related question, you should definitely tag it with homework, then people don't feel as timid about helping out :)
i m a newbie to haskell, currently i need a function 'f' which, given two integers, returns the number of prime numbers in between them (i.e., greater than the first integer but smaller than the second).
Main> f 2 4
1
Main> f 2 10
3
here is my code so far, but it dosent work. any suggestions? thanks..
f :: Int -> Int -> Int
f x y
| x < y = length [ n | n <- [x..y], y 'mod' n == 0]
| otherwise = 0
Judging from your example, you want the number of primes in the open interval (x,y), which in Haskell is denoted [x+1 .. y-1].
Your primality testing is flawed; you're testing for factors of y.
To use a function name as an infix operator, use backticks (`), not single quotes (').
Try this instead:
-- note: no need for the otherwise, since [x..y] == [] if x>y
nPrimes a b = length $ filter isPrime [a+1 .. b-1]
Exercise for the reader: implement isPrime. Note that it only takes one argument.
Look at what your list comprehension does.
n <- [x..y]
Draw n from a list ranging from x to y.
y `mod` n == 0
Only select those n which evenly divide y.
length (...)
Find how many such n there are.
What your code currently does is find out how many of the numbers between x and y (inclusive) are factors of y. So if you do f 2 4, the list will be [2, 4] (the numbers that evenly divide 4), and the length of that is 2. If you do f 2 10, the list will be `[2, 5, 10] (the numbers that evenly divide 10), and the length of that is 3.
It is important to try to understand for yourself why your code doesn't work. In this case, it's simply the wrong algorithm. For algorithms that find whether a number is prime, among many other sources, you can check the wikipedia article: Primality test.
I you want to work with large intervals, then it might be a better idea to compute a list of primes once (instead of doing a isPrime test for every number):
primes = -- A list with all prime numbers
candidates = [a+1 .. b-1]
myprimes = intersectSortedLists candidates primes
nPrimes = length $ myprimes