Je dois utiliser la programmation fonctionnelle pour implémenter la fonction suivante prend une liste de nombres allant de 0 à 9. Le but est de trouver les cinq éléments consécutifs de la liste qui ont le plus grand produit. La fonction doit renvoyer Tuple de l'index du plus grand produit et de la valeur du plus grand produit sans à l'aide de la fonction max .
Je peux facilement l'implémenter sans programmation fonctionnelle, mais j'ai du mal à l'implémenter sans boucles. C’est mon approche jusqu’à présent, mais la partie sur laquelle je suis coincé est la façon de parcourir le tableau pour trouver ces cinq nombres consécutifs sans boucles. J'essaie d'utiliser map pour faire cela, mais je ne pense pas que ce soit correct. Est-il possible d'incorporer énumérer de quelque manière que ce soit? Toute aide est appréciée.
def find_products(L):
val = map(lambda a: reduce(lambda x,y: x*y, L),L)
print (val)
Cela n'a pas de boucles explicites ou appelle la fonction max
. La fonction suppose qu'il y a au moins cinq éléments dans la liste d'entrée et génère un Tuple (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:])
crée un itérateur de fenêtre coulissante de taille 5 sur la liste de saisie. products = map(partial(reduce, operator.mul), win)
est un itérateur appelant partial(reduce, operator.mul)
(traduit par reduce(operator.mul, ...)
) sur chaque élément de win
. reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))
ajoute un compteur à products
et renvoie la paire index-valeur avec la valeur la plus élevée.
Si vous avez besoin d'une version plus générale et/ou que la liste de saisie est volumineuse, utilisez itertools.islice
:
from itertools import islice
def f(l, n=5):
win = Zip(*(islice(l, i, None) for i in range(n)))
...
Le code ci-dessus utilise une expression génératrice qui est techniquement une boucle. Une version fonctionnelle pure de cela pourrait ressembler
from itertools import islice
def f(l, n=5):
win = Zip(*map(lambda i: islice(l, i, None), range(n)))
...
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
contient tous les 5 produits possibles Tuple, puis en utilisant reduce
pour imiter la fonction max
, nous trouvons le maximum parmi les produits.
Vous pouvez faire ce qui suit:
range(0, len(L) - 5)
start
et au produit des éléments L[start:start + 5]
L[result:result + 5]
Cet algorithme pourrait être encore amélioré pour éviter de re-calculer les sous-produits, mais utilisez un "produit glissant", mis à jour à mesure que vous réduisez de gauche à droite, divisé par l'élément supprimé et multiplié par le nouvel élément. ajoutée.
voulez un liner utilisant max et sans max essayez ceci
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
Le paradigme impératif est souvent:
state = state0
while condition:
# change state
C'est la manière "naturelle" de programmer pour beaucoup de gens et vous savez comment procéder de cette façon.
Le paradigme pur fonctionnel interdit les variables, qui présentent certains avantages. Il fonctionne avec des fonctions qui communiquent via des paramètres (IN) et des valeurs de retour (OUT). Il utilise fréquemment des fonctions récursives.
Un schéma générique fonctionnel récursif est:
f = lambda *args : result(*args) if condition(*args) else f(*newparams(*args))
Ici, nous pouvons trouver une solution avec (l,i,imax,prodmax)
en tant que paramètres et:
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])
Aucune autre que les fonctions ont été définies.
Vous pouvez même ne définir aucune fonction pour cela, voir ici par exemple, mais la lisibilité en souffre encore plus.
Courir :
In [1]: f([random.randint(0,9) for i in range (997)],0,0,0)
Out[1]: (386, 59049)
Python limite cette approche en définissant la profondeur récursive sur 2000 et à partir de Python 3, en masquant les outils fonctionnels dans le module functools
.
Cette solution utilise reduce
pour calculer un produit à 5 valeurs, la compréhension de la liste pour générer tous ces produits, la création de tuples pour avoir l'index correspondant à chacun, reduce
pour obtenir le meilleur Tuple.
Un opérateur if else
est utilisé pour intercepter le cas où il n'y a pas 5 valeurs dans l'entrée.
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 sortie pour l'exemple d'appel est:
(7, 48)
Une solution Pure Python utilisant recursion
Tout d'abord, nous devons créer une recursive
function
pour trouver la product
d'une list
:
def product(l, i=0, s=1):
s *= l[i]
if i+1 < len(l):
return product(l, i+1, s)
return s
que nous pouvons faire des tests pour:
>>> product([1, 2, 3])
6
>>> product([1, 1, 1])
3
>>> product([2, 2, 2])
8
Ensuite, nous pouvons utiliser cette function
dans une autre recursive
function
pour résoudre votre problème:
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
qui fonctionne!
Voici quelques tests pour montrer qu'il fonctionne:
>>> 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)
Voici une solution Haskell purement fonctionnelle:
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]
Voici ce qu'il fait:
tails xs
donne tous les sous-ensembles commençant par différentes valeurs de départ:
> 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],[]]
Zip
avec des nombres naturels tels que l’index de départ y soit associé.multiply
. Là, ceux-ci sont réduits à un seul numéro, le produit.(5,450)
pour mes données d'entrée.