Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behaviour of list comprehensions

I'm learning basics of Haskell and trying to solve project Euler's simple tasks: find largest palindrome of 3 digit numbers (100.999). I wrote this code:

palindrome = maximum $ filter (\a -> reverse a == a) $
                                    map show [ x*y :: Int | x <- [100 .. 999],
                                                            y <- [x, x+1 .. 999]]

It gives a wrong answer = 99999, when I change it to x <- [307 .. 999]answer still is wrong: 94249 (all palindromes, but not the largest) and finally when I change it to x <- [308 .. 999], it gives me right answer: 906609.

I really don't understand this behaviour: it seems there is some kind of overflow and truncation happens inside the generated list. Can someone explain me this wrong behaviour? I don't want you to answer the task: i know my solution is not very efficient. I just want you to explain this code behaviour (list truncation or memory issues). Thanks.

like image 895
MainstreamDeveloper00 Avatar asked Jan 04 '23 19:01

MainstreamDeveloper00


1 Answers

The result of filter is a list of String values, so maximum is comparing them lexicographically. You need to convert the values back to Ints first. The type signature ensures that read returns values of the correct type.

palindrome :: Int
palindrome = maximum . map read . filter ...

Another approach is to only convert a value to a String in the filter itself:

palindrome :: Int
palindrome = maximum $ filter (\a -> let sa = show a in reverse sa == sa) [ x*y | x <- [100..999], y <- [x..999]]
like image 128
chepner Avatar answered Jan 07 '23 18:01

chepner