Il conto torna

Alla TV francese danno un programma TV che si intitola Des chiffres et des lettres in cui i concorrenti si sfidano a risolvere sia giochi di parole che di aritmetica. Uno dei giochini si intitola Le compte est bon: vengono dati alcuni numeri, e un numero obiettivo, e lo scopo è di ottenere l’obiettivo (o avvicinarcisi il più possibile) applicando le quattro operazioni aritmetiche alla serie di iniziale numeri.

Per capire di cosa si tratta, facciamo subito un piccolo esempio: dati i numeri 5, 100, 6, 3, 10 e 1, bisogna cercare di ottenere il numero 635 utilizzando soltanto le quattro operazioni +, -, * e /.

Una possibile sequenza che porta alla soluzione è:

5+100 = 105; 6*105 = 630; 3-1 = 2; 10/2 = 5; 630+5 = 635;

Come vedete, non è poi molto difficile, ma bisogna perderci un attimo di tempo a provare un po’ di combinazioni.

Viene fuori che la maestra di mio figlio, che frequenta la CM2 (quinta elementare) qui in Francia, propone questo tipo di esercizi per allenare i ragazzini a fare i conti. Divertente, no? Non l’avevo mai visto fare in Italia, ma può darsi che mi sbagli, se seguite questo blog e ne sapete di più sugli esercizi che vengono dati in quinta elementare in Italia, scrivetelo nei commenti! A questo sito trovare parecchi esercizi simili per tutte le classi delle elementari.

Fatto sta che qualche giorno fa, mio figlio si presenta con questa sequenza: 1, 2, 5, 10, 25, 50, e il numero da ottenere era 668. Non riusciva a trovare la soluzione, e voleva sapere se potevo trovarla io.

Dopo averci pensato qualche secondo, gli ho detto che secondo me non c’era soluzione. “Forse ho sbagliato a copiare qualche numero”, mi risponde lui, “ma mi sembrava di aver ricopiato attentamente dalla lavagna”.

Come sapere se c’è o no soluzione al problema? Beh, da buon ingegnere, ho pensato che il modo migliore era di scrivere un programmino che provasse tutte le combinazioni. Con 5 numeri non dovrebbero essere tantissime. Ovviamente, essendo un problema semplice, il modo veloce di risolverlo era usare il Python, il mio lignuaggio di fast-prototyping preferito ormai.

Volete provarci da soli? Allora non guardate il programma seguente.

import copy
import argparse

numeri = [5, 100, 6, 3, 10, 1]
soluzione = 635

def elimina(i, lista):
    l = []
    l = copy.copy(lista[:i])
    l = l + copy.copy(lista[(i+1):])
    return l


def operazione(lista, sol, ops, ris, operazione, a, b):
    l3 = copy.copy(lista)
    l3.append(ris)
    op = ops + str(a) + operazione + str(b) + ' = ' + str(ris) + '; '
    calcola(l3, sol, op)


def calcola(lista, sol, ops):
    if len(lista) == 1:
        if lista[0] == sol:
            print "TROVATO! ", ops
    else:
        n = lista[0]
        l = elimina(0, lista)
        for i, x in enumerate(l):
            l2 = elimina(i, l)

            n1 = n + x
            operazione(l2, sol, ops, n1, '+', n, x)

            n1 = n - x
            operazione(l2, sol, ops, n1, '-', n, x)

            n1 = x - n
            operazione(l2, sol, ops, n1, '-', x, n)

            n1 = n * x
            operazione(l2, sol, ops, n1, '*', n, x)

            if x != 0 and n % x == 0:
                n1 = n / x
                operazione(l2, sol, ops, n1, '/', n, x)

            if n != 0 and x % n == 0:
                n1 = x / n
                operazione(l2, sol, ops, n1, '/', x, n)


def main():
    parser = argparse.ArgumentParser(description='Inserisci i numeri')
    parser.add_argument('nums', nargs='+', default=numeri)
    parser.add_argument('--s', default=soluzione)

    args = parser.parse_args()
    num = [int(x) for x in args.nums]
    sol = int(args.s)

    print num, ' ??? ', sol
    calcola(num, sol, "")


if __name__ == "__main__":
    main()

E lanciando il programma si ottengono… ben 2 risultati!

[1, 2, 5, 10, 25, 50]  ???  668
TROVATO!  10-1 = 9; 2+5 = 7; 25+50 = 75; 9*75 = 675; 675-7 = 668; 
TROVATO!  1-25 = -24; 2+5 = 7; 10*50 = 500; -24*7 = -168; 500--168 = 668; 
TROVATO!  25-1 = 24; 2+5 = 7; 10*50 = 500; 24*7 = 168; 500+168 = 668; 

La seconda in realtà coinvolge dei numeri negativi, quindi andrebbe eliminata. E quindi aveva ragione mio figlio e torto io. Mai contare troppo sulle proprie doti matematiche!

Il programma l’ho scritto un po’ di fretta e non è il massimo dello stile, e non sono neanche completamente sicuro che sia corretto. E quindi, per chi volesse esercitarsi, ho tre domande a diverso grado di difficoltà:

  • Sapete modificare il programma per evitare che stampi soluzioni negative?
  • E se voleste memorizzarle tutte le soluzioni in un vettore per riutilizzarle dopo?
  • Infine, sapete dimostrarne la correttezza?

Dimenticavo: ovviamente, un programma analogo è disponibile in linea qui.

Ah, questi francesi!

Posta un commento o usa questo indirizzo per il trackback.

Lascia un commento

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.