@@Matthias Apsel
Man ermittle alle Zahlen n, für die gilt n = z.
Aus der Bildungsvorschrift von z ergibt sich, dass z maximal 10stellig sein kann. Damit können auch die gesuchten mit z übereinstimmenden n maximal 10stellig sein.
Auf die Suche!
Eine Methode, um die Vorkommen eines Zeichens (einer Zeichenkette) in einem String zu zählen:
String.prototype.occurrences = function (character) {
return this.match(new RegExp(character, 'g'))?.length || 0;
};
Ist es eigentlich eine gute oder eine blöde Idee, Basisobjekte prototypisch zu erweitern? (Ernsthafte Frage.)
Damit erhält man z(n):
function z(n) {
const nString = n.toString();
let zString = '';
for (let digit = 0; digit <= 9; digit++) {
zString += nString.occurrences(digit);
}
return Number.parseInt(zString, 10);
};
Jetzt braucht man nur noch alle maximal 10stelligen Zahlen untersuchen:
for (let n = 0; n < 1e10; n++) {
if (n == z(n)) {
console.log(n);
}
}
(Die nicht in N einthalten Zahlen 1111111111 (zehn Einsen), 2222222222, …, 9999999999 würde man einfach ignorieren, sollten sie Treffer sein.)
Das Problem daran: Das Script läuft eeeeeeeeeewig. Bzw.: Es tut es nicht; der Browser fragt immer wieder nach, ob er es weiter ausführen soll. Es läuft durch bis 10⁶; mit wiederholten Aufforderungen weiterzumachen kommt man auch bei 10⁷ zum Ende. Aber bis 10¹⁰ sind’s noch Größenordnungen …
Andere Implementierungen mögen schneller sein und keine Nachfrage erzeugen; 10¹⁰ Schleifendurchläufe sind auch dann kaum praktikabel. (Bei nur einer Zehntelmillisekunde pro Durchlauf würde das Script 10⁶ Sekunden laufen; das sind über 11½ Tage.)
Aber wir wissen schon mal, dass es keine Zahl n = z(n) gibt, die 7 oder weniger Stellen hat.
Das muss anders gehen als mit brute force; Gewalt ist keine Lösung.
Ich hatte mich schon gefragt, ob ich mit „Ich habe zwei Zahlen gefunden, für die n = z(z(n)) gilt“ nicht schon zu viel vom Lösungsweg verraten hatte …
Lassen wir uns doch mal z(n) ausgeben:
function check(n) {
console.log(n, n == z(n) ? '🌞🌞🌞' : z(n));
}
Für 0:
check(0);
Und jetzt setzen wir das Ergebnis wieder ein:
check(1000000000);
Und wieder und wieder:
check(9100000000);
check(8100000001);
check(7200000010);
check(7110000100);
check(6300000100);
check(7101001000);
Wir landen im Zyklus 6300000100 ↔︎ 7101001000.
Und dasselbe passiert auch für den Startwert 1, 2, 3, …, 98765, …
Das legt die Vermutung nahe, dass das für alle Startwerte so ist, d.h. dass es keine Zahl gibt, für die n = z(n) gilt.
An der Stelle kommt @Matthias Apsel ins Spiel, der mir zuflüsterte, dass es doch eine solche Zahl gibt. Dann heißt’s wohl, die Nadel im Heuhaufen zu suchen …
Und dafür eine Funktion geschrieben, die z(z(z(…))) berechnet, bis sie in den Zyklus läuft oder nach einigen Durchläufen abbricht. (Wie wir gesehen hatten, kommt man recht schnell in den Zyklus; 10 Schleifen sollten reichen.)
function attractor(n) {
for (let i = 0; i < 10; i++) {
if (n == 7101001000) {
return n;
}
else {
n = z(n);
}
}
return null;
};
console.log(attractor(0));
Voller Verzweiflung hab ich dann wahllos auf der Tastatur rumgeklimpert (ich schwör’s, so war’s):
console.log(attractor(42189658268));
Nanu? Reichen 10 Schleifen doch nicht? Auf 100 erhöht, 1000, 10000 – selbes Ergebnis.
Huch, was’n da los?
check(42189658268);
check(120112031);
check(2421000000);
check(6120100000);
check(6210001000);
Punker Maria, du ich hab die Nadel gefunden! (Didi)
Es gibt sie wirklich: 6210001000 ist so eine gesuchte Zahl mit n = z(n).
Jetzt stellt sich die Frage, ob ich einfach nur wahnsinnig viel Glück hatte oder ob es viele Startwerte gibt, die nicht in den Zyklus 6300000100 ↔︎ 7101001000, sondern zu 6210001000 führen.
Die Funktion abgewandelt zu
function attractor(n) {
const attractors = [
6210001000,
7101001000,
];
for (let i = 0; i < 10; i++) {
if (attractors.includes(n)) {
return n;
}
else {
n = z(n);
}
}
return null;
};
und mit 10000 Zufallszahlen aus dem Bereich [0, 10¹⁰[ geprüft ergibt: Etwa 34½ % der Zahlen führen zu 6210001000; 65½ % zum Zylus 7101001000 ↔︎ 6300000100. Es war keine Zahl dabei, die nicht zu einem der beiden führt.
Das ist ein Indiz, aber kein Beweis dafür, dass es nicht noch weitere Zyklen gibt; womöglich gar welche der Länge 1, d.h. weitere Zahlen mit der Eigenschaft n = z(n).
Um das auszuschließen, fiele mir jetzt wieder nur brute force ein …
Es war also doch nicht die Nadel, die ich im Heuhaufen gefunden hab; es gibt viele davon. Warum ich anfangs keine gefunden hatte: es gibt keine Nadeln < 10⁶. Die kleinste Zahl, die zu 6210001000 führt, ist 1000123.
Hier noch der Link zu meiner Spielwiese.
🖖 Stay hard! Stay hungry! Stay alive! Stay home!
--
Home Office ist so frustierend, weil man jetzt noch viel stärker bemerkt mit wievielen Menschen man zu tun hat, die nicht sinnerfassend lesen können. (
@Grantscheam)