et RPL : Produit interne

Produit interne

L’exemple classique de produit interne est la fonction SOMMEPROD d’Excel permettant de faire une somme de produits. Ceci se traduit en APL par :

1 2 3 +.× 4 5 6
Output: 32            ⍝ (1×4) + (2×5) + (3×6)

Ce cas particulier s’obtient facilement en RPL :

2: {1 2 3}
1: {4 5 6}
×           # Produit terme à terme des 2 listes
∑LIST       # Somme des éléments 

1: 32

D’autres cas utiles en version APL :

∧.<             ⍝ Tous plus petits que...
∨.<             ⍝ Au moins un plus petit que...

4 6 8 ∧.< 10
1             ⍝ Tous plus petits que 10
14 16 8 ∨.< 10
1             ⍝ Au moins un plus petit que 10

Et en version RPL :

2: {4 6 8}
1: 10
< ΠLIST      # Produit de booléens = ET

1: 1         # Tous plus petits que 10

2: {4 6 8}
1: 10
< ∑LIST SIGN     # Signe somme booléens = OU

1: 1         # Au moins un plus petit que 10

Remarquez que l’on aurait pu utiliser une écriture plus proche de l’APL :

2: {4 6 8}
1: « 10 < « AND » STREAM »
EVAL
1: 1         # Tous plus petits que 10

2: {4 6 8}
1: « 10 < « OR » STREAM »
EVAL
1: 1         # Au moins un plus petit que 10

On en déduit une généralisation du produit interne “x f.g y”,  Norman Brenner propose la fonction IN. (notée IOPROD dans le document original)

« → f « EVAL f STREAM » »
'IN. STO

Exemple :

4: {1 2 3}
3: {4 5 6}
2: « × »
1: « + »
VAR IN.

1: 32

Le principe est assez simple, l’opérateur + est mis dans la variable f (et disparait de la pile), EVAL fait alors le produit entre les 2 listes puis on réduit (application de manière récursive avec STREAM) en utilisant f, ce qui signifie ici faire la somme des termes.

Exercice révision
Plus grande valeur commune entre 2 listes

Il s’agit de trouver quelle est la plus grande valeur commune entre 2 listes (ces listes pouvant comporter des nombres négatifs ou nuls). Voici le résultat à traduire en RPL :

MAXI ← {⌈/ (⍺ ∊ ⍵) / ⍺}
2 3 8 1 MAXI 3 5 7 8 9
Output: 8

Solution : Le symbole ⍺ désigne l’opérande à gauche et ⍵ l’opérande à droite. On crée le vecteur logique ⍺ ∊ ⍵ qui permettra de ne garder que les éléments de ⍺ qui appartiennent à ⍵. On réduit “/” ensuite ce vecteur par la fonction max ⌈. En utilisant la fonction CL. que l’on a construite dans la première partie et qui permet de faire une compression logique :

« 2 « IF NOT THEN DROP END » DOLIST »
'CL. STO

Ou notre version simplifiée :

« SWAP IFT »
'CL. STO

On peut définir MAXI par :

« → v « DUP
 1 « v SWAP POS SIGN » DOLIST »   # ⍺ ∊ ⍵ ?
 CL.                              # (⍺ ∊ ⍵) / ⍺
 « MAX » STREAM                   # ⌈/
»
'MAXI STO

Testons :

2: {2 3 8 1}
1: {3 5 7 8 9}
VAR MAXI

1: 8

Ou, si l’on ne veut pas utiliser CL. et n’avoir qu’une seule boucle:

« → v 
 « DUP          
  2 « IF v SWAP POS NOT   # Boucle (⍺ ∊ ⍵) / ⍺
      THEN DROP END
  » DOLIST
 »
 « MAX » STREAM    # ⌈/
»
'MAXI STO

Signalons que « MAX » STREAM ne fonctionne pas lorsqu’une liste est vide.

2: {2 3 8 1}
1: {4 4 4 4}
VAR MAXI

STREAM Error    # Car aucun élément en commun

Lire la suite…