AUFGABE: Jeden tag eine Änderung des Bankcodes...

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.
PythonRookie9000
User
Beiträge: 2
Registriert: Mittwoch 1. Februar 2017, 17:16

AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon PythonRookie9000 » Mittwoch 1. Februar 2017, 17:29



Hey Leute!

Ich bin hier neu und ein Anfänger in Python. Ich versuche es mir selbst bei zu bringen, was etwas hartnäckig ist. Deswegen brauche ich Hilfe bei folgender Aufgabe:

"Ein Bankdirektor stellte auf dem Ziffernschloss zum Tresorraum die Codezahl 1986 ein. Aus Sicherheitsgründen sollte der Code täglich geändert werden. Dazu dachte sich der Direktor folgende Methode aus:

Er bildete die Summe der aktuellen vier Ziffern (am ersten Tag also 24) und fügte die Einerstelle dieser Summe (bei 24 also 4) der Codezahl rechts an, dafür wurde die erste linksstehende Ziffer (am ersten Tag die 1) gestrichen.

Nun wollte der Bankdirektor wissen, ob bei diesem Vorgehen die Zahl 1986 noch einmal als Code auftreten werde. Als ihm dies ein Computerexperte bestätigte, interessierte er sich brennend dafür, wieviele Tage vergehen werden, bis die Codezahl wieder 1986 lautet."

Das ist soweit meine Lösung:

  1. Code = "1986"
  2. Tag = 1
  3.  
  4. while Tag != 3000:
  5.     Summe = str(int(Code[0])+int(Code[1])+int(Code[2])+int(Code[3]))
  6.     Code = Code.replace(Code[0], "")
  7.     Code = str(Code + Summe[1])
  8.     print(Code)
  9.     Tag += 1
  10.     if Code == "1986":
  11.         print(Tag)
  12.         break


Ich habe jetzt einfach mal eine Schleife bis zum Tag 3000 erstmal genommen. Eig. funktioniert alles bis zum 10. Code, welcher dann plötzlich dreistellig ist, obwohl die Summe des Code davor wunderbar aussieht. Naja es wird mir ein IndexError angezeigt(string out of range) auf Zeile 5 hingewiesen.

Ich würde mich freuen, wenn ihr mir ein bisschen helfen könntet, da ich hier überfragt bin.

Viele Grüße!!

PS: Falls jemand Webseiten mit guten Python-Aufgaben für Anfänger kennt, immer rein damit!! :D
Zuletzt geändert von BlackJack am Mittwoch 1. Februar 2017, 17:31, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
BlackJack
Moderator
Beiträge: 31402
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon BlackJack » Mittwoch 1. Februar 2017, 17:40

@PythonRookie9000: Schau Dir doch einfach mal die Operation an bei der die Zahl dreistellig wird. Was passiert in dem Schritt denn genau? Wie sieht die Zahl vorher aus und welche Ziffern fehlen danach? Das sollte eigentlich offensichtlich sein was da passiert und warum es so nicht funktionieren kann wenn man es mal Schritt für Schritt durchgeht.

Als Endbedingung für die ``while``-Schleife hätte man auch einfach `True` verwenden können, also eine ”Endlosschleife” die ja abgebrochen wird wenn der Code wieder '1986' ist.

Man könnte aber auch eine ``for``-Schleife mit `itertools.count()` verwenden um das manuelle hochzählen des Tags zu vermeiden.

Der `str()`-Aufruf in Zeile 7 ist sinnfrei weil da bereits eine Zeichenkette übergeben wird und der Index 1 der in dieser Zeile verwendet wird ist ein weiterer Programmierfehler. Der stimmt nämlich nur wenn die Summe zweistellig ist. Man kann aber auch vier Ziffern haben die nur eine einstellige Summe haben, was dann zu einem `IndexError` führt.

Namenskonvention ist übrigens das nur Klassennamen mit einem Grossbuchstaben beginnen und Konstanten durchgehend in Grossbuchstaben geschrieben werden.
“A lesson I've learned over and over is that computer programs live far longer than you expect. It pays to do 'em better at the beginning, 'cause you're likely to live with them quite a while.” — Cameron Laird in c.l.p
Sirius3
User
Beiträge: 5414
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon Sirius3 » Mittwoch 1. Februar 2017, 17:42

@PythonRookie9000: schau mal in der Dokumentation nach, was Code.replace genau macht und wann das ein Problem werden könnte. Warum könnte Zeile 7 auch ein Problem machen?

Allgemein: Wenn man weiß, wie viele Durchläufe eine while-Schleife laut Schleifenbedingung macht, sollte man eine for-Schleife verwenden. Variablennamen werden komplett klein geschrieben.
PythonRookie9000
User
Beiträge: 2
Registriert: Mittwoch 1. Februar 2017, 17:16

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon PythonRookie9000 » Mittwoch 1. Februar 2017, 20:04

@BlackJack
@Sirius3
Aaaaalllsooo,

Ich habe jetzt anstatt das replace Kommando, einfach code[1:] genommen. Es war echt nicht so einfach das Problem zu erkennen( wegen dem mangelnden Verständnis der Vorgehensweise der Sprache) und dann noch zu lösen. Ich habe die ganze Zeit nach anderen Kommandos gesucht, aber dann war es doch so einfach...

In Linie 7 habe ich anstatt summe[1] , summe[-1] benutzt. Hätte ich gleich sehen müssen... Zu dem str in der Linie 7 sag ich mal lieber nichts mehr...

Und ab heute werden Variablennamen klein geschrieben!!

Vielen Dank für eure schnelle Antwort und dass ihr mir nicht gleich die Lösung verratet habt!

Ich denke mal ihr wollt unbedingt die wissen wie viele Tage es dauert bis der Code wieder 1986 lautet...1561. Unglaublich, ich weiß!
Benutzeravatar
BlackJack
Moderator
Beiträge: 31402
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon BlackJack » Mittwoch 1. Februar 2017, 23:47

@PythonRookie9000: Dabei hast Du jetzt aber den ersten Tag mitgezählt, ich komme nämlich nur auf 1560 Tage. Mit QBasic:
  1. CONST StartCode$="1986"
  2. Day=0
  3. Code$=StartCode$
  4. DO
  5.   Sum=0
  6.   FOR i=1 TO 4
  7.     Sum=Sum+VAL(MID$(Code$,i,1))
  8.   NEXT
  9.   Code$=MID$(Code$,2)+LTRIM$(STR$(Sum MOD 10))
  10.   Day=Day+1
  11.   PRINT "Day:";Day;" Code: ";Code$
  12. LOOP UNTIL Code$=StartCode$
“A lesson I've learned over and over is that computer programs live far longer than you expect. It pays to do 'em better at the beginning, 'cause you're likely to live with them quite a while.” — Cameron Laird in c.l.p
sebastian0202
User
Beiträge: 110
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon sebastian0202 » Donnerstag 2. Februar 2017, 08:39

Ich will auch :lol:
Nicht besonderes, aber zum warm werden bevor man anfängt zu arbeiten.
  1. def mathe():
  2.     ur_code = "1986"
  3.     Code = "1986"
  4.     Tag = 0
  5.     while True:
  6.         ergebnis = 0
  7.         for zahl in Code:
  8.             ergebnis += int(zahl)
  9.         Code += str(ergebnis)[-1]
  10.         Code = Code[1:]
  11.         Tag += 1
  12.         if Code == ur_code:
  13.             break
  14.     print("Es sind %s Tage vergangen, bis sich der Code wiederholt hat!" % Tag)
  15.  
  16.  
  17. if __name__ == '__main__':
  18.     mathe()
Benutzeravatar
BlackJack
Moderator
Beiträge: 31402
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon BlackJack » Donnerstag 2. Februar 2017, 08:56

  1. #!/usr/bin/env python
  2. from __future__ import absolute_import, division, print_function
  3. from itertools import count
  4.  
  5.  
  6. def main():
  7.     start_code = '1986'
  8.     code = start_code
  9.     for day in count(1):
  10.         code = code[1:] + str(sum(map(int, code)) % 10)
  11.         if code == start_code:
  12.             break
  13.     print('Nach {} Tagen ist der Code wieder {}.'.format(day, start_code))
  14.  
  15.  
  16. if __name__ == '__main__':
  17.     main()
“A lesson I've learned over and over is that computer programs live far longer than you expect. It pays to do 'em better at the beginning, 'cause you're likely to live with them quite a while.” — Cameron Laird in c.l.p
Benutzeravatar
BlackJack
Moderator
Beiträge: 31402
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon BlackJack » Donnerstag 2. Februar 2017, 11:25

@sebastian0202: Wenn Du die Funktion schon `mathe()` nennst, hätte ich ja mindestens erwartet, dass Du keine Zeichenketten sondern ausschliesslich Zahlen und mathematische Operationen verwendest. :P

@PythonRookie9000: Das wäre vielleicht eine interessante weitere Teilaufgabe, den Code als *eine* Zahl zu repräsentieren und nicht auf Zeichenkettenoperationen zurück zu greifen.
“A lesson I've learned over and over is that computer programs live far longer than you expect. It pays to do 'em better at the beginning, 'cause you're likely to live with them quite a while.” — Cameron Laird in c.l.p
sebastian0202
User
Beiträge: 110
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon sebastian0202 » Donnerstag 2. Februar 2017, 16:00

War etwas schwierig und lässt sich sicher auch eleganter lösen.
Aber hier die mathe Funktion nur mit Zahlen.
  1. def mathe(ur_code):
  2.     Code = ur_code
  3.     Zahl = ur_code
  4.     Tag = 0
  5.     while True:
  6.         zwischen_ergebnis = 0
  7.         rest_raw = 0
  8.         for potenz in (10,100,1000,10000):
  9.             rest_raw = Zahl % potenz
  10.             rest = Zahl % potenz
  11.             while rest > 9:
  12.                 rest /= 10
  13.             zwischen_ergebnis += rest
  14.             Zahl -= rest_raw
  15.  
  16.         Code -= rest_raw
  17.         Code *= 10
  18.         Code += zwischen_ergebnis % 10
  19.         Zahl = Code
  20.        
  21.         Tag += 1
  22.         if Zahl == ur_code:
  23.             break
  24.     return Tag
  25.  
  26. if __name__ == '__main__':
  27.     code = 1986
  28.     tag = mathe(code)
  29.     print("Es vergehen %i Tage, bis sich der Code %i wiederholt!" % (tag, code))
Sirius3
User
Beiträge: 5414
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon Sirius3 » Donnerstag 2. Februar 2017, 16:33

@sebastian0202: bei der Länge der Funktion ist es schon sinnvoll, mehrere Funktionen zu schreiben; z.B. kann man das Bilden der Quersumme gut in eine eigene Funktion packen.

  1. from itertools import count
  2. def cross_sum(number, base=10):
  3.     result = 0
  4.     while number:
  5.         number, residual = divmod(number, base)
  6.         result += residual
  7.     return result
  8.  
  9. def calculate_series_length(code):
  10.     original_code = code
  11.     for cnt in count(1):
  12.         code = (code % 1000) * 10 + cross_sum(code) % 10
  13.         if original_code == code:
  14.             break
  15.     return cnt
sebastian0202
User
Beiträge: 110
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon sebastian0202 » Donnerstag 2. Februar 2017, 16:44

Habe gesehen, dass es Probleme geben kann sobald eine 0 in der Zahl vorkommt.
Muss die Zahl also erst erweitern bevor ich mit ihr rechne.
Dafür darf der Code jetzt beliebig lang sein.

Nachtrag: Die vorige Funktion hatte ja nur 24 Zeilen. Für mich war sie übersichtlich.
Ich konnte mich damit noch nicht anfreunden, für jedes mögliche Problem was sich auslagern lässt, auch auszulagern.
Damit hat man unzählige Funktionen und da verliere ich schnell den Überblick.

  1. def stellen(zahl):
  2.     anzahl = 1
  3.     while zahl > 9:
  4.         zahl /= 10
  5.         anzahl += 1
  6.     return anzahl
  7.  
  8. def code_erweitern(code, stellen):
  9.     zahl = 1
  10.     for i in range(stellen):
  11.         zahl *= 10
  12.     code += zahl
  13.     return code
  14.  
  15. def rest_potenz(anzahl_stellen, zahl):
  16.     zwischen_ergebnis = 0
  17.     rest = 0
  18.     potenz = 0.1
  19.     for i in range(anzahl_stellen):
  20.         rest = zahl % 10
  21.         zwischen_ergebnis += rest
  22.         zahl -= rest
  23.         zahl /= 10
  24.         potenz *= 10
  25.     return rest, zwischen_ergebnis, potenz
  26.  
  27. def stelle_verrutschen(zahl, rest, zwischen_ergebnis, potenz):
  28.     zahl -= (rest * potenz)
  29.     rest = zahl % potenz
  30.     zahl -= rest
  31.     zahl += rest*10
  32.     zahl += zwischen_ergebnis % 10
  33.     return zahl
  34.  
  35. def mathe(ur_code):
  36.     anzahl_stellen = stellen(ur_code)
  37.     Code = code_erweitern(ur_code, anzahl_stellen)
  38.     Zahl = Code
  39.  
  40.     Tag = 0
  41.     while True:
  42.         rest, zwischen_ergebnis, potenz = rest_potenz(anzahl_stellen, Zahl)
  43.         Code = stelle_verrutschen(Code, rest, zwischen_ergebnis, potenz)
  44.         Zahl = Code
  45.         Tag += 1
  46.         if Zahl-potenz*10 == ur_code:
  47.             break
  48.     return Tag
  49.  
  50. if __name__ == '__main__':
  51.     code = 1986
  52.     tag = mathe(code)
  53.     print("Es vergehen %i Tage, bis sich der Code %i wiederholt!" % (tag, code))
  54.  
Benutzeravatar
BlackJack
Moderator
Beiträge: 31402
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon BlackJack » Donnerstag 2. Februar 2017, 18:02

@sebastian0202: Die Aufteilung auf die Funktionen ist ja auch total komisch. Das sieht irgendwie so willkürlich aus und nicht so als wenn man wirklich sinnvoll Teilprobleme in Funktionen ausgelagert hätte. So etwas wie `quersumme()` was eine Zahl bekommt und eine Zahl zurück gibt. Und `ziffern_verschieben()` das den Code und eine einstellige Zahl bekommt und eine Zahl zurück gibt die um eine Zehnerstelle verschoben ohne die erste Ziffer und mit der neuen Ziffer zurück gibt, also beispielsweise `ziffern_verschieben(4711, 3)` → 7113.
“A lesson I've learned over and over is that computer programs live far longer than you expect. It pays to do 'em better at the beginning, 'cause you're likely to live with them quite a while.” — Cameron Laird in c.l.p
Benutzeravatar
BlackJack
Moderator
Beiträge: 31402
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon BlackJack » Freitag 3. Februar 2017, 23:43

Das ganze mit Zahlen in Assembler für DOS (129 Bytes .COM-Datei):
  1.     cpu 386
  2.     org 0x0100
  3.     [map all]
  4.  
  5.     start_code equ 1986
  6.  
  7. segment .code
  8.  
  9. ; `code` is stored in SI register.
  10. ; `sum` is stored in DI register.
  11.  
  12. start:
  13.     xor ax,ax           ; day := 0
  14.     mov [day],ax
  15.     mov si,start_code   ; code := start_code
  16.  
  17. day_loop:
  18.     xor ax,ax           ; sum := 0
  19.     mov di,ax
  20.  
  21.     mov ax,si           ; divide code value by 10 until it reaches 0
  22.     mov bx,10           ; summing the remainder in `sum`.
  23. sum_loop:
  24.     or ax,ax
  25.     jz sum_loop_exit
  26.     xor dx,dx
  27.     div bx
  28.     add di,dx
  29.     jmp sum_loop
  30. sum_loop_exit:
  31.    
  32.     mov ax,di           ; CX = last decimal digit of `sum`
  33.     xor dx,dx
  34.     div bx
  35.     mov cx,dx
  36.  
  37.     mov ax,si           ; multiply `code` by 10 and add the digit in CX.
  38.     mul bx
  39.     add ax,cx
  40.    
  41.     mov bx,10000        ; get rid of digits beyound the four of the code.
  42.     div bx
  43.     mov si,dx
  44.  
  45.     inc word [day]      ; INC(day)
  46.  
  47.     ; check if we reached the day with the same code we started with
  48.     cmp si,start_code
  49.     jne day_loop
  50.  
  51.     mov ax,[day]        ; print day and code.
  52.     call print_number
  53.  
  54.     mov ah,2
  55.     mov dl,' '
  56.     int 0x21
  57.  
  58.     mov ax,si
  59.     call print_number
  60.  
  61.     mov ah,2
  62.     mov dl,13
  63.     int 0x21
  64.  
  65.     mov ah,2
  66.     mov dl,10
  67.     int 0x21
  68.  
  69. exit:
  70.     mov ax,0x4c00      ; AL = exit code.
  71.     int 0x21
  72.  
  73. ;--------------------------------------------------------------------
  74. print_number:
  75.     xor cx,cx
  76.     mov bx,10
  77. digit_loop:
  78.     or ax,ax
  79.     jz digit_loop_exit
  80.     xor dx,dx
  81.     div bx
  82.     add dl,'0'
  83.     push dx
  84.     inc cx
  85.     jmp digit_loop
  86. digit_loop_exit:
  87.     or cx,cx
  88.     jnz not_zero_digits
  89.     push word '0'
  90.     inc cx
  91. not_zero_digits:
  92.  
  93. print_loop:
  94.     mov ah,2
  95.     pop dx
  96.     int 0x21
  97.     loop print_loop
  98.  
  99.     ret
  100.  
  101. ;--------------------------------------------------------------------
  102.  
  103. segment .bss
  104.  
  105. day:
  106.     resw 1
“A lesson I've learned over and over is that computer programs live far longer than you expect. It pays to do 'em better at the beginning, 'cause you're likely to live with them quite a while.” — Cameron Laird in c.l.p
bords0
User
Beiträge: 161
Registriert: Mittwoch 4. Juli 2007, 20:40

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon bords0 » Freitag 3. Februar 2017, 23:52

Oder kurz, knackig und hässlich:
  1. c = 1968
  2. d = c + c // 10 + c // 100 + c // 1000
  3. for i in range(1, 10000):
  4.     c, d = 10 * (c % 1000) + d % 10, d + d % 10 - c // 1000
  5.     if c == 1968:
  6.         break
  7. print(i)
Benutzeravatar
BlackJack
Moderator
Beiträge: 31402
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: AUFGABE: Jeden tag eine Änderung des Bankcodes...

Beitragvon BlackJack » Samstag 4. Februar 2017, 01:00

Die Aufteilung auf Funktionen die ein bisschen weniger unübersichtlich aussehen in CoffeeScript:
  1. #!/usr/bin/env coffee
  2. 'use strict'
  3.  
  4. crossSum = (code) ->
  5.   sum = 0
  6.   while code > 0
  7.     digit = code % 10
  8.     code = (code - digit) / 10
  9.     sum += digit
  10.   sum
  11.  
  12.  
  13. shiftCode = (code, digit) ->
  14.   code * 10 % 10000 + digit
  15.  
  16.  
  17. main = ->
  18.   startCode = 1986
  19.   day = 0
  20.   code = startCode
  21.   loop
  22.     code = shiftCode(code, crossSum(code) % 10)
  23.     day++
  24.     break if code is startCode
  25.   console.log(day, code)
  26.  
  27.  
  28. main() if require.main == module
“A lesson I've learned over and over is that computer programs live far longer than you expect. It pays to do 'em better at the beginning, 'cause you're likely to live with them quite a while.” — Cameron Laird in c.l.p

Zurück zu „Allgemeine Fragen“

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]