domenica 12 febbraio 2017

La Susi 939

A Susi vengono mostrate due fotografie con cinque ragazzetti in crescita differenziata nel tempo tra le due foto, e il solito Gianni gli sussurra dolci parole come:

Carlo era più alto di Berto, ma non di Enzo.

Oppure:

Aldo era più basso sia di Carlo che di Berto.

E infine fa disporre i ragazzi (che despota!) nello stesso ordine in cui compaiono nelle foto e aggiunge:

Dario è più baso di Carlo, e Aldo è più alto di suo cugino.

E la prima domanda che mi faccio è: ma chi diavoletto è il cugino di Aldo?

Ma non è la domanda che pone il quesito, che invece è questa: come si chiama il bambino che ora è il più alto di tutti?

Questo è un lavoro per linguaggi come il Prolog, che ho già usato con il 921° quesito. Continuo ad aspettare di avere tempo e voglia di studiacchiare l'Oz e che Mozart2 implementi il supporto per la programmazione a vincoli, che è quello che ci serve per problemi come questo.

In questa tardiva puntata voglio usare GNU Smalltalk, che come Smalltalk è un po' sui generis dal momento che potete scrivere il codice in un file ed eseguirlo proprio come fareste se fosse scritto in Perl, Python e altri. Ma questi son dettagli.

Per la codifica della soluzione mi sono orientato come segue.

L'altezza di ogni ragazzo nei tre “momenti” diventa un numero:

2 1 4 3 5
3 4 5 1 2
1 5 3 2 4

I numeri non sono importanti, conta solo se sono minori o maggiori di altri della stessa riga. Tuttavia, pensandoli come altezze assolute, non ci piace vedere che un ragazzo decresce invece di crescere o almeno rimanere uguale. Le “altezze” usate per la grafica sono state:

2  1  4 3  5
7  8  9 5  6
8 12 10 9 11

Dopodiché si procede nel solito modo: si prova ad assegnare a ciascun ragazzo un nome e si verifica se tutte le affermazioni per le varie foto sono vere.

  • Prima foto
    • Carlo > Berto
    • Carlo < Enzo
  • Seconda foto
    • Aldo < Carlo
    • Aldo < Berto
  • Situazione attuale
    • Dario < Carlo
    • esiste X diverso da Aldo tale che Aldo > X

Un'implementazione possibile, sperabilmente corretta, è riportata di seguito1:

Eseguendola otterrete:

OrderedCollection ('Dario' 'Berto' 'Carlo' 'Aldo' 'Enzo' )

Cioè una OrderedCollection che ci dice che il secondo ragazzetto è Berto. Per avere un output più simpatico potete cambiare una riga (non vi dico quale: scopritelo da voi…!) così:

    (assignedNames join: ', ') displayNl.

Ma è solo estetica.

Più interessante è togliere il secondo vincolo della situazione attuale, cioè che Aldo non debba essere il più basso. Nel codice significa manipolare bl3 e farla diventare:

    bl3 := [ :a|
             (a at: 4) < (a at: 3) ].

In questo modo otteniamo due soluzioni:

Aldo, Berto, Carlo, Dario, Enzo
Dario, Berto, Carlo, Aldo, Enzo

(Sì, ho apportato in locale la modifica per l'output esteticamente gradevole, ma non ho cambiato il gist…)

Poiché in tutte e due i casi il bambino più alto di tutti, che è il secondo, si chiama Berto, possiamo dire che per rispondere alla domanda posta quel vincolo non è necessario.

Oppure che ho sbagliato qualcosa. A voi scoprirlo.

Soluzione manuale informale

Guardiamo la prima foto.

La frase «Carlo era più alto di Berto, ma non di Enzo» esclude che Carlo possa essere il più basso, quindi Carlo non è ②, cioè il bambino di cui il problema ci chiede il nome visto che poi diventerà il più alto. Nello stesso tempo Carlo non può essere nemmeno il più alto di questa prima foto, cioè il ⑤; e il più basso (il ②) non può essere Enzo.

Se Carlo fosse ①, Berto non potrebbe che essere ②, e Enzo uno qualunque dei rimanenti tre ragazzi.

Se Carlo fosse il ③, Berto potrebbe essere ①, ② o ④, ed Enzo sarebbe sicuramente ⑤.

Se Carlo fosse il ④, Berto potrebbe essere ① o ②, ed Enzo il ③ o il ⑤.

Osservate dove compare il ②, il bambino che poi sarà il ragazzetto più alto, e quale nome ipotetico gli stiamo assegnando: Berto. Non può essere né Carlo, né Enzo. Ma potrebbe essere anche Aldo o Dario. Quindi per il ② abbiamo questi nomi papabili: Aldo, Berto e Dario.

Ora guardiamo la seconda foto.

«Aldo era più basso sia di Carlo che di Berto». Aldo potrebbe essere il più basso in assoluto, ma non il più alto, né il secondo più alto, perché altrimenti sarebbe più basso solo di uno tra Carlo e Berto.

Poiché il ② ora è il secondo più alto, risultando più basso solo del ③, ne deduciamo che il ② non può essere Aldo. Quindi non ci restano che Berto e Dario.

Veniamo ad oggi.

«Dario è più basso di Carlo, e Aldo è più alto di suo cugino». Visto che non sappiamo chi è il cugino di Aldo, la frase «Aldo è più alto di suo cugino» ci sta solo dicendo che Aldo non è il più basso… Supponiamo che il ② sia Dario… Contraddizione, perché ora il ② è il più alto e quindi non può essere «più basso di» chicchessia.

Quindi non ci resta che una possibilità: ② è Berto.


  1. Se, come me, avete uno GNU Smalltalk che non implementa permutationsDo:, e volete provare ad eseguire veramente il codice, vi tocca fare uno snapshot con un'implementazione di permutationsDo. Oppure usare un'altra implementazione di Smalltalk come Pharo. In tal caso forse avrete permutationsDo:, ma forse vi toccherà pure fare qualche ritocchino al codice. Una volta che avete lo snapshot, potete eseguire il codice così: gst -I snapshot.im susi939.st.

Nessun commento:

Posta un commento

Sii educato, costruisci con cura le frasi, rifletti prima di pubblicare, evita parolacce e offese dirette, non uscire dal tema, cerca di non omettere la punteggiatura, evita errori ortografici, rileggi quel che hai scritto.