Dieser macht Spaß. Ich mag diese Frage. Ich habe die folgende Funktion geschrieben, um die Aufgabe auszuführen, und sie erledigt den Job.
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
)
Es gibt ein paar Dinge, die daran bemerkenswert sind. In erster Linie getopts
wird verwendet, um die Zahl umzukehren. Die Hauptfunktion von getopts
besteht darin, kurze Optionen zu analysieren, die möglicherweise alle aneinandergereiht sind oder nicht - und ist daher ein praktisches Werkzeug zum Durchlaufen jedes Bytes in einer Zeichenfolge.
Ich mag die $RAND
Funktion der bash
Shell nicht sehr , aber wahrscheinlich ist sie konservativer als meine rand()
Funktion, die nur eine No-Op-Task hinterlegt und ihre nicht mehr existierende PID dem in ihrem ersten Argument gespeicherten Variablennamen zuweist. Ziemlich billig, das gebe ich zu.
Das case
Konstrukt kann in einem einfachen Test leicht alle Facetten Ihrer Aufgabe bewerten. Ich mache:
case "$#.$n.$r" in
(100*) all done; printf %s\\n "$@";;
(*$r.$n) palindrome; set -- "$@" "$n";;
(*) no luck; $n+$r; go again;;
esac
Ich hatte anfangs große Schwierigkeiten damit. Zuerst habe ich Sachen gemacht wie:
(*$r.$n) set -- ...; n=$((n+1))
Das war eine schlechte Idee. Die außer Kontrolle geratene Addition vergrößerte die Zahlen sofort auf Größen, bei denen die bloße Anzahl der Ziffern ausreichte, um die Wahrscheinlichkeit zu verringern, jemals ein Palindrom zu finden. Ich habe herumgespielt, date +%S
aber ich dachte mir, wenn ich trotzdem einen anderen Prozess ausführen würde, könnte ich genauso gut die PID verwenden. Und dieser Prozess könnte in diesem Fall genauso gut ein Null-Op sein. Wie auch immer, der PID-Bereich ist klein genug, um so ziemlich jedes Mal im Runaway-Faktor zu regieren, wie es scheint.
Zum Beispiel werde ich dies jetzt ausführen und die Ergebnisse einfügen:
palindromes 76
AUSGABE
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
Es sind wahrscheinlich einige Dupes drin - es passiert anscheinend. Nicht viele. Ich weiß nicht, ob das ein Problem für Sie ist oder nicht, aber dies ist nur ein Beispiel dafür, wie es gemacht werden könnte.
Ein letzter Hinweis: Das Ausführen dash
ist weitaus schneller als das Einführen bash
. obwohl der Unterschied nur eine Sekunde oder so zu sein scheint. In jedem Fall müssen Sie , wenn Sie verwenden dash
, die rev()
set -- "$1"
Zeile in ändernset -- "${1#?}".
Ich habe gerade festgestellt, dass es eine zweistellige Anforderung gibt - obwohl ich den Verdacht habe, dass diese spezielle Regel ein Versuch ist, zu verhindern, dass die Aufgabe zu schwierig wird. Auf jeden Fall ist es sehr einfach, nur eine Teilmenge eines Strings abzurufen. In der Tat ist es das, womit ich mache, r=
wenn ich:
r="${2#"${2%%[1-9]*}"}"
... die immer r
einen Wert zuweist , der nicht mit einer Null beginnt.
Hier ist eine Version davon rand()
, die immer eine zweistellige Nummer zuweist $1
:
rand() { : & set -- "$1" "$!" "$(($!%100))"
: "$(($1=($3>10?$3:${#2}$3)))"
}
Sie können natürlich die gleiche Logik auf bash
's anwenden $RAND
. Der $((var=(value)?(assign if true):(assign if false)))"
ternäre Operator arbeitet mit nahezu jeder Ganzzahl. Hier weise ich ihm entweder das Modulo 100 (im Grunde genommen ein Perzentil) zu, wenn dieser Wert größer als zehn ist, oder ich weise das als zweite von zwei Ziffern zu, wobei die erste eine Zählung der Ziffern in ist $!
.
Laufen Sie so und die Ergebnisse sind etwas weniger aufregend:
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