projecteuler problem1; Hab ein Problem

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
SeppvonderWeide
User
Beiträge: 3
Registriert: Mittwoch 29. Oktober 2008, 20:01
Wohnort: Wien

Hallo Leute, ich bin noch neu hier sowie auch im programmieren was ihr wohl unten bemerken werdet :). Ich hab Python in der Schule gelernt also lediglich Gymnasium-Niveau und da das schon einige Zeit her ist hab ich wieder ein paar Dinge verlernt, auch wenn es eigentlich nur wenig zu verlernen gab...
Da ich mein Wissen ein klein wenig auffrischen wollte, hab ich vor kurzem wieder begonnen. Ich hab hier im Forum den link http://projecteuler.net/index.php?section=problems&id=1 gefunden und mich daran versucht bis ich nach langem hin und her endlich dieses Script hinbekommen habe, bis zur Summe hab ichs relativ verstanden aber dann hab ich aus einem thread, hier im Forum, diese Befehle für die Summe genommen eingefügt und es eigentlich zum laufen gebracht.
Nun zum eigentlichen Problem, falls ihr die Aufgabe nicht kennt, hier wird verlangt alle vielfachen von 3 und 5 unter 1000 (in meinem Script unter der gewünschten Zahl) zu summieren.
Als Beispiel des Rätsels wird 10 angegeben mit der Lösung 3+5+6+9= 23
Wenn ich mein script laufen lasse funktioniert es bei 10 mit der Lösung 23,
wenn ich aber 1000 eingebe kommt 266333 als Lösung raus, was aber falsch sein dürfte da Project-Euler sagt es ist falsch. Da ich nicht zu 100% genau weiß was ich da fabriziert habe fällt es mir auch dementsprechend schwer den Fehler zu finden... Falls jemand weiß was ich ändern muss oder besser mir ein paar Tipps geben könnte, damit ich es evtl selbst herausfinden/lösen kann wäre ich dankbar

Code: Alles auswählen

from math import *
a = raw_input("Zahl:")
b = int(a)
c = 0
d = 0
su = [] 
summe_total = []
sub = [] 
summe_totalb = []
summe_x = []
while c < (b-3):
    c+=1*3
    su +=[c] 
    summe = sum(su)    
    summe_total += [summe]
    #print summe_total

while d < (b-5):
    d+=1*5
    sub +=[d] 
    summeb = sum(sub)    
    summe_totalb += [summeb]
    #print summe_totalb

summe_x += [summe+summeb]
print summe_x
ps: Ich weiß das ich bei der Variablenbennenung und sonstiger Strukturierung es eindeutig besser hinkriegen hätte können aber mir war es in erster linie wichtig es zum laufen zu bringen, verschönern kann ich es dann immer noch :)
MfG Sepp
.robert
User
Beiträge: 274
Registriert: Mittwoch 25. April 2007, 17:59

Ich will dir nicht den Spaß am Knobeln nehmen, deswegen gebe ich dir keine Lösung, sondern nur einen Hinweis auf deinen Fehler:

15, 30, 45, 60, ...
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo SeppvonderWeide!

Willkommen im Python-Forum!

Du könntest den Modulo-Operator (%) verwenden.

Code: Alles auswählen

>>> 1 % 3
1
>>> 2 % 3
2
>>> 3 % 3
0
>>> 4 % 3
1
>>> 5 % 3
2
>>> 6 % 3
0
>>> 1 % 3 == 0
False
>>> 6 % 3 == 0
True
>>>

Wie du hier in diesem Beispiel siehst, bekommst du immer dann 0 zurück, wenn sich der Wert restlos durch 3 teilen lässt.

Weiters kannst du die Funktion ``sum()`` verwenden, um die Werte aufzusummieren. Das math-Modul ist dafür nicht notwendig.

Die fertige Lösung spare ich mir, da du ja selber drauf kommen möchtest. :-) Wenn du es geschafft hast, kannst du ja nachsehen, wie ich es gelöst habe. Aber nur wenn du wirklich willst. --> hier

mfg
Gerold
:-)
Zuletzt geändert von gerold am Freitag 31. Oktober 2008, 17:28, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
SeppvonderWeide
User
Beiträge: 3
Registriert: Mittwoch 29. Oktober 2008, 20:01
Wohnort: Wien

Oh mann ich Dummkopf da werden ja dann die gemeinsamen vielfachen von 5 und 3 doppelt gerechnet :)

Danke .Robert für den raschen Hinweis, das ich da nich eher drauf gekommen bin^^, naja dann werd ich da wohl noch bisschen rechnen/denken müssen...

mfg Sepp

edit: Danke Gerold auch für deine Tipps aber bis ich das kapiere werd ich alt ich hoffe ich kriegs auch mit meiner Methode hin und dann probier ich deine Variante, sollte ich es hinkriegen post ich hier das fertige dann rein ansonsten frag ich einfach nochmal :) (Hab erst jetzt gesehen das du was kleingedrucktes beigefügt hast^^ (typisch edit funktionen^^) ich hoffe ich werd das nicht anschaun müssen vorerst

MfG, die zweite, Sepp
BlackJack

Und gerold's Lösung in funktional:

Code: Alles auswählen

N = 1000
DS = [3, 5]
print sum(n for n in xrange(1, N) if any(n % d == 0 for d in DS))
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

gerold hat geschrieben: Die fertige Lösung spare ich mir, da du ja selber drauf kommen möchtest. :-) Wenn du es geschafft hast, kannst du ja nachsehen, wie ich es gelöst habe. Aber nur wenn du wirklich willst. --> hier
Und wenns nicht 1000 sondern zB 1234567891347583589347589389457893758930579305723456789123456789
sind ?

;-)

Code: Alles auswählen

def esum(n=10):
    n3 = long((n-1)/3.)
    n5 = long((n-1)/5.)
    n15 = long((n-1)/15.)

    sum3 = 3*n3*(n3+1)/2
    sum5 = 5*n5*(n5+1)/2
    sum15= 15*n15*(n15+1)/2
    
    print "sum: ",sum3+sum5-sum15
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

``long`` zu nehmen macht keinen Sinn mehr, da die beiden aus Python-Programmierer-Sicht nun gleich sind. ``int(sys.maxint+1)`` gibt auch einen ``long``, aber das ist unwichtig.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

Leonidas hat geschrieben:``long`` zu nehmen macht keinen Sinn mehr, da die beiden aus Python-Programmierer-Sicht nun gleich sind. ``int(sys.maxint+1)`` gibt auch einen ``long``, aber das ist unwichtig.
Jup, da hast du Recht, nicht notwendig :-)
Zum einen Gewohnheit, zumal man auch noch in anderen Sprachen unterwegs ist und rein mnemotechnisch, damit man weiss, dass auch bei grossen Werten die "Kosten" noch annehmbar sind ;-)
BlackJack

@Qubit: Also wenn Du schon mit so grossen Zahlen operierst, dann schau doch bitte nicht nur auf die Laufzeit, sondern auch auf die Korrektheit. Da geht bei Fliesskommazahlen einiges verloren. Hier eine genaue Lösung:

Code: Alles auswählen

def f(n, d):
    tmp = (n - 1) // d
    return (tmp**2 + tmp) * d // 2

def g(n):
    d_1 = 3
    d_2 = 5
    return f(n, d_1) + f(n, d_2) - f(n, d_1 * d_2)
Bei n=1234567891347583589347589389457893758930579305723456789123456789 liegt Dein `esum()` soweit daneben: 9167957429671051617259533553497145759516517847562799028997828616043122209889019469197777264707377959169958921

:-)
Qubit
User
Beiträge: 128
Registriert: Dienstag 7. Oktober 2008, 09:07

BlackJack hat geschrieben:@Qubit: Also wenn Du schon mit so grossen Zahlen operierst, dann schau doch bitte nicht nur auf die Laufzeit, sondern auch auf die Korrektheit. Da geht bei Fliesskommazahlen einiges verloren.
Ups, wer hat die Punkte bei n3,n5,n15 gemacht :lol:
Punkte weg, dann sollte es stimmen ;-)
SeppvonderWeide
User
Beiträge: 3
Registriert: Mittwoch 29. Oktober 2008, 20:01
Wohnort: Wien

Also Leute ein GROßES DANKE für die vielen inputs ich werd hoffentlich nicht so schnell aufgeben nur weil ich bei 99,9% eurer Aussagen/anderen Threads kein Wort verstehe ;).

Endlich hab ich es!!!!(Hab jetzt 5 Tage oder so dran rumgespielt...):

Code: Alles auswählen

a = raw_input("Zahl:")
b = int(a)
c = 0
d = 0
e = 0
su = []
sub = []
suc = [] 
summe_total = []
summe_totalb = []
summe_totalc = []
summe_x = []
while c < (b-3):
    c+=1*3
    su +=[c] 
    summe = sum(su)    
    summe_total += [summe]
    #print summe_total

while d < (b-5):
    d+=1*5
    sub +=[d] 
    summeb = sum(sub)    
    summe_totalb += [summeb]
    #print summe_totalb

while e < (b-15):
    e+=15
    suc +=[e]
    summec = sum(suc)    
    summe_totalc += [summec]
    #print summe_totalc

if b < 15:
    summe_x += [summe+summeb]
    print summe_x
else:    
    summe_x += [summe+summeb-summec]
    print summe_x
Eigentlich wollte ich euch ja wieder um Hilfe bitten da mein Programm unter dem Wert 16 immer falsche Werte hatte also es wurde trotzdem ein 15 abgezogen obwohl es gar nich so sein hätte sollen, is ja klar wo kein 15 da kein 15 weniger...
Da hatte ich auch noch nicht den "genialen" Einfall von:

Code: Alles auswählen

if b < 15:
    summe_x += [summe+summeb]
    print summe_x
else:    
    summe_x += [summe+summeb-summec]
    print summe_x
Ist mir gekommen wie ich euch berichten wollte was ich alles probiert habe und trotzdem immer wieder der selbe Fehler aufgetreten ist.
also statt

Code: Alles auswählen

while e < (b-15):
Die verschiedensten geratenen Variationen in Form von while b>e, oder if,etc...
Und dann bin ich auf diese if/else Anweisung gekommen^^

Als nächstes Versuche ich mich an der Module-Operator Methode, evtl ja sogar bei der nächsten Aufgabe(sofern es dort benötigt wird muss mal anschaun), bei der ich euch vermutlich wieder belästigen werde^^, da ich langsam gemerkt habe dass die meisten damit arbeiten...
Ich hab noch ein paar fragen:

Was ist der Unterschied von i in range() und i in xrange()?
Was bedeutet dieses long() (etwa so etwas ähnliches wie += oder range? ) und warum soll man es nicht mehr benutzen? Ich nehme aber an auf meinem Level ist das eh noch vollkommen egal.
edit: hätt fast die wichtigste Frage vergessen:
Wie lautet der Befehl dafür dass, das Eingabeaufforderungsfenster in Windows offen bleibt wenn das Programm fertig ist, da es jetzt immer sofort zugeht und man nichts ablesen könnte?

Ich weiß ich sollte lieber die Help Funktion in der Idle (ja schon gelesen Idle ist schlecht ich sollt was anderes benutzen^^ aber bevor ich mich da abplag mit addons runterladen und versuchen zu installieren belass ich es mal bei dem ich nehme an für Anfänger ist das eh noch irrelevant zumal ich zufrieden bin mit den Funktionen) benutzen oder FAQs aber bei den meisten FAQs wird schon vorausgesetzt das man wenigstens bisschen Ahnung hat vom programmieren und ich steh dann ziemlich staunend aber nichts checkend da.

Da treten noch weitere Fragen auf, kleine Anfängerfragen eher im Thread fragen oder per pn an Leute mit Ahnung? Vermutlich eher Thread da die meistens genug um die Ohren haben, aber ich frag halt mal.
Oder besser welche deutsch-sprachigen IRC channels könnt ihr empfehlen wo man sich an Leute wenden kann wenn man lieber Echtzeithilfe beanspruchen will.(Wobei mein Thread nur 11 min. warten musste bis zur ersten Hilfe was echt grandios war)

So das wars vorerst^^

MfG Sepp
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

SeppvonderWeide hat geschrieben:Oder besser welche deutsch-sprachigen IRC channels könnt ihr empfehlen wo man sich an Leute wenden kann wenn man lieber Echtzeithilfe beanspruchen will.(Wobei mein Thread nur 11 min. warten musste bis zur ersten Hilfe was echt grandios war)
irc.freenode.net #python.de

Allerdings solltest du nicht erwarten dass dir jemand Grundlagen erklärt die im Tutorial stehen.
BlackJack

@SeppvonderWeide: Neben Modulo solltest Du Dich auch mal mit Funktionen beschäftigen. Die drei ``while``-Schleifen machen ja fast das gleiche, nur halt mit anderen Werten, das ist also ein guter Kandidat um eine Funktion daraus zu machen.

In der Bedingung der ``while``-Schleife solltest Du den jeweiligen Wert (3, 5, 15) nicht abziehen müssen. Die Zählvariable sollte mit dem Wert beginnen und nicht mit 0, dann würde die letzte Schleife bei ``b < 15`` zum Beispiel gar nicht durchlaufen werden, und Du könntest Dir die Sonderbehandlung am Ende sparen.

Anhängen eines einzelnen Elementes an eine Liste wird in der Regel mit der `append()`-Methode gemacht und nicht so umständlich über ``+=`` und eine Liste mit einem Element.

Code: Alles auswählen

In [177]: a = list()

In [178]: a += [42]

In [179]: a
Out[179]: [42]

In [180]: a.append(23)

In [181]: a
Out[181]: [42, 23]
Das bilden der Summe in den Schleifen mit `sum()` verbrät unheimlich viel unnötige Rechenzeit, weil Du immer wieder eine Liste aufsummierst, die noch gar nicht komplett ist, und bis auf das Mal beim letzten Schleifendurchlauf alle Summenergebnisse sowieso verworfen werden.

Der Unterschied zwischen `range()` und `xrange()` ist, das ersteres einfach eine Liste mit Zahlen erzeugt, und letzteres eine "Sequenz", d.h. ein Objekt über das man in Schleifen iterieren kann und auf das man mit ``obj[index]`` auf einzelne "Elemente" zugreifen kann. Eine Liste braucht um so mehr Speicherplatz, je mehr Zahlen sie enthält, während das "xrange"-Objekt konstant viel Speicher benötigt, weil die Elemente erst beim Zugriff berechnet werden.

Deine ``while``-Schleifen kann man mit `range()` bzw. `xrange()` weg kürzen, weil man bei den Funktionen auch eine Schrittweite angeben kann. Beispiel für n = 31:

Code: Alles auswählen

In [193]: n = 31

In [194]: a = range(3, n, 3)

In [195]: a  # Vielfache von 3.
Out[195]: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

In [196]: b = range(5, n, 5)

In [197]: b  # Vielfache von 5.
Out[197]: [5, 10, 15, 20, 25, 30]

In [198]: c = range(15, n, 15)

In [199]: c  # Vielfache von 15.
Out[199]: [15, 30]

In [200]: sum(a) + sum(b) - sum(c)
Out[200]: 225
Antworten