How to build diagonal matrix with list comprehension - haskell

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..]]

Related

How to Set Slices in Haskell's HMatrix?

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

augdentity Haskell Implementation

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]]

Haskell replace an item in a existing list [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
Im trying to create a function that replace a given existing place with a new place
data Place = Place String Coord [Int]
deriving (Ord,Eq,Show,Read)
data Coord = Cord Double Double
deriving (Ord ,Eq ,Show ,Read)
testData :: [Place]
testData = [ Place "London" (Cord 51.5 (-0.1)) [0, 0, 5, 8, 8, 0, 0],
Place"Cardiff" (Cord 51.5 (-3.2)) [12, 8, 15, 0, 0, 0, 2],
Place"Norwich" (Cord 52.6 (1.3) ) [0, 6, 5, 0, 0, 0, 3],
Place "Birmingham" (Cord 52.5 (-1.9)) [0, 2, 10, 7, 8, 2, 2],
Place"Liverpool" (Cord 53.4 (-3.0)) [8, 16, 20, 3, 4, 9, 2],
Place "Hull" (Cord 53.8 (-0.3)) [0, 6, 5, 0, 0, 0, 4],
Place "Newcastle" (Cord 55.0 (-1.6)) [0, 0, 8, 3, 6, 7, 5],
Place "Belfast" (Cord 54.6 (-5.9)) [10, 18, 14, 0, 6, 5, 2],
Place "Glasgow" (Cord 55.9 (-4.3)) [7, 5, 3, 0, 6, 5, 0],
Place"Plymouth" (Cord 50.4 (-4.1)) [4, 9, 0, 0, 0, 6, 5],
Place "Aberdeen" (Cord 57.1 (-2.1)) [0, 0, 6, 5, 8, 2, 0],
Place "Stornoway" (Cord 58.2 (-6.4)) [15, 6, 15, 0, 0, 4, 2],
Place"Lerwick" (Cord 60.2 (-1.1)) [8, 10, 5, 5, 0, 0, 3],
Place"St Helier" (Cord 49.2 (-2.1)) [0, 0, 0, 0, 6, 10, 0] ]
replaceLocate :: String -> Place -> [Place] -> [Place]
replaceLocate _ _ [] = []
replaceLocate str (Place l d rains) ((Place p c rain):xs)
| str == p = Place l d rains : replaceLocate (Place l d rains) str xs
| otherwise = Place p c rain : replaceLocate (Place l d rains) str xs
while using String to search for the Places that I wanted to change.
But it gives me this error :
Smth.hs:96:22: error:
• Couldn't match type ‘Place’ with ‘[Char]’
Expected type: String
Actual type: Place
• In the pattern: Place l d rains
In an equation for ‘replaceLocate’:
replaceLocate str (Place l d rains) ((Place p c rain) : xs)
| str == p
= Place l d rains : replaceLocate (Place l d rains) str xs
| otherwise
= Place p c rain : replaceLocate (Place l d rains) str xs
|
96 | replaceLocate str (Place l d rains) ((Place p c rain):xs) | ^^^^^^^^^^^^^^^
Smth.hs:97:16: error:
• Couldn't match type ‘[Char]’ with ‘Place’
Expected type: Place
Actual type: String
• In the second argument of ‘(==)’, namely ‘p’
In the expression: str == p
In a stmt of a pattern guard for
an equation for ‘replaceLocate’:
str == p
|
97 | | str == p = Place l d rains : replaceLocate (Place l d rains) str xs | ^
Smth.hs:97:82: error:
• Couldn't match type ‘Place’ with ‘[Char]’
Expected type: String
Actual type: Place
• In the second argument of ‘replaceLocate’, namely ‘str’
In the second argument of ‘(:)’, namely
‘replaceLocate (Place l d rains) str xs’
In the expression:
Place l d rains : replaceLocate (Place l d rains) str xs
|
97 | | str == p = Place l d rains : replaceLocate (Place l d rains) str xs | ^^^
Smth.hs:98:86: error:
• Couldn't match type ‘Place’ with ‘[Char]’
Expected type: String
Actual type: Place
• In the second argument of ‘replaceLocate’, namely ‘str’
In the second argument of ‘(:)’, namely
‘replaceLocate (Place l d rains) str xs’
In the expression:
Place p c rain : replaceLocate (Place l d rains) str xs
|
98 | | otherwise = Place p c rain : replaceLocate (Place l d rains) str xs | ^^^
In your recurve call you are swapping the first two parameters. You need to replace this:
replaceLocate (Place l d rains) str xs
With this:
replaceLocate str (Place l d rains) xs

Elm quicksort visualization

I'm trying to display the sorting process of quicksort with Elm
[ 5, 8, 6, 2, 4, 1, 0, 3, 10, 7, 9 ]
[2,4,1,0,3] 5 [8,6,10,7,9]
[1,0] 2 [4,3] [6,7] 8 [10,9]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
Right now i can get the first 2 lines but I'm unsure how to approach this in a recursive manner.
list_to_html : List (List Int) -> Html msg
list_to_html x =
div [] [ x |> toString |> text ]
quicksort_partition : List Int -> Html msg
quicksort_partition list =
case list of
x :: xs ->
let
lower =
List.filter ((>=) x) xs
higher =
List.filter ((<) x) xs
in
list_to_html [ lower, [ x ], higher ]
[] ->
list_to_html []
This outputs:
[ 5, 8, 6, 2, 4, 1, 0, 3, 10, 7, 9 ]
[2,4,1,0,3] [5] [8,6,10,7,9]
If you are trying to get that kind of output, direct recursion inside the view isn't going to work well. Instead, I would approach it as writing a variation of quicksort which logs the state along the way.
Here is an example of quicksort which also returns a list of logs. The type aliases are included to try and make the function annotation more clear:
type alias Depth =
Int
type alias Log comparable =
( Depth, List comparable, comparable, List comparable )
quicksortLog : Depth -> List comparable -> ( List comparable, List (Log comparable) )
quicksortLog depth list =
case list of
[] ->
( [], [] )
x :: xs ->
let
( lower, lowerLog ) =
quicksortLog (depth + 1) (List.filter ((>=) x) xs)
( higher, higherLog ) =
quicksortLog (depth + 1) (List.filter ((<) x) xs)
log =
( depth, lower, x, higher )
in
( lower ++ [ x ] ++ higher, log :: lowerLog ++ higherLog )
Given that result, you could then write a view which displays the data in the way you see fit.

Converting [[Maybe Int]] to IO ()

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.

Resources