[BASE Cinque - Appunti di Matematica ricreativa]
Sintesi. Siete capaci di combinare i numeri 3, 3, 5, 5 e le
operazioni aritmetiche (+, -, *, /) per ottenere 18?
Questo tipo di puzzle
appartiene alla famiglia dei "giochi dei quattro numeri". Sono piccoli enigmi
che nascondono una sorprendente ricchezza combinatoria.
Vediamo come
costruire un programma che li esplori (quasi) tutti, dai casi più semplici fino
a varianti più generali e complesse.
Nota. Usiamo * per la moltiplicazione e / per la divisione, come nei linguaggi di programmazione e nella Matematica testuale.
La scrittura a / b può indicare una divisione o una frazione.
1. Un classico: i quattro 4
Usando quattro 4, le quattro
operazioni e le parentesi, si possono ottenere i numeri interi da 0 a 9. Non è
invece possibile ottenere 10.
Ecco una lista di possibili soluzioni.
0 = 4 + 4 - 4 - 4
1 = 4 - 4 + (4 / 4)
2 = 4 / 4 + 4 / 4
3 = (4 + 4 + 4) / 4
4 = 4 + 4 * (4 - 4)
5 = (4 * 4 + 4) / 4
6 = 4 + (4 + 4) / 4
7 = 4 + 4 - (4 / 4)
8 = 4 + 4 + 4 - 4
9 = 4 + 4 + (4 / 4)
2. Difficile per la IA: il problema 3, 3, 5, 5
Usando 3, 3, 5, 5 e le quattro operazioni, si può ottenere 18.
Soluzione.
5 * (3 + 3 / 5) = 5 * (18 / 5) = 18
Nota. Questo esercizio ha creato qualche difficoltà ad alcuni sistemi di IA di base (luglio 2026).
3. Una leggenda: il gioco del 24
Usando 3, 3, 8, 8 e le quattro operazioni, si può ottenere 24.
Soluzione.
8 / (3 - 8 / 3) = 8 / (1 / 3) = 24
La difficoltà deriva dal fatto che l'unica soluzione possibile richiede l'uso delle frazioni e della divisione uscendo dal campo dei soli numeri interi. Secondo una leggenda metropolitana, questo esercizio sarebbe stato usato nei colloqui tecnici di Google.
4. Quando le regole non bastano: il problema 2, 2, 2, 2
Usando i numeri 2, 2, 2, 2, le operazioni aritmetiche e le parentesi non si può ottenere 9.
Possiamo estendere le regole, per esempio ammettendo la concatenazione di due o più cifre per formare un numero a più cifre.
Soluzione.
22 / 2 - 2 = 9
5. Un problema storico: con quattro 3
Jack dice a suo fratello Harry: "Io sono capace di combinare quattro 3 e alcune operazioni aritmetiche in modo da ottenere esattamente 34. Tu sei capace di fare altrettanto?"
(Thomas Dilworth, Schoolmaster's Assistant, 1743)
Soluzione.
33 + 3/3 = 34
Scriviamo chiaramente le regole del gioco nella versione base.
Obiettivo del gioco
Ottenere uno o più valori bersaglio combinando 4 numeri dati tramite le operazioni aritmetiche e le parentesi.
Regole di Composizione
Numeri.
Operazioni.
Parentesi.
Vogliamo scrivere un programma che generi, valuti e stampi tutte le espressioni possibili. Ogni espressione sarà formata da 4 numeri e 3 operatori binari.
Cominciamo col pensare un algoritmo per eseguire una ricerca esaustiva di utte le possibili espressioni aritmetiche valide seguendo quattro passaggi fondamentali:
Ho scelto il linguaggio Decimal BASIC prima di tutto perché lo conosco bene e mi piace e in secondo luogo perché gestisce nativamente i numeri razionali e gli interi a grandezza arbitraria.
Se volete, potete tradurlo facilmente nel vostro linguaggio di programmazione preferito.
Trovate il codice nell'appendice 1.
Di seguito, riportiamo solo i primi risultati per alcune quaterne di numeri iniziali.
1) Con 1,1,1,1
Risultati trovati: ------------------ 0 = (1 + (1 - (1 + 1))) 1 = (1 + (1 - (1 * 1))) 2 = (1 + (1 + (1 - 1))) 3 = (1 + (1 + (1 * 1))) 4 = (1 + (1 + (1 + 1)))
2) Con 3,3,3,3
Risultati trovati: ------------------ 0 = (3 + (3 - (3 + 3))) 1 = (((3 + 3) - 3) / 3) 2 = (((3 * 3) - 3) / 3) 3 = (((3 + 3) + 3) / 3) 4 = ((3 + (3 * 3)) / 3) 5 = (3 + ((3 + 3) / 3)) 6 = (3 + (3 + (3 - 3))) 7 = (3 + (3 + (3 / 3))) 8 = ((3 * 3) - (3 / 3)) 9 = (((3 + 3) - 3) * 3) 10 = ((3 * 3) + (3 / 3))
3) Con 4,4,4,4
Risultati trovati: ------------------ 0 = (4 + (4 - (4 + 4))) 1 = (((4 + 4) - 4) / 4) 2 = (4 - ((4 + 4) / 4)) 3 = (((4 + 4) + 4) / 4) 4 = (4 + ((4 - 4) * 4)) 5 = ((4 + (4 * 4)) / 4) 6 = (4 + ((4 + 4) / 4)) 7 = (4 + (4 - (4 / 4))) 8 = (4 + (4 + (4 - 4))) 9 = (4 + (4 + (4 / 4))) 10 = non possibile
4) Con 3,3,5,5
Risultati trovati: ------------------ 0 = ((3 + 3) * (5 - 5)) 1 = ((3 - 3) + (5 / 5)) 2 = ((3 / 3) + (5 / 5)) 3 = (3 + (3 * (5 - 5))) 4 = ((3 - 5) * (3 - 5)) 5 = (((3 + 3) - 5) * 5) 6 = (3 + (3 + (5 - 5))) 7 = (3 + (3 + (5 / 5))) 8 = ((3 * 3) - (5 / 5)) 9 = (3 * (3 + (5 - 5))) 10 = ((3 - 3) + (5 + 5)) 11 = ((3 / 3) + (5 + 5)) 12 = ((3 - (3 / 5)) * 5) 13 = (3 + ((3 * 5) - 5)) 14 = non possibile 15 = non possibile 16 = (3 + (3 + (5 + 5))) 17 = (((3 * 5) - 3) + 5) 18 = ((3 + (3 / 5)) * 5) 19 = ((3 * 3) + (5 + 5)) 20 = (((3 * 3) - 5) * 5)
5) Con 2,4,6,8
Risultati trovati: ------------------ 0 = (((2 + 4) - 6) * 8) 1 = ((2 - 4) / (6 - 8)) 2 = (((2 * 6) + 4) / 8) 3 = ((2 + 4) / (8 - 6)) 4 = (2 + (4 + (6 - 8))) 5 = (2 + (4 * (6 / 8))) 6 = ((2 * 4) + (6 - 8)) 7 = ((2 / (4 - 6)) + 8) 8 = (2 + ((4 - 6) + 8)) 9 = (((2 + 4) / 6) + 8) 10 = (2 - (4 * (6 - 8)))
Avete certamente notato che con alcune quaterne di numeri non è possibile
ottenere tutti i risultati da 0 a 10.
E con quasi tutte le quaterne è
impossibile coprire l'intervallo da 0 a 20.
Diventa quindi irresistibile la tentazione di introdurre nuovi operatori matematici per ampliare la gamma dei numeri raggiungibili.
In modalità ARITHMETIC RATIONAL le divisioni n/10 e n/9 sono gestite come frazioni esatte, evitando errori di arrotondamento.
Trovate il codice nell'appendice 2.
Questa nuova versione del programma genera le soluzioni in due fasi a complessita crescente:
Ricordate però che il programma stampa solo la prima soluzione trovata per ogni numero obiettivo.
Perciò potrebbero non essere visibili soluzioni più semplici oppure più interessanti.
Per esplorare l'intero spazio delle soluzioni, il programma valuta un numero elevato di combinazioni:
In tutto sono:
Questo è un punto chiave del programma, che andrebbe approfondito.
Qui vi
lascio solo uno spunto.
Il numero di modi diversi in cui è possibile parentesizzare un'espressione
con n operatori binari applicati a n+1 operandi è l'ennesimo numero di Catalan,
cioè:
Cn = (2n)! / ((n! * n!)*(n+1))
Per n=3, ovvero 3 operatori e 4 operandi, abbiamo:
Cn = 6! / ((3! * 3!)*4 = 5
La tabella seguente mostra, attraverso un esempio pratico, i 5 tipi possibili di espressioni.
In questo esempio, i numeri sono 9, 1, 3, 2 e gli operatori +, *, -.
| Tipo | Versione RPN | Versione Algebrica | Risultato |
|---|---|---|---|
| 1 | 9 1 + 3 * 2 - | ((9 + 1) * 3) - 2 | 28 |
| 2 | 9 1 + 3 2 * - | (9 + 1) - (3 * 2) | 4 |
| 3 | 9 1 3 + * 2 - | (9 * (1 + 3)) - 2 | 34 |
| 4 | 9 1 3 + 2 * - | 9 - ((1 + 3) * 2) | 1 |
| 5 | 9 1 3 2 + * - | 9 - (1 * (3 + 2)) | 4 |
Di seguito, riportiamo i primi risultati per alcune quaterne di numeri iniziali.
1) Con 1,1,1,1
Trova espressioni per tutti i numeri obiettivo da 0 a 10 e oltre.
Risultati trovati: ------------------ 0 = (1 + (1 - (1 + 1))) 1 = (1 + (1 - (1 * 1))) 2 = (1 + (1 + (1 - 1))) 3 = (1 + (1 + (1 * 1))) 4 = (1 + (1 + (1 + 1))) 5 = (1 / ((1 + 1) * .1)) 6 = (1 + (1 / (.1 + .1))) 7 = ((1 / .(1)) - (1 + 1)) 8 = (1 * ((1 / .(1)) - 1)) 9 = (11 - (1 + 1)) 10 = (1 * (11 - 1)) 11 = (1 + (11 - 1)) 12 = (1 + (1 * 11)) 13 = (1 + (1 + 11)) 14 = non possibile 15 = non possibile 16 = non possibile 17 = (((1 + 1) / .(1)) - 1) 18 = ((1 + 1) * (1 / .(1)))
2) Con 4, 4, 4, 4
Trova tutte le soluzioni da 1 a 20 e oltre.
il primo numero che non riesce
a risolvere è 23.
Risultati trovati: ------------------ In particolare: 10 = ((44 - 4) / 4)
3) Con 3, 3, 3, 3
Trova tutte le soluzioni da 1 a 20 e oltre.
Risultati trovati: ------------------ In particolare: 14 = (3 + (33 / 3)) 15 = (3 + (3 + (3 * 3)))
4) Con 0,1,9,9
Risultati trovati: ------------------ 0 = (0 + (1 - (9 / 9))) 1 = (0 + (1 + (9 - 9))) 2 = (0 + (1 + (9 / 9))) 3 = (0 + (1 + (.(9) + .(9)))) 4 = non possibile 5 = (10 / (.(9) + .(9))) 6 = non possibile 7 = ((0 - 1) + (9 - .(9))) 8 = (((0 * 9) - 1) + 9) 9 = ((0 * (1 + 9)) + 9) 10 = (0 + (19 - 9))
Per ora mi fermo qui e riporto di seguito in codici dei due programmi.
DECLARE EXTERNAL SUB VALUTA_RPN
OPTION ARITHMETIC RATIONAL
OPTION BASE 0
! =============================================================
! PROGRAMMA PRINCIPALE (VERSIONE 10/08/26)
! =============================================================
! Le quattro cifre iniziali
DIM CIFRE(4)
DATA 4,4,4,4
FOR I = 1 TO 4
READ CIFRE(I)
NEXT I
! Gli operatori binari ammessi
DIM OP$(4)
LET OP$(1) = "+"
LET OP$(2) = "-"
LET OP$(3) = "*"
LET OP$(4) = "/"
! Array per contenere la prima soluzione trovata
! per ciascun numero, da 0 a 1000
DIM SOLUZIONE$(1000)
PRINT "Ricerca in corso..."
! 1. Ciclo su tutte le permutazioni dei 4 operandi (4! = 24)
FOR I1 = 1 TO 4
FOR I2 = 1 TO 4
IF I2 <> I1 THEN
FOR I3 = 1 TO 4
IF I3 <> I1 AND I3 <> I2 THEN
FOR I4 = 1 TO 4
IF I4 <> I1 AND I4 <> I2 AND I4 <> I3 THEN
DIM A(4)
LET A(1) = CIFRE(I1)
LET A(2) = CIFRE(I2)
LET A(3) = CIFRE(I3)
LET A(4) = CIFRE(I4)
! 2. Ciclo su tutte le disposizioni con ripetizione di 3 operatori (4^3 = 64)
FOR O1 = 1 TO 4
FOR O2 = 1 TO 4
FOR O3 = 1 TO 4
DIM OP_SEL$(3)
LET OP_SEL$(1) = OP$(O1)
LET OP_SEL$(2) = OP$(O2)
LET OP_SEL$(3) = OP$(O3)
! 3. Test delle 5 strutture RPN valide
FOR TIPO = 1 TO 5
CALL VALUTA_RPN(a, op_sel$, tipo, soluzione$)
NEXT TIPO
NEXT O3
NEXT O2
NEXT O1
END IF
NEXT I4
END IF
NEXT I3
END IF
NEXT I2
NEXT I1
! 4. Stampa dei risultati per i primi numeri naturali trovati
PRINT
PRINT "RISULTATI TROVATI:"
PRINT "------------------"
FOR N = 0 TO 1000
IF SOLUZIONE$(N) <> "" THEN
PRINT STR$(N) & " = " & SOLUZIONE$(N)
END IF
NEXT N
!Fine del programma principale
END
! =============================================================
! SUBROUTINE PER LA VALUTAZIONE DELLA STRUTTURA RPN
! =============================================================
!a(): contiene la permutazione corrente dei 4 numeri dati.
!Passato per riferimento.
!----------------------------------
!op_sel$(): contiene la combinazione corrente dei 3 operatori (stringhe)
!scelti per il calcolo. Passato per riferimento.
!----------------------------------
!tipo: identifica quale delle 5 strutture RPN valide si deve elaborare (numero).
!Passato per valore.
!----------------------------------
!soluzione$(): lista (ARRAY) globale delle soluzioni (stringhe) trovate
!per ogni numero naturale raggiungibile. Passata per riferimento.
!----------------------------------
EXTERNAL SUB VALUTA_RPN(a(), op_sel$(), tipo, soluzione$())
! TOKENS, i 7 elementi individuali (4 numeri e 3 operatori)
!che compongono l'espressione RPN
DIM tokens$(7)
! Assegnazione dei TOKENS in base alla struttura RPN selezionata
SELECT CASE tipo
CASE 1
! Struttura 1: A1 op1 (A2 op2 (A3 op3 A4))
! RPN: A1 A2 A3 A4 op3 op2 op1
LET tokens$(1) = STR$(a(1))
LET tokens$(2) = STR$(a(2))
LET tokens$(3) = STR$(a(3))
LET tokens$(4) = STR$(a(4))
LET tokens$(5) = op_sel$(3)
LET tokens$(6) = op_sel$(2)
LET tokens$(7) = op_sel$(1)
CASE 2
! Struttura 2: (A1 op1 A2) op2 (A3 op3 A4)
! RPN: A1 A2 op1 A3 A4 op3 op2
LET tokens$(1) = STR$(a(1))
LET tokens$(2) = STR$(a(2))
LET tokens$(3) = op_sel$(1)
LET tokens$(4) = STR$(a(3))
LET tokens$(5) = STR$(a(4))
LET tokens$(6) = op_sel$(3)
LET tokens$(7) = op_sel$(2)
CASE 3
! Struttura 3: A1 op1 ((A2 op2 A3) op3 A4)
! RPN: A1 A2 A3 op2 A4 op3 op1
LET tokens$(1) = STR$(a(1))
LET tokens$(2) = STR$(a(2))
LET tokens$(3) = STR$(a(3))
LET tokens$(4) = op_sel$(2)
LET tokens$(5) = STR$(a(4))
LET tokens$(6) = op_sel$(3)
LET tokens$(7) = op_sel$(1)
CASE 4
! Struttura 4: ((A1 op1 A2) op2 A3) op3 A4
! RPN: A1 A2 op1 A3 op2 A4 op3
LET tokens$(1) = STR$(a(1))
LET tokens$(2) = STR$(a(2))
LET tokens$(3) = op_sel$(1)
LET tokens$(4) = STR$(a(3))
LET tokens$(5) = op_sel$(2)
LET tokens$(6) = STR$(a(4))
LET tokens$(7) = op_sel$(3)
CASE 5
! Struttura 5: (A1 op1 (A2 op2 A3)) op3 A4
! RPN: A1 A2 A3 op2 op1 A4 op3
LET tokens$(1) = STR$(a(1))
LET tokens$(2) = STR$(a(2))
LET tokens$(3) = STR$(a(3))
LET tokens$(4) = op_sel$(2)
LET tokens$(5) = op_sel$(1)
LET tokens$(6) = STR$(a(4))
LET tokens$(7) = op_sel$(3)
END SELECT
! Calcolo dello stack (pila) RPN
DIM stack(10)
DIM stack_txt$(10)
! Stack Pointer, indica l'elemento in cima alla pila
LET sp = 0
FOR i = 1 TO 7
LET t$ = tokens$(i)
IF t$ = "+" OR t$ = "-" OR t$ = "*" OR t$ = "/" THEN
! Errore di stack, meno di 2 operandi disponibili
IF sp < 2 THEN EXIT SUB
! LIFO: estraiamo prima B e poi A per ripristinare ordine corretto (A op B)
LET val_b = stack(sp)
LET txt_b$ = stack_txt$(sp)
LET sp = sp - 1
LET val_a = stack(sp)
LET txt_a$ = stack_txt$(sp)
! Calcolo perazione corrente tramite SELECT CASE
SELECT CASE t$
CASE "+"
LET res = val_a + val_b
CASE "-"
LET res = val_a - val_b
CASE "*"
LET res = val_a * val_b
CASE "/"
! Controllo divisione per zero non valida
IF val_b = 0 THEN EXIT SUB
LET res = val_a / val_b
END SELECT
! Salva il risultato numerico e la sotto-espressione formattata
! con parentesi
LET stack(sp) = res
LET stack_txt$(sp) = "(" & txt_a$ & " " & t$ & " " & txt_b$ & ")"
ELSE
! È un numero: lo spingiamo (PUSH) in cima allo stack
LET sp = sp + 1
LET stack(sp) = VAL(t$)
LET stack_txt$(sp) = t$
END IF
NEXT i
! Salvataggio del risultato finale
! Un solo elemento rimasto: espressione RPN valida
IF sp = 1 THEN
LET res_finale = stack(1)
! Filtra solo i numeri naturali (interi >= 0)
IF res_finale >= 0 AND res_finale = INT(res_finale) THEN
LET n = res_finale
IF n <= 1000 THEN
! Registra la soluzione solo se per quel valore N
!non ne è già stata trovata una
IF soluzione$(n) = "" THEN
LET soluzione$(n) = stack_txt$(1)
END IF
END IF
END IF
END IF
END SUB
! =============================================================
! PROGRAMMA PRINCIPALE (VERSIONE 10/08/26)
! =============================================================
DECLARE EXTERNAL SUB valuta_rpn
OPTION ARITHMETIC RATIONAL
OPTION BASE 0
! Dichiarazione degli array
DIM cifre(4)
DIM op$(5)
DIM soluzione$(1000)
DIM a(4)
DIM a_txt$(4)
DIM a_orig(4)
DIM op_sel$(3)
! Inizializzazione cifre iniziali
DATA 2,2,2,2
FOR i = 1 TO 4
READ cifre(i)
NEXT i
! Gli operatori binari ammessi (inclusa la concatenazione "&")
LET op$(1) = "+"
LET op$(2) = "-"
LET op$(3) = "*"
LET op$(4) = "/"
LET op$(5) = "&"
! =============================================================
! FASE 1: Ricerca SENZA operatori unari D(n) e R(n)
! =============================================================
PRINT "Fase 1: Ricerca con sole operazioni base e concatenazione..."
FOR i1 = 1 TO 4
FOR i2 = 1 TO 4
IF i2 <> i1 THEN
FOR i3 = 1 TO 4
IF i3 <> i1 AND i3 <> i2 THEN
FOR i4 = 1 TO 4
IF i4 <> i1 AND i4 <> i2 AND i4 <> i3 THEN
! Configurazione operandi (cifre pure)
LET a(1) = cifre(i1)
LET a_txt$(1) = STR$(cifre(i1))
LET a_orig(1) = 1
LET a(2) = cifre(i2)
LET a_txt$(2) = STR$(cifre(i2))
LET a_orig(2) = 1
LET a(3) = cifre(i3)
LET a_txt$(3) = STR$(cifre(i3))
LET a_orig(3) = 1
LET a(4) = cifre(i4)
LET a_txt$(4) = STR$(cifre(i4))
LET a_orig(4) = 1
! Ciclo sugli operatori binari
FOR o1 = 1 TO 5
FOR o2 = 1 TO 5
FOR o3 = 1 TO 5
LET op_sel$(1) = op$(o1)
LET op_sel$(2) = op$(o2)
LET op_sel$(3) = op$(o3)
! Test delle 5 strutture RPN
FOR tipo = 1 TO 5
CALL valuta_rpn(a, a_txt$, a_orig, op_sel$, tipo, soluzione$)
NEXT tipo
NEXT o3
NEXT o2
NEXT o1
END IF
NEXT i4
END IF
NEXT i3
END IF
NEXT i2
NEXT i1
! =============================================================
! FASE 2: Ricerca CON operatori unari per i numeri non ancora trovati
! =============================================================
PRINT "Fase 2: Applicazione di Decimale D(n) e Periodico R(n)..."
FOR i1 = 1 TO 4
FOR i2 = 1 TO 4
IF i2 <> i1 THEN
FOR i3 = 1 TO 4
IF i3 <> i1 AND i3 <> i2 THEN
FOR i4 = 1 TO 4
IF i4 <> i1 AND i4 <> i2 AND i4 <> i3 THEN
! Ciclo sulle trasformazioni unarie
FOR m1 = 0 TO 2
FOR m2 = 0 TO 2
FOR m3 = 0 TO 2
FOR m4 = 0 TO 2
! Salta la combinazione 0,0,0,0 perché già elaborata nella Fase 1
IF m1 + m2 + m3 + m4 > 0 THEN
! Configurazione operando 1
IF m1 = 0 THEN
LET a(1) = cifre(i1)
LET a_txt$(1) = STR$(cifre(i1))
LET a_orig(1) = 1
ELSEIF m1 = 1 THEN
LET a(1) = cifre(i1) / 10
LET a_txt$(1) = "." & STR$(cifre(i1))
LET a_orig(1) = 0
ELSE
LET a(1) = cifre(i1) / 9
LET a_txt$(1) = ".(" & STR$(cifre(i1)) & ")"
LET a_orig(1) = 0
END IF
! Configurazione operando 2
IF m2 = 0 THEN
LET a(2) = cifre(i2)
LET a_txt$(2) = STR$(cifre(i2))
LET a_orig(2) = 1
ELSEIF m2 = 1 THEN
LET a(2) = cifre(i2) / 10
LET a_txt$(2) = "." & STR$(cifre(i2))
LET a_orig(2) = 0
ELSE
LET a(2) = cifre(i2) / 9
LET a_txt$(2) = ".(" & STR$(cifre(i2)) & ")"
LET a_orig(2) = 0
END IF
! Configurazione operando 3
IF m3 = 0 THEN
LET a(3) = cifre(i3)
LET a_txt$(3) = STR$(cifre(i3))
LET a_orig(3) = 1
ELSEIF m3 = 1 THEN
LET a(3) = cifre(i3) / 10
LET a_txt$(3) = "." & STR$(cifre(i3))
LET a_orig(3) = 0
ELSE
LET a(3) = cifre(i3) / 9
LET a_txt$(3) = ".(" & STR$(cifre(i3)) & ")"
LET a_orig(3) = 0
END IF
! Configurazione operando 4
IF m4 = 0 THEN
LET a(4) = cifre(i4)
LET a_txt$(4) = STR$(cifre(i4))
LET a_orig(4) = 1
ELSEIF m4 = 1 THEN
LET a(4) = cifre(i4) / 10
LET a_txt$(4) = "." & STR$(cifre(i4))
LET a_orig(4) = 0
ELSE
LET a(4) = cifre(i4) / 9
LET a_txt$(4) = ".(" & STR$(cifre(i4)) & ")"
LET a_orig(4) = 0
END IF
! Ciclo su tutte le combinazioni di 3 operatori binari
FOR o1 = 1 TO 5
FOR o2 = 1 TO 5
FOR o3 = 1 TO 5
LET op_sel$(1) = op$(o1)
LET op_sel$(2) = op$(o2)
LET op_sel$(3) = op$(o3)
! Test delle 5 strutture RPN
FOR tipo = 1 TO 5
CALL valuta_rpn(a, a_txt$, a_orig, op_sel$, tipo, soluzione$)
NEXT tipo
NEXT o3
NEXT o2
NEXT o1
END IF
NEXT m4
NEXT m3
NEXT m2
NEXT m1
END IF
NEXT i4
END IF
NEXT i3
END IF
NEXT i2
NEXT i1
! =============================================================
! STAMPA RISULTATI
! =============================================================
PRINT
PRINT "RISULTATI TROVATI:"
PRINT "------------------"
FOR n = 0 TO 1000
IF soluzione$(n) <> "" THEN
PRINT STR$(n) & " = " & soluzione$(n)
END IF
NEXT n
END
! =============================================================
! SUBROUTINE PER LA VALUTAZIONE DELLA STRUTTURA RPN
! =============================================================
EXTERNAL SUB valuta_rpn(a(), a_txt$(), a_orig(), op_sel$(), tipo, soluzione$())
! Dichiarazioni degli array all'inizio della SUB
DIM tokens_val(7)
DIM tokens_txt$(7)
DIM tokens_orig(7)
DIM stack(10)
DIM stack_txt$(10)
DIM stack_orig(10)
! Assegnazione dei TOKENS in base alla struttura RPN selezionata
SELECT CASE tipo
CASE 1
! Struttura 1: A1 op1 (A2 op2 (A3 op3 A4))
LET tokens_val(1) = a(1)
LET tokens_txt$(1) = a_txt$(1)
LET tokens_orig(1) = a_orig(1)
LET tokens_val(2) = a(2)
LET tokens_txt$(2) = a_txt$(2)
LET tokens_orig(2) = a_orig(2)
LET tokens_val(3) = a(3)
LET tokens_txt$(3) = a_txt$(3)
LET tokens_orig(3) = a_orig(3)
LET tokens_val(4) = a(4)
LET tokens_txt$(4) = a_txt$(4)
LET tokens_orig(4) = a_orig(4)
LET tokens_txt$(5) = op_sel$(3)
LET tokens_txt$(6) = op_sel$(2)
LET tokens_txt$(7) = op_sel$(1)
CASE 2
! Struttura 2: (A1 op1 A2) op2 (A3 op3 A4)
LET tokens_val(1) = a(1)
LET tokens_txt$(1) = a_txt$(1)
LET tokens_orig(1) = a_orig(1)
LET tokens_val(2) = a(2)
LET tokens_txt$(2) = a_txt$(2)
LET tokens_orig(2) = a_orig(2)
LET tokens_txt$(3) = op_sel$(1)
LET tokens_val(4) = a(3)
LET tokens_txt$(4) = a_txt$(3)
LET tokens_orig(4) = a_orig(3)
LET tokens_val(5) = a(4)
LET tokens_txt$(5) = a_txt$(4)
LET tokens_orig(5) = a_orig(4)
LET tokens_txt$(6) = op_sel$(3)
LET tokens_txt$(7) = op_sel$(2)
CASE 3
! Struttura 3: A1 op1 ((A2 op2 A3) op3 A4)
LET tokens_val(1) = a(1)
LET tokens_txt$(1) = a_txt$(1)
LET tokens_orig(1) = a_orig(1)
LET tokens_val(2) = a(2)
LET tokens_txt$(2) = a_txt$(2)
LET tokens_orig(2) = a_orig(2)
LET tokens_val(3) = a(3)
LET tokens_txt$(3) = a_txt$(3)
LET tokens_orig(3) = a_orig(3)
LET tokens_txt$(4) = op_sel$(2)
LET tokens_val(5) = a(4)
LET tokens_txt$(5) = a_txt$(4)
LET tokens_orig(5) = a_orig(4)
LET tokens_txt$(6) = op_sel$(3)
LET tokens_txt$(7) = op_sel$(1)
CASE 4
! Struttura 4: ((A1 op1 A2) op2 A3) op3 A4
LET tokens_val(1) = a(1)
LET tokens_txt$(1) = a_txt$(1)
LET tokens_orig(1) = a_orig(1)
LET tokens_val(2) = a(2)
LET tokens_txt$(2) = a_txt$(2)
LET tokens_orig(2) = a_orig(2)
LET tokens_txt$(3) = op_sel$(1)
LET tokens_val(4) = a(3)
LET tokens_txt$(4) = a_txt$(3)
LET tokens_orig(4) = a_orig(3)
LET tokens_txt$(5) = op_sel$(2)
LET tokens_val(6) = a(4)
LET tokens_txt$(6) = a_txt$(4)
LET tokens_orig(6) = a_orig(4)
LET tokens_txt$(7) = op_sel$(3)
CASE 5
! Struttura 5: (A1 op1 (A2 op2 A3)) op3 A4
LET tokens_val(1) = a(1)
LET tokens_txt$(1) = a_txt$(1)
LET tokens_orig(1) = a_orig(1)
LET tokens_val(2) = a(2)
LET tokens_txt$(2) = a_txt$(2)
LET tokens_orig(2) = a_orig(2)
LET tokens_val(3) = a(3)
LET tokens_txt$(3) = a_txt$(3)
LET tokens_orig(3) = a_orig(3)
LET tokens_txt$(4) = op_sel$(2)
LET tokens_txt$(5) = op_sel$(1)
LET tokens_val(6) = a(4)
LET tokens_txt$(6) = a_txt$(4)
LET tokens_orig(6) = a_orig(4)
LET tokens_txt$(7) = op_sel$(3)
END SELECT
! Esecuzione dello Stack RPN
LET sp = 0
FOR i = 1 TO 7
LET t$ = tokens_txt$(i)
IF t$ = "+" OR t$ = "-" OR t$ = "*" OR t$ = "/" OR t$ = "&" THEN
! Errore di stack
IF sp < 2 THEN EXIT SUB
LET val_b = stack(sp)
LET txt_b$ = stack_txt$(sp)
LET orig_b = stack_orig(sp)
LET sp = sp - 1
LET val_a = stack(sp)
LET txt_a$ = stack_txt$(sp)
LET orig_a = stack_orig(sp)
IF t$ = "&" THEN
! Concatenazione valida SOLO se entrambi sono cifre iniziali singole non trasformate
IF orig_a <> 1 OR orig_b <> 1 THEN EXIT SUB
! Unione algebrica delle due cifre: A * 10 + B
LET res = val_a * 10 + val_b
LET stack_txt$(sp) = STR$(res)
! Il numero a 2 cifre non è più concatenabile
LET stack_orig(sp) = 0
ELSE
SELECT CASE t$
CASE "+"
LET res = val_a + val_b
CASE "-"
LET res = val_a - val_b
CASE "*"
LET res = val_a * val_b
CASE "/"
! Divisione per zero non valida
IF val_b = 0 THEN EXIT SUB
LET res = val_a / val_b
END SELECT
LET stack_txt$(sp) = "(" & txt_a$ & " " & t$ & " " & txt_b$ & ")"
! Risultato calcolato: non più concatenabile
LET stack_orig(sp) = 0
END IF
LET stack(sp) = res
ELSE
! È un operando (numero normale, decimale o periodico)
LET sp = sp + 1
LET stack(sp) = tokens_val(i)
LET stack_txt$(sp) = tokens_txt$(i)
LET stack_orig(sp) = tokens_orig(i)
END IF
NEXT i
! Salvataggio del risultato finale
IF sp = 1 THEN
LET res_finale = stack(1)
! Verifica che res_finale sia un numero naturale (intero >= 0)
IF res_finale >= 0 AND res_finale = INT(res_finale) THEN
LET n = res_finale
IF n <= 1000 THEN
! Salva solo la prima soluzione trovata (dando precedenza alle soluzioni di Fase 1)
IF soluzione$(n) = "" THEN
LET soluzione$(n) = stack_txt$(1)
END IF
END IF
END IF
END IF
END SUB
...
Salvo errori & omissioni.
...
Pace e bene a tutti.
GfBo
Data creazione: Luglio 2026
Ultimo aggiornamento: Agosto 2026
Sito Web realizzato da Gianfranco Bo