Jump to content

Dada uma lista e um elemento, retornar todos os índices do elemento em uma lista


crislanio_macedo
 Share

Recommended Posts

Olá pessoal queria que dada uma lista e um elemento, retornar todos os índices do elemento em uma lista.

para isso tenho algumas funções em partes:

TakeUmElemento (t:ts) id | id==0 =t
|otherwise =takeUmElemento ts (id-1)
-- -------------------------------------------------------------------------
--dMod x = (x `mod` 10)
dDiv x =(x `div` 10)
inteiroPraLista :: Int -> [int]--
inteiroPraLista x | x<10 = [x] -- error "Entrada invalida"
|otherwise= if (dDiv x) >10 then (dMod x):inteiroPraLista (dDiv(x)) else dMod(x):[dDiv (x) ]
-- -------------------------------------------------------------------------
indice1 l@(t:ts) e = if e==t then inteiroPraLista(takeUmElemento l e) else indice1 ts e
--indice 2 [1,2,3,4,2] = [1,4]

Contudo vejo que a função indice1 não está bem como eu queria, me ajudem nessa lógica.

em indice1 eu tenho caso o elemento e seja igual ao 1° elemento da lista eu chamaria, a função takeUmElemento l e com a lista e o elemento, ela retornaria o índice do elemento para uma lista, caso o elemento não fosse igual chamaria o restante da função indice1 ts e

Mas o resultado está sendo.

*Main> indice1 [1,2,3,4,2] 2
[4]
*Main> indice1 [1,2,3,4,2] 3
*** Exception: Lista2.hs:(30,1)-(31,40): Non-exhaustive patterns in function takeUmElemento

Como eu faria para que a função takeUmElemento l e retornasse um elemento e esse elemento fosse adicionado a inteiroPraLista ?

Att,

Edited by pwseo
Corrigidas tags code.
Link to comment
Share on other sites

crislanio_macedo,

Vou dissecar o teu código passo-a-passo e vamos tentar chegar à solução do teu problema. Tomei a liberdade de reformatar algum do teu código.

-- tinhas aqui um erro: 'TakeUmElemento' em vez de 'takeUmElemento'
takeUmElemento (t:ts) id | id == 0   = t
                        | otherwise = takeUmElemento ts (id - 1)

Qual é o objectivo deste pedaço de código? É essencialmente a função do operador (!!), que é bastante mais claro em termos sintácticos:

*Main> "crislanio_macedo" !! 3
's'
*Main> takeUmElemento "crislanio_macedo" 3
's'

Depois temos este bloco:

-- por algum motivo tinhas comentado esta linha erradamente
dMod x = x `mod` 10
dDiv x = x `div` 10

inteiroPraLista :: Int -> [int]
inteiroPraLista x | x < 10 = [x] -- error "Entrada invalida"
                 | otherwise = if dDiv x > 10 then dMod x : inteiroPraLista (dDiv x)
                                              else dMod x : [dDiv x]

Sinceramente, não percebi. Qual é o objectivo de inteiroPraLista? Estás a tentar devolver uma lista com os algarismos de um número? Se sim, para que precisas disso e em que ponto do algoritmo entra esse passo?

Repara também que alterei o aspecto da tua função; tinhas imensos parênteses bastante mal colocados (é algo que deverás procurar esclarecer, essencial à escrita de código legível em Haskell, e muito diferente das linguagens imperativas mais comuns).

Depois chegamos à função indice1 (que limpei substituindo takeUmElement por !!):

indice1 l@(t:ts) e = if e == t then inteiroPraLista (l !! e)
                              else indice1 ts e

Esta função está completamente dependente da inteiroPraLista, que não faz grande sentido a meu ver.

A solução que tenho em mente é bastante mais simples, com apenas meia dúzia de linhas e completamente genérica. Ainda assim, aguardo as tuas respostas, para podermos levar-te à solução de uma forma mais didáctica do que apresentando o código final.

  • Vote 1
Link to comment
Share on other sites

crislanio_macedo,

Vou dissecar o teu código passo-a-passo e vamos tentar chegar à solução do teu problema. Tomei a liberdade de reformatar algum do teu código.

-- tinhas aqui um erro: 'TakeUmElemento' em vez de 'takeUmElemento'
takeUmElemento (t:ts) id | id == 0   = t
					 | otherwise = takeUmElemento ts (id - 1)

Qual é o objectivo deste pedaço de código? É essencialmente a função do operador (!!), que é bastante mais claro em termos sintácticos:

*Main> "crislanio_macedo" !! 3
's'
*Main> takeUmElemento "crislanio_macedo" 3
's'

Depois temos este bloco:

-- por algum motivo tinhas comentado esta linha erradamente
dMod x = x `mod` 10
dDiv x = x `div` 10

inteiroPraLista :: Int -> [int]
inteiroPraLista x | x < 10 = [x] -- error "Entrada invalida"
			  | otherwise = if dDiv x > 10 then dMod x : inteiroPraLista (dDiv x)
										   else dMod x : [dDiv x]

Sinceramente, não percebi. Qual é o objectivo de inteiroPraLista? Estás a tentar devolver uma lista com os algarismos de um número? Se sim, para que precisas disso e em que ponto do algoritmo entra esse passo?

Repara também que alterei o aspecto da tua função; tinhas imensos parênteses bastante mal colocados (é algo que deverás procurar esclarecer, essencial à escrita de código legível em Haskell, e muito diferente das linguagens imperativas mais comuns).

Depois chegamos à função indice1 (que limpei substituindo takeUmElement por !!):

indice1 l@(t:ts) e = if e == t then inteiroPraLista (l !! e)
						   else indice1 ts e

Esta função está completamente dependente da inteiroPraLista, que não faz grande sentido a meu ver.

A solução que tenho em mente é bastante mais simples, com apenas meia dúzia de linhas e completamente genérica. Ainda assim, aguardo as tuas respostas, para podermos levar-te à solução de uma forma mais didáctica do que apresentando o código final.

Mais uma vez muito útil e simples suas explicações. Grato.

Bom, a minha ideia ao usar a função inteiroPraLista seria a medida que eu pegasse o índice do elemento da lista eu adicionasse a lista.

Tentarei proceder aqui com minha resolução, mas como vossa excelentíssima pessoa está a perceber eu estou a ter dificuldades em ilustrar minhas ideias na linguagem (sintaxe).

Tentarei aqui proceder com minha resolução para que possa arguir-me das minhas premissas.

Link to comment
Share on other sites

indices :: Eq a=> a ->[a] -> [int]
indices x ys = [i | (i,y) <-zip [0..n] ys, x==y]
where n =length ys -1

Queria fazer algo diferente disso, algo não recursivo.

Como então fazer uma função para retornar o índice da função e não o valor e então adiciona-la a uma lista.

Edited by crislanio_macedo
Link to comment
Share on other sites

indice1 (t:ts) e = if e == t then e:indice1 ts e
						 else indice1 ts e

Eu precisaria de uma função para pegar os índices e só então adicionar a lista.

Teria alguma função que faça isso em algum módulo?

indice1 (t:ts) e = if e == t then Data.List.findIndices indice1 ts e
						 else indice1 ts e

Não estou nem a saber como usá-la

Edited by crislanio_macedo
Link to comment
Share on other sites

Percebo. Vou dar-te uma sugestão então, e depois vamos refinando a função até ficar mais simples de utilizar.

Para fazeres o que pretendes, precisas de uma função recursiva que mantenha registo de várias coisas:

  • O elemento que procuras
  • A lista onde procuras o elemento
  • A posição em que vais
  • Uma lista de posições onde já foi encontrado o elemento

Vou escrever o caso de base e tu vais tentar completar a função:

pos :: (Eq a, Num b) => a   -- o elemento que procuramos
                   -> [a]  -- a lista onde o procuramos
                   ->  b   -- a posição em que vamos
                   -> [b]  -- a lista de posições onde já encontrámos o elemento
-- caso base:
pos _ [] _ indices = indices  -- quando a lista onde procuramos acabar, devolver a lista de posições que acumulámos.
pos e (x:xs) i is  = -- agora completa tu aqui.

É suposto que aconteça o seguinte:

*Main> pos 2 [1,2,3,4,2] 0 []
[1,4]

Não te preocupes com os dois argumentos adicionais que passámos à pos. Eventualmente irão desaparecer; estão ali para te ajudar a perceber o funcionamento.

  • Vote 1
Link to comment
Share on other sites

Somente um detalhe a ser corrigido .

Prelude> :l Lista2.hs
[1 of 1] Compiling Main			 ( Lista2.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t pos
pos :: (Eq a, Num a1) => a -> [a] -> a1 -> [a1] -> [a1]
*Main> pos 2 [1,2,3,4,2] 0 []
[1,3]

pos _ [] _ indices = indices -- quando a lista onde procuramos acabar, devolver a lista de posições que acumulámos.
pos e (x:xs) i is = if e ==x then i:pos e xs i is else pos e xs (i+1) is		 -- agora completa tu aqui.

pos _ [] _ indices = indices -- quando a lista onde procuramos acabar, devolver a lista de posições que acumulámos.
pos e (x:xs) i is = if e ==x then i:pos e xs (i+1) is else pos e xs (i+1) is		 -- agora completa tu aqui.
---------------------
*Main> :r
[1 of 1] Compiling Main			 ( Lista2.hs, interpreted )
Ok, modules loaded: Main.
*Main> pos 2 [1,2,3,4,2] 0 []
[1,4]
*Main>

Muitas vezes se precisa auxiliar uma pessoa mesmo que esteja a resposta óbvia mas a pessoa não consiga enxergá-la.

Obrigado por me auxiliar , guiar meu raciocínio passo a passo.

Grato !!

Edited by crislanio_macedo
Link to comment
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
 Share

×
×
  • 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.