Glückliche oder Traurige Zahl?
Aufgabenstellung:
Die Dezimalziffern einer natürlichen Zahl n, n ≥ 1, werden einzeln quadriert und addiert. Anschließend wird mit der entstandenen Summe genauso verfahren. Die Ausgangszahl n ist fröhlich, wenn man bei diesem Vorgehen schließlich auf die Zahl 1 stößt, ansonsten ist sie traurig. Beispielsweise ist 7 eine fröhliche Zahl
Schreiben Sie ein Java-Programm, das alle fröhlichen Zahlen zwischen einer Unter- und einer Obergrenze berechnet und die zugehörigen Folgen ausgibt.
Der Dialog soll folgendermaßen ablaufen:
untere Grenze ein: 5
obere Grenze ein: 30
7 -> 49 -> 97 -> 130 -> 10 -> 1
10 -> 1
13 -> 10 -> 1
19 -> 82 -> 68 -> 100 -> 1
23 -> 13 -> 10 -> 1
28 -> 68 -> 100 -> 1
import java.util.Scanner;
public class GlücklicheZahl2 {
private int counter = 0;
private int[] summenSpeicher = new int[1];
private int zahl;
int summenCounter = 0;
Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
GlücklicheZahl2 zahl = new GlücklicheZahl2();
}
public GlücklicheZahl2() {
/*System.out.print("Zahl? ");
int zahl = scanner.nextInt();*/
System.out.print("untere Grenze? ");
int untereGrenze = scanner.nextInt();
System.out.print("obere Grenze? ");
int obereGrenze = scanner.nextInt();
for (int i = untereGrenze; i <= obereGrenze + 1; i++) {
this.zahl = i;
this.summenSpeicher = new int[1];
createIntArray(i);
}
}
public void rechnung(int[] intArray) {
boolean glücklich = false;
int summe = 0;
for (int i = 0; i < intArray.length; i++) {
summe += intArray[i] * intArray[i];
}
if (summe == 1) {
glücklich = true;
}
if (summenCounter >= summenSpeicher.length) {
int[] tmpArray = new int[summenSpeicher.length + 1];
for (int i = 0; i < summenSpeicher.length; i++) {
tmpArray[i] = summenSpeicher[i];
}
summenSpeicher = tmpArray;
}
summenSpeicher[summenSpeicher.length - 1] = summe;
summenCounter++;
if (glücklich) {
System.out.print(zahl);
for (int i = 0; i < summenSpeicher.length; i++) {
System.out.print(" -> " + summenSpeicher[i]);
}
System.out.println("");
} else {
if (counter < 50) {
counter++;
createIntArray(summe);
}
}
}
public void createIntArray(int x) {
String wert = Integer.toString(x);
char[] wertarray = wert.toCharArray();
int[] intArray = new int[wertarray.length];
for (int i = 0; i < wertarray.length; i++) {
intArray[i] = Character.getNumericValue(wertarray[i]);
}
rechnung(intArray);
}
}
Wieso erstellst du eine Instanz der Main Klasse mit einer Methode in dieser Klasse um den Konstruktor aufzurufen der ein Programm ausführt? Sieht sehr komisch aus.
keine Ahnung hat mein Tutor im Studium mal so gemacht
3 Antworten
Ich hab mich auch mal dran versucht (in C#) und folgendes ist dabei herausgekommen:
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Bitte geben Sie die untere Grenze ein: ");
int start = int.Parse(Console.ReadLine());
Console.WriteLine("Bitte geben Sie die obere Grenze ein: ");
int end = int.Parse(Console.ReadLine());
for (int i = start; i <= end; i++)
{
var sequence = new NumberSequence(i);
if (sequence.IsLucky)
{
Console.WriteLine(sequence.StringRepresentation);
}
}
}
}
internal class NumberSequence
{
private readonly List<int> _numbers;
public string StringRepresentation => string.Join(" -> ", _numbers);
public bool IsLucky => _numbers[_numbers.Count - 1] == 1;
public NumberSequence(int startNumber)
{
_numbers = new List<int>();
ExpandSequence(startNumber);
}
private void ExpandSequence(int number)
{
if (_numbers.Contains(number)) return;
_numbers.Add(number);
ExpandSequence(SumOfSquaredDigits(number));
}
private int SumOfSquaredDigits(int number)
{
if (number == 0) return 0;
int firstDigit = number % 10;
return firstDigit * firstDigit + SumOfSquaredDigits(number / 10);
}
}
ACHTUNG: Die ExpandSequence-Methode fügt rekursiv Elemente zur Sequence hinzu, bis sich irgendwann eines wiederholen würde (ab da würde die Sequence sich periodisch wiederholen und in eine Endlos-Rekursion ausarten). Ich bin mir nicht sicher, ob die Rekursion immer terminiert, daher kann man zur Sicherheit auch die Iterationen mitzählen und irgendwann abbrechen (etwa so wie zooper in seiner/ihrer Lösung auch nur 100 Iterationen durchgeführt hat).
Ist eine nette kleine Aufgabe, daher geb ich auch mal meinen Senf dazu:
public class GluecklicheZahl {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Unter- und Obergrenze abfragen
System.out.print("Bitte geben Sie die Untergrenze ein: ");
int lBound = scanner.nextInt();
System.out.print("Bitte geben Sie die Obergrenze ein: ");
int uBound = scanner.nextInt();
scanner.close();
// Jede Zahl zwischen Unter- und Obergrenze durchgehen
for (int i = lBound; i <= uBound; ++i) {
int num = i;
Set<Integer> iterationResults = new LinkedHashSet<>();
// Die Serie aufbauen
// Da als Abbruchbedingung nur vorgegeben ist, dass die Serie irgendwann bei einer 1 enden soll,
// wird als weitere Abbruchbedingung angenommen, dass die Serie sich ansonsten ab einem bestimmten Punkt wiederholt.
// Daher wird die Schleife abgebrochen sobald ein Element eingefügt werden soll, welches schon in der Serie ist.
while (num != 1 && !iterationResults.contains(num)) {
iterationResults.add(num);
num = Integer.toString(num).chars().map(Character::getNumericValue).map(value -> value * value).sum();
}
iterationResults.add(num);
// Serie ausgeben, falls sie mit einer 1 geendet ist.
if (num == 1) {
System.out.println(iterationResults.stream().map(n -> n.toString()).collect(Collectors.joining(" -> ")));
}
}
}
}
funktioniert nicht so ganz wenn ich es nur mit einer Zahl gemacht habe hat es funktioniert also im Konstruktor folgendes:
System.out.print("Zahl? ");
int zahl = scanner.nextInt();
createIntArray(zahl);
jetzt mit der schleife für den zahlenbereich net mehr wirklich. Bin auch dankbar für sonstige Anmerkungen wenn ihr das ganz anders gemacht hättet oder so