• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Isabel Macedo

duvida na ficha 4 de LEI - outra duvida :)

12 mensagens neste tópico

http://www.di.uminho.pt/~mjf/PFei/2008-09/page10/files/pf-aula4.pdf

A minha duvida está na pergunta 2) a). Não sei como percorrer duas listas numa mesma função. Tenho um pequeno rascunho da função mas nao a consigo desenvolver mais porque nao sei como percorrer as duas listas.

verifLista::ListaCompras->Stock->Bool
verifLista ( ( n , q ) : xs ) ( ( n1 , p , q1 ) : ys ) | n==n1 || elem n ys && verifLista xs ys = True
                                                        | otherwise = False

Tentei usar a função pré-defenida elem mas estao nao funciona na lista com tuplos. Por isso nao sei como resolver este problema. Obrigada pela ajuda.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sugeria-te que começasses por fazer uma função que dado um par (Produto,Quantidade) verifica se este pode ser satisfeito.

Depois essa função resumir-se-ia a percorrer a lista de compras, e chamar a função que indiquei acima para cada um dos produtos.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pelo que percebi, tenho de criar uma função que verifica se um par (Produto,Quantidade) existe no Stock. Pronto, consegui criar essa função

verfiicaPar :: ( Produto, Quantidade ) -> Stock -> Bool
verificaPar ( n , q ) [ ] = False
verificaPar ( n, q ) ( ( n1 , p , q1 ) : xs ) | n==n1 = True
                                              | otherwise = verificaPar ( n, q ) xs

Agora, não consigo perceber como vou aplicar esta função a uma lista de compras? Pois esta função apenas recebe um par...  Obrigado pela ajuda

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Afinal já consegui fazer a função.... :wallbash:

verificarLista::ListaCompras -> Stock -> Bool
verificarLista [] _ = True
verificarLista ((n,q):xs) l | verificarListaAux (n,q) l && verificarLista xs l = True
                             | otherwise = False

verificarListaAux::(Produto,Quantidade)->Stock->Bool
verificarListaAux (n,q) []=False
verificarListaAux (n,q) ((n1,p,q1):xs) | n==n1 = True
                                        | otherwise=verificarListaAux (n,q) xs

Obrigado pela ajuda... :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Agora surgiu-me outra duvida na pergunta 2) c)  :)

Para calcular o custo total da lista de compras eu pensei primeiro em fazer uma função k defina quais os pedidos k podem ser satisfeitos.

satisfeitos::ListaCompras->Stock->ListaCompras

satisfeitos [] _ =[]

satisfeitos ((n,q):xs) l | satisfeitosAux (n,q) l = (n,q):satisfeitos xs l

                        | otherwise = satisfeitos xs l

       

satisfeitosAux::(Produto,Quantidade)->Stock ->Bool

satisfeitosAux _ []=False

satisfeitosAux (n,q) ((n1,p,q1):xs) | n==n1 =True

                                    | otherwise = satisfeitosAux (n,q) xs

Agora keria definir uma função k fosse buscar os preços dos pedidos satisfeitos. 

buscarPreco :: ListaCompras -> Stock -> [Preco]      mas nao sei como faze-la.

Obrigado pela ajuda....

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes começar por fazer uma função que, dado um produto e a quantidade adquirida, retorne o preço que vais pagar por comprares essa quantidade desse produto. Para isso, tens de aceder ao stock que é onde está armazenado o preço unitário:

custoTotalAux :: (Produto,Quantidade) -> Stock -> Float
custoTotalAux (p,q) ((x,y,_):xs) | p == x = q*y
		         | otherwise = custoTotalAux (p,q) xs

Depois, apenas tens de aplicar essa função a todos os produtos da lista de compras. Para isso podes usar a função map, que aplica a função custoTotalAux a todos os elementos da Lista de Compras, fazendo de seguida o somatório da lista de preços resultantes:

custoTotal :: ListaCompras -> Stock -> Float
custoTotal lc st = sum $ map (\x -> custoTotalAux x st) lc

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Agora uma duvida na 2) d)  :bored:

Optei por usar acumuladores, porque acho k torna a função mais simples e facil de entender :)

 partePrecoAux::ListaCompras -> ListaCompras->Preco->(Produto,Quantidade)->Stock->(ListaCompras,ListaCompras)
partePrecoAux lc lc1 p _ [] =(lc,lc1)
partePrecoAux lc lc1 p (n,q) ((n1,p1,q1):xs) | n==n1 && p1<p =((n,q):lc,lc1)
                                             | n==n1 && p1>p =(lc,(n,q):lc1)
                                             | otherwise = partePrecoAux lc lc1 p (n,q) xs 

Agora queria usar a função map para aplicar a uma lista de compas.Mas esta função dá-me erro ....

partePreco::Preco->ListaCompras->Stock->(ListaCompras,ListaCompras)
partePreco p lc st = map (\x->partePrecoAux [] [] p x st) lc

Obrigado... :confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A função map devolve uma lista e na função partePreco estás a devolver um par de ListaCompras.

Provavelmente o que tu queres é:

custoProduto :: Produto -> Stock -> Float
custoProduto p ((x,y,_):xs) | p == x = y
		    | otherwise = custoProduto p xs

partePreco :: Preco -> ListaCompras -> Stock -> (ListaCompras,ListaCompras)
partePreco _ [] _ = ([],[])
partePreco p (x:xs) st | custoProduto (fst x) st < p = (x:lc1,lc2)
	       | otherwise = (lc1,x:lc2)
	where (lc1,lc2) = partePreco p xs st

Ou seja, primeiro fazes uma função que, dado o produto, acede ao stock para determinar o seu preço.

Na função partePreco depois apenas precisas de invocar, para cada elemento da lista de compras, essa função auxiliar e aí tens 2 casos:

- Se o preço do produto for menor que o preço que forneces para comparar, então esse item da lista de compras é adicionado ao 1º elemento do par de listas de compras, isto é, à lista cujos produtos têm preço inferior a p

- Caso contrário, adicionas ao 2º elemento do par.

Aquele tipo de construção do par final é utilizado para que se vá construindo o resultado final à medida que se itera pela lista, evitando assim percorrer 2 vezes a lista.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Estive a testar a função e se colocar um produto que não exista em stock ela não dá resultado, ou seja , não tem caso de paragem. Por exemplo,

partePreco 7 [("carne",3),("pao",5)]  [("iogurte",1,1),("pao",0.15,1)]

aqui a carne não está no stock e ao testar ela ó ghci dá exception.

Tentei definir o caso de paragem na função custoProduto :

custoProduto _ [ ]=0 

    ou   

custoProduto _ [ ] = error "o produto nao existe em Stock"

mas ambos não podem ser estar definidos na função. No 1º porque, mesmo que o produto não se encontre em Stock ele vai devolver na função partePreço pois zero é menor que qualquer preço. O 2º como é obvio também não pode ser :confused:

Não sei k caso de paragem hei-de colocar na função.....

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Para isso fazes uma função auxiliar que, dada uma Lista de Compras, verifica se todos os seus produtos existem no stock. Se existir então permanece na lista. Se não existir é retirado. Se bem que a lógica não deveria ser esta, isto é, não é depois de teres a lista de compras que vais ver se os produtos estão no stock, é ao contrário. Como não sei se já tens uma função desse género, fica a nota. Depois, na função partePreco, a primeira coisa que tens de fazer é invocar essa função sobre a Lista de Compras inicial antes de todo aquele procedimento, e depois o resto fica igual.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tenho uma dúvida numa função que o meu prof apresentou na aula, usando a função de ordem superior foldr

qtds ::Stock ->Quantidade
qtds l = foldr (\(n,p,q)qt -> q+qt)0 l

Esta função calcula a quantidade total que existe em stock.

Eu não percebo a função forldr nesta função  :bored:

Obrigado...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A função foldr tem como tipo:

foldr :: (a -> b -> b) -> b -> [a] -> b

Ou seja, recebe uma função que, dado um elemento do tipo a e outro do tipo b (ou seja, tipos diferentes), dá como resultado um elemento do tipo b. Recebe também um elemento do tipo b e uma lista de a e retorna um elemento do tipo b. Isto quer dizer que a função foldr vai executar a função (a -> b -> b) recursivamente entre os sucessivos elementos da lista [a], sendo o caso de paragem indicado por aquele 'b' isolado, tendo como resultado um elemento do tipo b. O 'r' no nome 'foldr' indica que a associação dos elementos é feita à direita, isto é, vai seguir um padrão semelhante àquele que é usado na definição de funções recursivas sobre listas.

Um exemplo que tenho aqui ao meu lado é o seguinte: realizar o somatório dos elementos de uma lista.

somatorio l = foldr (+) 0 l

Para a invocação desta função com os seguintes parâmetros:

foldr (+) 0 [1..5]

Isto vai ser desenvolvido da seguinte maneira:

somatorio [1..5] = foldr (+) 0 [1..5]
=> foldr (+) 0 [1..5]
=> 1 + (foldr (+) 0 [2..5])
=> 1 + (2 + (foldr (+) 0 [3..5])
=> 1 + (2 + (3 + (foldr (+) [4..5])
=> 1 + (2 + (3 + (4 + (foldr (+) 0 [5])
=> 1 + (2 + (3 + (4 + (5 + (foldr (+) 0 [])
=> 1 + (2 + (3 + (4 + (5 + 0))))

Como vês os vários resultados parciais são associados à direita do resultado já calculado. Aquele 'b' neste caso é o 0, isto é, o caso de paragem. O 'l' é a lista sobre a qual queres executar a função soma (+).

Então, analisando essa função da aula, temos o seguinte:

1) uma função anónima (sem nome), definida dentro do 1º parâmetro do foldr, como sendo uma função que dado um tuplo de 3 elementos (corresponde a um produto em stock, e tendo em atenção o tipo da função foldr, será o 'a') e um acumulador 'qt' (que será o 'b'), vai somar a quantidade do produto a esse acumulador, isto é, essa função vai somando as quantidades sucessivas dos produtos àquele acumulador, obtendo-se no fim a quantidade final, ou seja, um valor do mesmo tipo do acumulador ('b'). Daí que podemos inferir que:

1.1) (n,p,q) :: a

1.2) qt :: b

1.3) q+qt :: b (o mesmo tipo do resultado final do foldr)

2) O '0' corresponde ao caso de paragem, isto é, ao valor que é somado ao acumulador quando se tiver percorrido toda a lista de produtos no stock. 0 :: b

3) O 'l' corresponde ao stock. l :: [a]

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora