Jump to content
leia

Lista de lista com elementos sucessivos de uma lista

Recommended Posts

leia

Boa tarde ,

Ca ando eu as voltas com as listas outra vez .

Quero fazer uma lista de listas que tem elementos sucessivos da lista original.Tendo listSeq2 3 1 [1,2,3,4,5,6,7,8].Obtendo [[1,2,3][2,3,4],[3,4,5][4,5,6],[5,6,7],[6,7,8]]

Apesar de perceber o que pede o exercício me faz muita confusão quando tento escrever o código.

Acho muito complicada esta resolução e ao mesmo tempo bastante comprida

listSeq2 _ _ [] = []
listSeq2 y w xs | length xs >= y+1 =(seqAux y xs): (listSeq2 y w(drop w xs))
              | otherwise = (seqAux (length xs) xs): (listSeq2 y w [])

seqAux 0 _ = []
seqAux y (x:xs)= x: (seqAux(y-1) xs)

obgd

Edited by thoga31
Tags code + GeSHi

Share this post


Link to post
Share on other sites
thoga31

Vê este tópico

Bem, essa solução não se pode chamar de legível :/

Isso resolve-se com apenas uma função e com as patterns correctas. Pensemos:

  • A função recebe uma lista e devolve uma List of List, ou seja:
    listSeq :: [a] -> [[a]]
    


  • Se a lista tiver só 3 elementos, devolvemos a dita lista - esta vai ser a nossa condição de paragem da função recursiva.
    listSeq (x:y:z:[]) = [[x,y,z]]
    


  • Se a lista tiver mais do que 3 elementos, então pegamos nos primeiros 3 e fazemos com eles uma lista, e unimos ao resto da lista que há-de ser construída recursivamente. Ou seja, juntamos [x,y,z] a uma [[a]] que será calculada a partir de y:z:zs, sendo zs o resto da lista:
    listSeq (x:y:z:zs) = [x, y, z] : listSeq (y:z:zs)
    


    Se olhares para o tipo da função, isto faz sentido pois estamos a fazer isto:

    [a] : [[a]]  ->  [[a]]  -- o tipo de retorno é [[a]]
    


  • Caso a lista tenho menos elementos, devolvemos a respectiva List of List:
    listSeq l = [l]
    


Teste:

Prelude> listSeq [1..10]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8,9],[8,9,10]]

Não precisas de nenhum length, só precisas mesmo da própria lista. Tu tentaste simular um ciclo do paradigma estrutural com essa solução.

Está-te a faltar o pensamento recursivo, ainda. ;)

Edited by thoga31

Knowledge is free!

Share this post


Link to post
Share on other sites
leia

Boa tarde thoga31,

E verdade eu comencei a muito pouco tempo na programação e me baralho muito ainda com coisas que são basicas ate. Eu percebi esta resolução mas o tipo da função que eu quero e diferente

listSeq:: Int -> Int -> [a] -> [[a]]

Quero obter:

Main> listSeq 3 1 [1,2,3,4,5,6,7,8]

[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8]]

listSeq 4 2 [1,2,3,4,5,6,7,8]

[[1,2,3,4],[3,4,5,6],[5,6,7,8]]

Obrigada

Sem querer apaguei o que eu publiquei e a sua resposta (thoga31) da conversa principal e não sei por de volta sem ter que escrever de novo :\

Share this post


Link to post
Share on other sites
thoga31

Isso já muda um pouco a conversa... :D

Então tens de pensar assim: eu tenho de obter n elementos da lista e juntar ao resto (que será calculado recursivamente), desde que a lista tenha esses n elementos. Caso tenha só n ou menos do que n elementos, então tenho a condição de paragem.

Trocado por miúdos: obter uma lista de 4 sucessivos da lista [1..8], de 3 em 3:

  • [1,2,3,4,5,6,7,8] - temos os 4 elementos e ainda sobra: pegamos em [1,2,3,4] e fazemos o mesmo para [4..8], ou seja, descartámos os 3 primeiros elementos na análise seguinte;
  • [4,5,6,7,8] - temos 4 elementos, e juntamos [4,5,6,7]. Voltamos a descartar 3 elementos;
  • [7,8] - só temos 2 elementos de sobra, simplesmente devolvemos [[7,8]], sendo aqui a condição de paragem

Portanto, tu fazes um take de n elementos, e fazes um drop dos elementos que queres descartar para a análise seguinte. Para saberes se tens elementos suficientes, comparas n com o length da lista, à qual vou dar o nome de xs.

Não faz sentido que os dois valores passados por argumento sejam menores ou iguais que zero, pelo que convém controlá-los.

Desta vez será melhor fazer uma análise com pattern guards:

  • Se n<=0 ou jump<=0, então devolvemos [[]] (jump será o número de elementos a descartar para a próxima análise);
  • Se n>=length(xs) então temos menos elementos do que os necessários, pelo que devolvemos a lista inserida noutra lista: [xs];
  • Noutros casos, é fazer a "marosca": fazemos um take de n elementos da lista, e juntamos ao resultado de listSeq passando a lista "cortada", ou seja, com um drop de jump elementos.

Acho que te disse tudo, tenta lá ver se percebeste e ver se chegas ao código ;)

EDIT: o nº de elementos a descartar pode ser maior do que o nº de elementos a juntar? Ou seja, posso fazer listSeq 4 5 [1..10]?

Sem querer apaguei o que eu publiquei e a sua resposta (thoga31) da conversa principal e não sei por de volta sem ter que escrever de novo :\

Não apagaste nada. Eu é que movi os posts para um novo tópico, esqueci-me de dizer, pois esta é uma dúvida diferente. Dúvidas novas, tópicos novos. ;)

Edited by thoga31

Knowledge is free!

Share this post


Link to post
Share on other sites
leia

Acho que não segui bem o seu raciocínio mas assim funciona também. Queria era ver a sua versão pk não consegui por ela de pê para encaixar a função ...:\

listSeq4 n m = if m == 0
                      then error "deslocamento tem de ser >= 1"
                      else takeWhile (not.null) .map(take n). iterate (drop m)

obgd

Edited by thoga31
Tags code + GeSHi

Share this post


Link to post
Share on other sites
motherFFH

É isso mesmo. Isso é uma solução funcional. Muitas vezes tentamos pensar iterativamente nestes casos e originamos soluções menos claras.

A condição do takeWhile deve ser substituída por (\x -> length x == n).

Share this post


Link to post
Share on other sites
leia

Substituindo assim ?? me da False mas eu quero e obter a lista de listas como acima.

listSeq6 n m = if m == 0
                      then error "deslocamento tem de ser >= 1"
                      else  (\x -> length x == n)

obgd

esqueci de colocar takeWhile :) desculpa

o codigo acima ficara :

listSeq6 n m = if m == 0
                      then error "deslocamento tem de ser >= 1"
                     else takeWhile (\x -> length x == n) .map(take n). iterate (drop m)

jà agora como poderei resolver sem usar if ,then, else...? Usando recursiva,guards!!!!

obgd.

Edited by thoga31
Tags code + GeSHi

Share this post


Link to post
Share on other sites
thoga31

@leia, vê este tópico por favor, se não para a próxima serei obrigado a tomar medidas mais sérias. Não estou para estar sempre a editar os teus posts a colocar as tags CODE.

Bem, essa solução não me tinha passado pela cabeça pois eu pensei em algo mais simples, repara que eu vou aplicar exactamente aquilo que eu estava a dizer por pontos:

listSeq n jump xs | n <= 0 || jump <= 0 = [[]]
                 | n >= length xs      = [xs]
                 | otherwise           = (take n xs) : listSeq n jump (drop jump xs)


Knowledge is free!

Share this post


Link to post
Share on other sites
thoga31

listSeq6 n m = if m == 0
                      then error "deslocamento tem de ser >= 1"
                     else takeWhile (\x -> length x == n) .map(take n). iterate (drop m)

Já agora, vamos identar isto bem, que o Haskell é sensível, e vamos simplificar a condição do takeWhile. ;)

E como não gosto muito do error, vou colocar um output padrão que depois poderá ser tratado devidamente num main (a haver um).

E a condição deverá referir-se não só ao m mas também ao n, e deverá ser para menor ou igual a 0!

listSeq6 n m = if m <= 0 || n <= 0
              then [[]]
              else takeWhile ((== n) . length) . map (take n) . iterate (drop m)

Pessoalmente prefiro ver, sempre que possível, funções compostas do que funções lambda na condição.

Edited by thoga31

Knowledge is free!

Share this post


Link to post
Share on other sites
leia

Hum ,me esta a dar erro quando tento compilar.

ERROR "test2.hs":51 - Type error in conditional
*** Expression : if m <= 0 || n <= 0 then [[]] else takeWhile (flip (==) n . length) . map (take n) . iterate (drop m)
*** Term : takeWhile (flip (==) n . length) . map (take n) . iterate (drop m)
*** Type : [b] -> [[b]]
*** Does not match : [[a]]

E tambem descobri que duas das funções a cima não me estão a dar resultados coretos em todos os casos

listSeq6 n m = if m == 0
		  then error "deslocamento tem de ser >= 1"
		  else takeWhile (\x -> length x == n) .map(take n). iterate (drop m)

listSeq4 n m = if m == 0
		  then error "deslocamento tem de ser >= 1"
		  else takeWhile (not.null).map(take n).iterate (drop m)

porque obtenho

Main> listSeq4 3 1 [1,2,3,4,5,6,7,8]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8],[8]]
Main> listSeq4 4 2 [1,2,3,4,5,6,7,8]
[[1,2,3,4],[3,4,5,6],[5,6,7,8],[7,8]]
Main> listSeq4 2 2 [1,2,3,4,5,6,7,8]
[[1,2],[3,4],[5,6],[7,8]]
Main> listSeq4 3 2 [1,2,3,4,5,6,7,8]
[[1,2,3],[3,4,5],[5,6,7],[7,8]]

Main> listSeq6 3 1 [1,2,3,4,5,6,7,8]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8]]
Main> listSeq6 3 2 [1,2,3,4,5,6,7,8]
[[1,2,3],[3,4,5],[5,6,7]]
Main> listSeq6 4 2 [1,2,3,4,5,6,7,8]
[[1,2,3,4],[3,4,5,6],[5,6,7,8]]
Main> listSeq6 2 2 [1,2,3,4,5,6,7,8]
[[1,2],[3,4],[5,6],[7,8]]

em lugar de

Main> listSeq 3 2 [1,2,3,4,5,6,7,8]
[[1,2,3],[3,4,5],[5,6,7],[7,8]]
Main> listSeq 3 1 [1,2,3,4,5,6,7,8]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8]]
Main> listSeq 2 2 [1,2,3,4,5,6,7,8]
[[1,2],[3,4],[5,6],[7,8]]
Main> listSeq 4 2 [1,2,3,4,5,6,7,8]
[[1,2,3,4],[3,4,5,6],[5,6,7,8]]

Edited by Rui Carlos
GeSHi

Share this post


Link to post
Share on other sites
leia

Ja agora para meter o codigo as cores qual a opção ??? para não voltar a levar nas orelhas!!!!

Edited by leia

Share this post


Link to post
Share on other sites
thoga31

Porque fizeste um flip na condição do takeWhile?

Ja agora para meter o codigo as cores qual a opção ??? para não voltar a levar nas orelhas!!!!

No link diz que, após "code", se mete "=LP", onde "LP" é o nome da linguagem. Neste caso, é "haskell", logo, será "code=haskell":

[ code=haskell ]  <-- sem os espaços
código aqui
[ /code ]  <-- sem os espaços


Knowledge is free!

Share this post


Link to post
Share on other sites
leia

Boa noite,

aquele flip foi uma sugestão que me foi dada mais acima para fazer a troca do que tinha com a lambda.Podia me dizer faz favor porque não funcionou em todos os casos alterando meu resultado.?

leia

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.