PDA

View Full Version : [Haskell - Linguaggi funzionali] Matrice diagonale - a chi piace la ricorsione?


Gremo
28-08-2009, 02:32
Mi trovo a dover implementare una funzione in Haskell che restituisce True se una matrice (quadrata) è diagonale e False altrimenti. Il codice è riportato qui sotto, le matrici sono implementate come lista di liste per righe, ad esempio [[1, 0], [0, 2]].

Il codice non funziona correttamente e non capisco il perchè - forse perchè non mi è mai piaciuta la ricorsione :muro:. L'idea è: tutto quello che è a sinistra della diagonale deve essere nullo E la diagonale deve essere diversa da zero O questo deve verificarsi nella prossima riga E la parte a destra della diagonale deve essere nulla.

Come mai non va :mbe:


--
-- Determina se una matrice (quadrata) è diagonale
--
isDiagonal [] = False
isDiagonal (x:xs)
| length x == 1 = True -- matrice 1x1 è diagonale
| otherwise = all (==0) l && ((d /= 0) || isDiagonal xs) && all (==0) r
where
n = length x - length xs -- col. riga corrente - righe rimanenti
l = take (n-1) x -- parte sx diagonale
d = last (take n x) -- elemento diagonale
r = drop n x -- parte dx diagonale

-- NOTE (per chi non conosce la sintassi Haskell)
-- all (==0) restuisce True se ogni elemento della lista è nullo
-- /= 0 significa diverso da zero
-- x è la prima riga, xs rappresenta il resto della lista
-- (quindi le altre righe...)


a pensare ricorsivo mi va via la testa...poi funzionale non ne parliamo :rolleyes:

marco.r
28-08-2009, 09:40
Mi trovo a dover implementare una funzione in Haskell che restituisce True se una matrice (quadrata) è diagonale e False altrimenti. Il codice è riportato qui sotto, le matrici sono implementate come lista di liste per righe, ad esempio [[1, 0], [0, 2]].

Il codice non funziona correttamente e non capisco il perchè - forse perchè non mi è mai piaciuta la ricorsione :muro:. L'idea è: tutto quello che è a sinistra della diagonale deve essere nullo E la diagonale deve essere diversa da zero O questo deve verificarsi nella prossima riga E la parte a destra della diagonale deve essere nulla.

Come mai non va :mbe:


--
-- Determina se una matrice (quadrata) è diagonale
--
isDiagonal [] = False
isDiagonal (x:xs)
| length x == 1 = True -- matrice 1x1 è diagonale
| otherwise = all (==0) l && ((d /= 0) || isDiagonal xs) && all (==0) r
where
n = length x - length xs -- col. riga corrente - righe rimanenti
l = take (n-1) x -- parte sx diagonale
d = last (take n x) -- elemento diagonale
r = drop n x -- parte dx diagonale

-- NOTE (per chi non conosce la sintassi Haskell)
-- all (==0) restuisce True se ogni elemento della lista è nullo
-- /= 0 significa diverso da zero
-- x è la prima riga, xs rappresenta il resto della lista
-- (quindi le altre righe...)


a pensare ricorsivo mi va via la testa...poi funzionale non ne parliamo :rolleyes:

A naso direi che il problema e' che nel passo ricorsivo non vai a lavorare nella sottomatrice quadrata (n-1)x(n-1), ma nella (n-1)xn

Qualcosa come segue dovrebbe andare meglio:

isDiagonal [] = False
isDiagonal [[_]] = True
isDiagonal matrix
= let
row1 x = tail $ head x
col1 x = tail $ head $ transpose x
subMatrix x = map tail $ tail x
in
all (==0) (row1 matrix) && all (==0) (col1 matrix) && isDiagonal (subMatrix matrix)