Replace element in list - haskell

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]

Related

How to read input from the user?

How to ask a user to give a number of 7 digits and define a
function which converts these digits into a list of individual Integers. The example:
toDigits (1234567) = [1, 2, 3, 4, 5, 6, 7]
toDigitsReverse 1234567 = [7, 6, 5, 4, 3, 2, 1]
NB. (1234567) should be entered by the user.
I know how to prompt the user and the function to get it into an array but I do not know how to put them together. This is what I get so far - the function to separate them.
toDigits :: Integral x => x -> [x]
toDigits 0 = []
toDigits x = toDigits (x div 10) ++ [x mod 10]
main :: IO ()
main = do
putStr "The split array is "
print(toDigits 1234567)
How to get the todigit function to accept input?
I also tried the following but it gives an error
toDigits :: Integer -> [Int]
toDigits n = map (\x -> read [x] :: Int) (show n)
main :: IO ()
main = do
putStrLn "Please enter the USI number: "
usi <- getLine
let usiasnumber = read usi :: Int
print("The USI split into single digit array is " ++ toDigits usiasnumber)
I did this but its not working. Where am I going wrong? This is the error it is giving me
Couldn't match type ‘Int’ with ‘Char’ Expected type: [Char] Actual
type: [Int]
The usual way to get a number from the user is to actually get a string from the user, then convert it to a number. Going from there to digits is just about the same thing as converting back to a string. I therefore recommend that you just skip the intermediate step and go straight from string to list of digits. If you want to reverse the digits and print them back out, say, just do that:
import Control.Monad
main = putStrLn . reverse =<< getLine
If you are going to use the digits for something else, you may want them in number form rather than character form; digitToInt will do that for you.
import Data.Char
main = map digitToInt <$> getLine -- exercise for the reader: do somethin' with the digits

Сoncatenation returns more elements than it should

I need get neighbours of cells on 1D closed field
for example:
neighbours [1,2,3,4,5,-1] (6 elements)
must return [[-1,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,-1],[5,-1,1]] (6 elements)
my code of neighbours
neighbours :: [a] -> [[a]]
neighbours l = concat [[[last l, head l, last $ take 2 l]], neighbours' l, [[l !! (length l - 2), last l, head l]]] where
neighbours' :: [a] -> [[a]]
neighbours' (a:b:c:xs) = [a, b, c]:neighbours (b:c:xs)
neighbours' _ = []
main = print $ neighbours [1, 2, 3, 4]
returns [[4,1,2],[1,2,3],[4,2,3],[2,3,4],[4,3,4],[3,4,3],[3,4,2],[3,4,1]] (8 elements), but expected [[4,1,2],[1,2,3],[2,3,4],[3,4,1]] (4 elements)
if I comment neighbours' l it return
[[4,1,2],[3,4,1]] as expected (2 elements)
if you leave only neighbours' l it return
[[1,2,3],[2,3,4]] as expected (2 elements)
2+2=4, but in this case for some reason it is 8
why it happens?
P.s.
neighbours' create middle of list
neighbours' [1,2,3,4,5,-1] == [[1,2,3],[2,3,4],[3,4,5],[4,5,-1]]
[last l, head l, last $ take 2 l] create head of list [-1,1,2]
[l !! (length l - 2), last l, head l] create last element of list [5,-1,1]
Your code is somewhat hard to grasp because your two functions, neighbour and neighbour', are mutually recursive, which is sort of unusual.
The key line in your code is:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours (b:c:xs)
If we assume that this is NOT intentional, and you just meant to write:
neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
-----------------------------------------------+---------
then the code works as you seem to expect.
Note that having long (over 80 characters) lines of code makes the thing very difficult to debug.
Suggested code:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExplicitForAll #-}
import qualified Data.List as L
neighbours :: [a] -> [[a]]
neighbours l = concat [
[[last l, head l, last $ take 2 l]],
neighbours' l,
[[l !! (length l - 2), last l, head l]]
]
where
neighbours' :: [a] -> [[a]]
neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
neighbours' _ = []
-- neighbour is British English, neighbor is US English
neighbors :: [a] -> [[a]]
neighbors xs =
take count $ drop (count-1) allTriplets -- section of infinite list
where
count = length xs
allTriplets = map (take 3) (L.tails (cycle xs)) -- raw material
main :: IO ()
main = do
print $ "res1 = " ++ (show $ neighbours [1, 2, 3, 4])
print $ "res2 = " ++ (show $ neighbors [1, 2, 3, 4])
Program output:
"res1 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"
"res2 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"

What does the double-backslash \\ mean in Haskell?

I'm trying to figure out what \\ means in Haskell?
I've got a program that runs perfectly when compiled, implying that \\ is a built-in function, since it's not defined anywhere in the program. However, in GHCi, if I try to use it in the same manner, I get an error saying it's not in the scope.
Does it mean something special in each context?
Here is my code;
module Main where
import Data.List
numbersA = [1, 105, 103, 7, 4, 102, 3, 101, 107, 8, 9]
numbersB = [6, 9, 7, 8, 1, 5, 3, 2, 4]
type Number = Integer
type Run = [Number]
extractRuns :: [Number] -> [Run]
extractRuns [] = []
extractRuns xs = run : extractRuns xs'
where run = buildRun (head xs) (tail xs)
xs' = xs \\ run
buildRun :: Number -> [Number] -> Run
buildRun seed numbers
| endRun = [seed]
| otherwise = seed : buildRun seed' numbers'
where endRun = successors == []
successors = filter (.#. seed) numbers
numbers' = numbers \\ [seed]
seed' = head successors
(.#.) :: Number -> Number -> Bool
x .#. y = x /= y && abs (x - y) < 10
runs = extractRuns numbersA
main = print runs
\\ is the list difference operator. You can use it in GHCi you just have to import Data.List first.
Prelude> :m Data.List
Prelude Data.List> [1..5]\\[3,4]
[1,2,5]
On a sidenote, this is why I'd suggest avoiding mass imports like import Data.List and to be more specific import Data.List ( (\\) ) so you can be more aware of just what you're importing.
It is the list difference operation. Figuring things like this out is easy if you know to use hoogle.

Haskell - how to generate permutations

How can I create a function which lazily makes permutations for the chars '_' and '*' like this:
For example:
Main> function 3
["___","*__","_*_","__*","**_","_**","*_*","***"]
First element is made only from _, the next 3 are permutations that lists: *__, the second 3 are permutations that lists **_, and the last element contains only *.
How can I do that?
Here's another "correct order" version:
function :: Int -> [String]
function c = concatMap helper $ zip (reverse [0..c]) [0..c]
helper :: (Int, Int) -> [String]
helper (c, 0) = [replicate c '_']
helper (0, c) = [replicate c '*']
helper (cUnderscores, cAsterisks) = map ('_' :) (helper (cUnderscores - 1, cAsterisks))
++ map ('*' :) (helper (cUnderscores, cAsterisks - 1))
You might want to look at replicateM.
let k = ["_", "*"]
let p = [ a ++ b ++ c | a <- k, b <- k, c <- k ]
The “correct order” version:
import Data.List
function k = concatMap (nub . permutations . pat) [0..k]
where pat x = replicate x '*' ++ replicate (k-x) '_'
I don’t know how to step from one permutation to another in constant time, though.

Comparing 3 output lists in haskell

I am doing another Project Euler problem and I need to find when the result of these 3 lists is equal (we are given 40755 as the first time they are equal, I need to find the next:
hexag n = [ n*(2*n-1) | n <- [40755..]]
penta n = [ n*(3*n-1)/2 | n <- [40755..]]
trian n = [ n*(n+1)/2 | n <- [40755..]]
I tried adding in the other lists as predicates of the first list, but that didn't work:
hexag n = [ n*(2*n-1) | n <- [40755..], penta n == n, trian n == n]
I am stuck as to where to to go from here.
I tried graphing the function and even calculus but to no avail, so I must resort to a Haskell solution.
Your functions are weird. They get n and then ignore it?
You also have a confusion between function's inputs and outputs. The 40755th hexagonal number is 3321899295, not 40755.
If you really want a spoiler to the problem (but doesn't that miss the point?):
binarySearch :: Integral a => (a -> Bool) -> a -> a -> a
binarySearch func low high
| low == high = low
| func mid = search low mid
| otherwise = search (mid + 1) high
where
search = binarySearch func
mid = (low+high) `div` 2
infiniteBinarySearch :: Integral a => (a -> Bool) -> a
infiniteBinarySearch func =
binarySearch func ((lim+1) `div` 2) lim
where
lim = head . filter func . lims $ 0
lims x = x:lims (2*x+1)
inIncreasingSerie :: (Ord a, Integral i) => (i -> a) -> a -> Bool
inIncreasingSerie func val =
val == func (infiniteBinarySearch ((>= val) . func))
figureNum :: Integer -> Integer -> Integer
figureNum shape index = (index*((shape-2)*index+4-shape)) `div` 2
main :: IO ()
main =
print . head . filter r $ map (figureNum 6) [144..]
where
r x = inIncreasingSerie (figureNum 5) x && inIncreasingSerie (figureNum 3) x
Here's a simple, direct answer to exactly the question you gave:
*Main> take 1 $ filter (\(x,y,z) -> (x == y) && (y == z)) $ zip3 [1,2,3] [4,2,6] [8,2,9]
[(2,2,2)]
Of course, yairchu's answer might be more useful in actually solving the Euler question :)
There's at least a couple ways you can do this.
You could look at the first item, and compare the rest of the items to it:
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [4,5,6] ]
False
Prelude> (\x -> all (== (head x)) $ tail x) [ [1,2,3], [1,2,3], [1,2,3] ]
True
Or you could make an explicitly recursive function similar to the previous:
-- test.hs
f [] = True
f (x:xs) = f' x xs where
f' orig (y:ys) = if orig == y then f' orig ys else False
f' _ [] = True
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> f [ [1,2,3], [1,2,3], [1,2,3] ]
True
*Main> f [ [1,2,3], [1,2,3], [4,5,6] ]
False
You could also do a takeWhile and compare the length of the returned list, but that would be neither efficient nor typically Haskell.
Oops, just saw that didn't answer your question at all. Marking this as CW in case anyone stumbles upon your question via Google.
The easiest way is to respecify your problem slightly
Rather than deal with three lists (note the removal of the superfluous n argument):
hexag = [ n*(2*n-1) | n <- [40755..]]
penta = [ n*(3*n-1)/2 | n <- [40755..]]
trian = [ n*(n+1)/2 | n <- [40755..]]
You could, for instance generate one list:
matches :: [Int]
matches = matches' 40755
matches' :: Int -> [Int]
matches' n
| hex == pen && pen == tri = n : matches (n + 1)
| otherwise = matches (n + 1) where
hex = n*(2*n-1)
pen = n*(3*n-1)/2
tri = n*(n+1)/2
Now, you could then try to optimize this for performance by noticing recurrences. For instance when computing the next match at (n + 1):
(n+1)*(n+2)/2 - n*(n+1)/2 = n + 1
so you could just add (n + 1) to the previous tri to obtain the new tri value.
Similar algebraic simplifications can be applied to the other two functions, and you can carry all of them in accumulating parameters to the function matches'.
That said, there are more efficient ways to tackle this problem.

Resources