Este é divertido. Eu gosto dessa pergunta. Eu escrevi a seguinte função para executar a tarefa e fazer o trabalho.
palindromes() (
rev() while getopts : o "-$1" ||
! r="${2#"${2%%[1-9]*}"}"
do set -- "$1" "$OPTARG$2"
done
rand() { : & : "$(($1=$!))"; }
[ "$1" -gt 10 ] || exit
n=$1; set --
while OPTIND=1; rev "$n"
case "$#.$n.$r" in
(100.*) ! printf '%s\t%s\t%s\t%s\t%s\n' "$@" ;;
(*.$r.$n) set -- "$@" "$n"; rand n ;;
(*) n=$((${n#-}+${r%-})) ;;
esac; do :; done
)
Há algumas coisas que são dignas de nota sobre isso. Em primeiro lugar, getopts
é usado para inverter o número. A função primária de getopts
é analisar as opções curtas que podem ou não estar todas juntas - e, portanto, é uma ferramenta conveniente para fazer o loop de todos os bytes de uma string.
Eu não gosto muito da função $RAND
do bash
shell, mas provavelmente é mais conservadora do que a minha função rand()
que apenas faz uma tarefa no-op e atribui seu PID defunto a qualquer varname é armazenado em seu primeiro argumento. Muito barato, eu admito.
A construção case
pode avaliar facilmente todas as facetas da sua tarefa em um teste simples. Eu faço:
case "$#.$n.$r" in
(100*) all done; printf %s\n "$@";;
(*$r.$n) palindrome; set -- "$@" "$n";;
(*) no luck; $n+$r; go again;;
esac
Eu tive muita dificuldade com isso no começo. No começo eu estava fazendo coisas como:
(*$r.$n) set -- ...; n=$((n+1))
Essa foi uma idéia ruim. A adição descontrolada imediatamente aumentou os números para tamanhos que a contagem de dígitos foi suficiente para afastar qualquer probabilidade de encontrar um palíndromo. Eu mexi com date +%S
, mas achei que se eu fosse executar outro processo, eu poderia usar o PID. E esse processo, nesse caso, poderia ser apenas um nulo. De qualquer forma, o intervalo PID é pequeno o suficiente para reinar no fator runaway quase sempre, parece.
Por exemplo, vou executar isso agora e cole os resultados:
palindromes 76
OUTPUT
484 29292 49294 69296 89298
215512 50605 90609 446644 886688
123321 52625 92629 468864 663787366
134431 54645 94649 881585188 7667585634365857667
145541 23432 43434 63436 83438
147741 24442 44444 64446 84448
158851 25452 45454 65456 85458
169961 13231 46464 66466 86468
49985258994 27472 47474 67476 87478
14355341 28482 48484 68486 88488
395593 29492 49494 69496 89498
219912 121121 11244211 441144 881188
125521 165561 15522551 463364 7365409856589045637
136631 211112 17858768886785871 485584 893974888888479398
147741 23632 43634 63636 83638
149941 24642 44644 64646 84648
523325 25652 45654 65656 85658
567765 13331 46664 66666 86668
2358532 27672 47674 67676 87678
2236322 28682 48684 68686 88688
Existem provavelmente alguns enganados lá - isso acontece, aparentemente. Nao muitos. Eu não sei se isso é um problema para você ou não, mas isso é apenas um exemplo de como isso pode ser feito.
Uma última nota - executar isso em dash
é muito mais rápido do que em bash
; embora a diferença pareça ser apenas um segundo ou mais. Em qualquer caso, se você usar , use dash
para alterar a linha rev()
set -- "$1"
para set -- "${1#?}".
Acabei de perceber que há um requisito de dois dígitos - embora suspeite que essa regra específica seja uma tentativa de evitar que a tarefa seja muito difícil. De qualquer forma, obter apenas um subconjunto de uma string é muito fácil de fazer. Na verdade, é o que eu faço com r=
quando eu:
r="${2#"${2%%[1-9]*}"}"
... que sempre atribui r
um valor que não começa com zero.
Aqui está uma versão de rand()
que sempre atribui um número de dois dígitos a $1
:
rand() { : & set -- "$1" "$!" "$(($!%100))"
: "$(($1=($3>10?$3:${#2}$3)))"
}
Você pode aplicar a mesma lógica a bash
$RAND
, é claro. O operador $((var=(value)?(assign if true):(assign if false)))"
ternary funcionará com praticamente qualquer conjunto inteiro. Aqui eu ou atribuo a ele o módulo de 100 (basicamente um percentil) se esse valor for maior que dez, senão eu atribuo isso como o segundo de dois dígitos onde o primeiro é uma contagem dos dígitos em $!
.
Corra dessa forma e seus resultados são um pouco menos empolgantes:
333 66 484 1111 4884
77 88 99 121 121
363 484 77 4884 44044
88 99 121 121 363
484 1111 4884 88 8813200023188
99 121 121 363 484
1111 4884 44044 8813200023188 99
44 55 66 77 44
99 121 121 363 484
424 11 33 44 55
66 77 88 99 121
22 33 22 55 66
77 88 99 121 121
33 44 55 33 77
88 99 121 121 363
44 55 66 77 44
99 121 121 363 484
55 66 77 88 99
55 121 363 484 1111
66 77 88 99 121