Uma questão que supostamente aparece em entrevistas para cargos de programação é o FizzBuzz. O enunciado é simples: imprima todos os números de 1 a n, mas imprima fizz para os múltiplos de 3, buzz para os múltiplos de 5, e fizzbuzz para os múltiplos de 3 e 5.
Sabemos que 3 e 5 são relativamente primos, então eles só vão juntos dividir n a cada 15 valores.
Um solução óbvia, então, é usar um pequeno mapeamento:
#!/usr/bin/perl
use strict;
for(1..99) {
print [
'fizzbuzz',
$_,
$_,
'fizz',
$_,
'buzz',
'fizz',
$_,
$_,
'fizz',
'buzz',
$_,
'fizz',
$_,
$_]->[$_%15]."\n";
}
Tudo bem, não tão óbvia como usar uma sequência de ifs.
Agora, não quero recriar o array dentro do loop a cada iteração, então vou tirá-lo e trocar os valores por funções. Algumas funções retornam o número que for passado como parâmetro, outras passam fizz, ou buzz, ou fizzbuzz.
Adicionei uma pequena otimização: o mapeamento é espelhado pela metade. O resultado do espelhamento tem uma posição extra, mas isso não incomoda.
#!/usr/bin/perl
use strict;
my @map=(
sub {'fizzbuzz'},
sub {shift},
sub {shift},
sub {'fizz'},
sub {shift},
sub {'buzz'},
sub {'fizz'},
sub {shift}
);
push @map, reverse @map;
for(1..99) {
print $map[$_%15]->($_)."\n";
}
Com um pouquinho de mágica, podemos simplificar ainda mais. Resulta que o resto de n4 por 15 só produz os valores 0, 1, 6, e 10. Magicamente, podemos mapeá-los diretamente ao que queremos:
#!/usr/bin/perl
use strict;
my %map=(
0 => sub {'fizzbuzz'},
1 => sub {shift},
6 => sub {'fizz'},
10=> sub {'buzz'}
);
for(1..99) {
print $map{$_**4%15}->($_)."\n";
}
Os detalhes dessa solução e a generalização para quaisquer outros números estão neste artigo.
Se alguém for usar uma solução dessas numa entrevista, recomendo explicar direitinho que não vai fazer isso com o código da empresa.
Nenhum comentário:
Postar um comentário