Perl: 8 o 10 personaggi distinti
s/// soluzione: 10 distinti, 13 in totale
La tecnica (presunta; vedi sotto) sed funziona sempre anche in perl e produce il numero di nomi di caratteri distinti (10):
s/[aeiou]//gi
Per esempio:
$ echo 'This program will remove VOWELS. So we can speak without them.' |
perl -ple 's/[aeiou]//gi'
Ths prgrm wll rmv VWLS. S w cn spk wtht thm.
Sono 10 personaggi distinti, come dimostra:
$ echo 's/[aeiou]//gi' | perl -nle '@s{split//}=(); print scalar keys %s'
10
Il problema con la soluzione sed è che la sua /iè non parte POSIX sed, e quindi non è portatile:
$ echo 'This program will remove VOWELS. So we can speak without them.' |
sed -e 's/[aeiou]//gi'
sed: 1: "s/[aeiou]//gi": bad flag in substitute command: 'i'
È in esecuzione su un sistema OpenBSD. Al contrario, poiché /ifa davvero sempre parte del perl standard, puoi contare sul fatto che è sempre lì. A differenza di sed.
Se vuoi includere "y" nell'elenco delle vocali, è ovviamente uno maggiore se usi la stessa tecnica:
$ echo 'This nifty program remove any VOWELS. So we easily can speak without them.' |
perl -ple 's/[aeiouy]//gi'
Ths nft prgrm rmv n VWLS. S w sl cn spk wtht thm.
$ echo 's/[aeiouy]//gi' | perl -nle '@s{split//}=(); print scalar keys %s'
11
E ora sono 14 personaggi in totale.
tr[][] soluzione: 8 distinti 10 in totale
Puoi anche usare tr///per rimuovere tutto ciò che corrisponde. Perl può persino usare l' y///alias di sed per tr:
y/aeiou//d
che ora è composto da 8 caratteri distinti, ma non funziona in maiuscolo. Alla fine devi aggiungere altri 5 personaggi per far fronte alle casemap:
$ echo 'y/aeiouAEIOU//d' | perl -nle '@s{split//}=(); print scalar keys %s'
13
e ovviamente questo è ora 15 in totale.
Tuttavia, l'aggiunta di "y" al mix come vocale non aumenta il numero di caratteri distinti come nella s///versione:
$ echo 'This nifty program remove any VOWELS. So we easily can speak without them.' |
perl -ple 'y/aeiouy//d'
Ths nft prgrm rmv n VOWELS. S w sl cn spk wtht thm.
Quindi questo è ancora solo l'8 originale distinto su 11 totale:
$ echo 'y/aeiouy//d' | perl -nle '@s{split//}=(); print scalar keys %s'
8
EDIT : contabilità per i segni diacritici
E gli input come Renée’s naïveté? L'output corretto dovrebbe ovviamente essere Rn’s nvt. Ecco come farlo, usando il /rflag v5.14 per s///:
$ echo 'Renée’s naïveté' |
perl5.14.0 -CS -MUnicode::Normalize -nle 'print NFD($_)=~s/[aeiou]\pM*//rgi'
Rn’s nvt
Sono 27 personaggi distinti:
$ echo 'print NFD($_) =~ s/[aeiou]\pM*//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
27
Puoi tagliarlo a 26 se puoi garantire che stai eseguendo almeno la v5.10 sostituendo printa say:
$ echo 'Renée’s naïveté' |
perl -Mv5.14 -CS -MUnicode::Normalize -nlE 'say NFD($_) =~ s/[aeiou]\pM*//rgi'
Rn’s nvt
$ echo 'say NFD($_) =~ s/[aeiou]\pM*//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
26
E puoi farlo scendere a 22 se non ti dispiace spostare i segni diacritici invece di rimuoverli:
$ echo 'Renée’s naïveté' |
perl -Mv5.14 -CS -MUnicode::Normalize -nlE 'say NFD($_) =~ s/[aeiou]//rgi'
Rń’s n̈vt́
Il che è ... interessante da guardare, per non dire altro. :) Ecco il suo conteggio distinto:
$ echo 'say NFD($_) =~ s/[aeiou]//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
22
Buona fortuna a far sì che qualsiasi altra lingua affronti correttamente i segni diacritici usando meno personaggi di così!