updating all values on a row in a haskell matrix - haskell

I have such a code;
type El = Int
type Idx = Int
type Mat a = [[a]]
type Row a = [a]
mapr :: Idx -> (Row El -> Row El) -> Mat El -> Mat El
mapr ----- ??????
main = do
let a = [[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]]
let res = mapr 2 a
By using mapr function type, I want to update all values on a row on a matrix. Let's say I want to increase all the values in a specific row by 1. But the way I have explained mapr function is wrong. How should I modify my code to update values on a row on matrix a by using mapr function type?

I think it would be easiest to write this in a recursive function
mapr n _ [] = error $ "index: "++ show n ++" out of bounds"
mapr n f (x:xx) | n < 0 = error "negative index"
| n == 0 = f x : xx
| otherwise = x : mapr (n-1) f xx
the following code runs:
main :: IO ()
main = do let a = [[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]]
res = mapr 2 (const []) a
print res
you can replace const [] with all functions that work on rows - for example map (+1) as well.
Update:
Here is one version that uses zip to get indices for comparison, and I have changed the type of the function to work element-wise instead of row wise.
mapr' :: Idx -> (El -> El) -> Mat El -> Mat El
mapr' n f xx = map (mapIf n f) $ zip xx [0..]
where mapIf n f (row,idx) = if idx == n then (map f row)
else row
This is a bit terse so, would ask you to fire up ghci and evaluate the following expressions to get a feeling what it does:
zip ['a'..'z'] [0..]
map succ ['a'..'c'] and map (*3) [10,9..1]
let mapIf n f (row,idx) = if idx == n then (map f row) else row
mapIf 1 (*3) ([10,9..1],0)
mapIf 0 (*3) ([10,9..1],0)
map (map (*3)) [[1,2,3],[1,2,4]]

Your code contains several problems:
the mapr function should take three arguments (an index, a function that should be applied to the row, and a matrix), but the stub implementation contains only two
mapr idx f m = ...
the +1 in the definition of mapr should be replaced by the function that is provided as an argument to mapr
mapr idx f m = ... f ...
there should be parentheses around +1
(+1)
your mapr expects a function of type [a] -> [a]; +1 doesn't fit the bill, you need map (+1)
Altogether, we get:
type El = Int
type Idx = Int
type Mat a = [[a]]
type Row a = [a]
mapr :: Idx -> (Row El -> Row El) -> Mat El -> Mat El
mapr idx f m = [ m!!i | i <- [0.. (idx-1)]] ++ [(f (m !! idx))] ++ [m!!i | i <- [(idx+1) .. (length m-1)]]
main =
let
a = [[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]]
res = mapr 2 (\x -> map (\y -> y + 1) x) a
in
print res

Related

Find the max in a list of lists of type Numbers in Haskell

I'm pretty new to Haskell and am trying to find the max value in a list of lists that contain type Numbers. Numbers is defined as:
data Numbers = StrNumber String | IntNumber Int
deriving (Show, Read, Eq)
I already have a function that finds the max int value in a list of lists of type int.
nested_max :: [[Int]] -> Int
nested_max [] = minBound::Int
nested_max list = maxL (map maxL list)
where
maxL xs = foldr gt (minBound::Int) xs
gt x y = if x < y then y else x
And can use getInt to convert Numbers to ints.
getInt x = read x::Int
I've been trying to map getInt to every value in the list being passed in and then applying nested_max on that list, but keep getting errors.
This is what I've been trying:
getInt x = read x::Int
to_int :: [[Numbers]] -> [[Int]]
to_int list = map (\x-> getInt x) list
An example of what the program should do is...
Input: find_max_number [[StrNumber "9",IntNumber 2,IntNumber 8],[StrNumber "4",IntNumber 5],[IntNumber 6,StrNumber "7"],[],[StrNumber "8"]]
Output: 9
The following is my attempt:
data Numbers
= StrNumber String
| IntNumber Int
nestedMax :: [[Numbers]] -> Int
nestedMax = maximum . map toInt . concat
where toInt (StrNumber x) = read x
toInt (IntNumber x) = x
main = do
print $ nestedMax [[StrNumber "9",IntNumber 2,IntNumber 8],[StrNumber "4",IntNumber 5],[IntNumber 6,StrNumber "7"],[],[StrNumber "8"]] -- 9
I hope the code is straightforward...

Calculate module of "Just int" in Haskell

I'm trying to calculate the module of an index of a list.
list=[5,6,7,8]
a = elemIndex 7 list
b = mod a 2
Ideally, this would give me b = 0 since a = 2 (technically).
But I'm getting error messages since a is not 2 but Just 2.
You can do this with fmap :: Functor f => (a -> b) -> f a -> f b or its operator variant (<$>) :: Functor f => (a -> b) -> f a -> f b to apply a function to the item wrapped in the Just … data constructor:
b = (`mod` 2) <$> a
this will then return Just 0 when a is Just 2, and Nothing if the elemIndex returned a Nothing. This thus means that if elemIndex fails (because the index is out of range), b will be Nothing.
You can just use pattern matching with let to get to the inner part of the Maybe value when it is guaranteed to be Just _:
list = [5,6,7,8]
a = elemIndex 7 list
b = mod a 2
foo list = [b | n <- [5,6,7,8]
, let a = elemIndex n [5,6,7,8]
, let Just i = a
, let b = mod i 2]
= [b | n <- list
, let Just i = elemIndex n list
, let b = mod i 2]
= [b | (_, i) <- zip list [0..]
, let b = mod a 2]
= ls where ls = [0,1] ++ ls
bar list = [(n,b) | n <- list
, let Just i = elemIndex n list
, let b = mod i 2]
= [(n,b) | (n, i) <- zip list [0..]
, let b = mod i 2]
= zip list ls where ls = cycle [0,1]
Normally this kind of pattern matching is frowned upon since it is partial, i.e. can cause error if the value is actually Nothing, but here it is correct by construction.
But then really, why put it into a Just -- just use it as it is. And we did.

Generate next lexicographical string in Haskell

If I was given a string like skhfbvqa, how would I generate the next string? For this example, it would be skhfbvqb, and the next string of that would be skhfbvqc, and so on. The given string (and the answer) will always be N characters long (in this case, N=8).
What I tried:
I tried to generate the entire (infinite) list of possible combinations, and get the required (next) string of the given string, but unsurprisingly, it's so slow, that I don't even get the answer for N=6.
I used list comprehension:
allStrings = [ c : s | s <- "" : allStrings, c <- ['a'..'z'] ]
main = do
input <- readFile "k.in"
putStrLn . head . tail . dropWhile (not . (==) input) . map reverse $ allStrings
(Please excuse my incredibly bad Haskell-ing :) Still a noob)
So my question is, how can I do this? If there are multiple methods, a comparison between them is much appreciated. Thanks!
Here's a version with base conversion (this way you could add and subtract arbitrarily if you like):
encode x base = encode' x [] where
encode' x' z | x' == 0 = z
| otherwise = encode' (div x' base) ((mod x' base):z)
decode num base =
fst $ foldr (\a (b,i) -> (b + a * base^i,i + 1)) (0,0) num
Output:
*Main> map (\x -> toEnum (x + 97)::Char)
$ encode (decode (map (\x -> fromEnum x - 97) "skhfbvqa") 26 + 1) 26
"skhfbvqb"
I would go and make a helper function f :: Integer -> String and one g :: String -> Integer, where f 1 = "a", ... f 27 = "aa", f 28 = "ab" and so on and the inverse g.
Then incrementString = f . succ . g
Note: I omitted the implementation of f on purpose for learning
Update
for a different approach you could define a increment with carry function inc' :: Char -> (Char, Bool), and then
incString :: String -> String
incString = reverse . incString'
where incString' [] = []
incString' (x:xs) = case inc' x of (x',True) -> x': incString' xs
(x',False) -> x':xs
Note: this function is not tail recursive!
I found this to work. It just uses pattern matching to see if the string begins with a z and adds an additional a accordingly.
incrementString' :: String -> String
incrementString' [] = ['a']
incrementString' ('z':xs) = 'a' : incrementString' xs
incrementString' (x:xs) = succ x : xs
incrementString :: String -> String
incrementString = reverse . incrementString' . reverse

Defining a Boolean function on Haskell that determines if an element occurs once in a list

So I'm trying to define a function in Haskell that if given an integer and a list of integers will give a 'true' or 'false' whether the integer occurs only once or not.
So far I've got:
let once :: Eq a => a -> [a] -> Bool; once x l =
But I haven't finished writing the code yet. I'm very new to Haskell as you may be able to tell.
Start off by using pattern matching:
once x [] =
once x (y:ys) =
This won't give you a good program immediately, but it will lead you in the right direction.
Here's a solution that doesn't use pattern matching explicitly. Instead, it keeps track of a Bool which represents if a occurance has already been found.
As others have pointed out, this is probably a homework problem, so I've intentionally left the then and else branches blank. I encourage user3482534 to experiment with this code and fill them in themselves.
once :: Eq a => a -> [a] -> Bool
once a = foldr f False
where f x b = if x == a then ??? else ???
Edit: The naive implementation I was originally thinking of was:
once :: Eq a => a -> [a] -> Bool
once a = foldr f False
where f x b = if x == a then b /= True else b
but this is incorrect as,
λ. once 'x' "xxx"
True
which should, of course, be False as 'x' occurs more than exactly once.
However, to show that it is possible to write once using a fold, here's a revised version that uses a custom monoid to keep track of how many times the element has occured:
import Data.List
import Data.Foldable
import Data.Monoid
data Occur = Zero | Once | Many
deriving Eq
instance Monoid Occur where
mempty = Zero
Zero `mappend` x = x
x `mappend` Zero = x
_ `mappend` _ = Many
once :: Eq a => a -> [a] -> Bool
once a = (==) Once . foldMap f
where f x = if x == a then Once else Zero
main = do
let xss = inits "xxxxx"
print $ map (once 'x') xss
which prints
[False,True,False,False,False]
as expected.
The structure of once is similar, but not identical, to the original.
I'll answer this as if it were a homework question since it looks like one.
Read about pattern matching in function declarations, especially when they give an example of processing a list. You'll use tools from Data.List later, but probably your professor is teaching about pattern matching.
Think about a function that maps values to a 1 or 0 depending on whethere there is a match ...
match :: a -> [a] -> [Int]
match x xs = map -- fill in the thing here such that
-- match 3 [1,2,3,4,5] == [0,0,1,0,0]
Note that there is the sum function that takes a list of numbers and returns the sum of the numbers in the list. So to count the matches a function can take the match function and return the counts.
countN :: a -> [a] -> Int
countN x xs = ? $ match x xs
And finally a function that exploits the countN function to check for a count of only 1. (==1).
Hope you can figure out the rest ...
You can filter the list and then check the length of the resulting list. If length == 1, you have only one occurrence of the given Integer:
once :: Eq a => a -> [a] -> Bool
once x = (== 1) . length . filter (== x)
For counting generally, with import Data.List (foldl'), pointfree
count pred = foldl' (\ n x -> if pred x then n + 1 else n) 0
applicable like
count (< 10) [1 .. 10] == 9
count (== 'l') "Hello" == 2
gives
once pred xs = count pred xs == 1
Efficient O(n) short-circuit predicated form, testing whether the predicate is satisfied exactly once:
once :: (a -> Bool) -> [a] -> Bool
once pred list = one list 0
where
one [] 1 = True
one [] _ = False
one _ 2 = False
one (x : xs) n | pred x = one xs (n + 1)
| otherwise = one xs n
Or, using any:
none pred = not . any pred
once :: (a -> Bool) -> [a] -> Bool
once _ [] = False
once pred (x : xs) | pred x = none pred xs
| otherwise = one pred xs
gives
elemOnce y = once (== y)
which
elemOnce 47 [1,1,2] == False
elemOnce 2 [1,1,2] == True
elemOnce 81 [81,81,2] == False

Doing a binary search on some elements in Haskell

I'm trying to complete the last part of my Haskell homework and I'm stuck, my code so far:
data Entry = Entry (String, String)
class Lexico a where
(<!), (=!), (>!) :: a -> a -> Bool
instance Lexico Entry where
Entry (a,_) <! Entry (b,_) = a < b
Entry (a,_) =! Entry (b,_) = a == b
Entry (a,_) >! Entry (b,_) = a > b
entries :: [(String, String)]
entries = [("saves", "en vaut"), ("time", "temps"), ("in", "<`a>"),
("{", "{"), ("A", "Un"), ("}", "}"), ("stitch", "point"),
("nine.", "cent."), ("Zazie", "Zazie")]
build :: (String, String) -> Entry
build (a, b) = Entry (a, b)
diction :: [Entry]
diction = quiksrt (map build entries)
size :: [a] -> Integer
size [] = 0
size (x:xs) = 1+ size xs
quiksrt :: Lexico a => [a] -> [a]
quiksrt [] = []
quiksrt (x:xs)
|(size [y|y <- xs, y =! x]) > 0 = error "Duplicates not allowed."
|otherwise = quiksrt [y|y <- xs, y <! x]++ [x] ++ quiksrt [y|y <- xs, y >! x]
english :: String
english = "A stitch in time save nine."
show :: Entry -> String
show (Entry (a, b)) = "(" ++ Prelude.show a ++ ", " ++ Prelude.show b ++ ")"
showAll :: [Entry] -> String
showAll [] = []
showAll (x:xs) = Main.show x ++ "\n" ++ showAll xs
main :: IO ()
main = do putStr (showAll ( diction ))
The question asks:
Write a Haskell programs that takes
the English sentence 'english', looks
up each word in the English-French
dictionary using binary search,
performs word-for-word substitution,
assembles the French translation, and
prints it out.
The function 'quicksort' rejects
duplicate entries (with 'error'/abort)
so that there is precisely one French
definition for any English word. Test
'quicksort' with both the original
'raw_data' and after having added
'("saves", "sauve")' to 'raw_data'.
Here is a von Neumann late-stopping
version of binary search. Make a
literal transliteration into Haskell.
Immediately upon entry, the Haskell
version must verify the recursive
"loop invariant", terminating with
'error'/abort if it fails to hold. It
also terminates in the same fashion if
the English word is not found.
function binsearch (x : integer) : integer
local j, k, h : integer
j,k := 1,n
do j+1 <> k --->
h := (j+k) div 2
{a[j] <= x < a[k]} // loop invariant
if x < a[h] ---> k := h
| x >= a[h] ---> j := h
fi
od
{a[j] <= x < a[j+1]} // termination assertion
found := x = a[j]
if found ---> return j
| not found ---> return 0
fi
In the Haskell version
binsearch :: String -> Integer -> Integer -> Entry
as the constant dictionary 'a' of type
'[Entry]' is globally visible. Hint:
Make your string (English word) into
an 'Entry' immediately upon entering
'binsearch'.
The programming value of the
high-level data type 'Entry' is that,
if you can design these two functions
over the integers, it is trivial to
lift them to to operate over Entry's.
Anybody know how I'm supposed to go about my binarysearch function?
The instructor asks for a "literal transliteration", so use the same variable names, in the same order. But note some differences:
the given version takes only 1
parameter, the signature he gives
requires 3. Hmmm,
the given version is not recursive, but he asks for a
recursive version.
Another answer says to convert to an Array, but for such a small exercise (this is homework after all), I felt we could pretend that lists are direct access. I just took your diction::[Entry] and indexed into that. I did have to convert between Int and Integer in a few places.
Minor nit: You've got a typo in your english value (bs is a shortcut to binSearch I made):
*Main> map bs (words english)
[Entry ("A","Un"),Entry ("stitch","point"),Entry ("in","<`a>"),Entry ("time","te
mps"),*** Exception: Not found
*Main> map bs (words englishFixed)
[Entry ("A","Un"),Entry ("stitch","point"),Entry ("in","<`a>"),Entry ("time","te
mps"),Entry ("saves","en vaut"),Entry ("nine.","cent.")]
*Main>
A binary search needs random access, which is not possible on a list. So, the first thing to do would probably be to convert the list to an Array (with listArray), and do the search on it.
here's my code for just the English part of the question (I tested it and it works perfectly) :
module Main where
class Lex a where
(<!), (=!), (>!) :: a -> a -> Bool
data Entry = Entry String String
instance Lex Entry where
(Entry a _) <! (Entry b _) = a < b
(Entry a _) =! (Entry b _) = a == b
(Entry a _) >! (Entry b _) = a > b
-- at this point, three binary (infix) operators on values of type 'Entry'
-- have been defined
type Raw = (String, String)
raw_data :: [Raw]
raw_data = [("than a", "qu'un"), ("saves", "en vaut"), ("time", "temps"),
("in", "<`a>"), ("worse", "pire"), ("{", "{"), ("A", "Un"),
("}", "}"), ("stitch", "point"), ("crime;", "crime,"),
("a", "une"), ("nine.", "cent."), ("It's", "C'est"),
("Zazie", "Zazie"), ("cat", "chat"), ("it's", "c'est"),
("raisin", "raisin sec"), ("mistake.", "faute."),
("blueberry", "myrtille"), ("luck", "chance"),
("bad", "mauvais")]
cook :: Raw -> Entry
cook (x, y) = Entry x y
a :: [Entry]
a = map cook raw_data
quicksort :: Lex a => [a] -> [a]
quicksort [] = []
quicksort (x:xs) = quicksort (filter (<! x) xs) ++ [x] ++ quicksort (filter (=! x) xs) ++ quicksort (filter (>! x) xs)
getfirst :: Entry -> String
getfirst (Entry x y) = x
getsecond :: Entry -> String
getsecond (Entry x y) = y
binarysearch :: String -> [Entry] -> Int -> Int -> String
binarysearch s e low high
| low > high = " NOT fOUND "
| getfirst ((e)!!(mid)) > s = binarysearch s (e) low (mid-1)
| getfirst ((e)!!(mid)) < s = binarysearch s (e) (mid+1) high
| otherwise = getsecond ((e)!!(mid))
where mid = (div (low+high) 2)
translator :: [String] -> [Entry] -> [String]
translator [] y = []
translator (x:xs) y = (binarysearch x y 0 ((length y)-1):translator xs y)
english :: String
english = "A stitch in time saves nine."
compute :: String -> [Entry] -> String
compute x y = unwords(translator (words (x)) y)
main = do
putStr (compute english (quicksort a))
An important Prelude operator is:
(!!) :: [a] -> Integer -> a
-- xs!!n returns the nth element of xs, starting at the left and
-- counting from 0.
Thus, [14,7,3]!!1 ~~> 7.

Resources