Perl: 8 ou 10 caracteres distintos
s/// solução: 10 distintas, 13 totais
A técnica (suposta; veja abaixo) sed sempre funciona em perl também e produz o número do nome de caracteres distintos (10):
s/[aeiou]//gi
Por exemplo:
$ 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.
São 10 caracteres distintos, pois isso prova:
$ echo 's/[aeiou]//gi' | perl -nle '@s{split//}=(); print scalar keys %s'
10
O problema com a solução sed é que a sua /ié não parte de POSIX sed, e, portanto, não é portátil:
$ 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'
Isso está sendo executado em um sistema OpenBSD. Por outro lado, como /isempre faz parte do perl padrão, é possível contar com ele sempre lá. Ao contrário do sed.
Se você deseja incluir "y" na lista de vogais, é claro que será uma maior se você usar a mesma técnica:
$ 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 agora são 14 caracteres no total.
tr[][] solução: 8 distintas 10 no total
Você também pode usar tr///para remover qualquer coisa que corresponda. O Perl pode até usar o y///alias do sed para tr:
y/aeiou//d
agora com 8 caracteres distintos, mas não funciona em maiúsculas. Você acaba tendo que adicionar mais 5 caracteres para lidar com os mapas de caso:
$ echo 'y/aeiouAEIOU//d' | perl -nle '@s{split//}=(); print scalar keys %s'
13
e é claro que agora são 15 no total.
No entanto, adicionar "y" à mistura como vogal não aumenta o número de caracteres distintos, como ocorreu com a s///versão:
$ 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.
Portanto, ainda são apenas os 8 originais distintos do total de 11:
$ echo 'y/aeiouy//d' | perl -nle '@s{split//}=(); print scalar keys %s'
8
EDIT : Contabilidade para diacríticos
E quanto a entradas como Renée’s naïveté? A saída correta, obviamente, deve ser Rn’s nvt. Veja como fazer isso, usando o /rsinalizador da v5.14 para s///:
$ echo 'Renée’s naïveté' |
perl5.14.0 -CS -MUnicode::Normalize -nle 'print NFD($_)=~s/[aeiou]\pM*//rgi'
Rn’s nvt
São 27 caracteres distintos:
$ echo 'print NFD($_) =~ s/[aeiou]\pM*//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
27
Você pode apará-lo para 26 se puder garantir que está executando pelo menos a v5.10 trocando o printpor um 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 você pode reduzi-lo para 22 se não se importar de mover os diacríticos em vez de removê-los:
$ echo 'Renée’s naïveté' |
perl -Mv5.14 -CS -MUnicode::Normalize -nlE 'say NFD($_) =~ s/[aeiou]//rgi'
Rń’s n̈vt́
O que é ... interessante de se ver, para dizer o mínimo. :) Aqui está sua contagem distinta:
$ echo 'say NFD($_) =~ s/[aeiou]//rgi' |
perl -nle '@s{split//}=(); print scalar keys %s'
22
Boa sorte em conseguir que qualquer outro idioma lide corretamente com diacríticos usando menos caracteres do que isso!