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
Related
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]]
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...
I'm trying to understand how Haskell evalutes sep [1, 2, 3, 4, 5] to get ([1, 3], [2, 4, 5]) where:
sep [ ] = ([ ], [ ])
sep [x] = ([ ], [x])
sep (x1:x2:xs) = let (is, ps) = sep xs in (x1:is, x2:ps)
I start like this:
sep [1, 2, 3, 4, 5] = let (is, ps) = sep [3, 4, 5] in (1:is, 2:ps)
but then?
Finally I understood.
1) sep [1, 2, 3, 4, 5] = let (is, ps) = sep [3, 4, 5] in (1:is, 2:ps)
2) sep [3, 4, 5] = let (is, ps) = sep [5] in (3:is, 4:ps)
3) sep [5] = ([], [5])
In 2) sep [3, 4, 5] = let (is, ps) = ([], [5]) in (3:is, 4:ps) = ([3], [4, 5])
In 1) sep [1, 2, 3, 4, 5] = let (is, ps) = ([3], [4, 5]) in (1:is, 2:ps) = ([1, 3], [2, 4, 5])
After going through a couple of chapters of "Learn You A Haskell", I wanted to write something hands on and decided to implement a Sudoku solver.I am trying to implement the B1 function from here: http://www.cse.chalmers.se/edu/year/2013/course/TDA555/lab3.html
My code:
data Sudoku = Sudoku { getSudoku :: [[Maybe Int]] } deriving (Show, Eq)
rows :: Sudoku -> [[Maybe Int]]
rows (Sudoku rs) = rs
example :: Sudoku
example = Sudoku
[ [Just 3, Just 6, Nothing,Nothing,Just 7, Just 1, Just 2, Nothing,Nothing]
, [Nothing,Just 5, Nothing,Nothing,Nothing,Nothing,Just 1, Just 8, Nothing]
, [Nothing,Nothing,Just 9, Just 2, Nothing,Just 4, Just 7, Nothing,Nothing]
, [Nothing,Nothing,Nothing,Nothing,Just 1, Just 3, Nothing,Just 2, Just 8]
, [Just 4, Nothing,Nothing,Just 5, Nothing,Just 2, Nothing,Nothing,Just 9]
, [Just 2, Just 7, Nothing,Just 4, Just 6, Nothing,Nothing,Nothing,Nothing]
, [Nothing,Nothing,Just 5, Just 3, Nothing,Just 8, Just 9, Nothing,Nothing]
, [Nothing,Just 8, Just 3, Nothing,Nothing,Nothing,Nothing,Just 6, Nothing]
, [Nothing,Nothing,Just 7, Just 6, Just 9, Nothing,Nothing,Just 4, Just 3]
]
printSudoku :: Sudoku -> IO ()
printSudoku s = do
print . map (map (\x -> if isNothing x then 0 else fromJust x)) $ rows s
I am trying to get it to print as
Sudoku> printSudoku example
36..712..
.5....18.
..92.47..
....13.28
4..5.2..9
27.46....
..53.89..
.83....6.
..769..43
but I can only get it to print as
[[3,6,0,0,7,1,2,0,0],[0,5,0,0,0,0,1,8,0],[0,0,9,2,0,4,7,0,0],[0,0,0,0,1,3,0,2,8],[4,0,0,5,0,2,0,0,9],[2,7,0,4,6,0,0,0,0],[0,0,5,3,0,8,9,0,0],[0,8,3,0,0,0,0,6,0],[0,0,7,6,9,0,0,4,3]]
I apologize if this is the wrong place for such beginner questions. It's just that I have been trying for a while and getting stuck on something relatively trivial and its getting frustrating. Thanks
You are very near!
The key point is this anonymous function:
(\x -> if isNothing x then 0 else fromJust x)
BTW, there are 2 warning flags here: The use of isNothing and fromJust.
Now, as this function returns numbers, you can have only numbers displayed. But you want characters instead. Hence, just rewrite this as a local function like:
showcell Nothing = '.'
showcell (Just n) = ....
=== EDIT: More general advice ===
Whenever you find yourself writing:
if isNothing x then a else f (fromJust x)
you should replace it with an explicit local function or
maybe a f x
In your case, you'd initially written just:
(\x -> maybe 0 id x)
which reduces to the much nicer
maybe 0 id
and now you just had to change it to:
maybe '.' (head . show)
or something.
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..]]