<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>muvik-multigrid &#187; Python</title>
	<atom:link href="http://www.muvik.de/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.muvik.de</link>
	<description>open source - engineering - programming</description>
	<lastBuildDate>Wed, 28 Jul 2010 07:56:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Projecteuler: Lösung zu Problem 10</title>
		<link>http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/</link>
		<comments>http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 07:42:12 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Eratosthenes]]></category>
		<category><![CDATA[Primzahlen]]></category>
		<category><![CDATA[Projecteuler]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=1384</guid>
		<description><![CDATA[Primzahlen sind das Thema des Projecteuler-Problems Nummer 10. Nach dem 3. und 7. Problem befasst sich nun auch das 10. Problem mit den beliebten Zahlen, die durch beinahe nichts teilbar sind. In diesem Artikel wird, wie gewohnt, das Problem eingegrenzt und mit Python gelöst. Problemvorstellung Wer die Probleme 3 und 7 bereits gelöst hat, wird [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Projecteuler: Lösungen mit Python und C++" src="http://muvik.de/categorie_images/projecteuler_serie_start.gif" title="Projecteuler: Lösungen mit Python und C++" width="443" height="98" />
<p class="preview">Primzahlen sind das Thema des Projecteuler-Problems Nummer 10. Nach dem 3. und 7. Problem befasst sich nun auch das 10. Problem mit den beliebten Zahlen, die durch beinahe nichts teilbar sind. In diesem Artikel wird, wie gewohnt, das Problem eingegrenzt und mit Python gelöst.</p>
<p><span id="more-1384"></span></p>
<h3>Problemvorstellung</h3>
<p>Wer die Probleme <a href="http://www.muvik.de/2010/04/03/projecteuler-loesung-zu-problem-3/">3</a> und <a href="http://http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/">7</a> bereits gelöst hat, wird mit dem <a href="http://projecteuler.net/index.php?section=problems&#038;id=10">10. Projecteuler-Problem</a> keine Mühe haben. Wieder geht es um Primzahlen und wieder kann der Sieb des Eratosthenes verwendet werden, um die Lösung zu finden.</p>
<p>Ins Deutsche übersetzt lautet die Aufgabenstellung: </p>
<p><strong>Finde die Summe aller Primzahlen, die kleiner als zwei Millionen sind.</strong></p>
<p>Mit dem Hintergrundwissen aus den bereits gelösten Problemen, bräuchte ich eigentlich keinen zusätzlichen Artikel mehr zu verfassen. Es sind bereits alle Mittel, die hierzu benötigt werden, bereits vorgestellt und mit Erfolg verwendet worden.</p>
<p>Aus diesem Grund lässt es sich nicht wirklich nachvollziehen, warum zum heutigen Zeitpunkt lediglich 47699 der insgesamt 114874 Projecteuler-Teilnehmer eine richtige Lösung zu diesem Problem einreichen konnten. Wahrscheinlich sind sie zeitlich verhindert gewesen <img src='http://www.muvik.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> !</p>
<h3>Problemeingrenzung</h3>
<p>Obwohl alle Tipps und Tricks zur vollständigen und erfolgreichen Lösung des Problems bereits im Rahmen dieser Artikelserie genannt und beschrieben wurden, möchte ich einige Tatsachen dennoch der Vollständigkeit wegen wiederholen.</p>
<p>In erster Linie ist das wichtiges Werkzeug, welches bei bisher allen Problemen mit Primzahlen bei mir zum Einsatz kam und es auch diesmal tut <a href="http://de.wikipedia.org/wiki/Sieb_des_Eratosthenes">das Siebes von Eratosthenes</a>. Hierbei handelt es sich um eine Methode, mit welcher man alle Primzahlen bis zu einer gegebenen Zahl <code>N</code> relativ effizient finden kann.</p>
<h4>Das Sieb des Eratosthenes</h4>
<p>Die Vorgehensweise beim <em>Sieben</em> ist recht simpel und schnell erklärt, dabei geht man am besten grafisch vor: Um alle Zahlen bis <code>N</code> mit dem Sieb zu finden, schreibt man die Zahlen, bildlich gesprochen, alle auf. Dann fängt man mit der ersten bekannten Primzahl, also der 2, an und streicht alle Vielfachen dieser Zahl wieder aus der Liste. Hat man das erledigt, so geht es mit der nächsten <strong>nicht</strong> gestrichenen Zahl weiter, die nun eine Primzahl sein sollte. </p>
<p>Wenn nichts schief gegangen ist, so bleiben am Ende alle Primzahlen bis <code>N</code> übrig.</p>
<p>Um einige Rechenoperationen, Vergleiche und Abfragen zu sparen, kann die Methode etwas verfeinert werden. Zum einen ist es bekannt, dass es keine geraden Primzahlen gibt. Also können diese sofort aus der Betrachtung ausgeschlossen werden. Zum anderen ist während des Siebens ebenfalls bekannt, dass alle Vielfachen der Primzahl 5 bereits gestrichen sind, wenn die Primzahl 11 an der Reihe ist. Das gilt auch für alle Primzahlen zwischen 5 und 11. Somit kann die nächste zu streichende Vielfache frühstens 11*11 sein.</p>
<p>Aus der zuletzt angestellten Betrachtung folgt sogleich, dass die größte zu prüfende Primzahl maximal die Wurzel aus N sein kann.<br />
<code class="bash"> x*x <= N</code></p>
<p>Werden die Verfeinerungen im Code angewendet, erhält man einen relativ effizienten Sieb, der mit den vorgegebenen zwei Millionen mühelos fertig werden sollte.</p>
<h3>Problemlösung</h3>
<p>Wie versprochen, brauchen wir zur Lösung des zehnten Projecteuler-Problem nur den Sieb des Eratosthenes und eine Summe aller gefundenen Primzahlen, das war es schon!<br />
Im folgenden die kompakte Lösung:</p>
<pre class="brush:python">import time as t
import numpy as np

def eratosthenes_vect(N):
    primes = np.arange(3,N+1,2)  # only uneven figures
    primes = np.insert(primes,0,2,0) # ... and two

    nUneven = np.size(primes) - 1.0

    for i in np.arange(3,np.ceil(np.sqrt(N))+2,2):
        primes[(i*i+1)/2-1:nUneven+1.0:i] = 0;

    return np.trim_zeros(np.sort(primes))

def solver(N):
    Primes = eratosthenes_vect(N)

    erg = 0;

    for i in Primes:
        erg = erg + i

    return erg

N = 2000000

t0 = t.clock()
Prim = solver(N)
tn = t.clock() - t0

print("Benoetigte Zeit: %15.6f" %tn)
print("Gefundene Summe: %i" %Prim)</pre>
<p>Die Ausgabe des Codes zeigt die benötigt Zeit und die gesuchte Summe:<br />
<code class="bash">Benoetigte Zeit:        5.940000<br />
Gefundene Summe: 142913828922<br />
</code></p>
<p>Sechs Sekunden Rechenzeit für alle Primzahlen, die kleiner als zwei Millionen sind, und die Summe daraus ist, denke ich, annehmbar.</p>
<h3>Schlusswort</h3>
<p>Nach einer etwas langwierigen Zeit, während der nur wenige Artikel in der Serie "Lösungen zu Projecteuler-Problemen mit Python" erschienen sind, gleich zwei Lösungen nach einander. Das ist schon ein Wort und sollte eigentlich mit einem dritten Artikel zum 11. Problem gefeiert werden. Vielleicht lasse ich mich dazu hinreißen <img src='http://www.muvik.de/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> !</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/">Permalink</a> |
<a href="http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/&title=Projecteuler: Lösung zu Problem 10">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/&title=Projecteuler: Lösung zu Problem 10">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/&title=Projecteuler: Lösung zu Problem 10">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/eratosthenes/" rel="tag">Eratosthenes</a>, <a href="http://www.muvik.de/tag/primzahlen/" rel="tag">Primzahlen</a>, <a href="http://www.muvik.de/tag/projecteuler/" rel="tag">Projecteuler</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/07/27/projecteuler-loesung-zu-problem-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projecteuler: Lösung zu Problem 9</title>
		<link>http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/</link>
		<comments>http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 07:48:30 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Projecteuler]]></category>
		<category><![CDATA[Pythagoras]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=1351</guid>
		<description><![CDATA[Jetzt geht es beinahe schon Schlag auf Schlag: nach der Vorstellung der Lösung des achten folgt sofort die Lösung des neunten Problems. Das neunte Projecteuler-Problem beschäftigt sich mit dem Satz von Pythagoras und der Bildung von sogenannten Pythagoras-Tripeln. Wie gewohnt, erfolgt auch diesmal die Lösung mit Python. Problemvorstellung Das neunte Projecteuler-Problem dreht sich um den [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Projecteuler: Lösungen mit Python und C++" src="http://muvik.de/categorie_images/projecteuler_serie_start.gif" title="Projecteuler: Lösungen mit Python und C++" width="443" height="98" />
<p class="preview">Jetzt geht es beinahe schon Schlag auf Schlag: nach der Vorstellung der Lösung des achten folgt sofort die Lösung des neunten Problems. Das neunte Projecteuler-Problem beschäftigt sich mit dem Satz von Pythagoras und der Bildung von sogenannten Pythagoras-Tripeln. Wie gewohnt, erfolgt auch diesmal die Lösung mit Python.</p>
<p><span id="more-1351"></span></p>
<h3>Problemvorstellung</h3>
<p>Das <a href="http://projecteuler.net/index.php?section=problems&#038;id=9">neunte Projecteuler-Problem</a> dreht sich um den <a href="http://de.wikipedia.org/wiki/Satz_des_Pythagoras">Satz von Pythagoras</a>, welcher eine Aussage über die Seitenlängen eines rechtwinkligen Dreiecks liefert. Wie die meisten Schüler mehr oder weniger leidvoll erfahren haben, ergibt sich aus der Addition der Quadrate der zwei kürzeren Seiten, der Katheten, eines rechtwinkligen Dreiecks genau das Quadrat der längsten Seite, der Hypotenuse. Dass der Satz des Pythagoras auch heute noch bei Schülern sehr gefragt  ist, lässt sich auf <a href="http://www.gutefrage.net/frage/mathe-pythagoras-pendel-hilfe">gutefrage.net</a> nachlesen.</p>
<p>Ist nun die Länge der zwei Katheten und der Hypotenuse eines Dreiecks durch natürliche Zahlen (ganze Zahlen) beschreibbar, so bezeichnet man die drei Zahlen als pythagoreisches Tripel.</p>
<p>In dem neunten Projecteuler-Problem geht es darum, ein bestimmtes pythagoreisches Tripel zu finden. Dieses Tripel soll folgende Bedingungen erfüllen:</p>
<ol>
<li><code>a + b + c = 1000</code>,</li>
<li><code>a < b < c </code> und natürlich</li>
<li><code>a^2 + b^2 = c^2</code></li>
</ol>
<p>So viel sei zur Aufgabenstellung angemerkt.</p>
<p>Obwohl der Satz des Pythagoras eine elementare Unterrichtseinheit in der Schule darstellt, haben zum heutigen Zeitpunkt trotzdem nur 52711 der insgesamt 114860 Projecteuler-Teilnehmer die Aufgabe mit Erfolg gelöst und das richtige Ergebnis eingegeben.</p>
<p>Als Ergebnis werden übrigens nicht die drei Zahlen <code>a, b, c</code> erwartet, sondern ihr Produkt: <code>a * b * c</code>.</p>
<h3>Problemeingrenzung</h3>
<p>Geht man ganz unbedarft an das Problem heran, kommt man schnell auf die Lösung, einfach alle Zahlen für a und b einzusetzen, die die Bedingung <code>a < b</code> erfüllen. Dann muss die Hypotenuse errechnet werden. Was noch bleibt, ist zu testen, ob die Summe der drei Zahlen auch wirklich 1000 ergibt.</p>
<p>Damit hätte man zwei <code>for</code>-Schleifen und eine <code>if</code>-Abfrage und natürlich die Lösung des Problems. Eine elegante Lösung ist jedoch etwas anderes!</p>
<p>Ebenso unbedarft kann das Problem nur ein wenig genauer angeschaut werden. Ein Quäntchen Glück vorausgesetzt, erkennt man dabei, dass man bei drei Unbekannten genau zwei Gleichungen gegeben hat. Dies kann ausgenutzt werden, um die Lösung etwas komplizierter erscheinen zu lassen.</p>
<p>Dabei lässt sich zum Beispiel die erste Bedingung <code>a + b + c = 1000</code> nach <code>c</code> auflösen und in die dritte einsetzen:<br />
<code class="bash">a + b + c = N<br />
c = N - a - b<br />
a^2 + b^2 - N^2 - 2*N*(a+b) - (a+b)^2 = 0</code></p>
<p>Die letzte Gleichung kann nun nach zum Beispiel <code>b</code> aufgelöst werden:<br />
<code class="bash">b = (0.5*N^2 - N*a)/(N - a)</code></p>
<p>Das Auflösen nach <code>b</code> lässt sich über die zweite Bedingung motivieren. Wenn wir nun Zahlen von 1 ausgehend für a einsetzen, dann wird die zweite Bedingung immer erfüllt bleiben.</p>
<p>Damit müssen wir nur noch die Zahlen für a vorgeben und testen, ob der Quotient eine natürliche Zahl ergibt.</p>
<p>Weiter wollen wir das Problem nicht mehr mit mathematischem Hintergrund aufblasen und gehen zur Lösung mit Python über.</p>
<h3>Problemlösung</h3>
<p>Abgesehen davon, dass dieses Problem eigentlich keiner Implementierung in einer Programmiersprache bedarf, wenn die Informationen zur <a href="http://de.wikipedia.org/wiki/Pythagoreisches_Tripel">Erzeugung eines pythagoreischen Tripels</a> ausgenutzt werden, ist es wohl eines der kürzesten Lösungen, die ich im Rahmen dieser Serie bisher vorgestellt habe.</p>
<pre class="brush:python">def search(a,N):
    found = 0

    while (found == False):
        for i in a:
            num = 0.5*N*N - N * i
            denom = N - i
            if (num%denom == 0.0):
                found = 1
                result = np.array([i,num/denom])
    return result

N = 1000.0

aa = np.arange(int(N)/3)

erg = search(aa,N)

a = erg[0]
b = erg[1]
c = N-a-b

print(a,b,c,a*b*c)</pre>
<p>Innerhalb dieser Zeilen habe ich die wenigen Gedanken aus der Problemeingrenzung verarbeitet. Der aufmerksame Leser wird gemerkt haben, dass noch eine zusätzliche Vereinfachung im Code berücksichtigt wurde.</p>
<p>Aufgrund der gegebenen Bedingungen wurde für <code>a</code> ein etwas kleinerer Suchbereich von maximal bis 300 eingestellt. Gehen wir von einem Extremfall aus:<br />
<code class="bash">a = 300<br />
b = 301<br />
a^2 + b^2 = c^2 = 180601<br />
=> c = 424.972<br />
</code></p>
<p>Prüfen wir die erste Bedingung, so finden wir, dass die Summe bereits ca. 1026 beträgt. Das ist schon zu viel.</p>
<p>Lässt man sich nun das Ergebnis berechnen, so erhält man folgende Ausgabe:<br />
<code class="bash">(200.0, 375.0, 425.0, 31875000.0)</code></p>
<p>Damit wäre die gesuchte Zahl: <code>31875000</code>.</p>
<h3>Schlusswort</h3>
<p>Ich gebe zu, dass der Lösungsvorschlag nicht der Weisheit letzter Schluss ist, doch für dieses Problem funktioniert er gut und zuverlässig. Die Grenzen, die Projecteuler vorgibt, werden nicht annähernd erreicht.</p>
<p>Natürlich wäre ich daher besonders froh, den einen oder anderen Lösungsvorschlag in den Kommentaren zu sehen <img src='http://www.muvik.de/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/">Permalink</a> |
<a href="http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/&title=Projecteuler: Lösung zu Problem 9">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/&title=Projecteuler: Lösung zu Problem 9">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/&title=Projecteuler: Lösung zu Problem 9">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/projecteuler/" rel="tag">Projecteuler</a>, <a href="http://www.muvik.de/tag/pythagoras/" rel="tag">Pythagoras</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/07/26/projecteuler-loesung-zu-problem-9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projecteuler: Lösung zu Problem 8</title>
		<link>http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/</link>
		<comments>http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 07:41:04 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Projecteuler]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=1291</guid>
		<description><![CDATA[Und weiter geht es in der Lösungen zu Projecteuler Problemen mit Python Serie. Heute steht das achte Problem auf dem Plan. Dieses etwas andere Problem als die bisherigen wird, wie gewohnt, erläutert, die Herausforderung hierbei werden eingegrenzt und die Lösung mit Python nach bestem Wissen und Gewissen herausgefunden. Problemvorstellung Die Aufgabenstellung des achten Problems ist, [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Projecteuler: Lösungen mit Python und C++" src="http://muvik.de/categorie_images/projecteuler_serie_start.gif" title="Projecteuler: Lösungen mit Python und C++" width="443" height="98" />
<p class="preview">Und weiter geht es in der Lösungen zu Projecteuler Problemen mit Python Serie. Heute steht das achte Problem auf dem Plan. Dieses etwas andere Problem als die bisherigen wird, wie gewohnt, erläutert, die Herausforderung hierbei werden eingegrenzt und die Lösung mit Python nach bestem Wissen und Gewissen herausgefunden.</p>
<p><span id="more-1291"></span></p>
<h3>Problemvorstellung</h3>
<p>Die <a href="http://projecteuler.net">Aufgabenstellung des achten Problems</a> ist, wie bereits beim siebten, sehr kurz geraten. Und trotzdem bekommt der unvorbereitete Besucher der Projekteuler-Seite etwas das Grausen, wenn er die Aufgabenstellung sieht. Neben der textlichen Anweisung, was zu tun ist, wird nämlich das Untersuchungsobjekt gleich mitgeliefert.</p>
<p>Aber nur der Reihe nach: zuerst die Aufgabenstellung ins Deutsche übersetzten:</p>
<p><strong>Finde das größte Produkt von fünf aufeinander folgenden Ziffern innerhalb einer Zahl mit 1000-Stellen.</strong></p>
<p>Nach der Problembeschreibung folgt das Untersuchungsobjekt:<br />
<code class="bash">73167176531330624919225119674426574742355349194934<br />
96983520312774506326239578318016984801869478851843<br />
85861560789112949495459501737958331952853208805511<br />
12540698747158523863050715693290963295227443043557<br />
66896648950445244523161731856403098711121722383113<br />
62229893423380308135336276614282806444486645238749<br />
30358907296290491560440772390713810515859307960866<br />
70172427121883998797908792274921901699720888093776<br />
65727333001053367881220235421809751254540594752243<br />
52584907711670556013604839586446706324415722155397<br />
53697817977846174064955149290862569321978468622482<br />
83972241375657056057490261407972968652414535100474<br />
82166370484403199890008895243450658541227588666881<br />
16427171479924442928230863465674813919123162824586<br />
17866458359124566529476545682848912883142607690042<br />
24219022671055626321111109370544217506941658960408<br />
07198403850962455444362981230987879927244284909188<br />
84580156166097919133875499200524063689912560717606<br />
05886116467109405077541002256983155200055935729725<br />
71636269561882670428252483600823257530420752963450</code></p>
<p>Zum heutigen Zeitpunkt haben sich genau 52538 mutige Projecteuler-Teilnehmer an die Aufgabe mit erfolgreichem Ausgang getraut. Das entspricht grob der Hälfte der insgesamt 115013 registrierten Leidensgenossen.</p>
<h3>Problemeingrenzung</h3>
<p>Unbeeindruckt von der Wucht großer Zahlen machen wir uns an die Problemanalyse und -eingrenzung heran.</p>
<p>Die erste Idee, welche sich beinahe sofort in die Gedanken einmischt, ist die straight-forward-Methode: Man nehme die ersten fünf Ziffern, multipliziere sie und vergleiche sie mit dem Produkt der Ziffern 2-6. So läuft man durch das ganze Feld, bis man am Ende angekommen ist. Das ist eine sehr simple Methode, die todsicher zum richtigen Ergebnis führt.</p>
<p>Doch so einfach möchten wir uns das ganze bloß nicht machen. Nach dem Motto &#8220;<em>Warum einfach, wenn es auch kompliziert geht?</em>&#8221; überdenken wir die offensichtlichen Nachteile der simplen, ersten Idee:</p>
<ol>
<li>In erster Linie wäre die Aufgabe so viel zu einfach. Der Reiz des Unmöglichen geht verloren!</li>
<li>In zweiter Linie sind wir sparsame Menschen und sehen sofort, dass bei der trivialen Lösung sehr oft multipliziert wird. Genauer betrachtet, stellen wir fest, dass in einer Reihe wie <code>(2 3 4 5 0 5 5 2 3)</code> genau 20 mal eine Multiplikation durchgeführt wird, ohne dass ein Produkt größer als 0 herauskommt.</li>
</ol>
<p>Ok, das sind uns Nachteile genug, um die Lösung nochmal zu überdenken.</p>
<p>Schauen wir uns einen Ausschnitt aus der ersten Ziffernreihe an und veranschaulichen uns, wie die Produkte gebildet werden:</p>
<p><code class="bash">624919225119674426574742355349194934<br />
62491<br />
_24919<br />
__49192<br />
___91922<br />
...</code></p>
<p>Was erkennen wir daraus?</p>
<ol>
<li>Zuerst muss ein reguläres Produkt aus fünf Ziffern gebildet werden.</li>
<li>Das nachfolgende Produkt besteht zu einem Großteil aus den Ziffern seines Vorgängers. Lediglich die erste Ziffer entfällt und eine neue kommt hinzu.</li>
</ol>
<p>Diese Erkenntnisse können wir uns nun zu Nutze machen, indem wir vom Vorgänger stets die erste Zahl dividieren und die nächste multiplizieren! Dadurch haben wir die Anzahl an Rechenoperationen halbiert.</p>
<p>Da der neue Vorschlag nun neben der Multiplikation auch eine Division aufweist, müssen wir zusätzliche Vorsicht walten lassen, denn durch Null teilen ist verboten.</p>
<p>Nach dem Motto &#8220;<em>Vorbeugen ist besser als Bekämpfen</em>&#8221; sieht jeder ein, dass das Problem mit der Division durch Null nicht auftreten kann, wenn keine Vorgänger null sind, also kein Quintett eine Null enthält. Das realisieren wir folgendermaßen:</p>
<ol>
<li>Solange keine Null auftritt, die zur Bildung eines neuen Produkts nötig wäre, kann der bisher beschriebene Algorithmus durchgeführt werden.</li>
<li>Sobald eine Null auftritt, wird die Bildung des Quintetts abgebrochen. Danach wird versucht, ein neues Quintett aus den fünf Ziffern nach der Null zu bilden. Sollte hierbei wieder eine Null vorkommen, so wird der Vorgang wieder abgebrochen und ein neues Quintett mit den Ziffern nach dieser zweiten Null gebildet.</li>
</ol>
<p>Was haben wir damit erreicht? In erster Linie teilen wir nie wieder durch Null und in zweiter Linie werden kein Quintett mit einer Null gebildet und somit diese unnötigen Multiplikationen eingespart.</p>
<p>Damit sind wir erst einmal zufrieden. Wie das in Python-Code aussieht, steht im folgenden Abschnitt.</p>
<h3>Problemlösung</h3>
<p>Neben den rein mathematischen Schwierigkeiten bei dem 8.Problem, treffen wir noch auf ein rein programmiertechnisches Problem, nämlich dem Import der gegebenen Zahl. Ich habe mich dafür entschieden, die Zahl von der Projecteuler-Webseite in eine einzelne Datei (<code>data.dat</code>) zu kopieren und im Python-Programm nur die Datei zu importieren. Dabei bietet es sich an, die Zeilenumbrüche zu ignorieren und die ganze Zahl in einem eindimensionalen Numpy-Array zu speichern.</p>
<p>Der langen Rede kurzer Sinn, heute mal am Stück:</p>
<pre class="brush:python">import numpy as np
import time as t

fileO =  open('data.dat','r')
peData = fileO.read()

def create_long_array(data):
    fdata = np.array([])

    print("Following data will be red:")
    print(data+"\n")

    for lines in data:
        for item in lines:
            if (item != "\n"):
                fdata = np.append(fdata,float(item))
    return fdata

def search_greatest_product(data,N):
    Ndata = len(data)
    print("%i values will be checked!" %Ndata)
    print("Product interval: %i\n" %N)

    greatest = 1
    for i in range(0,N):
        greatest = greatest * data[i]

    greater = greatest

    i = N
    while (i <= Ndata-1):

        factor = data[i]
        if (factor == 0):
            j = 1
            k = i
            greater = 1

            while ((j <= N) &#038; (k<=Ndata-N)):
                k = i + j
                factor = data[k]
                if (factor == 0):
                    j = 1
                    i = k
                    greater = 1
                else:
                    greater = greater * data[k]
                    j = j + 1

            i = i+j-1

        else:
            greater = greater / data[i-N] * data[i]

        if (greater > greatest):
            print("Found greater product: %i - %i" %(greatest, greater))
            greatest = greater

        i = i + 1

    return greatest

fdata = create_long_array(peData)

t0 = t.time()
greatest = search_greatest_product(fdata,5)
tn = t.time()

print("\nFound solution: %i in %.15f seconds!" %(greatest,tn-t0))</pre>
</p>
<p>Wie elegant die Realisierung des Lösungsvorschlags ist, kann ich als Anfänger nicht wirklich beurteilen. Das Gute an dem gesamten Konzept ist auf jede Fall, dass beliebige Zahlen eingegeben werden können. Es wird immer das größte Produkt der N aufeinander folgenden Zahlen gefunden.</p>
<h3>Lösungsanalyse</h3>
<p>Wird das vorgeschlagene Programm auf das 8.Projecteuler-Problem losgelassen, so liefert es folgende Ausgabe in der Konsole:</p>
<p><code class="bash">Following data will be red:<br />
73167176531330624919225119674426574742355349194934<br />
96983520312774506326239578318016984801869478851843<br />
85861560789112949495459501737958331952853208805511<br />
12540698747158523863050715693290963295227443043557<br />
66896648950445244523161731856403098711121722383113<br />
62229893423380308135336276614282806444486645238749<br />
30358907296290491560440772390713810515859307960866<br />
70172427121883998797908792274921901699720888093776<br />
65727333001053367881220235421809751254540594752243<br />
52584907711670556013604839586446706324415722155397<br />
53697817977846174064955149290862569321978468622482<br />
83972241375657056057490261407972968652414535100474<br />
82166370484403199890008895243450658541227588666881<br />
16427171479924442928230863465674813919123162824586<br />
17866458359124566529476545682848912883142607690042<br />
24219022671055626321111109370544217506941658960408<br />
07198403850962455444362981230987879927244284909188<br />
84580156166097919133875499200524063689912560717606<br />
05886116467109405077541002256983155200055935729725<br />
71636269561882670428252483600823257530420752963450<br />
1000 values will be checked!<br />
Product interval: 5<br />
Found greater product: 882 -> 1764<br />
Found greater product: 1764 -> 6048<br />
Found greater product: 6048 -> 15552<br />
Found greater product: 15552 -> 16128<br />
Found greater product: 16128 -> 18144<br />
Found greater product: 18144 -> 40824<br />
Found solution: 40824 in 0.022379159927368 seconds!</code></p>
<p>Mit diesem Ergebnis bewegen wir uns erwartungsgemäß in den Grenzen, die von Projecteuler vorgegeben sind und haben auf Anhieb die richtige Zahl gefunden.</p>
<h3>Schlusswort</h3>
<p>Wahrscheinlich merken die Leser schon an der Länge der Artikels, dass es mir viel Spaß bereitet hat, dieses Problem zu lösen, obwohl es eher eines von den einfacheren Problem war. Wie auch immer, es ist gelöst und vielleicht auf einem nicht ganz konventionellen Wege.</p>
<p>Andere Lösungsvorschläge in den Kommentaren, oder Aussagen zu meinem Lösungsvorschlag sind wie immer sehr willkommen.</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/">Permalink</a> |
<a href="http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/&title=Projecteuler: Lösung zu Problem 8">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/&title=Projecteuler: Lösung zu Problem 8">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/&title=Projecteuler: Lösung zu Problem 8">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/projecteuler/" rel="tag">Projecteuler</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/07/22/projecteuler-loesung-zu-problem-8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projecteuler: Lösung zu Problem 7</title>
		<link>http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/</link>
		<comments>http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 09:12:21 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Eratosthenes]]></category>
		<category><![CDATA[Primzahlen]]></category>
		<category><![CDATA[Projecteuler]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=1050</guid>
		<description><![CDATA[Diese Woche geht es gleich weiter mit der Lösung des siebten Projecteuler-Problems mit Python. Die guten Vorsätze von letzter Woche scheinen noch nicht abgelegt zu sein, deswegen beschäftigen wir uns in diesem Artikel wieder etwas mit Primzahlen und dem Sieb des Eratosthenes. Natürlich wird das Problem mit der Programmiersprache Python angegangen und gelöst! Problemvorstellung Das [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Projecteuler: Lösungen mit Python und C++" src="http://muvik.de/categorie_images/projecteuler_serie_start.gif" title="Projecteuler: Lösungen mit Python und C++" width="443" height="98" />
<p class="preview">Diese Woche geht es gleich weiter mit der Lösung des siebten Projecteuler-Problems mit Python. Die guten Vorsätze von letzter Woche scheinen noch nicht abgelegt zu sein, deswegen beschäftigen wir uns in diesem Artikel wieder etwas mit Primzahlen und dem Sieb des Eratosthenes. Natürlich wird das Problem mit der Programmiersprache Python angegangen und gelöst!</p>
<p><span id="more-1050"></span></p>
<h3>Problemvorstellung</h3>
<p>Das <a href="http://projecteuler.net/index.php?section=problems&#038;id=7">siebte Projecteuler-Problem</a> ist ein sehr kurzes Problem! Zumindest was die textliche Beschreibung angeht. Laut dem Motto &#8220;In der Kürze liegt die Würze&#8221; lautet die Aufgabenstellung folgendermaßen:</p>
<p>
<strong>Finde die 10001.Primzahl!</strong>
</p>
<p>Also kann mit drei Worten, einer Zahl und zwei Satzzeichen etwas formuliert werden, was jedes Grüblerherz höher schlagen lässt.</p>
<p>Diejenigen Leser, die meine Serie &#8220;Projecteuler: Lösungen mit Python und C++&#8221; bisher mitverfolgt haben, auch ohne aktives Eingreifen in Form von Kommentaren im Blog oder auch ohne die Probleme selber gelöst zu haben, werden wissen, dass es bereits eine Aufgabe gab, die Primzahlen zum Thema hatte.</p>
<p>Im Rahmen der <a href="http://www.muvik.de/2010/04/03/projecteuler-loesung-zu-problem-3/">Lösung zum dritten Problem</a>, wo es um eine Primfaktorenzerlegung ging, finden wir wichtige Werkzeuge auch zur Lösung des siebten Problems. Doch dazu später mehr, zuvor etwas Statistik:</p>
<p>Ganz aktuell gemessen, haben von insgesamt 112279 registrierten Projecteuler-Nutzern genau 57841 das Problem mit Bravour gelöst. Das entspricht ziemlich genau der Hälfte der Nutzer. Und wir sind dabei <img src='http://www.muvik.de/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> !</p>
<h3>Problemeingrenzung</h3>
<p>Die Schwierigkeiten bei dieser Fragestellung liegen auf der Hand: </p>
<ol>
<li>Zunächst ist es nett zu wissen, welche Zahlen denn nun überhaupt Primzahlen sind. Denn nur dann können sie auch gezählt werden. Also ist die erste Herausforderung das Filtern von Primzahlen.</li>
<li>Da nicht alle Primzahlen bis zu einer bestimmten ganzen Zahl gesucht sind, sondern eine bestimmte <em>Anzahl an Primzahlen</em>, sind die gängigsten Werkzeuge erst mal nicht zu gebrauchen, oder besser: sind zu überdenken. Es müssen weiterhin alle Primzahlen gesucht und gezählt werden, ein Limit ist jedoch nicht gegeben.</li>
</ol>
<p>Wie eingangs bereits angedeutet, können wir uns aus der Lösung zu Problem 3 eines ganz nützlichen Werkzeugs bedienen: dem <a href="http://de.wikipedia.org/wiki/Sieb_des_Eratosthenes">Sieb des Eratosthenes</a>.</p>
<p>Mit diesem Sieb lassen sich alle Primzahlen bis zu einer gegebenen ganzen Zahl N bestimmen. Wie im verlinkten Wikipedia-Artikel erläutert, müssen hierbei einfach alle Zahlen bis N &#8220;aufgeschrieben&#8221; werden. Dann werden mit der 2 beginnend alle Vielfachen wieder gestrichen. Hat man das für die 2 erledigt, so geht es in der Reihenfolge mit der nächsthöheren Zahl weiter, also der 3, dann 5, 7, 11, &#8230;</p>
<p>Das Sieb des Eratosthenes liefert uns also alle Primzahlen, die kleiner oder gleich N sind. Gesucht ist jedoch die 10001.Primzahl. Somit kommen wir mit dem Sieb des Eratosthenes nicht direkt zum Ziel.</p>
<p>Sollen nun im Zahlenbereich bis N noch keine 10001 Primzahlen identifiziert sein, so muss der Bereich erweitert und die Suche fortgesetzt werden. Wie das realisiert werden kann, steht unter der Überschrift:</p>
<h3>Problemlösung</h3>
<p>Der erste Teil der Lösung ist klar und bereits aus der <a href="http://www.muvik.de/2010/04/03/projecteuler-loesung-zu-problem-3/">Lösung zum Problem 3</a> bekannt: </p>
<pre class="brush:python">def eratosthenes_vect(N):
    primes = np.arange(3,N+1,2)  # only uneven figures
    primes = np.insert(primes,0,2,0) # ... and two

    nUneven = np.size(primes) - 1.0

    for i in np.arange(3,np.ceil(np.sqrt(N))+2,2):
        primes[(i*i+1)/2-1:nUneven+1.0:i] = 0;

    return np.trim_zeros(np.sort(primes))</pre>
</p>
<p>Damit erhalten wir alle Primzahlen bis zur Zahl N.</p>
<p>Die einfachste Lösung wäre nun, einfach einen großes N vorzugeben und zu hoffen, dass es mindestens 10001 Primzahlen im Sieb hängen bleiben. Ist man in der Lage, ein gut passendes N abzuschätzen, so hat man mit dem Sieb des Eratosthenes eine sehr effiziente Lösungsmethode gefunden.</p>
<p>Diese Tatsache möchten wir im Folgenden ausnutzen und durch eine Erweiterung etwas absichern:</p>
<pre class="brush:python">def eratosthenes_limits(StartN, EndN, Primes):
    """
    Rechnet alle Primzahlen im Zahlenraum StartN, EndN.
    Primes: alle Primzahlen bis StartN.
    """
    if (StartN%2 == 0):
        SearchField = np.arange(StartN+1,EndN+1,2)
        limitleft = StartN+1
        limitright = EndN
    else:
        SearchField = np.arange(StartN,EndN+1,2)
        limitleft = StartN
        limitright = EndN

    for item in Primes:
        itemQ = item*item
        if itemQ <= limitright:
            for i in range(0,SearchField.size,1):
                if (SearchField[i]%item == 0):
                    SearchField[i] = 0

            SearchField = np.trim_zeros(np.sort(SearchField))
            limitleft   = SearchField[0]
            limitright  = SearchField[-1]

    return np.append(Primes,SearchField)

def solver(N,NEra):
    Primes = eratosthenes_vect(NEra)

    while (Primes.size < N):
        Primes = eratosthenes_limits(NEra+1, NEra*2, Primes)
        NEra = NEra*2

    print("Suchbereich bis N=%i" %NEra)
    return Primes[N-1]</pre>
</p>
<p>Der gegebene Vorschlag ist wahrscheinlich nicht die eleganteste Methode, aber er funktioniert für das Problem recht ordentlich.</p>
<p>Die Funktion <code>eratosthenes_limits</code> kommt zum Einsatz, wenn der Zahlenbereich, den wir geschätzt haben, zu klein ist. Sie geht im Grunde genau nach dem Prinzip des Siebes von Eratosthenes vor. Es werden alle Zahlen in einem Bereich zwischen <code>StartN</code> und <code>EndN</code> auf Teilbarkeit durch die Primzahlen bis zur Zahl <code>StartN</code> untersucht. Da wir davon ausgehen, dass der zu Beginn geschätzte Zahlenbereich nicht sehr stark vergrößert werden muss, steigern wir in der <code>solver</code>-Funktion den Suchbereich um das doppelte, wenn nicht genug Primzahlen gefunden wurden.<br /> Auf diese Weise kann es nicht vorkommen, dass die Funktion <code>eratosthenes_limits</code> ins Stocken gerät, weil Primzahlen aus dem aktuellen neuen Suchbereich benötigt werden, um alle Vielfachen zu streichen. Dafür müsste der Suchbereich schon quadratisch vergrößert werden: <code>StartN = N, EndN=N*N</code>.</p>
<p><p><script type="text/javascript"><!--
google_ad_client = "pub-1356270213107195";
/* 468x60_incontent_text */
google_ad_slot = "2104479285";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p></p>
<h4>Schätzen des Suchbereichs zu Beginn</h4>
<p>Das Schätzen des richtigen Suchbereichs ist das A und O bei der vorgeschlagenen Lösung. Dazu lohnt sich ein Blick auf die Statistik. Betrachtet man bereits die Häufigkeit von Primzahlen im Bereich von 1-10 und von 20-30, so stellt man fest, dass die Anzahl abnimmt. Diese Tatsache lässt sich mathematisch beweisen, was wir hier aber nicht machen wollen.</p>
<p>In dem Zahlenbereich, der für das siebte Projecteuler-Problem interessant ist, treten laut der <a href="http://www.maerku69.ch/Primzahlen-auflisten.html">Analyse auf maerku69.ch</a> Primzahlen mit einer Häufigkeit von etwas unter 10% auf.</p>
<p>Daraus schließen wir, dass eine Schätzung des Suchbereichs mit etwas mehr als dem zehnfachen von 10001 ganz ordentlich sein sollte.</p>
<h3>Lösungsanalyse</h3>
<p>Genug der trockenen Theorie, nun kommt die Analyse:</p>
<pre class="brush:python">import time as t
import numpy as np

def eratosthenes_vect(N):
    ...

def eratosthenes_limits(StartN, EndN, Primes):
    ...

def solver(N,NEra):
    ...

N = 10001

N1 = 11*N

t0 = t.clock()
Prim = solver(N,N1)
tn = t.clock() - t0

print("Benoetigte Zeit: %15.6f" %tn)
print("Gefundene Primzahl: %i" %Prim)</pre>
</p>
<p>Mit einem derart optimierten Suchbereich (<code>11*10001</code>) ist eine Erweiterung nicht nötig, die Lösung wird allein durch das Sieb des Eratosthenes gefunden (Ausgabe):<br />
<code class="bash">Suchbereich bis N=110011<br />
Benoetigte Zeit:        0.320000<br />
Gefundene Primzahl: 104743</code></p>
<p>Unterschätzt man den Suchbereich etwas (10*10001), dann dauert die Suche schon etwas länger:<br />
<code class="bash">Suchbereich bis N=200020<br />
Benoetigte Zeit:        2.810000<br />
Gefundene Primzahl: 104743</code></p>
<p>Hierbei wurde der Suchbereich ein mal vergrößert.</p>
<p>Wird dagegen der Suchbereich überschätzt (12*10001), dann dauert die Suche nur unwesentlich länger:<br />
<code class="bash">Suchbereich bis N=120012<br />
Benoetigte Zeit:        0.350000<br />
Gefundene Primzahl: 104743<br />
</code></p>
<h3>Schlusswort</h3>
<p>Primzahlen sind immer wieder gut für Knobel-Spielchen geeignet, so auch diesmal.</p>
<p>Das Lösen des siebte Problem hat mir persönlich viel Spass bereitet. Ich hoffe, dass es meinen Lesern nicht anders ging oder noch gehen wird und freue mich auf andere Lösungsvorschläge in den Kommentaren oder vielleicht als Reaktion im eigenen Blog.</p>
<p>Meinungen, Anregungen, Verbesserungen sind immer willkommen.</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/">Permalink</a> |
<a href="http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/&title=Projecteuler: Lösung zu Problem 7">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/&title=Projecteuler: Lösung zu Problem 7">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/&title=Projecteuler: Lösung zu Problem 7">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/eratosthenes/" rel="tag">Eratosthenes</a>, <a href="http://www.muvik.de/tag/primzahlen/" rel="tag">Primzahlen</a>, <a href="http://www.muvik.de/tag/projecteuler/" rel="tag">Projecteuler</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/07/06/projecteuler-loesung-zu-problem-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projecteuler: Lösung zu Problem 6</title>
		<link>http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/</link>
		<comments>http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/#comments</comments>
		<pubDate>Wed, 30 Jun 2010 08:10:06 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Mathematik]]></category>
		<category><![CDATA[Projecteuler]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=918</guid>
		<description><![CDATA[Nach etwas über einem Monat kann dieser Beitrag zur Serie &#8220;Lösungen mit Python und C++&#8221; der projecteuler.net &#8211; Problemen als Lebenszeichen gedeutet werden. Die Serie gibt es noch und an dieser Stelle wird der sechste Teil vorgestellt. Wie bereits im fünften Teil der Serie, gibt es auch beim 6. eine einfache Lösung mit Papier und [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Projecteuler: Lösungen mit Python und C++" src="http://muvik.de/categorie_images/projecteuler_serie_start.gif" title="Projecteuler: Lösungen mit Python und C++" width="443" height="98" />
<p class="preview">Nach etwas über einem Monat kann dieser Beitrag zur Serie &#8220;Lösungen mit Python und C++&#8221; der <a href="http://projecteuler.net">projecteuler.net</a> &#8211; Problemen als Lebenszeichen gedeutet werden. Die Serie gibt es noch und an dieser Stelle wird der sechste Teil vorgestellt. Wie bereits im fünften Teil der Serie, gibt es auch beim 6. eine einfache Lösung mit Papier und Bleistift und eine kurze Lösungen in Python.</p>
<p><span id="more-918"></span></p>
<h3>Problemvorstellung</h3>
<p>Projecteuler bietet mittlerweile gut 300 Aufgabe, die mehr oder weniger herausfordernd sind. In meiner Serie habe ich bisher erst fünf Lösungen vorgestellt und heute kommt die sechste hinzu. Dabei muss ich zu meiner Schande gestehen, ist die Frequenz, mit der neue Probleme hinzukommen höher als die Veröffentlichungsfrequenz der Lösungen. Aber ich möchte mich bessern <img src='http://www.muvik.de/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> !</p>
<p>Die <a href="http://projecteuler.net/index.php?section=problems&#038;id=6">sechste Aufgabe</a> stellt für alle, die Geschichten über den <a href="http://de.wikipedia.org/wiki/Carl_Friedrich_Gau%C3%9F">Mathematiker Gauss</a> als kleinen Jungen kennen, kein Problem dar. Ehrlich gesagt, ist es auch für Leute, welche die Geschichten nicht kennen, keine größere Herausforderung.</p>
<p>Ins Deutsche übersetzt, lautet die Aufgabe folgendermaßen:</p>
<p><strong>Finde die Differenz zwischen dem Quadrat der Summe und der Quadratsumme der natürlichen Zahlen bis einschließlich 100.</strong></p>
<p>Laut der Statistik von Projecteuler.net haben bis zum heutigen Tag genau 68751 Teilnehmer das Problem gelöst. Das entspricht grob gesagt der Hälfte aller registrierten User (112160).</p>
<h3>Problemeingrenzung</h3>
<p>Abgesehen von der rein mathematischen Lösung durch etwas nachdenken und Anwenden der Summenformeln, sehe ich bei dieser Aufgabe lediglich die Herausforderung, sich nicht mit einer straight-forward Lösung zufrieden zu geben, sondern zu versuchen, die Anzahl an Rechenoperationen zu minimieren.</p>
<p>Läge der Schwerpunkt in dieser Artikelserie auf der Mathematik, die hinter den Lösungen steckt, so müssten die Summenformeln hergeleitet werden. Damit wäre der Beweis der Summenformeln die Herausforderung. In unserem Fall soll die Kernaufgabe jedoch mit Hilfe von Python gelöst werden, daher sehe ich keine weitere Herausforderung.</p>
<h3>Der Problemlösung erster Teil</h3>
<p>Im ersten Lösungsvorschlag geht es darum, wie das 6.Problem gelöst werden kann, wenn man lediglich Papier und einen Bleistift zur Verfügung hat. Des Weiteren müssen wir die zusätzliche Einschränkung einführen, dass nicht viel Zeit benötigt werden darf. Nicht, dass noch jemand auf die Idee kommt alles von Hand oder im Kopf zu rechnen.</p>
<p>Wenden wir uns der ersten Teilaufgabe zu: Berechnung des Quadrats der Summe von 1 bis 100.</p>
<p>Hierfür können wir erst einmal die <a href="http://de.wikipedia.org/wiki/Formelsammlung_Algebra#Summenformeln">Gauss-Formel</a> verwenden:<br />
<code class="bash">1 + 2 + 3 + ... + 98 + 99 + 100 = n (n+1) * 0.5 = 5050</code></p>
<p>Wird das Ergebnis der Summenformel (5050) noch quadriert, so erhalten wird schon den ersten Teil der Lösung:<br />
<code class="bash">5050 * 5050 = 25502500</code></p>
<p>Der zweite Teil, also die Quadratsumme, macht uns das Leben nicht so einfach. Aber mit Hilfe einer zweiten Summenformel auch nicht wirklich schwer:<br />
<code class="bash">1*1 + 2*2 + 3*3 + ... + 98*98 + 99*99 + 100*100 = n * (n+1) * (2n+1) * (1/6) = 338350</code></p>
<p>Damit wäre das 6.Projecteuler-Problem gelöst:<br />
<code class="bash">25502500 - 338350 = 25164150</code></p>
<h3>Der Problemlösung zweiter Teil</h3>
<p>Kommen wir zu der versprochenen Implementierung in Python:</p>
<pre class="brush:python">def direct(N):
    SOSq = 0
    SqOS = 0

    for i in range(1,N+1):
        SOSq = SOSq + i*i
        SqOS = SqOS + i

    return SqOS*SqOS - SOSq</pre>
</p>
<p>Zugegebenermaßen ist dieser Vorschlag nun wirklich ganz einfach und leicht nach zu vollziehen. Die Variable <em>SOSq</em> speichert hierbei die Summe der Quadrate und <em>SqOS</em> das Quadrat der Summe. Ausgegeben wird die gesuchte Differenz.</p>
<p>Natürlich habe ich an dieser Stelle auch etwas weiter gedacht und versucht die Lösung zu optimieren. Jedoch führten meine Gedanken mich immer wieder in Richtung der bereits vorgestellten Summenformeln.</p>
<h3>Schlusswort</h3>
<p>Das war nun wieder ein Lebenszeichen der Serie zu Lösungen von Projecteuler-Problemen. Der Python-Teil ist diesmal etwas kurz ausgefallen, was in Anbetracht des Problems aber nicht wirklich verwunderlich ist. Sollte ein Leser eine raffinierte Lösung parat haben, so freue ich mich auf den Kommentar.</p>
<p>An dieser Stelle sei allen, die neben der Mathematik und vielen Stunden Programmierarbeit noch etwas Zeit finden zum Lesen, das Buch <a href="http://www.amazon.de/gp/product/3499241005?ie=UTF8&#038;tag=wwwmuvikde-21&#038;linkCode=as2&#038;camp=1638&#038;creative=19454&#038;creativeASIN=3499241005">Die Vermessung der Welt*</a><img src="http://www.assoc-amazon.de/e/ir?t=wwwmuvikde-21&#038;l=as2&#038;o=3&#038;a=3499241005" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> von Daniel Kehlmann empfohlen. Es geht um zwei herausragende deutsche Wissenschaftler: Carl Friedrich Gauss und Alexander von Humboldt. Es ist ein interessantes Buch, welches durch einen lockeren Schreibstil gekennzeichnet ist, perfekt um in den Kopf zweier Genies einzutauchen.</p>
<p>*: Partnerlink</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/">Permalink</a> |
<a href="http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/&title=Projecteuler: Lösung zu Problem 6">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/&title=Projecteuler: Lösung zu Problem 6">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/&title=Projecteuler: Lösung zu Problem 6">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/mathematik/" rel="tag">Mathematik</a>, <a href="http://www.muvik.de/tag/projecteuler/" rel="tag">Projecteuler</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/06/30/projecteuler-loesung-zu-problem-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Tutorial: Lesen von csv-Daten 2</title>
		<link>http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/</link>
		<comments>http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 08:10:15 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[InputOutput]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=823</guid>
		<description><![CDATA[Los gehts: Sehr schnell nach der Veröffentlichen des ersten Tutorials zum Lesen von csv-Daten mit Python, kamen von zwei Identi.ca-Teilnehmern der Hinweis auf das Python csv-Modul. Darauf möchte ich nun eingehen. Reaktionen auf das erste Tutorial Erstaunlicherweise kamen buchstäblich Sekunden nach der Veröffentlichung des ersten Tutorials von lutzgh und evgeni über identi.ca zwei Reaktionen in [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Tutorials auf die einfachste Weise" src="http://muvik.de/categorie_images/simple_tutorial.png" title="Tutorials auf die einfachste Weise" width="443" height="98" />
<p class="preview">Los gehts: Sehr schnell nach der Veröffentlichen des ersten Tutorials zum <a href="http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/">Lesen von csv-Daten mit Python</a>, kamen von zwei Identi.ca-Teilnehmern der Hinweis auf das Python csv-Modul. Darauf möchte ich nun eingehen.</p>
<p><span id="more-823"></span></p>
<h3>Reaktionen auf das erste Tutorial</h3>
<p>Erstaunlicherweise kamen buchstäblich Sekunden nach der Veröffentlichung des ersten Tutorials von lutzgh und <a href="http://identi.ca/evgeni">evgeni</a> über <a href="http://identi.ca/muvik">identi.ca</a> zwei Reaktionen in gleiche Richtung. Beide wiesen mich auf das <a href="http://docs.python.org/library/csv.html">csv-Modul</a> hin, welches genutzt werden kann, um diverse Daten zu importieren.</p>
<p>Natürlich kam mir sofort der Gedanke, warum ich das Modul nicht selber entdeckt habe. Ich muss zugeben, dass ich gar nicht gesucht habe. Mir ist auf Anhieb die Lösung mit den regulären Ausdrücken eingefallen. Doch, aus zwei Gründen bin ich glücklich, dass es nun so gekommen ist:</p>
<ol>
<li>Auf dieser Grundlage lässt sich ein weiterer netter Blog-Artikel schreiben <img src='http://www.muvik.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</li>
<li>Aus eins mach zwei: Ursprünglich als alleinstehendes Thema geplant, ist es nun in zunächst zwei verschiedenen Ausführungen vorhanden, die sich prächtig ergänzen. Dadurch ergibt sich eine breitere Grundlage und noch mehr Wissen für meine Leser.</li>
</ol>
<p>Also nur Vorteile für alle im Thema interessierten.
</p>
<h3>Das csv-Modul</h3>
<p>Das csv-Modul, welches es laut der Python-Dokumentationseite, seit der Version 2.3 gibt, unterstützt den Programmierer in seiner Arbeit beim Import und Export von Daten, welche tabellarisch im csv-Format gespeichert sind oder werden sollen. Dafür stellt es diverse Funktionen zur Verfügung, von denen ich die <em>reader()</em> und <em>writer()</em>-Funktionen als die für mich wichtigsten einstufe.</p>
<p>Sehr interessant ist die Möglichkeit mit Hilfe des csv-Moduls, Excel-Daten zu importieren und in Excel-Stil zu exportieren. Dazu muss lediglich ein bestimmter Parameter übergeben werden, der das Format definiert. Das scheint mir einer der größten Vorteile dieses Moduls zu sein.</p>
<h3>Datensatz und Import der Daten mit dem csv-Modul</h3>
<p>Wie bereits im ersten Tutorial wird auch hier der kleine Beispiel-Datensatz von <a href="http://www.walkingrandomly.com/?p=2654">walkingrandomly.org</a> übernommen:<br />
<code class="bash">header 1;<br />
header 2;<br />
1031,-948,-76, ,"12"<br />
507,635,-1148, ,"34"<br />
-1031,948,750, ,"45"<br />
-507,-635,114, ,"67"</code></p>
<p>
Diese Zeilen sollen nun mit dem csv-Modul in das Programm importiert werden und in drei verschiedenen Listen gespeichert werden. Dabei interessieren uns lediglich die Daten, die nicht Kopfdaten sind oder in Anführungszeichen stehen. Dazu  habe ich folgendes Python-Skript geschrieben:</p>
<pre class="brush:python">import csv
fileO = open('walking_example.dat','r')
csvreader=csv.reader(fileO, delimiter=',')
k= []; l = []; m = [];

for row in csvreader:
    if len(row) > 1:
        k.append(float(row[0]))
        l.append(float(row[1]))
        m.append(float(row[2]))

print(k,l,m)

fileO.close()</pre>
</p>
<h4>Schrittweise erklärt</h4>
<p>1.Zeile: Import des csv-Moduls</p>
<p>2.Zeile: Erstellen eines <em>file</em>-Objekts, welcher die Datei mit dem gezeigten Datensatz enthält.</p>
<p>3.Zeile: Einlesen der Daten von <em>fileO</em> mit der <em>reader()</em>-Funktion des csv-Moduls. Die Funktion erwartet mindestens einen Übergabeparameter und zwar das <em>file</em>-Objekt. Des Weiteren kann ein sogenannter Dialekt vorgegeben werden, welcher für sich die Struktur der csv-Daten definiert. Ein Dialekt könnte zum Beispiel Excel sein (<em>dialect=&#8217;excel&#8217;</em>). Weitere optionale Argumente wie das Trennungszeichen (<em>delimiter=&#8217;,&#8217;</em>) können hinzugefügt werden.</p>
<p>4.Zeile: Initialisieren der Listen, mit welchen weiter gerechnet werden soll.</p>
<p>7-10.Zeile: Das Auslesen der importierten Daten erfolgt an dieser Stelle. Die <em>reader()</em>-Funktion liest die Daten zeilenweise ein, dabei spielt es zunächst keine Rolle, ob es Kopfdaten sind oder nicht. Dieses Vorwissen muss bei der vorgestellten Methode vorhanden sein. Im Beispiel haben wir zwei Zeilen mit Kopfdaten, welche ignoriert werden sollen. Dies geschieht über die Abfrage der Länge der Liste <em>row</em>. Zuletzt werden in den Zeilen noch die Listen <em>k,l,m</em> um die ersten drei Spalten erweitert.</p>
<p>11-12.Zeile: Ausgabe der Listen und schließen des <em>file</em>-Objekts.</p>
<h3>Schlusswort</h3>
<p>Die Vorteile des csv-Moduls im Vergleich zu der Lösung mit regulären Ausdrücken liegen auf der Hand. Zum einen ist der Import effizienter und einfacher zu schreiben und zum anderen ist die Fehleranfälligkeit nicht so hoch.</p>
<p>Auf der anderen Seite stellen die regulären Ausdrücke eine viel allgemeinere Methode dar, Daten zu importieren. Hierbei muss lediglich die Struktur der Daten bekannt sein, Kopfzeilen werden automatisch ignoriert. Des Weiteren stellen zusätzliche Störungen in den Daten für reguläre Ausdrücke kein Problem dar.</p>
<p>Sollte ich jemals in die Verlegenheit kommen, mich zwischen den zwei Lösungen entscheiden zu müssen, so werde ich natürlich das dem Problem am besten angepasste nutzen. Das heißt: bei relativ sauberen Daten das csv-Modul und bei stark ungeordneten Daten die regulären Ausdrücke.</p>
<p>Nun hoffe ich auf konstruktive Kritik!</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/">Permalink</a> |
<a href="http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/&title=Python Tutorial: Lesen von csv-Daten 2">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/&title=Python Tutorial: Lesen von csv-Daten 2">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/&title=Python Tutorial: Lesen von csv-Daten 2">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/inputoutput/" rel="tag">InputOutput</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a>, <a href="http://www.muvik.de/tag/tutorial/" rel="tag">Tutorial</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/06/08/python-tutorial-lesen-von-csv-daten-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Tutorial: Lesen von csv-Daten</title>
		<link>http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/</link>
		<comments>http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 11:26:41 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[InputOutput]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=781</guid>
		<description><![CDATA[Los gehts: Tutorials, die nicht in die Kurztipp-Serie passen, weil sie zu groß, zu lang, zu wichtig sind oder ein besonderes Feature enthalten haben nun ebenfalls eine eigene Kategorie-Grafik. Diesmal geht es um das Einlesen beliebiger, durch ein Komma getrennter Daten aus sogenannten csv-Dateien (comma-seperated-values) in Python mit Hilfe der regulären Ausdrücke (regular expressions). Idee [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Tutorials auf die einfachste Weise" src="http://muvik.de/categorie_images/simple_tutorial.png" title="Tutorials auf die einfachste Weise" width="443" height="98" />
<p class="preview">Los gehts: Tutorials, die nicht in die Kurztipp-Serie passen, weil sie zu groß, zu lang, zu wichtig sind oder ein besonderes Feature enthalten haben nun ebenfalls eine eigene Kategorie-Grafik. Diesmal geht es um das Einlesen beliebiger, durch ein Komma getrennter Daten aus sogenannten csv-Dateien (comma-seperated-values) in Python mit Hilfe der regulären Ausdrücke (regular expressions).</p>
<p><span id="more-781"></span></p>
<h3>Idee und Intention</h3>
<p>Wie aus der Seitenleiste des Blogs entnommen werden kann, lese ich regelmäßig die Artikel des <a href="http://www.walkingrandomly.com">walkingrandomly.com</a> Blogs von Mike Croucher. Am 21. Mai 2010 schrieb Mike ein <a href="http://www.walkingrandomly.com/?p=2654">Matlab Tutorial</a>, dessen Inhalt es war, wie csv-Dateien in Matlab eingelesen werden können. Im Rahmen dieses Artikels ging er auf verschiedene Möglichkeiten ein, eine csv-Datei zu importieren.</p>
<p>Begonnen hat er mit einer einfachen zu importierenden Datei, worin die Daten ohne Ausnahmen durch eine Komma getrennt waren. Richtig interessant wurde es beim Import von Daten aus einer unordentlich definierten csv-Datei. Das Beispiel stammte von einem Leser seines Blogs und soll hier ebenfalls verwendet werden. </p>
<h3>Der Datensatz</h3>
<p>Es lässt sich unendlich lange darüber unterhalten, wie sinnvoll oder sinnlos es ist, innerhalb einer Datei mit csv-Daten weitere Daten zu integrieren, welche nicht durch Kommas getrennt werden und eventuell andere Datentypen sind. Abgesehen davon ist das Beispiel, welches auch Mike verwendet folgendes:</p>
<p><code class="bash">header 1;<br />
header 2;<br />
1031,-948,-76, ,"12"<br />
507,635,-1148, ,"34"<br />
-1031,948,750, ,"45"<br />
-507,-635,114, ,"67"</code></p>
<p>Da das Ziel beim Import der Daten ist, mit ihnen weiter zu rechnen oder zu plotten, ergeben sich für mich zwei Herausforderungen, bei dem gegebenen Datensatz:</p>
<ol>
<li>Eine straight-forward Lösung bricht sich bereits an der ersten Zeile das Bein, an der ersten Kopfzeile. Also müssen eine vorgegebene Anzahl an Zeilen beim Importieren ignoriert werden können.</li>
<li>Da die letzte Spalte nicht nur durch ein Komma getrennt ist, sondern in Anführungszeichen steht, soll angenommen werden, dass es reiner Text ist und soll beim Import ignoriert werden.</li>
</ol>
<p>Damit wären die Stolpersteine lokalisiert und können aus dem Weg geräumt werden.</p>
<h3>Reguläre Ausdrücke (regular expressions, kurz: regex)</h3>
<p>Es gibt mehrere Möglichkeiten das beschriebene Problem anzugehen und die regulären Ausdrücke stellen in meinen Augen nicht die schlechteste dar. Zum einen wird aus den zwei Herausforderungen nur noch eine und zum anderen ist die Lösung sehr schnell auf dem Tisch und sieht elegant aus. Sollte sich die Struktur der csv-Daten noch ändern, stellt es für die Lösung mit regulären Ausdrücken kein großes Problem dar. Es muss lediglich eine Zeile angepasst werden.</p>
<p>Reguläre Ausrücke habe ich persönlich bisher sehr sporadisch gebraucht, würde aber dennoch folgendes Vorgehen vorschlagen:</p>
<ol>
<li>Klären der Struktur der Daten</li>
<li>Erkennen eines Musters</li>
<li>Definition des Musters in regulären Ausdrücken</li>
<li>Implementierung des Rahmenprogramms: öffnen einer Datei, ausgeben der Ergebnisse &#8230;</li>
</ol>
<p>Die Struktur des Datensatzes haben wir schon geklärt: es ist ein Datensatz, dessen Elemente durch Kommata getrennt sind. Die zwei Kopfdateien interessieren uns hierbei nicht, die sollen nicht importiert werden.
</p>
<p>Das Muster ergibt sich, indem logische Bereiche von einer Zeile betrachtet werden:<br />
<code class="bash">-1031,948,750, ,"45"</code><br />
Zum Einen ist zu bemerken, dass alle Zahlen ganze Zahlen sind. Zudem ist ein Minus auch erlaubt. Also ergibt sich aus der Überlegung folgendes Muster: drei aufeinander folgenden Integer-Zahlen, die durch jeweils ein Komma getrennt sind und evt. ein Minus vor der Integer-Zahl.</p>
<p>Daraus lässt sich nun der folgende einfache reguläre Ausdruck ableiten:<br />
<code class="bash">(-?[0-9]*),(-?[0-9]*),(-?[0-9]*),.*</code><br />
Es sei angemerkt, dass auch an dieser Stelle viele Wege nach Rom führen. Drei Programmierern fallen bestimmt spontan neun verschiedene reguläre Ausdrücke ein, die alle die korrekte Lösung liefern.
</p>
<h3>Reguläre Ausdrücke in Python</h3>
<p>Der glückliche und aktive Linux Benutzer kann reguläre Ausdrücke in sehr vielen Programmen und Tools anwenden. Als Beispiele seien nur die Tools <a href="http://de.wikipedia.org/wiki/Grep">grep</a> und <a href="http://de.wikipedia.org/wiki/Awk">awk</a> genannt.</p>
<p>Ich möchte nicht behaupten, dass die meisten Bücher, jedoch sehr viele erklären reguläre Ausdrücke in Kombination mit der Skriptsprache <a href="http://de.wikipedia.org/wiki/Perl_%28Programmiersprache%29">Perl</a>. In Python lassen sich die regulären Ausdrücke doch ebenso leicht verwenden. Dazu muss lediglich das Modul <em>re</em> importiert werden:<br />
<code class="bash">import re</code> Damit sind wir mit einer mächtigen Waffe ausgestattet.</p>
<h3>Import der csv-Daten und Ausgabe der Listen (Arrays)</h3>
<p>Gehen wir es an und importieren den Datensatz mit den unordentlich formatierten Daten. Dazu schlage ich folgendes kleines Python-Skript vor:</p>
<pre class="brush:python">import re

# define a pattern for matching the needed data

fileO = open('walking_example.dat','r')
search_data = fileO.readlines()

fileO.seek(0,0)

print("Following data will be parsed:\n")
print(fileO.read())

fileO.close()

pattern = '(-?[0-9]*),(-?[0-9]*),(-?[0-9]*),.*'
r = []; s = []; t = [];

for line in search_data:
    found = re.search(pattern, line)
    if found:
        r.append(float(found.group(1)))
        s.append(float(found.group(2)))
        t.append(float(found.group(3)))

print("\nThe parsed lists:\n")
print(r,s,t)</pre>
</p>
<h4>Schrittweise erklärt:</h4>
<p>1.Zeile: Zu Beginn wird das Modul zur Verwendung regulärer Ausdrücke importiert.</p>
<p>5.Zeile: Es wird ein <em>file</em>-Objekt angelegt, welches die Datei mit dem Datensatz enthält. Die Funktion <em>open</em> erhält im ersten Übergabeparameter die Datei inklusive dem Pfad und im zweiten die Option &#8216;r&#8217;, was bedeutet, dass nur gelesen werden soll. Da in meinem Fall die csv-Datei sich im selben Ordner befindet, wie das Python-Skript, muss lediglich der Dateiname angegeben werden.</p>
<p>6.Zeile: Um die Daten aus dem <em>file</em>-Objekt zu verwenden, werden sie zeilenweise eingelesen und in der Variablen <em>search_data</em> gespeichert.</p>
<p>7-11.Zeile: Dieser Abschnitt ist optional. Zunächst wird die Position im <em>file</em>-Objekt wieder auf den Ausgangszustand zurückgesetzt, damit der Datensatz erneut mittels <em>read()</em> gelesen und dadurch einfach mit <em>print()</em> ausgegeben werden kann. Dies alles dient nur der leichten Kontrolle des regulären Ausdrucks.</p>
<p>13.Zeile: Das <em>file</em>-Objekt wird geschlossen.</p>
<p>15.Zeile: Der bereits vorgestellte reguläre Ausdruck wird in der Variable <em>pattern</em> gespeichert.</p>
<p>16.Zeile: Initialisierung leerer Listen für die drei Spalten aus den Datensatz.</p>
<p>19.Zeile: Anwendung des regulären Ausdrucks für jede Zeile aus <em>search_data</em>, was mit Hilfe der <em>for</em>-Schleife aus Zeile 18 bewerkstelligt wird. Hierzu wird die Funktion <em>search</em> aus dem <em>re</em>-Modul verwendet. <em>search</em> erhält als erstes Argument das Muster und als zweites die zu untersuchende Zeile des Datensatzes.</p>
<p>21-23.Zeile: Wenn <em>re.search</em> etwas gefunden hat, dann werden die Teile, welche im regulären Ausdruck in runden Klammern stehen in die drei Listen <em>r,s,t</em> geschrieben. Vor dem eigentlichen Anhängen an die Liste mittels <em>append</em> wird der Inhalt in <em>float</em>-Zahlen umgewandelt.</p>
<p>26.Zeile: Zu guter Letzt werden die Listen zur Kontrolle ausgegeben.</p>
<h3>Ergebnis und Kontrolle</h3>
<p>Die Arbeit ist getan, jetzt gilt es nur noch die Lorbeeren zu pflücken.</p>
<p>Dazu schauen wir uns an, was das Skript in der Shell ausgibt:<br />
<code class="bash">Following data will be parsed:<br />
header 1;<br />
header 2;<br />
1031,-948,-76, ,"12"<br />
507,635,-1148, ,"34"<br />
-1031,948,750, ,"45"<br />
-507,-635,114, ,"67"<br />
The parsed lists:<br />
([1031.0, 507.0, -1031.0, -507.0], [-948.0, 635.0, 948.0, -635.0], [-76.0, -1148.0, 750.0, 114.0])</code><br />
Es ist ganz leicht zu erkennen, dass das kleine Programm für diesen Fall richtig funktioniert hat.</p>
<h3>Schlusswort</h3>
<p>Reguläre Ausdrücke sind ein mächtiges Instrument, welches jedoch aufgrund der etwas undurchsichtigen Syntax oft als zu umständlich abgelehnt werden. Aus meiner Sicht lohnt sich eine kurze Einarbeitung in die Syntax, wenn öfter mal bestimmte Bereiche eines Datensatzes extrahiert werden müssen, was bei mir der Fall ist.</p>
<p>An dieser Stelle ein Dankeschön an Mike vom walkingrandomly.com-Blog für die Steilvorlage.</p>
<p>Weiterhin würde mich interessieren, wie meine Leser an die Sache herangegangen wären und welche Erfahrungen sie gemacht haben in Bezug auf reguläre Ausdrücke.</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/">Permalink</a> |
<a href="http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/#comments">ein Kommentar</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/&title=Python Tutorial: Lesen von csv-Daten">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/&title=Python Tutorial: Lesen von csv-Daten">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/&title=Python Tutorial: Lesen von csv-Daten">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/inputoutput/" rel="tag">InputOutput</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a>, <a href="http://www.muvik.de/tag/tutorial/" rel="tag">Tutorial</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/06/04/python-tutorial-lesen-von-csv-daten/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Links zum Thema &#8211; Python Lernen</title>
		<link>http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/</link>
		<comments>http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/#comments</comments>
		<pubDate>Tue, 25 May 2010 08:10:42 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Links zum Thema]]></category>
		<category><![CDATA[eBook]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=657</guid>
		<description><![CDATA[Thema der ersten Liste lautet: Python (Programmieren-) Lernen. Diesen sehr allgemeine Beginn möchte ich kurz begründen, bevor es zur eigentlichen Linkliste geht. Die Linkliste enthält heute einige eBooks und einen Verweis zu Screencasts bzw. Videos zum Thema. Nur in den seltensten Fällen gibt es lediglich einen gewichtigen Grund für ein Vorgehen oder einen Entschluss eines [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Leseempfehlungen durch die Links zum Thema" src="http://muvik.de/categorie_images/links_zum_thema.gif" title="Leseempfehlungen zu bestimmten Themen" width="443" height="98" />
<p class="preview">Thema der ersten Liste lautet: Python (Programmieren-) Lernen. Diesen sehr allgemeine Beginn möchte ich kurz begründen, bevor es zur eigentlichen Linkliste geht. Die Linkliste enthält heute einige eBooks und einen Verweis zu Screencasts bzw. Videos zum Thema.</p>
<p><span id="more-657"></span></p>
<p>Nur in den seltensten Fällen gibt es lediglich einen gewichtigen Grund für ein Vorgehen oder einen Entschluss eines Menschen; die Auswahl des heutigen Themas stellt dahingehen auch keine Ausnahme dar. Aus folgenden Gründen gibt es heute Links zu dem sehr allgemein gehaltenen Thema &#8220;Python Lernen&#8221;:</p>
<ul>
<li>Python als Programmiersprache und Problemlösungswerkzeug stellt eine wichtige Säule auf meinem Blog dar. Insbesondere steht hierbei das Erlernen von Python im Vordergrund. Das allein ist schon Grund genug, um an dieser Stelle eine Liste mit allgemeinen Büchern für Anfänger und Fortgeschritten in der Python-Programmierung zu erstellen.</li>
<li>Da ich selber noch ein Anfänger bin, kann ich beurteilen, wie viel Wert eine kompakte Sammlung an Links für Anfänger darstellt. Diese möchte ich auf meiner Webseite daher nicht missen.</li>
<li>Da ich grundsätzlich nicht vor habe, überwiegend brandaktuelle News in der Linkliste aufzuführen, kann die Linkliste sich zu einer Informationsquelle für im Thema interessierte Leser entwickeln.</li>
</ul>
<p>Damit möchte ich die Begründung als ausreichen ansehen und zur eigentlichen Linkliste übergehen.
</p>
<h3>4 eBooks zum Thema Python Lernen</h3>
<div class="list-img">
<p><a href="http://openbookproject.net//thinkCSpy/"><img src="http://www.muvik.de/wp-content/uploads/2010/05/LzT01-01.png" alt="eBook-How to Think Like a Computer Scientist" title="How to Think Like a Computer Scientist" width="100" height="100" class="alignleft size-full wp-image-670" /></a><a href="http://openbookproject.net//thinkCSpy/">How to Think Like a Computer Scientist</a><br />
In 21 Kapiteln wird sowohl auf die Grundlagen der Python-Programmierung eingegangen, wie auch auf fortgeschrittene Konzepte wie die objektorientierte Modellierung und Programmierung. Man lernt, wie eigene Module erstellt und die installierten Module mit PyDoc durchsucht werden können.</p>
</div>
<div class="list-img">
<p><a href="http://ada.rg16.asn-wien.ac.at/~python/how2think/index.htm"><img src="http://www.muvik.de/wp-content/uploads/2010/05/LzT01-02.png" alt="Deutsche Übersetzung von &quot;How to Think Like a Comuter Scientist&quot;" title="Deutsche Übersetzung von &quot;How to Think Like a Comuter Scientist&quot;" width="100" height="100" class="alignleft size-full wp-image-675" /></a><a href="http://ada.rg16.asn-wien.ac.at/~python/how2think/index.htm">Wie ein Informatiker denken lernen &#8230; mit Python</a><br />
Die deutsche Übersetzung des zuvor vorgestellten Buchs hat meiner Meinung nach nicht die Qualität des englischen Buchs, für Leute, die lieber deutsche Fachbücher lesen ist es aber dennoch geeignet.</p>
</div>
<div class="list-img">
<p><a href="http://www.swaroopch.com/notes/Python"><img src="http://www.muvik.de/wp-content/uploads/2010/05/LzT01-03.png" alt="eBook: A Byte of Python" title="eBook: A Byte of Python" width="100" height="100" class="alignleft size-full wp-image-678" /></a><a href="http://www.swaroopch.com/notes/Python">A Byte of Python</a><br />
Dieses englische eBook gibt eine nahezu vollständige Einführung in Python, ist angenehm zu Lesen und hat bereits eine breite Anwendergemeinde gefunden. Das Buch ist online sowie als pdf-Datei geniesbar.</p>
</div>
<div class="list-img">
<p><a href="http://diveintopython.org/"><img src="http://www.muvik.de/wp-content/uploads/2010/05/LzT01-04.png" alt="eBook: Dive into Python" title="eBook: Dive into Python" width="100" height="100" class="alignleft size-full wp-image-681" /></a><a href="http://diveintopython.org/">Dive Into Python</a><br />
Ebenfalls ein englischsprachiges eBook, welches sehr tief in die Thematik einsteigt. Auf das Arbeiten mit Python unter Windows, Mac OS und Linux wird eingegangen. Sogar das Thema <em>Regular Expressions</em> und die Optimierung eines Python-Programms wird abgehandelt.</p>
</div>
<h3>Videos und Screencasts zum Thema Python Lernen</h3>
<div class="list-img">
<p><a href="http://showmedo.com/learningpaths/19/view"><img src="http://www.muvik.de/wp-content/uploads/2010/05/LzT01-05.png" alt="Videos und Screencasts auf showmedo.com" title="Videos und Screencasts auf showmedo.com" width="100" height="100" class="alignleft size-full wp-image-684" /></a> <a href="http://showmedo.com/learningpaths/19/view">ShowMeDo.com</a><br />
Viele Screencast und Videos zu diversen Themen aus dem opensource Bereich lassen sich auf showmedo.com finden. Das interessante Konzept des <em>lerning-path</em> führt den Lernenden durch die Sammlung in einer sinnvollen Reihenfolge.</p>
</div>
<h3>Schlusswort</h3>
<p>Das waren die ersten fünf Links zu Resourcen, die mir wichtig waren und sind und denen ich zutraue, dass sie meinen lieben Lesern ebenfalls hilfreich sein können.</p>
<p>Natürlich würde ich mich über Kommentare diesbezüglich freuen. Weitere Links zum Thema &#8220;Python Lernen&#8221; nehme ich gerne auf und veröffentliche sie in einer weiteren Linkliste.</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/">Permalink</a> |
<a href="http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/&title=Links zum Thema &#8211; Python Lernen">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/&title=Links zum Thema &#8211; Python Lernen">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/&title=Links zum Thema &#8211; Python Lernen">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/ebook/" rel="tag">eBook</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a>, <a href="http://www.muvik.de/tag/tutorial/" rel="tag">Tutorial</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/05/25/links-zum-thema-python-lernen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projecteuler: Lösung zu Problem 5</title>
		<link>http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/</link>
		<comments>http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/#comments</comments>
		<pubDate>Mon, 17 May 2010 11:46:47 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Primzahlen]]></category>
		<category><![CDATA[Projecteuler]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=617</guid>
		<description><![CDATA[In langsamen Schritten mehren sich die Lösungsvorschläge zu den projecteuler.net Problemen in dieser Serie. Nun sind es fünf an der Zahl. Zur Feier des Tages werden heute eine ganz simple, handschriftliche Lösung vorgestellt und die dazu äquivalente Implementierung in Python gezeigt. Problemvorstellung Die Probleme von projecteuler.net sind aufgrund des meist recht hohen Rechenaufwands nicht nur [...]]]></description>
			<content:encoded><![CDATA[<p><img class="cat-img-wide" title="Projecteuler: Lösungen mit Python und C++" src="http://muvik.de/categorie_images/projecteuler_serie_start.gif" alt="Projecteuler: Lösungen mit Python und C++" width="443" height="98" /></p>
<p class="preview">In langsamen Schritten mehren sich die Lösungsvorschläge zu den projecteuler.net Problemen in dieser Serie. Nun sind es fünf an der Zahl. Zur Feier des Tages werden heute eine ganz simple, handschriftliche Lösung vorgestellt und die dazu äquivalente Implementierung in Python gezeigt.</p>
<p><span id="more-617"></span></p>
<h3>Problemvorstellung</h3>
<p>Die Probleme von <a href="http://projecteuler.net" target="_blank">projecteuler.net</a> sind aufgrund des meist recht hohen Rechenaufwands nicht nur durch Überlegen mit Bleistift und Papier zu lösen. Zumindest nicht in einem vertretbaren zeitlichen Rahmen. Ebenso häufig, wie die Probleme nicht ohne weiteres mit Bleistift und Papier lösbar sind, helfen diese Mittel das Problem besser zu verstehen und eine elegante Lösung zu erarbeiten.</p>
<p>Wie bereits bei der <a href="http://www.muvik.de/2010/04/30/projecteuler-loesung-zu-problem-4/">Lösung des vierten Problems</a>, lassen sich auch hier einige Gedanken machen, die schnell zur Lösung führen. Diesmal geht es sogar soweit, dass eine rein schriftliche Lösung ohne großen Aufwand eingereicht werden kann.</p>
<p>Obwohl das Problem an sich keine Herausforderung mehr darstellt, wenn die Probleme 1 bis 4 gelöst sind, habe von derzeit 1802789 Projecteuler-Mitgliedern nur 64072 es auch gelöst.</p>
<p>Doch worum handelt das Problem, welches spätestens auf den zweiten Blick einfach erscheint?</p>
<p><strong>Finde die kleinste Zahl, welche durch alle Zahlen von 1 bis 20 gerade teilbar ist!</strong></p>
<p>Als Beispiel zu dieser Fragestellung haben die Macher hinter Projecteuler.net das gleiche Problem mit den Zahlen von 1 bis 10  gelöst. Hiernach ergibt sich als Lösung: 2520.</p>
<h3>Problemeingrenzung</h3>
<p>Spätestens seit der <a href="http://www.muvik.de/2010/04/03/projecteuler-loesung-zu-problem-3/">Lösung des dritten Projecteuler-Problems</a> wissen wir, dass alle Zahlen eine eindeutige Primfaktorenzerlegung besitzen. Ebenfalls aus dem dritten Problem ist bekannt, wie wir eine Primfaktorenzerlegung durchführen können, dieses Wissen hilft uns an dieser Stelle weiter.</p>
<p>Wie können wir das bereits erworbene Wissen auf dieses Problem übertragen?</p>
<p>Gesucht ist eine Zahl, die durch alle Zahlen von 1 bis 20 ohne Rest teilbar ist. Gleichwertig kann auch eine Zahl gefunden werden, welche durch alle Primfaktoren der Zahlen 1 bis 20 ohne Rest teilbar ist. Also suchen wir erst einmal eine Menge an Primzahlen, welche die Zahlen 1 bis 20 abbilden kann. Dabei ist es nicht wichtig, dass alle 21 Zahlen gleichzeitig aus der Menge heraus gebildet werden können.</p>
<p>In Kürze ergibt sich aus den Überlegungen und dem bereits vorhandenen Wissen folgendes Vorgehen:</p>
<ol>
<li>Suchen aller Primzahlen bis 20 entweder im Kopf oder mit dem Sieb des Eratosthenes.</li>
<li>Suchen der Primfaktorenzerlegung aller Zahlen von 1 bis 20 und zusammenfassen aller Primfaktoren mit ihren Häufigkeiten in einer Menge.</li>
<li>Reduzieren der Häufigkeiten, damit jede Zahl mindestens ein Mal aus den Primfaktoren gebildet werden kann.</li>
</ol>
<p>Also beschränkt sich die Herausforderung der Aufgabe lediglich auf eine Primfaktorenzerlegung und etwas Abzählen der Häufigkeiten. Gehen wir es an!
</p>
<h3>Problemlösung</h3>
<p>Wie bereits in der Einleitung angedroht, versuche ich mich zum ersten Mal in dieser Serie mit einer einfachen, handschriftlichen Rechnung. Dazu gehe ich zielführenden nach den Punkten 1-3 aus dem vorangegangenen Abschnitt vor:</p>
<ol>
<li>Die Primzahlen bis 20 inkl. der 1:<code class="bash">1 2 3 5 7 11 13 17 19</code></li>
<li>Primfaktoren aller Zahlen außer der Primzahlen von 1 bis 20:<br />
<code class="bash">4: 2 2<br />
6: 2 3<br />
8: 2 2 2<br />
9: 3 3<br />
10: 2 5<br />
12: 2 2 3<br />
14: 2 7<br />
15: 3 5<br />
16: 2 2 2 2<br />
18: 2 3 3<br />
20: 2 2 2 5</code><br />
Daraus ergibt sich die folgende Gesamtverteilung:<br />
<div id="attachment_634" class="wp-caption alignnone" style="width: 410px"><img src="http://www.muvik.de/wp-content/uploads/2010/05/primefactors-e1274094265862.png" alt="Häufigkeitsverteilung der Primfaktoren" title="Primfaktoren" width="400" height="299" class="size-full wp-image-634" /><p class="wp-caption-text">Häufigkeitsverteilung der Primfaktoren</p></div><br />
Zur Lösung des Problems ist eine solche Darstellung nicht nötig. Um jedoch zu verdeutlichen, wie viel kleiner die gesuchte Zahl ist, wenn alle Faktoren, die zu viel sind, gestrichen werden, eignet sie sich hervorragend.
</li>
<li>Jetzt bleibt nur noch die einzelnen Primfaktorzerlegungen durch zu gehen und die Häufigkeiten der Primfaktoren zu zählen. Daraus ergibt sich folgende Verteilung:<br />
<div id="attachment_638" class="wp-caption alignnone" style="width: 410px"><img src="http://www.muvik.de/wp-content/uploads/2010/05/primefactor_red-e1274094888619.png" alt="Reduzierte Primfaktoren" title="Reduzierte Primfaktoren" width="400" height="300" class="size-full wp-image-638" /><p class="wp-caption-text">reduzierte Häufigkeitsverteilung</p></div><br />
Das war es schon! Das Multiplizieren aller verbleibenden Faktoren führt zu der gesuchten Zahl:<br />
<code class="bash">1*2*2*2*2*3*3*5*7*11*13*17*19 = 232792560</code>
</li>
</ol>
<h3>Alternative Lösung</h3>
<p>Als alternative Lösung verkaufe ich heute einfach die Python-Implementierung des zuvor beschriebenen handschriftlichen Lösungswegs:</p>
<pre class="brush:python">import numpy as np

def eratosthenes(N):
    """liefert alle Primzahlen bis N"""
    primes = np.arange(1,N+1,1)

    for i in np.arange(2,np.ceil(np.sqrt(N))+1,1):
        primes[i*i-1:N:i] = 0;

    return primes

def prime_fact_counter(N,testPrimes):
    nPrimes = np.size(testPrimes)
    countPrimes = np.zeros_like(testPrimes)

    for i in range(1,nPrimes,1):
        actPrime = testPrimes[i]
        while ((N%actPrime == 0) &#038; (N >= actPrime)):
            N = N / actPrime;
            countPrimes[i] = countPrimes[i] + 1
        countPrimes[0] = 1
    return countPrimes

def solver(N):
    searchProduct = 1.0
    testPrimes = np.trim_zeros(np.sort(eratosthenes(N)))

    freq = np.zeros_like(testPrimes) # array of prime occurance for each factor 1..20
    totFreq = np.zeros_like(testPrimes) # array of total prime occurance

    print(testPrimes)

    for i in range(1,N+1,1):
        freq = prime_fact_counter(i,testPrimes)
        for j in range(0,freq.size,1):
            if (freq[j] > totFreq[j]):
                totFreq[j] = freq[j]

    print(totFreq)

    for j in range(0,totFreq.size,1):
        searchProduct = searchProduct * (testPrimes[j])**(totFreq[j])

    return searchProduct

N = 20

print(solver(N))</pre>
<p>Insgesamt habe ich drei Funktionen definiert. Die erste Funktion ist der bereits bekannte Sieb des Eratosthenes. Sie berechnet alle Primzahlen bis zu einer Zahl N, oder anders ausgedrückt, alle in der Primfaktorenzerlegung vorkommenden Primzahlen der Zahl N.</p>
<p>Die zweite Funktion zählt die Anzahl der Primfaktoren einer bestimmten Zahl N. Das ist wichtig, um die maximale Häufigkeit eines Faktors in einer Zahl festzustellen. Zum Beispiel enthält die 16 genau vier mal die 2 als Faktor: <code class="bash">2*2*2*2 = 16</code>
</p>
<p>Die solver-Funktion durchläuft alle Zahlen von 1 bis 20, berechnet die Primfaktorenzerlegung und überprüft die Häufigkeiten. Am Ende wird aus der reduzierten Häufigkeitsverteilung die gesuchte Zahl errechnet.</p>
<p>Damit wäre das fünfte Problem von Projecteuler gelöst!</p>
<h3>Schlusswort</h3>
<p>Aufgrund des niedrigen Schwierigkeitsgrades des fünften Problems konnte zum ersten Mal in dieser Serie eine rein handschriftliche Lösung präsentiert werden. Alternativ dazu wurde auch eine Python-Implementierung aufgeführt, welche auch für Zahlen größer als N=20 geeignet ist.</p>
<p>In der Hoffnung, dass die simple Idee, die hinter dem Lösungsvorschlag steckt, klar geworden ist, freue ich mich wie immer auf Kommentare und Verbesserungsvorschläge.</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/">Permalink</a> |
<a href="http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/&title=Projecteuler: Lösung zu Problem 5">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/&title=Projecteuler: Lösung zu Problem 5">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/&title=Projecteuler: Lösung zu Problem 5">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/primzahlen/" rel="tag">Primzahlen</a>, <a href="http://www.muvik.de/tag/projecteuler/" rel="tag">Projecteuler</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/05/17/projecteuler-loesung-zu-problem-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kurztipp 5: Python-Code mit DocStrings testen</title>
		<link>http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/</link>
		<comments>http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/#comments</comments>
		<pubDate>Wed, 05 May 2010 09:00:13 +0000</pubDate>
		<dc:creator>Viktor Müller</dc:creator>
				<category><![CDATA[Kurztipps]]></category>
		<category><![CDATA[DocString]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.muvik.de/?p=540</guid>
		<description><![CDATA[Heute im Fokus: Testen von Funktionen mit den DocStrings. Auch unter Programmierern sind Stammtischgespräche verbreitet. Je nach Bewusstseinszustand vertritt der eine oder andere sogar die Meinung, dass der überwiegende Anteil der Zeit beim Entwickeln einer Software auf das Debuggen, Fehlersuchen und Testen verwendet wird. Auch wenn das wahr sein sollte, besteht für Python-Programmierer keinen Grund [...]]]></description>
			<content:encoded><![CDATA[<img class="cat-img-wide" alt="Viktors Kurztipp" src="http://muvik.de/categorie_images/viktorskurztipp.gif" title="Viktors Kurztipp zu diversen Themen" width="443" height="98" />
<p class="preview">Heute im Fokus: Testen von Funktionen mit den DocStrings. </br><br />
Auch unter Programmierern sind Stammtischgespräche verbreitet. Je nach Bewusstseinszustand vertritt der eine oder andere sogar die Meinung, dass der überwiegende Anteil der Zeit beim Entwickeln einer Software auf das Debuggen, Fehlersuchen und Testen verwendet wird. Auch wenn das wahr sein sollte, besteht für Python-Programmierer keinen Grund zur Unruhe, denn es gibt das <a href="http://docs.python.org/library/doctest.html" target="_blank">doctest</a>-Modul, welches das Testen von Python-Code leichter macht.</p>
<p><span id="more-540"></span></p>
<p>In dem Artikel &#8220;<a href="http://www.muvik.de/2010/03/26/python-dokumentation-mit-docstring/">Python Dokumentation mit DocString</a> bin ich bereits auf die DocStrings und die Möglichkeiten, welche diese bieten etwas eingegangen. Ganz beiläufig hieß es dabei (Zitat): </p>
<blockquote><p>Somit ergeben sich folgende Vorteile für Anwender und Coder:</p>
<ul>
<li>&#8230;</li>
<li>Beispiele in DocStrings können zum Veranschaulichen und Testen verwendet werden.</li>
</ul>
</blockquote>
<p>Dieser Aussage möchte ich heute anhand eines kleinen Beispiels mehr Inhalt geben. Zumindest was das &#8220;Testen&#8221; angeht.
</p>
<h3>Szenario</h3>
<p>Die modulare Entwicklung von Software birgt etliche Vorteile, von denen an dieser Stelle besonders eine ganz wichtig ist. Zum Einen steigert die modulare Methode die Übersichtlichkeit und erleichtert das Verstehen der kleineren Bausteine im Vergleich zum großen Ganzen. Der größte Vorteil ist jedoch der enorme Zeitgewinn. An jedem Modul kann ein anderer Programmierer sich die Finger wund tippen. Am Ende werden die voll funktionsfähigen Einzelmodule zusammengeführt und ergeben das endgültige Produkt. </p>
<p>Damit das Zusammenführen reibungslos vonstatten gehen kann, müssen die Einzelmodule zuvor eingehen getestet werden. An dieser Stelle kommen die DocStrings mit dem doctest-Module ins Spiel.</p>
<p>Einleitend in dieses Thema lässt sich die Funktion der Kombination aus DocString und doctest-Modul folgendermaßen zusammenfassen: Innerhalb des DocStrings wird der Python-Kommandozeilenaufruf nachgestellt und das zu erwartende Ergebnis angegeben.</p>
<p>An einem kleinen Beispiel wird dies deutlicher.</p>
<h3>Komplizierte Beispielfunktion</h3>
<p>Um den Kurztipp anschaulicher zu gestalten, habe ich mir eine sehr wichtige Funktion einfallen lassen <img src='http://www.muvik.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> :</p>
<pre class="brush:python">def addtwo(x):
    """Addiert zu jeder Zahl eine Zwei hinzu:

    >>> addtwo(3.0)
    5.0

    >>> addtwo(0.0)
    2.0
    """

    return x + 2.0</pre>
</p>
<p>Die Beispielfunktion erhöht jede Zahl x um zwei und gibt diese zurück. Damit mit Sicherheit klar ist, was sie tut, wird der Zweck und Sinn innerhalb eines DocStrings beschrieben. Zusätzlich wird die Funktion im DocString zwei Mal &#8220;aufgerufen&#8221; und das dazugehörige Ergebnis angegeben.</p>
<p>Die drei spitzen Klammern sollen hierbei die Python-Kommandozeile symbolisieren.</p>
<p>Wie erfolgt nun der Test, ob die Funktion auch das richtige Ergebnis liefert?</p>
<p>Das doctest-Modul führt die Anweisungen, vor denen der Python-Prompt (>>>) steht, aus und vergleicht das Ergebnis mit dem erwarteten Wert, welcher unterhalb des Prompts steht. In der Standardeinstellung liefert doctest nichts zurück, wenn beide Zahlen gleich sind, stimmen sie nicht überein, so gibt es eine Fehlermeldung:<br />
<code class="bash">> python -m doctest addtwo.py </code></p>
<p>Dieser Skriptaufruf hat keine Ausgabe zur Folge, weswegen man sich entspannen und davon ausgehen kann, dass die Funktion in Ordnung ist.</p>
<p>Möchte man auf etwas Feedback nicht verzichten, dann lässt sich das Skript auch mit einer ausführlichen Version starten:<br />
<code class="bash">> python -m doctest -v addtwo.py<br />
Trying:<br />
    addtwo(3.0)<br />
Expecting:<br />
    5.0<br />
ok<br />
Trying:<br />
    addtwo(0.0)<br />
Expecting:<br />
    2.0<br />
ok<br />
1 items had no tests:<br />
    addtwo<br />
1 items passed all tests:<br />
   2 tests in addtwo.addtwo<br />
2 tests in 2 items.<br />
2 passed and 0 failed.<br />
Test passed.</code></p>
<p>Und wenn etwas nicht richtig läuft, wenn zum Beispiel statt zwei nur eins hinzu addiert wird:<br />
<code class="bash">> python -m doctest -v addtwo.py<br />
Trying:<br />
    addtwo(3.0)<br />
Expecting:<br />
    5.0<br />
***************************************************<br />
File "addtwo.py", line 4, in addtwo.addtwo<br />
Failed example:<br />
    addtwo(3.0)<br />
Expected:<br />
    5.0<br />
Got:<br />
    4.0<br />
Trying:<br />
    addtwo(0.0)<br />
Expecting:<br />
    2.0<br />
***************************************************<br />
File "addtwo.py", line 7, in addtwo.addtwo<br />
Failed example:<br />
    addtwo(0.0)<br />
Expected:<br />
    2.0<br />
Got:<br />
    1.0<br />
1 items had no tests:<br />
    addtwo<br />
***************************************************<br />
1 items had failures:<br />
   2 of   2 in addtwo.addtwo<br />
2 tests in 2 items.<br />
0 passed and 2 failed.<br />
***Test Failed*** 2 failures.<br />
</code>
</p>
<h3>Fazit</h3>
<p>DocStrings in Kombination mit doctest stellen in meinen Augen eine praktische und leicht handhabbare Methode dar, um Module, Funktion und Klassen zu testen und gleichzeitig den Funktionsaufruf direkt im DocString und damit in der Dokumentation zu demonstrieren.</p>
<p><a href="http://partners.webmasterplan.com/click.asp?ref=515746&site=6989&type=text&tnb=1" target="_blank">
Deine Stadt - Dein Preis</a><br />Mit CityDeal und vielen Anderen
den Preis drücken!<br /><img src="http://banners.webmasterplan.com/view.asp?ref=515746&site=6989&type=text&tnb=1&js=1" BORDER="0" WIDTH="1" HEIGHT="1" /></p>
<hr />
<p><small>© Muvik for <a href="http://www.muvik.de">muvik-multigrid</a>, 2010. |
<a href="http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/">Permalink</a> |
<a href="http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/#comments">keine Kommentare</a> |
Teile es mit deinen Freunden:
<a href="http://del.icio.us/post?url=http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/&title=Kurztipp 5: Python-Code mit DocStrings testen">del.icio.us</a>
<a href="http://www.mister-wong.de/addurl/?bm_url=http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/&title=Kurztipp 5: Python-Code mit DocStrings testen">MisterWong</a>
<a href="http://twitter.com/home?status=http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/&title=Kurztipp 5: Python-Code mit DocStrings testen">Twitter</a>
<br/>
Tags: <a href="http://www.muvik.de/tag/docstring/" rel="tag">DocString</a>, <a href="http://www.muvik.de/tag/python/" rel="tag">Python</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://www.muvik.de/2010/05/05/kurztipp-5-python-code-docstrings-testen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

