NOTE: I'm not allowed to use any built-in functions
Given positive ints r and c indicating the number of rows and columns, create a 2D list that represents the "augmented identity matrix" with that dimension: It's the k x k identity matrix (where k = min(r,c)), and augmented rightwards or downwards as needed with zeroes in order to be of size r x c. Stated another way, it's an r x c matrix filled with zeroes that has ones along its main diagonal. I have to write this in both python and Haskell. I wrote the python solution but I'm kinda stuck on Haskell. The Haskell function has to be the following form:
augdentity :: Int -> Int -> [[Int]]
*Homework4> augdentity 3 3
[[1,0,0],[0,1,0],[0,0,1]]
*Homework4> augdentity 3 5
[[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0]]
*Homework4> augdentity 5 3
[[1,0,0],[0,1,0],[0,0,1],[0,0,0],[0,0,0]]
*Homework4> augdentity 2 2
[[1,0],[0,1]]
def augdentity(r,c):
answer = []
for row in range(0, r):
newRow = [0] * c
for col in range(0, c):
if row == col:
newRow[col] = 1
answer.append(newRow)
return answer
So I got this for my haskell function. Put zeros in list when x != y but I don't know how to put 1 when x == y
augdentity :: Int -> Int -> [[Int]]
augdentity x y = [[0 | y <- [1 .. y], x /= y] | x <- [1 .. x]]
How about using if ... then ... else:
augdentity :: Int -> Int -> [[Int]]
augdentity r c = [[ if i == j then 1 else 0 | j <- [1..c] ] | i <- [1..r] ]
main = mapM_ (print . uncurry augdentity) [(3,3),(3,5),(5,3),(2,2)]
-- [[1,0,0],[0,1,0],[0,0,1]]
-- [[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0]]
-- [[1,0,0],[0,1,0],[0,0,1],[0,0,0],[0,0,0]]
-- [[1,0],[0,1]]
Similarly, the python code could be simplified:
def augdentity(rows, cols):
return [[int(i == j) for j in range(cols)] for i in range(rows)]
for dim in [(3,3),(3,5),(5,3),(2,2)]:
print(augdentity(*dim))
# [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
# [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0]]
# [[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0], [0, 0, 0]]
# [[1, 0], [0, 1]]
Related
Haskell's HMatrix allows you to conveniently get slices:
m ?? (All, Take 3)
But how can you set slices, especially non-rectangular ones? For instance, in Python's Numpy I'd do:
>>> x = np.arange(12).reshape(3, 4)
>>> x
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x[[0,0], [1,3]] += x[[2,2], [1,3]] # to ix (0, 1) add (2, 1) and to ix (0, 3) add (2, 3)
>>> x
array([[ 0, 10, 2, 14],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
I'm able to write this helper function myself, but, it's sure ugly, and partial, and required I add zipWith3M_ which should exist in the vector library but doesn't:
setSlice :: (Element t, Num t) => Matrix t -> (Extractor, Extractor) -> Vector t -> Matrix t
setSlice parent (Pos (V.map fromIntegral -> irows), Pos (V.map fromIntegral -> icols)) sub = runST $ do
tparent <- thawMatrix parent
zipWith3M_ (writeMatrix tparent) irows icols sub
freezeMatrix tparent
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 am trying to do extended unpacking of tuple with * syntax. I'm trying to format string with f'' string syntax. None of those work in visual-studio-code python3.7.3 linuxmint64 system.
l = [1, 2, 3, 4, 5, 6]
a, *b = l
print(a, b)
Here is the error :
line 3
a, *b = l
^
SyntaxError: invalid syntax
Your Code:
l = [1, 2, 3, 4, 5, 6]
a, *b = l
print(a, b)
The above code won't as the correct syntax is b=[*l]. The * is used to unpack a list.
So if you want to have some values in both a and b so the code below...
l = [1, 2, 3, 4, 5, 6]
d = [3,2,1]
a , b = [*l] , [*d] # Here [*l] unpacks l in a list and assign it to a and
# and [*d] unpacks d in a list and assign it to b
print(a , b)
Hope this helps...
Hello i am a beginner in haskell and i have a problem with comparing/matching Strings from a set List with a given String as Parameter.
What i want to achieve is:
I have a set List
colorTypes = ["red" , "blue" ,"yellow" , "green" ]
what i want to do is make a Function to compare each element of the List with a given String using the isInfixOf Function from Data.List and depending on the outcome from isInfixOf return a Pattern
Example if i use the function:
getColorData colorTypes "red"
it should return
[1, 0, 0, 0]
What i have tried is:
import Data.List
getColorData :: [String] -> String -> [Int]
getColorData (g:h:j:k) str
| isInfixOf g str = [1, 0, 0, 0]
| isInfixOf h str = [0, 1, 0, 0]
| isInfixOf j str = [0, 0, 1, 0]
| isInfixOf k str = [0, 0, 0, 1]
| otherwise = []
i get the error : Parse error in pattern: isInfixOf with this function
i also tried this with case
getColorData :: [String] -> String -> [Int]
getColorData (g:h:j:k) str = case (g:h:j:k) of
isInfixOf g str -> [1, 0, 0, 0]
isInfixOf h str -> [0, 1, 0, 0]
isInfixOf j str -> [0, 0, 1, 0]
isInfixOf k str -> [0, 0, 0, 1]
this also doesnt work and i get the Couldn't match type error.
I don't know if my approach is wrong or if there are any other ways to get what i want but i appreciate any help
The problem is here that you pattern match with:
getColorData (g:h:j:k) str
Here g, h, and j are the heads (first elements) of the list, but k is the tail of the list (the remaining items). So k has as type [String], not String.
We can fix it by using [g,h,j,k] which is a list of four elements:
getColorData :: [String] -> String -> [Int]
getColorData [g,h,j,k] str
| isInfixOf g str = [1, 0, 0, 0]
| isInfixOf h str = [0, 1, 0, 0]
| isInfixOf j str = [0, 0, 1, 0]
| isInfixOf k str = [0, 0, 0, 1]
| otherwise = []
But still it is not really good design. Since for lists with less, or more than four elements, this function will error. I'm also not sure whether using an isInfixOf condition is a good idea at all: it means that the order of the list can sometimes determine what the result will be: a list where two elements are swapped might result in a different. Finally the code is very repetitive (not following the Don't Repeat Yourself principle).
A more elegant version could be:
getColorData :: Eq a => [a] -> [a] -> Maybe [Int]
getColorData [] _ = Nothing
getColorData (x:xs) s | isInfixOf x s = Just (1: map (const 0) xs)
| otherwise = fmap (0:) (getColorData xs s)
Here we let it work for any type a where two as have an equality relation. Furthermore it works with lists of all lengths. It returns Nothing if the elements can not be found, and Just e with e an entity vector with the length of the list as the number of dimensions.
How can I build an infinite matrix with numbers placed in it diagonally with list comprehension?
[[ 1, 2, 4, 7, 11, ...],
[ 3, 5, 8, 12, 17, ...],
[ 6, 9, 13, 18, 24, ...],
[10, 14, 19, 25, 32, ...],
...]
I've tried to do it like this:
firstColumn = take 6 $ map fst $ iterate (\(a,b) -> (a+b,b+1)) (1,2)
matr :: [[Int]]
matr = [take 6 $ map fst $ iterate (\(x,y) -> (x+y, y+1)) (a, i) | a <- firstColumn, let i = 1]
But how can I pass (i + 1) to next every row (in other words, how do I iterate for additional rows)
By finding a formula for the x and y indices, f.e.:
[[ 1 + (x + y) * (x + y + 1) `div` 2 + y | x <- [0..]] | y <- [0..]]