[ index | links | mail ]

TPR03/1 - Cantor

Ovvero: Di come valga piu' la pratica della grammatica

Mettiamola cosi': se non altro posso essere soddisfatto perche' la soluzione che avevo "pensato" sfrutta lo stesso approccio del vincitore (che e' lo stesso per la maggior parte delle soluzioni). Magra consolazione, in effetti, visto che per l'approccio in questione mi ero ispirato a ("l'avevo scopiazzato da") Mathworld... Come mi aspetto abbiano fatto anche gli altri.

Quindi la reazione, guardando le soluzioni, non e' stata un "Questa e' magia nera!", come di solito mi accade, ma un per certi versi piu' amaro "Toh! Bastava pensarci!". Riporto la mia soluzione, per far vedere come, dopo sapiente maquillage, essa possa diventare qualcosa di dignitoso, addirittura competitivo.

#        1         2         3         4         5         6         7
#2345678901234567890123456789012345678901234567890123456789012345678901234
%r=('-','- -',$",$"x3);$_="-$/";$n=shift;while($n--){s/(.)/$r{$1}/eg}print

Magari la riscrivo in forma meno stringata:

%r = (
	'-' => '- -',
	$" => $"x3
);
$_="-$/";
$n=shift;
while( $n-- ) {
	s/(.)/$r{$1}/eg
}
print

Chiaro, no? Viene applicata $n volte, attraverso l'espressione regolare, la regola di riscrittura definita nella hash %r. Di trucchi in pratica non ce ne sono, a parte l'uso di variabili predefinite al posto di spazi e newline. In effetti si potrebbero mangiar via un altro paio di caratteri, considerando che l'input e' garantito essere costituito da un solo parametro e che quindi uno shift vale quanto un pop. Diciamo quindi che scendiamo da 74 a 72 caratteri.

Ma l'idea che permette di ridurre drasticamente il numero di caratteri e' un'altra. Attenzione alla regola di riscrittura (che riporto scritta "in chiaro"):

%r = (
	'-' => '- -',
	' ' => '   '
);

Devo ammettere che ho passato diversi minuti fissando questa hash, cercando metodi per riscriverla in maniera piu' stringata. Pero', nada. Qui si vede la prima zampata dei primi classificati.

La buona idea a proposito di questa hash e' che... non c'e per niente bisogno di una hash.

Un trattino va riscritto come due trattini con uno spazio in mezzo.
Uno spazio va riscritto come due spazio con uno spazio in mezzo.
Un * va riscritto come due * con uno spazio in mezzo.

Ma questa e' un'istruzione s/// scritta in italiano: in Perl si dice s/./$& $&/ Senza nessun bisogno di tabelle di riscrittura. Non vale dire che lo avevate notato subito; se non altro, e' indelicato nei miei confronti. Riscrivo ancora la soluzione:

#        1         2         3         4 
#23456789012345678901234567890123456789012345
$_="-$/";$n=pop;while($n--){s/./$& $&/g}print

Da 72 a 45 caratteri. -27, direi che non c'e' male.

Magia nera

"Un colpo di genio, J.F, o una cattiva digestione?"
-- da Blade Runner

Da qui alla soluzione del vincitore, pero', ce ne corre. Ecco il programma di Rick Klement, Mtv Europe, Marko Nippula, Eirik Ben Hanssen e MeowChow (che condividono a parimerito la prima posizione in classifica):

s/./$& $&/gfor($\="-
")x pop;print
E qui c'e' proprio della magia nera, non c'e' niente da fare. Credo che si capisca tutto a parte lo strano costrutto
for( $\ = "-\n" ) x pop

Partiamo dall'operatore x: in un contesto di lista, se l'operando di sinistra e' una lista allora restituisce la lista ripetuta tante volte quante sono indicate dall'operando di destra. Per chiarezza, riscrivo il costrutto esplicitando le parentesi:

for(( $\ = "-\n" ) x pop)

Ma cosa e' l'operando di sinistra? E' $\ dopo che l'assegnazione e' avvenuta. Se ad esempio il parametro passato fosse 3, il codice eseguito sarebbe equivalente a questo:

$\ = "-\n";
for( $\, $\, $\ ) {
	s/./$& $&/g;
}
print

Il resto e' chiaro. Ad ogni iterazione (tante quante gli elementi della lista) $_ diventa un alias di $\, e l'espressione regolare fa il resto, come ho spiegato sopra.

Riferimenti

Perl Golf
"The root of all evil"
Cantor Dust -- Mathworld
La pagina di Mathworld (un sito bellissimo), dove tra le altre cose viene descritta la tecnica di riscrittura usata nella maggior parte delle soluzioni al problema.
golf@perl.org archive
L'archivio della mailing-list dedicata a TPR e al PerlGolf in generale.

Last modified: 09:05:37 09-May-2002 / Maintained by larsen