Kontrollstrukturen (Iterationen)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
erdal93
User
Beiträge: 6
Registriert: Freitag 4. November 2016, 01:46

Hallo Leute. Habe eine Aufgabe zu erledigen, leider komme ich nicht weiter. Folgendes soll gemacht werden:
1. Eingabe vom Benutzer (n Element der natürlichen Zahlen)
2. Jede einzelne Ziffer quadrieren
3. Quadrate addieren
4. Ergebnis muss entweder =1 (fröhliche Zahl) oder =4 (nicht fröhliche Zahl, gleichzeitig Periode) sein.

Ich bin nun soweit gekommen, dass ich nach der Eingabe diese in eine Liste umwandle und die einzelnen Elemente quadriere. Nur leider weiß ich nun nicht weiter. Ich würde es gerne von euch lernen, heißt ich will keine Lösung (falls möglich), sondern eher geleitet werden.

Das Problem, wie ihr sicherlich schon mitbekommen habt, ist, dass ich extremer Anfänger bin im Programmieren. Aber ich will es unbedingt lernen, da ich es für mein Studium brauche. Habe schon stundenlang gegooglet und probiert, aber leider nichts gefunden was geklappt hat.

Hoffe ihr könnt mir helfen. Unten füge ich noch meinen Code ein, evtl ist der ja bis dahin schon eine reine Katastrophe^^.

Gruß
erdal93

Code: Alles auswählen

zahl = input ('Geben Sie eine Zahl ein:')
liste=list(zahl)
for number in liste:
    x = int(number) ** 2
    print (x)
Zuletzt geändert von Anonymous am Freitag 4. November 2016, 11:38, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@erdal93: wie bist Du an dieses Problem herangegangen? Google programmiert ja nicht für einen. Erster Schritt ist immer, das Problem in kleinere Teilprobleme soweit aufzuteilen, dass man jeden Schritt einfach lösen kann. Nun ist die Aufgabenstellung ja fast schon in ihre Atome zerlegt und Du hast, soweit ich sehe, Punkt 1 und 2 erledigt. Als nächstes folgt Punkt 3 und wo hängst Du da nun konkret?
erdal93
User
Beiträge: 6
Registriert: Freitag 4. November 2016, 01:46

Ich weiß nicht, wie ich die einzelnen Quadrate addiere, und das solange bis entweder eine 1 oder eine 4 ausgerechnet wird. Der Durchlauf soll nach 100 Malen abbrechen.
BlackJack

@erdal93: Du müsstest Dir eine Variable einführen die Du am Anfang auf 0 setzt und dann in jedem Schleifendurchlauf den aktuellen Quadradwert aufaddierst.

Was soll denn als Ergebnis heraus kommen wenn nach 100 Schritten weder 1 noch 4 erreicht wurde?
erdal93
User
Beiträge: 6
Registriert: Freitag 4. November 2016, 01:46

Mir wurde folgendes geschickt.

Code: Alles auswählen

def froh(zahl):
   liste = list(str(zahl))
   sum = 0
   for ziffer in liste:
       x = int(ziffer) ** 2
       sum += x
   print(sum, end= ' ')
   return sum

zahl = int(input('Bitte geben Sie eine Zahl ein: '))
while zahl != 1 and zahl != 4:
    zahl = froh(zahl)
Ich habe es ausgeführt und es klappt auch so wie es sein sollte (denk ich zumindest).

@BlackJack: Wenn nach 100 Schritten weder 1 noch 4 erreicht wurde soll der Algorithmus einfach abbrechen.
Zuletzt geändert von Anonymous am Samstag 5. November 2016, 12:57, insgesamt 2-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@erdal93: Das klappt in sofern nicht als das nicht nach 100 Schritten abbricht. Es ist auch recht ausschweifend ausgedrückt und die Namen sind teilweise nicht gut gewählt. `froh()` beschreibt keine Tätigkeit, was Funktionsnamen üblicherweise tun sollten (oder Bedingungen bei Funktionen die etwas testen), `liste` ist zu allgemein und beschreibt den Typ statt die Bedeutung (`ziffern`), und `sum` ist der Name einer eingebauten Funktion, den man nicht mit anderen Werten verdecken sollte.

Bei `liste` hat man das Problem, dass öfter während der (Weiter)Entwicklung die Typen von Werten verändert werden, und dann hat man entweder irreführende Namen im Quelltext oder man muss alle betroffenen Namen im Quelltext ändern. Hier hätten wir sogar ein prima Beispiel dafür, denn der `list()`-Aufruf ist überflüssig weil auch die Zeichenkette schon als iterierbares Objekt über die einzelnen Zeichen, oder konkreter Ziffern, funktioniert.

Es gibt Programmiersprachen da muss man die Zeichenkette tatsächlich erst in eine Liste umwandeln um über die Zeichen zu iterieren beziehungsweise eine Operation auf alle Elemente anzuwenden. Io wäre so eine Sprache. Spasseshalber mal eine Lösung in Io die nach 100 Schritten abbricht, also drei Ergebnisse haben kann:
[codebox=io file=Unbenannt.txt]#!/usr/bin/env io

askNumber := method(
loop(
"Bitte eine Zahl eingeben: " print
result := File standardInput readLine asNumber
result isNan ifFalse(return(result))
)
)


Number isHappy := method(maxSteps,
number := self
maxSteps repeat(
number switch(
1, return(true),
4, return(false),
number = number asString asList map(d, d asNumber squared) sum
)
)
nil
)


main := method(
maxSteps := 100
number := askNumber
result := number isHappy(maxSteps) switch(
true, "glücklich",
false, "traurig",
nil, "nicht in #{maxSteps} Schritten entscheidbar" interpolate
)
"#{number} ist #{result}" interpolate println
)


isLaunchScript ifTrue(main)[/code]
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Eine Python-Lösung befindet sich auch hier:
https://en.wikipedia.org/wiki/Happy_num ... ng_example
BlackJack

Wobei das zweite Beispiel dort nicht praxistauglich ist weil das eine rekursive Lösung in einer Sprache ohne Tail Call Optimization ist. Wenn die Sequenz zu lang wird, dann endet das mit einer Ausnahme. Oder bei anderen Implementierungen als CPython eventuell auch in einem harten Programmabsturz wenn der Aufrufstapel zu gross wird.
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Ich glaube, die Rekursion wird in der Praxis nicht ausgestoppt, weil die Folge sehr schnell konvergiert.

Beispiel:
Zahl hat 100000 Stellen und jede Ziffer ist 9.
Dann ist 100000*9*9= 81000000 die erste Happy-Zahl.

Folge: 8100000 65 61 37 58 89 145 42 20 4
BlackJack

@heiner88: Trotzdem ist das schlechter Code. Wenn man erst einmal damit anfängt oder das Anfänger lesen, versuchen die oft auch andere Schleifen als Rekursion zu schreiben. Dann ist diese Funktion vielleicht das i-Tüpfelchen was den Aufrufstapel sprengt.
BlackJack

Mal sprachlich etwas näher zu Python, eine Lösung in Hy (Lisp-Dialekt in Python implementiert):

Code: Alles auswählen

#!/usr/bin/env hy
 
(defn ask-number []
  (while True
    (try
      (setv result (integer (input "Bitte eine Zahl eingeben: ")))
      (except [ValueError] (print "Fehler! Das war keine ganze Zahl."))
      (else (break))))
  result)
 
 
(defn square [number]
  (* number number))
 
 
(defn happy-step [number]
  (sum (map (fn [digit] (square (integer digit))) (str number))))
 
 
(defn happy? [number max-steps]
  (setv result None)
  (for [n (take max-steps (iterate happy-step number))]
    (cond
      [(= n 1) (setv result True) (break)]
      [(= n 4) (setv result False) (break)]))
  result)
 
 
(defmain [&rest argv]
  (let [max-steps 100
        number (ask-number)
        result (happy? number max-steps)]
    (print
      (.format "{} ist {}."
        number
        (cond
          [(= result True) "glücklich"]
          [(= result False) "traurig"]
          [(= result None)
              (.format "nicht in {} Schritten entscheidbar" max-steps)])))))
BlackJack

Ohne eine Umwandlung der Zahl in eine Zeichenkette; in QBasic:
[codebox=qbasic file=Unbenannt.txt]Const cMaxSteps = 100

Input "Bitte eine Zahl eingeben";Number

x = Number
Result$ = "nicht in" + Str$(cMaxSteps) + " Schritten entscheidbar"
For i = 1 To cMaxSteps
Select Case x
Case 1
Result$ = "glücklich"
Exit For
Case 4
Result$ = "unglücklich"
Exit For
Case Else
tmp = 0
While x > 0
tmp = tmp + (x Mod 10)^2
x = x \ 10
Wend
x = tmp
End Select
Next

Print Number;" ist ";Result$;"."[/code]
Antworten