C :: Aufgabe #130
1 Lösung
Beharrlichkeit natürlicher Zahlen
Anfänger - C
von hollst
- 30.09.2016 um 12:20 Uhr
Mathematiker denken sich manchmal ziemlich unsinnige Dinge aus, frei nach dem Motte
"Was interessiert mich der Sinn der Objekte, die ich mir ausgedacht habe,
wichtig (und aufregend) ist für mich lediglich, die Eigenschaften dieser Objekte zu
erkunden".
So verstehen einige Mathematiker unter der "Beharrlichkeit" (englisch persistence)
einer natürlichen Zahl, dargestellt als Folge dezimaler Digits, die "Widerstandskraft"
der Zahl gegenüber einer wiederholenden Verkleinerung durch Multiplikation ihrer Digits.
Beispiele:
pers(38) = 2
(wegen 3 * 8 = 24 und 2 * 4 = 8, d. h. zweifache Wiederholung der Multiplikationen, jeweils
auf das Ergebnis der Vorgängermultiplikationen bezogen)
pers(1236) = 3
(1 * 2 * 3 * 6 = 36; 3 * 6 = 18; 1 * 8 = 8).
Eine Reduzierung der beschriebenen Art bis auf lediglich ein Digit ist bei jeder natürlichen
Zahl möglich. Die Zahlen 0 ... 9 haben es ganz schlecht, denn ihre Beharrlichkeit ist gleich
Null. Schlechte Karten haben auch alle mehrstelligen Zahlen, bei denen irgendein Digit Null
ist, sie reduzieren sich mit nur einem einzigen Multiplikationszyklus auf die
Beharrlichkeit Eins.
Es gibt aber andere Zahlen, die wesentlich beharrlicher sind.
Die Aufgabenstellung besteht nun darin, für alle 2-stelligen, 3-stelligen ... bis hin zu
allen 6-stelligen natürlichen Dezimalzahlen diejenigen zu ermitteln, die innerhalb ihres
Definitionsbereiches (Anzahl der Dezimalstellen) die größte Beharrlichkeit aufweisen.
Erschwerung: Zwei Zahlen, die durch Vertauschung von Digits ineinander überführt werden
können, sind als gleich zu betrachten (z. B. 18 und 81 oder 1317 und 3711) und es ist
lediglich die kleinere (hier die 18 bzw. die 1317) zu berücksichtigen.
"Was interessiert mich der Sinn der Objekte, die ich mir ausgedacht habe,
wichtig (und aufregend) ist für mich lediglich, die Eigenschaften dieser Objekte zu
erkunden".
So verstehen einige Mathematiker unter der "Beharrlichkeit" (englisch persistence)
einer natürlichen Zahl, dargestellt als Folge dezimaler Digits, die "Widerstandskraft"
der Zahl gegenüber einer wiederholenden Verkleinerung durch Multiplikation ihrer Digits.
Beispiele:
pers(38) = 2
(wegen 3 * 8 = 24 und 2 * 4 = 8, d. h. zweifache Wiederholung der Multiplikationen, jeweils
auf das Ergebnis der Vorgängermultiplikationen bezogen)
pers(1236) = 3
(1 * 2 * 3 * 6 = 36; 3 * 6 = 18; 1 * 8 = 8).
Eine Reduzierung der beschriebenen Art bis auf lediglich ein Digit ist bei jeder natürlichen
Zahl möglich. Die Zahlen 0 ... 9 haben es ganz schlecht, denn ihre Beharrlichkeit ist gleich
Null. Schlechte Karten haben auch alle mehrstelligen Zahlen, bei denen irgendein Digit Null
ist, sie reduzieren sich mit nur einem einzigen Multiplikationszyklus auf die
Beharrlichkeit Eins.
Es gibt aber andere Zahlen, die wesentlich beharrlicher sind.
Die Aufgabenstellung besteht nun darin, für alle 2-stelligen, 3-stelligen ... bis hin zu
allen 6-stelligen natürlichen Dezimalzahlen diejenigen zu ermitteln, die innerhalb ihres
Definitionsbereiches (Anzahl der Dezimalstellen) die größte Beharrlichkeit aufweisen.
Erschwerung: Zwei Zahlen, die durch Vertauschung von Digits ineinander überführt werden
können, sind als gleich zu betrachten (z. B. 18 und 81 oder 1317 und 3711) und es ist
lediglich die kleinere (hier die 18 bzw. die 1317) zu berücksichtigen.
Lösungen:
Konsolenausgabe:
Anzahl Dezimalstellen: 6
Beste Beharrlichkeit 7 bei:
168889
238889
246889
266688
267799
336888
344889
346688
347799
366779
377779
377889
444689
446668
467789
666778
Anzahl Dezimalstellen: 7
Beste Beharrlichkeit 8 bei:
2677889
2799999
3477889
3667788
3679999
4467789
4666778
6888999
6999999
/*********************************************
* pers.c Beharrlichkeit natürlicher Zahlen
*********************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct _pers_entry {
int pers_zahl;
int pers_wert;
} t_pers_entry;
/* Berechne Querprodukt einer Zahl */
int calc_prod(int z) {
char sz[10];
char *ps;
int qp=1;
sprintf(sz, "%d", z);
ps=sz;
while (*ps)
qp *= (int)(*ps++ - '0');
return qp;
}
/* Berechne Persistenz einer Zahl */
int calc_pers(int z) {
int prs=1;
while (1) {
if ((z = calc_prod(z)) < 10)
break;
prs++;
}
return prs;
}
/* Prüfe ob Persistenz einer Zahl maximal ist
* falls ja, Zahl und Persistenzwert merken.
* Ergebnisausgabe für z==0
*/
void check_pers(int z) {
static t_pers_entry pers_list[100];
static int pmax=2;
static int next=0;
int i, p;
if (z == 0) {
/* Ausgabe Ergebnis */
printf("Beste Beharrlichkeit %d bei:\n", pmax);
for (i=0; i<next; i++)
if (pers_list[i].pers_wert == pmax)
printf("%d\n", pers_list[i].pers_zahl);
return;
}
if ((p = calc_pers(z)) >= pmax) {
if (p > pmax) {
pmax = p;
next = 0;
}
if (next < 99) {
pers_list[next].pers_zahl = z;
pers_list[next].pers_wert = pmax;
next++;
}
else {
fprintf(stderr, "no space left in pers array.\n");
exit(EXIT_FAILURE);
}
}
}
/*** main ***/
int main(int argc, char **argv) {
int ndec, zahl;
int i,j,k,l,m,n,p;
printf("Anzahl Dezimalstellen: ");
scanf("%d", &ndec);
if (ndec < 2 || ndec > 7) {
fprintf(stderr, "Anzahl muss in {2..7} liegen.\n");
return 1;
}
/* Loop Zahlen generieren (ohne Permutationen)
* und ihre Persistenz prüfen */
for (i=1; i<=9; i++) {
zahl = i*10;
for (j=i; j<=9; j++) {
zahl += j;
if (ndec==2) {
check_pers(zahl);
}
else {
zahl *= 10;
for (k=j; k<=9; k++) {
zahl += k;
if (ndec==3) {
check_pers(zahl);
}
else {
zahl *= 10;
for (l=k; l<=9; l++) {
zahl += l;
if (ndec==4) {
check_pers(zahl);
}
else {
zahl *= 10;
for (m=l; m<=9; m++) {
zahl += m;
if (ndec==5) {
check_pers(zahl);
}
else {
zahl *= 10;
for (n=m; n<=9; n++) {
zahl += n;
if (ndec==6) {
check_pers(zahl);
}
else {
zahl *= 10;
for (p=n; p<=9; p++) {
zahl += p;
check_pers(zahl);
zahl -= p;
}
zahl /= 10;
}
zahl -= n;
}
zahl /= 10;
}
zahl -= m;
}
zahl /= 10;
}
zahl -= l;
}
zahl /= 10;
}
zahl -= k;
}
zahl /= 10;
}
zahl -= j;
}
}
check_pers(0);
return 0;
}
