Programação recursiva em listas
Padrão 1: realizar uma operação de redução numérica em uma lista de valores
Exemplo
Escreva um programa para calcular a soma dos valores de uma lista. Ex: \( {3, 8, 20, 21, 34, 44} \).
Formulação recursiva
\( soma({}) = 0 \) \( soma({a_{1}, ...a_{n}}) = a_{1} + soma({...a_{n}}) \)
Implementação em JavaScript
const soma = (lista) => {
if (lista.length == 0) {
return 0
} else {
const head = lista[0]
const tail = lista.slice(1)
return (head + soma(tail))n
}
}
Versão com uso do já conhecido operador spread para listas.
const soma = (lista) => {
if (lista.length == 0) {
return 0
} else {
const [x, ...xs] = lista
return x + soma(xs)
}
}
Versão com teste acerca de valor indefinido e operador condicional ternário
const soma = ([x, ...xs]) => x === undefined ? 0 : x + soma(xs)
Padrão 2: retornar o elemento de uma lista que atenda a um determinado critério
Exemplo
Encontre o maior elemento de uma lista.
Formulação recursiva
\( maior({}) = vazia \) \( maior({a_{1}}) = a_{1} \) \( maior({a_{1}, ...a_{n}}) = a_{1} \), se \( a_[1} > maior({...a_{n}}) \)
Implementação em JavaScript
const maior = ([x, ...xs]) => {
if (x === undefined) {
return 'Lista vazia'
} else {
return maiorAux([x, ...xs])
}
}
const maiorAux = ([x, ...xs]) => {
if (xs.length == 0) {
return x
} else {
const maior = maiorAux([...xs])
return (x > maior) ? x : maior
}
}
Padrão 3: realizar operações sobre elementos de uma lista, gerando uma nova lista.
Exemplo
Inverta a ordem dos elementos de uma lista.
Formulação recursiva
\( inverte({}) = {} \) \( inverte({a_{1}, ...a_{n}}) = {inverte({...a_{n}}), a_{1}} \)
Implementação em JavaScript
const inverte = ([x, ...xs]) =>
x === undefined ? [] : [...inverte(xs), x]
Exemplo
Duplique a presença de cada elemento de uma lista.
Formulação recursiva
\( duplica({}) = {} \) \( duplica({a_{1} ...a_{n}}) = {a_{1}, a_{1}, ...duplica({...a_{n}})} \)
Implementação em JavaScript
const duplica = ([x, ...xs]) =>
x === undefined ? [] : [x, x, ...duplica(xs)]
Padrão 4: verificar se uma lista possui um elemento que atenda a uma dada propriedade/característica
Exemplo
Verifique se uma lista possui um determinado elemento.
Formulação recursiva \( elem(e, {}) = F \) \( elem(e, {a_{1} ...a_{2}}) = (e = a_{1}) \lor elem(e, {...a_{n}}) \)
Implementação em JavaScript
const elem = (e, [x, ...xs]) => {
if (x === undefined) {
return false
} else {
return (e === x) || elem(e, [...xs])
}
}
Padrão 5: verificar se a lista atende a uma determinada propriedade
Exemplo
Teste se uma string consiste num palíndromo.
Formulação recursiva
\( palindromo('') = T \) \( palindromo('char1') = T \) \( palindromo('char_{1}...meio...char_{n}') = (char_{1} = char_{n}) \land palindromo('meio') \)
Implementação em JavaScript
const palindromo = (str) => {
if (str.length < 2) {
return true
} else {
const primeiro = str.slice(0, 1)
const ultimo = str.slice(-1)
const meio = str.slice(1, -1)
return (primeiro === ultimo) && palindromo(meio)
}
}