Haskell optimization program - haskell

Have the task
I need to implement the function Change, which will take the value and split it into the possible combinations from list of coins(random list)
Example:
coins = [2,3,7]
GHCi> change 7
[[2,2,3],[2,3,2],[3,2,2],[7]]
That's what I did:
coins :: Num a => [a]
coins = [2, 3, 7]
change :: (Ord a, Num a) => a -> [[a]]
change n = uniqEl (filter (\x -> sum x == n) take ()(subsequences (replic' n coins coins)))
replic' n x y | n == 1 = y
| otherwise = replic' (n-1) x (y ++ x)
uniqEl :: Eq a => [a] -> [a]
uniqEl [] = []
uniqEl (x:xs) = if (x `elem` xs) then uniqEl xs else x : (uniqEl xs)
But this code is very slow. Help to make this program more quickly. As part of the job it is said that this task is easily done with the help of generators lists and recursion. Thank you in advance for your help.

import Data.List
change :: [Int] -> Int -> [[Int]]
change _ 0 = []
change coins n = do
x <- [c | c <- coins, c <= n]
if x == n
then return [x]
else do
xs <- change coins (n - x)
-- if (null xs)
-- then return [x]
-- else if x < (head xs)
-- then []
-- else return (x:xs)
return (x:xs)
change' :: Int -> [[Int]]
change' = change [2,3,7]
test7 = change' 7
test6 = change' 6
test5 = change' 5
test4 = change' 4

You're doing a lot of filtering, eleming and so on, and placing a lot of constraints on the data types.
Think of this more as a dynamic problem, that you constantly need to figure out how many ways there are to return change for a total amount.
Once you have found the amount of possibilities for a specific coin, you can remove it from the list.
Here is my proposed solution wrapped up in one function.
In the list comprehension, note that I assign values to the remaining variable, and that these values range from [0,total], with jumps every x, where x is the denomination.
For example, if you had to calculate how many times $0.25 goes into a $2 total, that list comprehension ends up doing:
[countChange 2, countChange 1.75,countChange 1.5, countChange 1.25,...], but also these next iterations of countChange don't include the 0.25 coin - because we just "tested" that.
-- Amount to return -> List of Coin denominations available
countChange :: Integer -> [Integer] -> Integer
countChange _ [] = 0 -- No coins at all, so no change can be given
countChange 0 _ = 1 -- Only one way to return 0 change
countChange total (x:xs) = sum [countChange (total-remaining) xs | remaining <- [0,x..total]]

Use MemoCombinators. This is fast ! Pls. try change 100
import Data.List
import qualified Data.MemoCombinators as Memo
coins :: [Int]
coins = [2,3,7]
change :: Int -> [[Int]]
change = Memo.integral change'
change' 0 = []
change' n = do
x <- [c | c <- coins, c <= n]
if x == n
then return [x]
else do
xs <- change (n - x)
-- if (null xs)
-- then return [x]
-- else if x < (head xs)
-- then []
-- else return (x:xs)
return (x:xs)

Related

Double a list (numbers in the list) in Haskell

Can someone else this codes in Haskell:
Doubling Digits
The digits need to be doubled, for this the following function can be defined:
doubleDigits :: [Integer] -> [Integer]
The function doubleDigits must double every other number starting from the right.
The second-to-last number is doubled first, then the fourth-to-last, ..., and so on.
Input: doubleDigits [1,2,3,4,5,6,7]
Output: [1,4,3,8,5,12,7]
toDigitsReverse :: Integer -> [Integer]
toDigitsReverse n = reverse (toDigits n)
-- function to help double every other element of list
doubleDigitsHelper :: [Integer] -> Integer -> [Integer]
doubleDigitsHelper l t
| l == [] = []
| t == 0 = [head l] ++ (doubleDigitsHelper (drop 1 l) 1)
| t == 1 = [2*(head l)] ++ (doubleDigitsHelper (drop 1 l) 0)
-- function to double every other element
doubleDigits :: [Integer] -> [Integer]
doubleDigits l = reverse (doubleDigitsHelper (reverse l) 0)
An alternate approach:
Let's zip the elements of the list with their indices.
[1,2,3,4,5,6,7] `zip` [0..]
We get:
[(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6)]
Then we can map this to the desired result:
let f (x, i) = if even i then x else x * 2 in map f $ [1,2,3,4,5,6,7] `zip` [0..]
And the result is:
[1,4,3,8,5,12,7]
Or written a little bit differently:
doubleDigits lst = map f lst'
where
lst' = lst `zip` [0..]
f (x, i)
| even i = x
| otherwise = x * 2
Because you want to double every other element starting from the right, you can simply reverse the list, zip it with indices, map, then reserve the output.
doubleDigits lst = reverse $ map f lst'
where
lst' = (reverse lst) `zip` [0..]
f (x, i)
| even i = x
| otherwise = x * 2
I would say that first of all there is no point to reverse list, determine if accumulator (t) is even or odd (there are build in functions for that - for example even) and then act accordingly. Next what can imporve the code - use pattern matching instead of == and head/tail calls. Also I've changed the order of the helper function:
-- function to help double every other element of list
doubleDigitsHelper :: Integer -> [Integer] -> [Integer]
doubleDigitsHelper _ [] = []
doubleDigitsHelper t (x:xs) | even t = x : doubleDigitsHelper (t+1) xs
| otherwise = 2*x : doubleDigitsHelper (t+1) xs
-- function to double every other element
doubleDigits :: [Integer] -> [Integer]
doubleDigits = doubleDigitsHelper 0
You could put the alternating functions you want to apply in a list (cycle [id, (*2)]) and apply these to your list using zipWith.
doubleDigits :: Num a => [a] -> [a]
doubleDigits = reverse . zipWith ($) (cycle [id, (*2)]) . reverse
I don't see an elegant way around reversing the list if you want to alternate starting from the right. You could, for example, look at the length of the list first and change the order of the functions based on that, but that would complicate the function a little.
doubleDigits xs = zipWith ($) fs xs
where fs = (if even . length $ xs then tail else id) $ cycle [id, (*2)]

create a function ved that will only remove the last occurrence of the largest item in the list using recursion

You must use recursion to define rmax2 and you must do so from “scratch”. That is, other than the cons operator, head, tail, and comparisons, you should not use any functions from the Haskell library.
I created a function that removes all instances of the largest item, using list comprehension. How do I remove the last instance of the largest number using recursion?
ved :: Ord a => [a] -> [a]
ved [] =[]
ved as = [ a | a <- as, m /= a ]
where m= maximum as
An easy way to split the problem into two easier subproblems consists in:
get the position index of the rightmost maximum value
write a general purpose function del that eliminates the element of a list at a given position. This does not require an Ord constraint.
If we were permitted to use regular library functions, ved could be written like this:
ved0 :: Ord a => [a] -> [a]
ved0 [] = []
ved0 (x:xs) =
let
(maxVal,maxPos) = maximum (zip (x:xs) [0..])
del k ys = let (ys0,ys1) = splitAt k ys in (ys0 ++ tail ys1)
in
del maxPos (x:xs)
where the pairs produced by zip are lexicographically ordered, thus ensuring the rightmost maximum gets picked.
We need to replace the library functions by manual recursion.
Regarding step 1, that is finding the position of the rightmost maximum, as is commonly done, we can use a recursive stepping function and a wrapper above it.
The recursive step function takes as arguments the whole context of the computation, that is:
current candidate for maximum value, mxv
current rightmost position of maximum value, mxp
current depth into the original list, d
rest of original list, xs
and it returns a pair: (currentMaxValue, currentMaxPos)
-- recursive stepping function:
findMax :: Ord a => a -> Int -> Int -> [a] -> (a, Int)
findMax mxv mxp d [] = (mxv,mxp)
findMax mxv mxp d (x:xs) = if (x >= mxv) then (findMax x d (d+1) xs)
else (findMax mxv mxp (d+1) xs)
-- top wrapper:
lastMaxPos :: Ord a => [a] -> Int
lastMaxPos [] = (-1)
lastMaxPos (x:xs) = snd (findMax x 0 1 xs)
Step 2, eliminating the list element at position k, can be handled in very similar fashion:
-- recursive stepping function:
del1 :: Int -> Int -> [a] -> [a]
del1 k d [] = []
del1 k d (x:xs) = if (d==k) then xs else x : del1 k (d+1) xs
-- top wrapper:
del :: Int -> [a] -> [a]
del k xs = del1 k 0 xs
Putting it all together:
We are now able to write our final recursion-based version of ved. For simplicity, we inline the content of wrapper functions instead of calling them.
-- ensure we're only using authorized functionality:
{-# LANGUAGE NoImplicitPrelude #-}
import Prelude (Ord, Eq, (==), (>=), (+), ($), head, tail,
IO, putStrLn, show, (++)) -- for testing only
ved :: Ord a => [a] -> [a]
ved [] = []
ved (x:xs) =
let
findMax mxv mxp d [] = (mxv,mxp)
findMax mxv mxp d (y:ys) = if (y >= mxv) then (findMax y d (d+1) ys)
else (findMax mxv mxp (d+1) ys)
(maxVal,maxPos) = findMax x 0 1 xs
del1 k d (y:ys) = if (d==k) then ys else y : del1 k (d+1) ys
del1 k d [] = []
in
del1 maxPos 0 (x:xs)
main :: IO ()
main = do
let xs = [1,2,3,7,3,2,1,7,3,5,7,5,4,3]
res = ved xs
putStrLn $ "input=" ++ (show xs) ++ "\n" ++ " res=" ++ (show res)
If you are strictly required to use recursion, you can use 2 helper functions: One to reverse the list and the second to remove the first largest while reversing the reversed list.
This result in a list where the last occurrence of the largest element is removed.
We also use a boolean flag to make sure we don't remove more than one element.
This is ugly code and I really don't like it. A way to make things cleaner would be to move the reversal of the list to a helper function outside of the current function so that there is only one helper function to the main function. Another way is to use the built-in reverse function and use recursion only for the removal.
removeLastLargest :: Ord a => [a] -> [a]
removeLastLargest xs = go (maximum xs) [] xs where
go n xs [] = go' n True [] xs
go n xs (y:ys) = go n (y:xs) ys
go' n f xs [] = xs
go' n f xs (y:ys)
| f && y == n = go' n False xs ys
| otherwise = go' n f (y:xs) ys
Borrowing the implementation of dropWhileEnd from Hackage, we can implement a helper function splitWhileEnd:
splitWhileEnd :: (a -> Bool) -> [a] -> ([a], [a])
splitWhileEnd p = foldr (\x (xs, ys) -> if p x && null xs then ([], x:ys) else (x:xs, ys)) ([],[])
splitWhileEnd splits a list according to a predictor from the end. For example:
ghci> xs = [1,2,3,4,3,2,4,3,2]
ghci> splitWhileEnd (< maximum xs) xs
([1,2,3,4,3,2,4],[3,2])
With this helper function, you can write ven as:
ven :: Ord a => [a] -> [a]
ven xs =
let (x, y) = splitWhileEnd (< maximum xs) xs
in init x ++ y
ghci> ven xs
[1,2,3,4,3,2,3,2]
For your case, you can refactor splitWhileEnd as:
fun p = \x (xs, ys) -> if p x && null xs then ([], x:ys) else (x:xs, ys)
splitWhileEnd' p [] = ([], [])
splitWhileEnd' p (x : xs) = fun p x (splitWhileEnd' p xs)
ven' xs = let (x, y) = splitWhileEnd' (< maximum xs) xs in init x ++ y
If init and ++ are not allowed, you can implement them manually. It's easy!
BTW, I guess this may be your homework for Haskell course. I think it's ridiculous if your teacher gives the limitations. Who is programming from scratch nowadays?
Anyway, you can always work around this kind of limitations by reimplementing the built-in function manually. Good luck!

Circular prime numbers

I am trying to convert the following function which test the number if it's prime to another one that test if the integer is a circular prime.
eg. 1193 is a circular prime, since 1931, 9311 and 3119 all are also prime.
So i need to rotate the digits of the integer and test if the number is prime or not. any ideas?
note: I am new to Haskell Programming
isPrime :: Integer -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime n
| (length [x | x <- [2 .. n-1], n `mod` x == 0]) > 0 = False
| otherwise = True
isCircPrime :: Integer -> Bool
You can improve the efficiency and elegance of your isPrime function easily by implementing it as:
isPrime :: Integral i => i -> Bool
isPrime 1 = False
isPrime n = all ((/=) 0 . mod n) (takeWhile (\x -> x*x <= n) [2..])
In order to rotate numbers, we can make use of two helper functions here: one to convert a number to a list of digits, and one to convert a list of digits to a number, we do this in reverse, since that is more convenient to implement, but will not matter:
num2dig :: Integral i => i -> [i]
num2dig n | n < 10 = [n]
| otherwise = r : num2dig q
where (q, r) = quotRem n 10
dig2num :: (Foldable t, Num a) => t a -> a
dig2num = foldr ((. (10 *)) . (+)) 0
Now we can make a simple function to generate, for a list of items, all rotations:
import Control.Applicative(liftA2)
import Data.List(inits, tails)
rots :: [a] -> [[a]]
rots = drop 1 . liftA2 (zipWith (++)) tails inits
So we can use this to construct all rotated numbers:
rotnum :: Integral i => i -> [i]
rotnum = map dig2num . rots . num2dig
For example for 1425, the rotated numbers are:
Prelude Control.Applicative Data.List> rotnum 1425
[5142,2514,4251,1425]
I leave using isPrime on these numbers as an exercise.
Referencing your question here, you can achieve what you want by adding a single new function:
check :: Integer -> Bool
check n = and [isPrime (stringToInt cs) | cs <- circle (intToString n)]
This is to add an easier to understand solution from where you already were in your specific code, as I can see you were asking for that specifically. Usage:
*Main> check 1931
True
*Main> check 1019
False
Mind you, I have made some type-changes. I assume you want each function to be type-specific, due to their names. Full code, taken from your example:
circle :: String -> [String]
circle xs = take (length xs) (iterate (\(y:ys) -> ys ++ [y]) xs)
stringToInt :: String -> Integer
stringToInt x = read (x) :: Integer
intToString :: Integer -> String
intToString x = show x
isPrime :: Integer -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime n
| (length [x | x <- [2 .. n-1], n `mod` x == 0]) > 0 = False
| otherwise = True
check :: Integer -> Bool
check n = and [isPrime (stringToInt cs) | cs <- circle (intToString n)]

Group Sum to N: working with list of lists

I'm learning Haskell and working on a problem where you take in a number, n, and list, iL. With these you check what consecutive numbers would be < than n and store it in a list. You can have more than one list. I've created a function called groupSumtoN that would return this list of lists.
I've created a helper function helperToSum to recursively create the list and return the output, which takes the number n, input , and acc ( the result).
Here is what I have tried so far:
groupSumtoN :: (Ord a, Num a) => a -> [a] -> [[a]]
groupSumtoN n [] = []
groupSumtoN n iL = (helperToSum n iL [])
helperToSum n [] acc = acc
helperToSum n (x:xs) acc | (sum acc) + x < n = (helperToSum n xs (acc : x))
| (sum acc) + x > n = acc:(helperToSum n xs [x])
I get two infinite type errors, one for calling helperToSum from groupSumtoN and another in this line.
(sum acc) + x < n = (helperToSum n xs (acc : x))
As an example I have an example how this function should work below:
groupSumtoN 15 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[[1,2,3,4,5],[6,7],[8],[9],[10]]
Any help would be greatly appreciated.
The base case:
helperToSum n [] acc = acc
Does not make much sense, since it expects a list of lists. You need to return a singleton list:
helperToSun n [] acc = [acc]
Another problem is that (acc : x) is not valid. (:) is a constructor of a list, and has type (:) :: a -> [a] -> [a]. You can not use it to append values. We could, for now, use (x : acc). In that case, you will later need to reverse.
It is furthermore better to use otherwise as second guard. Here for example it is possible that the sum is exactly n, and that case is not covered right now.
With these problems in mind, we can fix the compilation errors, with the following function:
helperToSum :: (Ord a, Num a) => a -> [a] -> [a] -> [[a]]
helperToSum n [] acc = [acc]
helperToSum n (x:xs) acc | (sum acc) + x <= n = (helperToSum n xs (x : acc))
| otherwise = acc:(helperToSum n xs [x])
But here the groups will be reversed, and furthermore it is not very efficient. We can make a more lazy variant that on the fly calculates how much space is left in a group, and aims to assign the items in the current, or the next group based on that condition:
groupSumtoN :: (Ord a, Num a) => a -> [a] -> [[a]]
groupSumtoN n = go n
where go _ [] = [[]]
go r (x:xs) | x <= r = let (t:tl) = go (r-x) xs in (x:t) : tl
| x > n = error "Item too large"
| otherwise = [] : go n (x:xs)
Here an empty lists, will produce a single group:
Prelude> groupSumtoN 15 []
[[]]
I leave it as an exercise to further improve this.

Haskell: A function to compute the median value of a list

I have written a function to compute the median value of a list
task3 xs | null xs = Nothing
| odd len = xs !! mid
| even len = evenMedian
where len = length xs
mid = len `div` 2
evenMedian = (xs !! mid + xs !! (mid+1)) / 2
I thought it is right and it also pass the load. But when I use the function, it did not work.
What is wrong here?
As Lee mentioned, the list must be sorted first.
(The median of [1,1,8,1,1] is 1 (not 8). so you have to sort it to [1,1,1,1,8] and then take the one in the middle).
The other thing is, that you return Nothing, so the other results have to be of type Maybe a too:
Just $ xs !! mid
Just evenMedian
You can use sort from Data.List to sort your list before applying it to task3.
Like so:
task xs = task3 (sort xs)
How about Median of Medians? Note that this computes only an approximation to the median.
Here is a Haskell implementation:
import Data.List
median :: Ord a => [a] -> a
median xs = select (length xs `div` 2) xs
select :: Ord a => Int -> [a] -> a
select i xs
| n <= 5
= sort xs !! i
| lengthLower == i
= medianOfMedians
| lengthLower < i
= select (i - lengthLower - 1) upperPartition
| otherwise
= select i lowerPartition
where
n = length xs
medianOfMedians = median (map median (chunksOf 5 xs))
(lowerPartition, _:upperPartition) = partition (< medianOfMedians) xs
lengthLower = length lowerPartition
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs
| (beginning, rest) <- splitAt n xs
= beginning : chunksOf n rest
Recursion could do the job also.
import Data.List
medianFromSorted :: Fractional a => [a] -> Maybe a
medianFromSorted [] = Nothing
medianFromSorted [a] = Just a
medianFromSorted [a,b] = Just ((a + b) / 2)
medianFromSorted (a:xs) = medianFromSorted (init xs) -- init is not efficient
median :: Ord a => Fractional a => [a] -> Maybe a
median = medianFromSorted . sort
My version of median for Integer
import Data.List (sort)
getMiddle [] = 0
getMiddle xs = (a' + b') `div` 2
where a' = head $ drop a xs
b' = head $ drop b xs
a = (n `div` 2)
b = n' - 1
n' = n `div` 2
n = length xs
median :: [Integer] -> Integer
median [] = 0
median xs = result
where result = if (n `mod` 2 == 0)
then getMiddle sorted
else head $ drop a sorted
a = (n - 1) `div` 2
n = length xs
sorted = sort xs
main = print $ median [1, 4, 5, 7, 9, 100]
-- 6
Even with kaan's answer, this code will still not produce a correct median. Another issue that has been overlooked is that Haskell lists are zero indexed. As a result, all of the code is correct with kaan's additions except
evenMedian = (xs !! mid + xs !! (mid+1)) / 2
which should actually be
evenMedian = (xs !! (mid - 1) + xs !! mid) / 2
Otherwise the result is incorrect. The wrong way produces task3 [1, 2, 3, 4] == Just 3.5, while the correct way produces task3 [1, 2, 3, 4] == Just 2.5

Resources