et RPL : Réduction

En APL, l’association du symbole de réduction / et d’une fonction dyadique permet d’appliquer cette dernière entre tous les éléments de l’opérande (terme de droite). Exemples :

+/ 1 2 3 4
Output : 10       ⍝ (1 + (2 + (3 + 4)))

⌈/ 1 5 2 4       ⍝ x ⌈ y <=> max(x,y)
Output : 5       ⍝ max(1, max(5, max(2,4)))

On a un équivalent plutôt élégant en RPL avec STREAM :

2: { 1 2 3 4 }       # L'opérande
1: « + »             # La fonction à appliquer
PRG LIST PROC STREAM

1: 10                # (((1 + 2) + 3) + 4)

2: { 1 5 2 4 }
1: « MAX »
STREAM

1: 5                # max(max(max(1, 5), 2), 4)

Attention, en APL les calculs se font de la droite vers la gauche, alors qu’en RPL ils se font de la gauche vers la droite :

2: { 1 2 3 4 }
1: « - »         # Soustraction
STREAM

1: -8            # (((1 - 2) - 3) - 4)

2: { 4 3 2 1 }
1: « - »         # Soustraction
STREAM

1: -2            # (1 - (2 - (3 - 4)))

et en APL :

-/ 1 2 3 4
¯2               ⍝ (1 - (2 - (3 - 4)))

Il est également possible en APL et préciser le nombre d’éléments à traiter lors de chaque réduction, par exemple :

2 +/ 1 2 3 4 5
3 5 7 9       ⍝ Par 2 : 1+2=3, 2+3=5, 3+4=7...

Et bien c’est également possible en RPL avec DOSUBS :

3: {1 2 3 4 5}
2: 2             # Traiter les éléments 2 par 2 
1: « + »         # Opération pour la réduction
PRG LIST PROC DOSUB

1: {3. 5. 7. 9.}

Dans le cas où le nombre d’éléments à traiter est égal à 1, cela revient finalement à faire un MAP, c’est-à-dire une transformation terme à terme des éléments de la suite.

Remarquons aussi que dans ce cas, DOSUBS et DOLIST ont le même effet :

2: {9 10 12}
1: « 1 « SQ » DOSUB »   # Mettre au carré 1 par 1
EVAL

1: {81. 100. 144.}

2: {9 10 12}
1: « 1 « SQ » DOLIST »  # Mettre au carré 1 liste
EVAL

1: {81. 100. 144.}

A priori pas d’intérêt car { 9 10 12 } SQ donne le même résultat, cependant regardons cet exemple tiré d’une de mes vidéos sur l’APL

Exemple 2 – Meilleurs score

Récupérer les meilleurs scores de 3 équipes :

BEST (4 8 9) (5 10 3) (7 12)  ⍝ 3 équipes
9 10 12      ⍝ Meilleurs score de chaque équipe

On voudrait cet équivalent en RPL :

1: {{4 8 9} {5 10 3} {7 12}}
VAR BEST

1: {9. 10. 12.}

Il faut donc que l’on prenne le MAX de CHAQUE liste, c’est  à la fois une réduction par le maximum et un mapping. D’où simplement :

« 1 « « MAX » STREAM » DOSUBS »
'BEST STO

Exemple 3 – Combien sont plus grands que moi ?

Toujours tiré d’une de mes vidéos sur l’APL, on voudrait connaitre, pour chaque élément d’une liste, combien sont plus grands. Par exemple :

{1 30 4 16 5 1 8}
VAR SUP
{5. 0. 4. 1. 3. 5. 2.}

Ce qui signifie que 5 valeurs sont strictement plus grandes que 1, aucune n’est plus grande que 30, 4 sont strictement plus grandes que 4, etc.

Chaque élément doit être comparé à l’ensemble de la liste, ce qui va créer un vecteur logique dont il faudra additionner les termes (réduction). Par exemple

1 < {1 30 4 16 5 1 8}

{0. 1. 1. 1. 1. 0. 1.}

dont la somme fait 5.  Cette addition peut se faire par un

« + » STREAM

ou bien sûr par :

∑LIST

Finalement, le programme SUP peut s’écrire :

« DUP →s           # Copie de la liste dans s
 « 1               # Début du mapping
  « s < ∑LIST      # Vecteur booléen et réduction
  » DOSUBS         # ou DOLIST
 »
»
'SUP STO

Il y a plusieurs solutions en APL (voir vidéo) mais celle analogue à la version RPL est :

SUP ← {{+/ ⍵ < s}¨ s ← ⍵}
SUP 1 30 4 16 5 1 8

Output: 5 0 4 1 3 5 2

On a l’affectation s ← ⍵ de la liste vers s, puis pour chaque (noté par le ¨ ) élément ⍵, on compte +/ combien l’éléments sont plus grands que ⍵.

Lire la suite…