This question already has an answer here:
Haskell get all the numbers whose sum is X
(1 answer)
Closed last year.
I'm Trying to create a program that finds every paritions of a number.
For example the ways to decompose 4 are:
[1, 1, 1, 1]
[1, 1, 2]
[1, 3]
[2, 2]
[4]
I've done it in Python with:
n = 4
x = [0 for i in range(n+1)]
t = [0 for i in range(n+1)]
x[0] = 1
def partition(i):
for j in range(x[i-1], (n - t[i-1])//2 + 1):
x[i] = j
t[i] = t[i-1] + j
partition(i+1)
x[i] = n - t[i-1]
print(x[1:i+1])
partition(1)
But i need to write it in Haskell. Is there any way?
Here's a hint:
It will be valuable to reverse the order while thinking about this, so you are trying to generate:
[1, 1, 1, 1]
[2, 1, 1]
[2, 2]
[3, 1]
[4]
So, first choose every possible first element, here 1, 2, 3, or 4. Say we've chosen 1, then there are 3 remaining. We can recursively compute all the partitions of 3, and then prepend 1 to each of them.
(Oh, that's not quite right! Still a good place to start. But you will have e.g. [1,2,1] generated, so you will need to add a parameter, I think, saying "don't generate any numbers greater than m")
And we have to make sure to get the base case right. How many partitions are there of 0? There is one, the empty partition!
You can also translate it very literally using mutable vectors. The main difference is that you need to separate reads and writes very explicitly in Haskell, so it becomes a bit more messy.
This is what I came up with without understanding your algorithm:
import Data.Foldable ( for_ )
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as M
main :: IO ()
main = do
let n = 4
x <- M.replicate (n + 1) 0
t <- M.replicate (n + 1) 0
M.write x 0 1
let partition i = do
x' <- M.read x (i - 1)
t' <- M.read t (i - 1)
for_ [x' .. (n - t') `quot` 2] $ \j -> do
M.write x i j
t' <- M.read t (i - 1)
M.write t i (t' + j)
partition (i + 1)
t' <- M.read t (i - 1)
M.write x i (n - t')
x' <- V.freeze (M.slice 1 i x)
print (V.toList x')
partition 1
Related
My current code is below. I think all of the functions, except for the last one are correct. What I'm trying to achieve with changeValueMatrix is to give a matrix, a matrix position and a value and then that value will replace the one that is at the current position. I've managed to reach the position and to change the value but I can only return the row on which I changed it and not the whole matrix. I am a Haskell beginner and I've only learned recursion just now but it would be ideal to use it here if possible.
type Matrix a = [[a]]
type MatrixDimension = (Int,Int)
type MatrixPosition = (Int,Int)
matrixDimension :: Matrix a -> MatrixDimension
matrixDimension m = (length m, length (head m))
returnValueList :: Int -> [a] -> a
returnValueList 0 (x:xs) = x
returnValueList i(x:xs) = returnValue (i-1)(xs)
changeValueList :: Int -> a -> [a] -> [a]
changeValueList 0 value (x:xs) = (value:xs)
changeValueList i value (x:xs) = x:(changeValueList (i-1) (value) (xs))
returnValueMatrix :: MatrixPosition-> Matrix a -> a
returnValueMatrix(m,n) matrix = returnValueList n (returnreturnValueList matrix)
changeValueMatrix :: MatrixPosition -> a -> Matrix a -> Matrix a
changeValueMatrix(0,c) value (x:xs) = a:xs
where a = changeValueList c value x
changeValueMatrix(r,c) valor (x:xs) =
where
row = returnValueList r (x:xs)
b = changeValueList c value row
You can build changeValueMatrix from the functions you’ve already defined:
changeValueMatrix :: MatrixPosition -> a -> Matrix a -> Matrix a
changeValueMatrix (r, c) value matrix
= changeValueList r -- (3)
(changeValueList c value -- (2)
(returnValueList r matrix)) -- (1)
matrix
At (1) you look up the row at index r in matrix, at (2) you replace the element at column c in that row with value, and at (3) you replace the row at index r in matrix with the modified row. For example:
-- Given: mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
changeValueMatrix (1, 1) 0 mat
==
changeValueList 1
(changeValueList 1 0
(returnValueList 1 mat))
mat
==
changeValueList 1
(changeValueList 1 0 [4, 5, 6])
mat
==
changeValueList 1 [4, 0, 6] mat
==
[ [1, 2, 3]
, [4, 0, 6]
, [7, 8, 9]
]
If you want a version of this using explicit recursion, which only traverses the rows once, you can inline the definition of changeValueList into changeValueMatrix:
changeValueMatrix (0, c) value (x : xs)
= changeValueList c value x : xs
changeValueMatrix (r, c) value (x : xs)
= x : changeValueMatrix (r - 1, c) value xs
Be aware that your code has a few failure cases, though:
Negative indices will produce infinite loops because you only test for 0 and recur with i - 1 on any other number
Overly large indices will run into the end of the list and crash because you don’t handle the [] case—the pattern matches are non-exhaustive, which the compiler will point out when enabling all warnings with -Wall
Similarly, matrices of zero width or height are representable, but these functions don’t handle the possibility (e.g. matrixDimension calls head on a possibly-empty list); you can avoid this using Data.List.NonEmpty or Data.Array as your backing type, the latter of which is also more efficient
I have a simple question about list in haskell. (I am a beginner in haskell)
I would know how can i replace an element in an array but as simple as possible.
[1, 2, 4, 4, 5]
to
[1, 2, 3, 4, 5]
And also how can i happend a number to a list
[1, 2, 3, 4]
to
[1, 2, 3, 4, 5]
I have already read that tutorial : http://learnyouahaskell.com/starting-out
I was thinking about this for the first problem :
array = [1, 2, 4, 4, 5]
array[2] = 2
and that for the second :
array = [1, 2, 3, 4]
array ++ [5]
Ps : the array ++ [5] works with ghci but when i do like that in code :
array = [1, 2, 3, 4]
modifyarray = do
print $ array !! 2
array ++ [5]
print $ array !! 4
that doesn't work ...
EDIT :
module Main where
import Lib
import System.Environment
import System.Exit
redPoint = [3,4,2]
fillArray file x = do
let line = lines file
print $ line
replaceAt x y = map (\(i,v) -> if (i==x) then y else v) . zip [1..]
replaceArray = do
print $ redPoint !! 2
replaceAt 2 9 redPoint
print $ redPoint !! 2
openfile a n path = do
file <- readFile path
fillArray file 0
replaceArray
exit = exitWith ExitSuccess
error_exit = exitWith (ExitFailure 84)
parse [a, n, path] = openfile a n path >> exit
parse [] = error_exit
main = do
getArgs >>= parse
This error :
Couldn't match type ‘[]’ with ‘IO’
Expected type: IO Integer
Actual type: [Integer]
• In a stmt of a 'do' block: replaceAt 2 9 redPoint
In the expression:
do print $ redPoint !! 2
replaceAt 2 9 redPoint
print $ redPoint !! 2
In an equation for ‘replaceArray’:
replaceArray
= do print $ redPoint !! 2
replaceAt 2 9 redPoint
print $ redPoint !! 2
you don't do mutation on the list but create a new list from the given list.
an example, without any error handling...
> replaceAt x y = map (\(i,v) -> if (i==x) then y else v) . zip [1..]
> replaceAt 3 10 [1..5]
[1,2,10,4,5]
create an indexed list by zipping with the counting numbers, write a map function to change the value at the desired index.
Lens! (Maybe it is overhead but anyway)
_drop 0 = id
_drop n = _tail . _drop (n - 1)
And use case
[1..5] & _drop 1 %~ (5:) -- [1,5,2,3,4]
Using lens
> import Control.Lens
Control.Lens> [1..5] & (ix 1) .~ 5
[1,5,3,4,5]
First of all, please ask only one question in a single post.
Here is an implementation which doesn't use Lens and more suitable for a beginner. The replaceAt function error handling needs some brain work. Without error handling it could be fitted in a single line.
These functions work on infinite lists, too. Execution time of replaceAt depends of i. Replacing element in the end of the list is slower than in the beginning because of the recursive nature of Haskell's lists.
module ListOperations where
replaceAt :: Int -> a -> [a] -> [a]
replaceAt i x xs = case (i<0, splitAt i xs) of
(False,(start,(_:end))) -> start ++ (x:end)
_ -> error "Index out of bounds"
append :: a -> [a] -> [a]
append x xs = xs ++ [x]
I want to write something like this:
> [(i, j) | i <- [1..10],
Just j <- [if (even i) then Just (i `div` 2) else Nothing]]
[(2,1),(4,2),(6,3),(8,4),(10,5)]
Putting the condition in a list and using <- to extract the result seems ad hoc.
I tried:
> [(i, j) | i <- [1..10],
let Just j = if (even i) then Just (i `div` 2) else Nothing]
But that failed.
The following works but seems awkward:
> [(i, j) | i <- [1..10],
let x = if (even i) then Just (i `div` 2) else Nothing,
isJust x,
let Just j = x]
[(2,1),(4,2),(6,3),(8,4),(10,5)]
Is there a preferred way to do this.
I know this particular problem can be solved in other ways, but let's assume I want to pattern match conditionally in a list comprehension. Is there a good way to do that?
Thanks.
Would this be acceptable for you?
[(i, j) | i <- [1..10], even i, let j = i `div` 2]
Another (IMO worse) option:
[(i, j) | i <- [1..10],
j <- if even i then [i `div` 2] else []]
Yet another:
do i <- [1..10]
j <- guard (even i) >> return (i `div` 2)
return (i,j)
Yet another:
[(i, j) | i <- [1..10],
j <- [i `div` 2 | even i]]
Really overkill and strongly not recommended:
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
testEvenRight :: Integral a => Either b a -> Maybe a
testEvenRight (Right n) | even n = Just n
testEvenRight _ = Nothing
pattern EvenRight n <- (testEvenRight -> Just n)
list1 = [Right 2, Right 1, Left "abc", Right 4, Right 5]
list2 = [(i,j) | EvenRight i <- list1 , let j = i `div` 2]
I'm new to Haskell. I was trying to solve the diophantine equation |x^y-y^x| is prime, using Haskell, for a given upper bound x, y < n.
So, I wrote this Haskell code:
-- list of primes
listprimesupto :: Integral a => a -> [a]
listprimesupto 1 = []
listprimesupto 2 = [2]
listprimesupto n = let halflstprimes = (listprimesupto (n `div` 2))
in halflstprimes++[i|i<-[((n `div` 2)+1)..n], (length [x|x<-halflstprimes, (i `mod` x) == 0])==0 ]
-- is prime?
is_prime :: Integral a => a -> Bool
is_prime 1 = False
is_prime n = let halflstprimes = (listprimesupto (n `div` 2))
in (length [x|x<-halflstprimes, (n `mod` x) == 0])==0
-- solve |x^y - y^x| == prime
xy_yx_p :: Integral t => t -> [(t, t)]
--xy_yx_p n = [(x,y)|x<-[2..n], y<-[2..n], x < y, (abs (x^y-y^x)) `elem` (listprimesupto (n^3))] -- version 1, works but upper limit too small
xy_yx_p n = [(x,y)|x<-[2..n], y<-[2..n], x < y, (let t=abs (x^y-y^x) in is_prime t)==True] -- version 2, hangs for n>3 ...
xy_yx_p n (version 2, uncommented) hangs for n > 3, in GHCi. Ctrl-C doesn't even work. I have to kill ghc from Activity Monitor (I'm on Mac).
Any idea what am I doing wrong in xy_yx_p? The other two functions seem to work fine.
Thanks in advance.
So, if it hangs for n = 4, what's so special about that case? Well, it's t. For x = 2 and y = 4, you will get
t = abs (2 ^ 4 - 4 ^ 2)
= abs (16 - 16 )
= abs 0
= 0
Therefore, you use 0 in is_prime, and thereby also in listprimesupto. This leads to a never ending recursion:
listprimesupto 0 = let halflstprimes = (listprimesupto (0 `div` 2))
in -- .....
So make sure that you handle non-positive inputs:
listprimesupto n | n <= 0 = []
is_prime n | n <= 1 = False
I'm trying to transform my recursive Fibonacci function into an iterative solution. I tried the following:
fib_itt :: Int -> Int
fib_itt x = fib_itt' x 0
where
fib_itt' 0 y = 0
fib_itt' 1 y = y + 1
fib_itt' x y = fib_itt' (x-1) (y + ((x - 1) + (x - 2)))
I want to save the result into variable y and return it when the x y matches with 1 y, but it doesn't work as expected. For fib_itt 0 and fib_itt 1, it works correctly, but for n > 1, it doesn't work. For example, fib_rek 2 returns 1 and fib_rek 3 returns 2.
Your algorithm is wrong: in y + (x-1) + (x-2) you only add up consecutive numbers - not the numbers in the fib.series.
It seems like you tried some kind of pair-approach (I think) - and yes it's a good idea and can be done like this:
fib :: Int -> Int
fib k = snd $ fibIt k (0, 1)
fibIt :: Int -> (Int, Int) -> (Int, Int)
fibIt 0 x = x
fibIt k (n,n') = fibIt (k-1) (n',n+n')
as you can see: this passes the two needed parts (the last and second-to-last number) around as a pair of numbers and keeps track of the iteration with k.
Then it just gives back the second part of this tuple in fib (if you use the first you will get 0,1,1,2,3,... but of course you can adjust the initial tuple as well if you like (fib k = fst $ fibIt k (1, 1)).
by the way this idea directly leeds to this nice definition of the fib.sequence if you factor the iteration out to iterate ;)
fibs :: [Int]
fibs = map fst $ iterate next (1,1)
where
next (n,n') = (n',n+n')
fib :: Int -> Int
fib k = fibs !! k