programacion funcional funcion python list lambda functional-programming

python - programacion - ¿Cómo usar la programación funcional para iterar y encontrar el producto máximo de cinco números consecutivos en una lista?



funcion filter python (8)

Aquí hay una solución Haskell, que es puramente funcional:

import Data.List multiply :: [Int] -> Int multiply = foldr (*) 1 consecutiveProducts :: [Int] -> [(Int,Int)] consecutiveProducts xs = [(i,multiply $ take 5 h) | (i,h) <- zipped, length h >= 5] where indices = reverse [0..(length xs)] zipped = zip indices (tails xs) myComp (i1,h1) (i2,h2) = compare h2 h1 main = print $ head $ sortBy myComp $ consecutiveProducts [4,5,3,1,5,3,2,3,5]

Esto es lo que hace:

  • Comenzando en la última línea, calcula los productos consecutivos de esa lista.
  • tails xs da todos los subconjuntos comenzando con diferentes valores iniciales:

    > tails [4,5,3,1,5,3,2,3,5] [[4,5,3,1,5,3,2,3,5],[5,3,1,5,3,2,3,5],[3,1,5,3,2,3,5],[1,5,3,2,3,5],[5,3,2,3,5],[3,2,3,5],[2,3,5],[3,5],[5],[]]

  • De estas colas solo tomamos las que tienen al menos 5 elementos de longitud.
  • Luego los creamos con números naturales de manera que tengamos el índice de inicio asociado.
  • De cada uno de los subconjuntos tomamos los primeros cinco elementos.
  • Estos cinco elementos se pasan a la función multiply . Ahí se reducen a un solo número, el producto.
  • Después de eso volvemos a la última línea, ordenamos la lista por el valor del producto descendiente.
  • De la lista resultante solo tomamos el primer elemento.
  • Y luego imprimimos el resultado, que es (5,450) para mis datos de entrada.

Tengo que usar la programación funcional para implementar la siguiente función. Toma una lista de números del 0 al 9. El objetivo es encontrar los cinco elementos consecutivos de la lista que tienen el mejor producto. La función debe devolver una tupla del índice del producto más grande y el valor del producto más grande sin usar la función máxima .

Puedo implementar esto fácilmente sin programación funcional, pero tengo problemas para implementarlo sin ningún bucle. Este es mi enfoque hasta el momento, pero la parte en la que estoy atascado es cómo recorrer la matriz para encontrar esos cinco números consecutivos sin bucles. Estoy tratando de usar el mapa para hacer eso, pero no creo que sea correcto. ¿Es posible incorporar enumerate de alguna manera? Cualquier ayuda es apreciada.

def find_products(L): val = map(lambda a: reduce(lambda x,y: x*y, L),L) print (val)


El paradigma imperativo es a menudo:

state = state0 while condition: # change state

Esta es la forma "natural" de programación para muchas personas y usted sabe cómo hacerlo de esta manera.

El paradigma funcional puro prohíbe las variables, que tienen algunas ventajas. Funciona con funciones que se comunican a través de parámetros (IN) y valores de retorno (OUT). Con frecuencia usa funciones recursivas.

Un esquema recursivo funcional genérico es:

f = lambda *args : result(*args) if condition(*args) else f(*newparams(*args))

Aquí podemos encontrar una solución con (l,i,imax,prodmax) como parámetros, y:

condition = lambda l,i,_,__ : i>=len(l)-5 result = lambda _,__,*args : args newparams = lambda l,i,imax,prodmax: (l, i+1, imax, prodmax) / if l[i]*l[i+1]*l[i+2]*l[i+3]*l[i+4] <= prodmax / else (l, i+1, i, l[i]*l[i+1]*l[i+2]*l[i+3]*l[i+4])

No se han definido otras funciones.

Incluso puede definir ninguna función para hacer eso, consulte aquí, por ejemplo, pero la legibilidad sufre aún más.

Correr :

In [1]: f([random.randint(0,9) for i in range (997)],0,0,0) Out[1]: (386, 59049)

Python limita este enfoque al establecer profundidad recursiva en 2000, y desde Python 3, al ocultar herramientas funcionales en los módulos functools .


Esta solución usa reduce para calcular un producto de 5 valores, enumerar la comprensión para generar todos esos productos, creación de tuplas para tener el índice para cada uno, reduce nuevamente para obtener la mejor tupla.

Se utiliza un operador if else para detectar el caso cuando no hay 5 valores en la entrada.

from functools import reduce def find_products(values): return None if len(values) < 5 else reduce( lambda best, this: this if this[1] > best[1] else best, [(i, reduce(lambda a,b: a*b, values[i:i+5], 1)) for i in range(0, len(values)-4)] ) result = find_products([1, 0, 8, 3, 5, 1, 0, 2, 2, 3, 2, 2, 1]) print (result)

La salida para la llamada de ejemplo es:

(7, 48)


Esto no tiene ningún bucle explícito ni llama a la función max . La función asume que hay al menos cinco elementos en la lista de entrada y genera una tupla (start_index, max_product) .

from functools import reduce, partial import operator def f(l): win = zip(l, l[1:], l[2:], l[3:], l[4:]) products = map(partial(reduce, operator.mul), win) return reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))

In [2]: f([1, 2, 3, 4, 7, 8, 9]) Out[2]: (2, 6048) In [3]: f([2, 6, 7, 9, 1, 4, 3, 5, 6, 1, 2, 4]) Out[3]: (1, 1512)

win = zip(l, l[1:], l[2:], l[3:], l[4:]) crea un iterador de ventana deslizante de tamaño 5 sobre la lista de entrada. products = map(partial(reduce, operator.mul), win) es un iterador que llama partial(reduce, operator.mul) (se traduce para reduce(operator.mul, ...) ) en cada elemento de win . reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products)) agrega un contador a los products y devuelve el par índice-valor con el valor más alto.

Si necesita una versión más general y / o la lista de entrada es grande, debería usar itertools.islice :

from itertools import islice def f(l, n=5): win = zip(*(islice(l, i, None) for i in range(n))) ...

El código anterior usa una expresión de generador que es un bucle, técnicamente. Una versión funcional pura de eso podría verse como

from itertools import islice def f(l, n=5): win = zip(*map(lambda i: islice(l, i, None), range(n))) ...


Usted podría hacer lo siguiente:

  • Para cada índice de inicio en el range(0, len(L) - 5)
  • Asigne el índice a la tupla de start y al producto de los elementos L[start:start + 5]
  • Reduce las tuplas a la que tiene el producto más alto
  • Obtenga el primer valor de la tupla resultante = el índice de inicio de los 5 elementos que tienen el producto más alto
  • Devuelve la porción L[result:result + 5]

Este algoritmo podría mejorarse aún más para evitar volver a calcular los subproductos, pero use un "producto rodante", que se actualiza a medida que se reduce de izquierda a derecha, dividiendo por el elemento que se eliminó y multiplicando por el nuevo elemento que fue adicional.


quiero un forro usando max y sin max probar esto

from numpy import prod l=[2,6,7,9,1,4,3] max([prod(l[i:i+5]) for i in range(len(l))]) sorted([prod(l[i:i+5]) for i in range(len(l))])[-1] // without max


Una solución Pure Python que usa recursion

Primero, necesitamos crear una function recursive para encontrar el product de una list :

def product(l, i=0, s=1): s *= l[i] if i+1 < len(l): return product(l, i+1, s) return s

para lo cual podemos hacer algunas pruebas:

>>> product([1, 2, 3]) 6 >>> product([1, 1, 1]) 3 >>> product([2, 2, 2]) 8

Entonces, podemos usar esta function en otra function recursive para resolver su problema:

def find_products(l, i=0, t=(0, -1)): p = product(l[i:i+5]) if p > t[1]: t = (i, p) if i+5 < len(l): return find_products(l, i+1, t) return t

que funciona!

Aquí hay algunas pruebas para mostrar que funciona:

>>> find_products([1, 1, 5, 5, 5, 5, 5, 1, 1]) (2, 3125) >>> find_products([1, 1, 1, 1, 1, 0, 0, 0, 0]) (0, 1) >>> find_products([1, 4, 5, 2, 7, 9, 3, 1, 1]) (1, 2520)


from functools import reduce #only for python3, python2 doesn''t need import def find_products(L): if len(L)==0: return 0 if len(L) <= 5: return reduce( lambda x,y:x*y, L) pdts = ( reduce(lambda a,b:a*b,L[pos:pos+5]) for pos in range(len(L)-4)) # or pdts = map(lambda pos: reduce(lambda a,b:a*b,L[pos:pos+5],0),range(len(L)-4)) mx = reduce(lambda x,y: x if x>y else y, pdts) return mx

pdts contiene todos los posibles 5 productos de tupla, y luego usa reduce para imitar la función max , encontramos el máximo entre los productos.