{-|
Module      : Tarefa0_geral
Description : Funções auxiliares gerais.

Módulo que define funções genéricas sobre listas e matrizes.
-}

module Tarefa0_geral where

-- * Tipos de dados

-- | Uma matriz é um conjunto de elementos a duas dimensões.
--
-- Em notação matemática, é geralmente representada por:
--
-- <<https://haslab.github.io/Teaching/LI1/2526/img/matriz.png>>
type Matriz a = [[a]]

-- | Uma posição numa matriz é dada como um par (/linha/,/colunha/).
-- As coordenadas são dois números naturais e começam com (0,0) no canto superior esquerdo, com as linhas incrementando para baixo e as colunas incrementando para a direita.
--
-- <<https://haslab.github.io/Teaching/LI1/2526/img/posicaomatriz.png>>
type Posicao = (Int,Int)

-- | A dimensão de uma matrix dada como um par (/número de linhas/,/número de colunhas/).
type Dimensao = (Int,Int)

-- | Uma direção é dada pela rosa dos ventos. Ou seja, os 4 pontos cardeais e os 4 pontos colaterais.
--
-- <<https://haslab.github.io/Teaching/LI1/2526/img/rosadosventos.jpg>>
data Direcao = Norte | Nordeste | Este | Sudeste | Sul | Sudoeste | Oeste | Noroeste
    deriving (Direcao -> Direcao -> Bool
(Direcao -> Direcao -> Bool)
-> (Direcao -> Direcao -> Bool) -> Eq Direcao
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Direcao -> Direcao -> Bool
== :: Direcao -> Direcao -> Bool
$c/= :: Direcao -> Direcao -> Bool
/= :: Direcao -> Direcao -> Bool
Eq,Eq Direcao
Eq Direcao =>
(Direcao -> Direcao -> Ordering)
-> (Direcao -> Direcao -> Bool)
-> (Direcao -> Direcao -> Bool)
-> (Direcao -> Direcao -> Bool)
-> (Direcao -> Direcao -> Bool)
-> (Direcao -> Direcao -> Direcao)
-> (Direcao -> Direcao -> Direcao)
-> Ord Direcao
Direcao -> Direcao -> Bool
Direcao -> Direcao -> Ordering
Direcao -> Direcao -> Direcao
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Direcao -> Direcao -> Ordering
compare :: Direcao -> Direcao -> Ordering
$c< :: Direcao -> Direcao -> Bool
< :: Direcao -> Direcao -> Bool
$c<= :: Direcao -> Direcao -> Bool
<= :: Direcao -> Direcao -> Bool
$c> :: Direcao -> Direcao -> Bool
> :: Direcao -> Direcao -> Bool
$c>= :: Direcao -> Direcao -> Bool
>= :: Direcao -> Direcao -> Bool
$cmax :: Direcao -> Direcao -> Direcao
max :: Direcao -> Direcao -> Direcao
$cmin :: Direcao -> Direcao -> Direcao
min :: Direcao -> Direcao -> Direcao
Ord,Int -> Direcao -> ShowS
[Direcao] -> ShowS
Direcao -> String
(Int -> Direcao -> ShowS)
-> (Direcao -> String) -> ([Direcao] -> ShowS) -> Show Direcao
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Direcao -> ShowS
showsPrec :: Int -> Direcao -> ShowS
$cshow :: Direcao -> String
show :: Direcao -> String
$cshowList :: [Direcao] -> ShowS
showList :: [Direcao] -> ShowS
Show,ReadPrec [Direcao]
ReadPrec Direcao
Int -> ReadS Direcao
ReadS [Direcao]
(Int -> ReadS Direcao)
-> ReadS [Direcao]
-> ReadPrec Direcao
-> ReadPrec [Direcao]
-> Read Direcao
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Direcao
readsPrec :: Int -> ReadS Direcao
$creadList :: ReadS [Direcao]
readList :: ReadS [Direcao]
$creadPrec :: ReadPrec Direcao
readPrec :: ReadPrec Direcao
$creadListPrec :: ReadPrec [Direcao]
readListPrec :: ReadPrec [Direcao]
Read,Int -> Direcao
Direcao -> Int
Direcao -> [Direcao]
Direcao -> Direcao
Direcao -> Direcao -> [Direcao]
Direcao -> Direcao -> Direcao -> [Direcao]
(Direcao -> Direcao)
-> (Direcao -> Direcao)
-> (Int -> Direcao)
-> (Direcao -> Int)
-> (Direcao -> [Direcao])
-> (Direcao -> Direcao -> [Direcao])
-> (Direcao -> Direcao -> [Direcao])
-> (Direcao -> Direcao -> Direcao -> [Direcao])
-> Enum Direcao
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Direcao -> Direcao
succ :: Direcao -> Direcao
$cpred :: Direcao -> Direcao
pred :: Direcao -> Direcao
$ctoEnum :: Int -> Direcao
toEnum :: Int -> Direcao
$cfromEnum :: Direcao -> Int
fromEnum :: Direcao -> Int
$cenumFrom :: Direcao -> [Direcao]
enumFrom :: Direcao -> [Direcao]
$cenumFromThen :: Direcao -> Direcao -> [Direcao]
enumFromThen :: Direcao -> Direcao -> [Direcao]
$cenumFromTo :: Direcao -> Direcao -> [Direcao]
enumFromTo :: Direcao -> Direcao -> [Direcao]
$cenumFromThenTo :: Direcao -> Direcao -> Direcao -> [Direcao]
enumFromThenTo :: Direcao -> Direcao -> Direcao -> [Direcao]
Enum)

-- * Funções não-recursivas.

-- | Verifica se o indice pertence à lista.
eIndiceListaValido :: Int -> [a] -> Bool
eIndiceListaValido :: forall a. Int -> [a] -> Bool
eIndiceListaValido = Int -> [a] -> Bool
forall a. HasCallStack => a
undefined

-- | Calcula a dimensão de uma matriz.
--
-- __NB:__ Note que não existem matrizes de dimensão /m * 0/ ou /0 * n/, e que qualquer matriz vazia deve ter dimensão /0 * 0/.
dimensaoMatriz :: Matriz a -> Dimensao
dimensaoMatriz :: forall a. Matriz a -> Dimensao
dimensaoMatriz = Matriz a -> Dimensao
forall a. HasCallStack => a
undefined

-- | Verifica se a posição pertence à matriz.
ePosicaoMatrizValida :: Posicao -> Matriz a -> Bool 
ePosicaoMatrizValida :: forall a. Dimensao -> Matriz a -> Bool
ePosicaoMatrizValida = Dimensao -> Matriz a -> Bool
forall a. HasCallStack => a
undefined

-- | Move uma posição uma unidade no sentido de uma direção.
movePosicao :: Direcao -> Posicao -> Posicao
movePosicao :: Direcao -> Dimensao -> Dimensao
movePosicao = Direcao -> Dimensao -> Dimensao
forall a. HasCallStack => a
undefined

-- Versão da função 'movePosicao' que garante que o movimento não se desloca para fora de uma janela.
--
-- __NB:__ Considere uma janela retangular com origem no canto superior esquerdo definida como uma matriz. A função recebe a dimensao da janela.
movePosicaoJanela :: Dimensao -> Direcao -> Posicao -> Posicao
movePosicaoJanela :: Dimensao -> Direcao -> Dimensao -> Dimensao
movePosicaoJanela = Dimensao -> Direcao -> Dimensao -> Dimensao
forall a. HasCallStack => a
undefined

-- | Converte uma posição no referencial em que a origem é no canto superior esquerdo da janela numa posição em que a origem passa a estar no centro da janela.
--
-- | __NB:__ Considere posições válidas.
origemAoCentro :: Dimensao -> Posicao -> Posicao
origemAoCentro :: Dimensao -> Dimensao -> Dimensao
origemAoCentro = Dimensao -> Dimensao -> Dimensao
forall a. HasCallStack => a
undefined

-- * Funções recursivas.

-- | Devolve o elemento num dado índice de uma lista.
--
-- __NB:__ Retorna @Nothing@ se o índice não existir.
encontraIndiceLista :: Int -> [a] -> Maybe a
encontraIndiceLista :: forall a. Int -> [a] -> Maybe a
encontraIndiceLista = Int -> [a] -> Maybe a
forall a. HasCallStack => a
undefined

-- | Modifica um elemento num dado índice.
--
-- __NB:__ Devolve a própria lista se o elemento não existir.
atualizaIndiceLista :: Int -> a -> [a] -> [a]
atualizaIndiceLista :: forall a. Int -> a -> [a] -> [a]
atualizaIndiceLista = Int -> a -> [a] -> [a]
forall a. HasCallStack => a
undefined

-- | Devolve o elemento numa dada posição de uma matriz.
--
-- __NB:__ Retorna @Nothing@ se a posição não existir.
encontraPosicaoMatriz :: Posicao -> Matriz a -> Maybe a
encontraPosicaoMatriz :: forall a. Dimensao -> Matriz a -> Maybe a
encontraPosicaoMatriz = Dimensao -> Matriz a -> Maybe a
forall a. HasCallStack => a
undefined

-- | Modifica um elemento numa dada posição de uma matriz.
--
-- __NB:__ Devolve a própria matriz se o elemento não existir.
atualizaPosicaoMatriz :: Posicao -> a -> Matriz a -> Matriz a
atualizaPosicaoMatriz :: forall a. Dimensao -> a -> Matriz a -> Matriz a
atualizaPosicaoMatriz = Dimensao -> a -> Matriz a -> Matriz a
forall a. HasCallStack => a
undefined

-- | Aplica uma sequência de movimentações a uma posição, pela ordem em que ocorrem na lista.
moveDirecoesPosicao :: [Direcao] -> Posicao -> Posicao
moveDirecoesPosicao :: [Direcao] -> Dimensao -> Dimensao
moveDirecoesPosicao = [Direcao] -> Dimensao -> Dimensao
forall a. HasCallStack => a
undefined

-- | Aplica a mesma movimentação a uma lista de posições.
moveDirecaoPosicoes :: Direcao -> [Posicao] -> [Posicao]
moveDirecaoPosicoes :: Direcao -> [Dimensao] -> [Dimensao]
moveDirecaoPosicoes = Direcao -> [Dimensao] -> [Dimensao]
forall a. HasCallStack => a
undefined

-- Verifica se uma matriz é válida, no sentido em que modela um rectângulo.
--
-- __NB:__ Todas as linhas devem ter o mesmo número de colunas. 
eMatrizValida :: Matriz a -> Bool
eMatrizValida :: forall a. Matriz a -> Bool
eMatrizValida = Matriz a -> Bool
forall a. HasCallStack => a
undefined