Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > de.comp.lang.java > #12917 > unrolled thread
| Started by | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| First post | 2016-04-08 23:28 +0200 |
| Last post | 2016-04-25 21:42 +0200 |
| Articles | 20 on this page of 39 — 6 participants |
Back to article view | Back to de.comp.lang.java
Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-08 23:28 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-09 16:13 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-10 15:41 +0200
Re: Rekursion bricht nicht ab Peter Büttner <not_for_mail_peb@gmx.net> - 2016-04-10 16:45 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-10 18:28 +0200
Re: Rekursion bricht nicht ab Wanja Gayk <brixomatic@yahoo.com> - 2016-04-13 19:25 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-13 21:56 +0200
Re: Rekursion bricht nicht ab Wanja Gayk <brixomatic@yahoo.com> - 2016-04-23 16:13 +0200
Re: Rekursion bricht nicht ab Wanja Gayk <brixomatic@yahoo.com> - 2016-04-23 16:13 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-23 17:31 +0200
Re: Rekursion bricht nicht ab Wanja Gayk <brixomatic@yahoo.com> - 2016-04-25 00:53 +0200
Re: Rekursion bricht nicht ab Wanja Gayk <brixomatic@yahoo.com> - 2016-04-25 00:56 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-23 19:22 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-14 00:42 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-14 09:20 +0200
Re: Rekursion bricht nicht ab Christoph Schneegans <Christoph@Schneegans.de> - 2016-04-14 18:47 +0200
Re: Rekursion bricht nicht ab Wanja Gayk <brixomatic@yahoo.com> - 2016-04-23 16:13 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-25 12:07 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-25 17:38 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-25 22:36 +0200
Re: Rekursion bricht nicht ab Wanja Gayk <brixomatic@yahoo.com> - 2016-04-28 08:26 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-10 22:15 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-12 15:46 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-12 18:32 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-13 20:44 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-14 12:07 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-23 13:35 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-23 14:57 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-25 23:05 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-26 01:16 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-23 16:05 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-25 12:48 +0200
Re: Rekursion bricht nicht ab v_borchert@despammed.com (Volker Borchert) - 2016-04-10 06:07 +0000
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-10 15:40 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-11 11:21 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-12 15:57 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-12 18:28 +0200
Re: Rekursion bricht nicht ab "Christian H. Kuhn" <qno-news@qno.de> - 2016-04-12 23:36 +0200
Re: Rekursion bricht nicht ab Patrick Roemer <sangamon@netcologne.de> - 2016-04-25 21:42 +0200
Page 1 of 2 [1] 2 Next page →
| From | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| Date | 2016-04-08 23:28 +0200 |
| Subject | Rekursion bricht nicht ab |
| Message-ID | <dmqm4qFkm0hU1@mid.individual.net> |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Hallo Gemeinde, Die letzten paarundzwanzig Mal hat sich die Lösung beim Schreiben der Hilfebitte gefunden, diesmal wohl nicht ... Ich bringe mir gerade Continous Integration bei, weil ich nicht ausschließen will, dass ich das mal beruflich brauche. Eclipse, Git, Maven, Jenkins, verteilt auf LapTop, Tower und remote server. Ein paar Tests mit Checkstyle, JUnit4, JaCoCo. Was genau davon sinnvoll ist, ist diskutierbar, hier geht es eher um die Bedienung. Und um die Technik zu testen, habe ich mir als Fingerübung einen Lösungsfinder für das Android-Spiel Lyfoes geschrieben. Die Vorbereitung war natürlich das aufwendigste. TDD, ein paar Klassen, aus denen die Hauptklasse nachher zusammengesetzt wird, die ganzen Tests, Checkstyle besteht auf javadoc, Variablennamen im richtigen Format, dann doch einen Testfall vergessen und zu geringe Testabdeckung (und dabei auch gelernt, warum 100% Testabdeckung nicht immer nur Fetisch ist), und ganz zum Schluss die eigentliche Lösungssuche. Natürlich per Rekursion. Die Lyfoes werden durch Buchstaben repräsentiert, die Reagenzgläser durch Vector<Character>, das gesamte Setup durch Vector<Vector<Character>>. Im Prinzip wird bei getResult() überprüft: - - Stellung gelöst? Dann Zugfolge bis hierher als Lösung zurückgeben. - - Stellung schon mal gesehen? Dann null zurückgeben, ansonsten hash der Stellung in Set für diesen Rekursionszweig zufügen. - - Mögliche Zugliste generieren. Liste leer? Null zurückgeben. - - Züge ausführen, auf neue Stellung getResult() aufrufen (die Rekursion). Wenn erhaltenes result != null, kommt es in eine Liste allResults. - - Nach ausführen aller Züge: Wenn allResults leer, null zurückgeben. Sonst eine kürzeste Zugfolge aus allResults zurückgeben. Klappt in einigen einfachen Testfällen. Klappt insbesondere dann, wenn in der Startposition nur ein leeres Reagenzglas als Puffer fürs Umsortieren ist. Sobald da zwei sind, bricht die Rekursion nicht mehr ab. Ich sehe zwei Möglichkeiten: Entweder habe ich eine Abbruchbedingung übersehen. Ich finde aber keine weitere. Oder die hashCode-Funktion für die Stellungen taugt nix. Den Verdacht hatte ich eh, aber eher in die andere Richtung: dass ich für eine neue Stellung den gleichen hash habe wie für eine bisherige und deshalb Lösungen nicht finde. Ideal wäre eine bijektive hash-Funktion, die aber den Zahlenraum int nicht sprengt ... Aufgrund dieser allgemeinen Beschreibung wird mir niemand helfen können. Der Quellcode ist hier: https://www.qno.de/lyfoesolver.zip steht unter keiner Lizenz (jedenfalls wüsste ich nichts), lachen ist erlaubt ;-) (ebenfalls zu Lernzwecken habe ich alles Mögliche und vermutlich manches mehr mit Exceptions geregelt). Für Hinweise, wo genau ich mich wie dämlich angestellt habe, bin ich dankbar. TIA QNo -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJXCCKNAAoJEGVI2lsCpSdTX6kP/3/l3+9Jt/bV8WxEJL25H1tQ WkD0L3iuJSL5g/zIo5LzwMIUV3aviSKwJbNJe51NAxO7V68WG24HcQVhMjd0WX0O eUcFZiCA8weqEC5636gKrGB5Z82N//fp/THDeH/TohFqe3egc8579+oXWb9mRxh6 sq1oLiKkVDDz7GViqzhbEOyX6YBR1GanZyn8XdlbVBEMEsfLzcpfr3rYPw5tsu4m udrAExVCGFByDAo4yJ1/ll58mKc4LiYWYnTQ+qg5VSumg3YJAdbtH9zfFSrTOtUj nuL0sSNRn2dYd7QzOLco/el2ktdQILXwLoC+EPC3MsJAKWv2S3eAzMCNdfUyMTzg oVh/oak65aL8N2MIG5Vz2YyNsMaNtqdi55AvjO5oNxCFCArTa0F0URSmwDfl23AT cz6msKE6amOKn83ExcObGBChi9XKoaZupBn/naVBXbwhfllcYpABmMOXf0PyoA5l jQvgDcC5DPl0++Z5L4VcggikXwufjgXlZ8147ErBa/PMT5GAcywa09Ln/LAASWWg 0B4MQ/2AHqls841FbXmDkfYoiL9gFtOtnVQUJ035IgJcABUQtolSYZPMKRg3vVuy f42ULLw4NfZNyyhEQkUh/0TTw3VUzuPbLrFzQpq9RymU/a0/EJmnHnD+Idnj17Xs Y2/PUTTaAxwhMnUOyEY5 =KC/a -----END PGP SIGNATURE-----
[toc] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-04-09 16:13 +0200 |
| Message-ID | <neb2mi$m27$1@newsreader4.netcologne.de> |
| In reply to | #12917 |
Responding to Christian H. Kuhn: > Klappt in einigen einfachen Testfällen. Klappt insbesondere dann, wenn > in der Startposition nur ein leeres Reagenzglas als Puffer fürs > Umsortieren ist. Sobald da zwei sind, bricht die Rekursion nicht mehr ab. Geh das kleinstmögliche Szenario, bei dem das Verhalten auftritt, mal mit Papier und Stift von Hand durch. Dann lass in Deinem Programm in jedem Rekursionsschritt den Spielzustand ausgeben (oder steppe im Debugger durch) und vergleiche mit Deinen Erwartungen. Oft findet man so schon raus, wo es hakt. > Aufgrund dieser allgemeinen Beschreibung wird mir niemand helfen > können. Der Quellcode ist hier: https://www.qno.de/lyfoesolver.zip Es wird wohl schwierig, anhand dieses Codes hier Hilfe zu finden - schon alleine, weil man ja erst mal verstehen müsste, worum es bei dem Spiel überhaupt geht. :) Zumindest wäre es sinnvoll, ein paar funktionierende Testfälle beizulegen, und einen, der das Problem demonstriert. Viele Grüße, Patrick
[toc] | [prev] | [next] | [standalone]
| From | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| Date | 2016-04-10 15:41 +0200 |
| Message-ID | <dmv3g8Fngq5U2@mid.individual.net> |
| In reply to | #12918 |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Am 09.04.2016 um 16:13 schrieb Patrick Roemer: > Responding to Christian H. Kuhn: Geh das kleinstmögliche Szenario, > bei dem das Verhalten auftritt, mal mit Papier und Stift von Hand > durch. Dann lass in Deinem Programm in jedem Rekursionsschritt den > Spielzustand ausgeben (oder steppe im Debugger durch) und > vergleiche mit Deinen Erwartungen. Oft findet man so schon raus, > wo es hakt. Also erstmal versucht, das kleinstmögliche Szenario zu finden. Und dabei festgestellt, dass der Rekursionsbaum bei sonst gleichbleibenden Bedingungen exponentiell mit der Anzahl der leeren Reagenzgläser wächst. Ich hatte keine nicht abbrechende Rekursion, ich habe lediglich die Rechenzeit massiv unterschätzt. Tage statt Minuten. Ich werde also einen anderen Ansatz verwenden müssen, der den Suchbaum Stufe für Stufe aufbaut und auf Lösungen überprüft, bevor die nächste Stufe berechnet wird. > Es wird wohl schwierig, anhand dieses Codes hier Hilfe zu finden - > schon alleine, weil man ja erst mal verstehen müsste, worum es bei > dem Spiel überhaupt geht. Ich nahm an, ein Spiel, das sogar ich kenne, müsse allgemein bekannt sein, offensichtlich irrte ich Lyfoes ist ein Android-Spiel. Man hat einen Satz von gefärbten pelzigen Lebewesen, genannt Lyfoes. Die kommen in verschiedenen Farben. Ausgangslage: Viele Lyfoes bunt verteilt auf Reagenzgläser (Anzahl pro Farbe gleich Fassungsvermögen eines Glases, bisher gesichtet 3 oder 4. Anzahl der Gläser gleich Anzahl der Farben plus eins oder zwei für leere Gläser). Ziel: Alle Gläser nur mit gleichfarbigen gefüllt oder leer. Zug: Lyfoe aus einem Glas in ein leeres oder in ein nichtvolles mit gleichfarbigem oberem Lyfoe. > Zumindest wäre es sinnvoll, ein paar funktionierende Testfälle > beizulegen, und einen, der das Problem demonstriert. Sind in LSBoard.main(). Vielen Dank QNo -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJXClf7AAoJEGVI2lsCpSdT2/QP/RI15A3F5IYHe9kVoS4WrMQy aSXXsdkPO7FpDjCDPQEWjbf9rBK7OExVOuMLSBiwioV3Qce+pNpc+KHE06FgkjtF qLvfMVel2EnOP8Hzk+sBp7ko76qC5HJ/hRwzrs/ZXZ7ut7Qy0JibzHVVfVG30Vd6 eALFiRZHLJcTNkjblEZ7XqQU7bQrMFcemcC2ZqJFbkMIj/Ic+NWb0/PrHyvkaoeu Wbxn6zMbFPxDbFi1kUe4pTsRZ+w5NAbcppTJQpoIibnVl1lJBrMuSp9bbaPyV3oP KAM9ucsUyEkc7Z7ba5vM4VO9C/DQGhQHxh0mfbBTKY4FtpPA8n09iww31y4jJWGd Zn8H4LyVWQHYseNxgdcuZeUL93MfcOC2FCoxPPA6VQrTCXxlmFnSpbaXaA9cP7ir X4s8UyGZC+zqoSQHVzgRN4t6p6qdGuRfLnSB2F9Oy9ojBzwpYJtblR2mpvoBnpVw BZYm/YU7w37EUbudUNIuVnCGOYj+sMFKVhU4ei06oIZDpC0AuX3GxxGRyCzpe2Yu lEN2fVMXT8Be9DDYomjSsOIlNZIyg4M387v3U0ziikjh2QhBOmAnCx9u0YrXNeTw xCVQ3/IyfTpBJ4v7wlJuce6YInAszf2uqSA1KputXMFRfDzDdoh/gRBSXCB3YCeE dHpcs9gt2Qc9ItgnVTsG =Vn1e -----END PGP SIGNATURE-----
[toc] | [prev] | [next] | [standalone]
| From | Peter Büttner <not_for_mail_peb@gmx.net> |
|---|---|
| Date | 2016-04-10 16:45 +0200 |
| Message-ID | <dmv77lFoggiU1@mid.individual.net> |
| In reply to | #12922 |
Am 10.04.2016 15:41, schrieb Christian H. Kuhn: >> schon alleine, weil man ja erst mal verstehen müsste, worum es bei >> dem Spiel überhaupt geht. > Ich nahm an, ein Spiel, das sogar ich kenne, müsse allgemein bekannt > sein, offensichtlich irrte ich Lyfoes ist ein Android-Spiel. Man > hat einen Satz von gefärbten pelzigen Lebewesen, genannt Lyfoes. Die > kommen in verschiedenen Farben. Ausgangslage: Viele Lyfoes bunt > verteilt auf Reagenzgläser (Anzahl pro Farbe gleich Fassungsvermögen > eines Glases, bisher gesichtet 3 oder 4. Anzahl der Gläser gleich > Anzahl der Farben plus eins oder zwei für leere Gläser). Ziel: Alle > Gläser nur mit gleichfarbigen gefüllt oder leer. Zug: Lyfoe aus einem > Glas in ein leeres oder in ein nichtvolles mit gleichfarbigem oberem > Lyfoe. Letztlich wie ein Kartenspiel Patience (da gibt es hunderte, eins passt schon). Vielleicht findest du da ein Konzept zur Lösung, oder eine Inspiration. "Sortieren mit beschränkten Ressourcen". Das es bei dir mit Brute force zu lange dauert kann natürlich auch an 'schlecht Programmiert' liegen:-) (deinen Code schaute ich mir nicht an). Peter
[toc] | [prev] | [next] | [standalone]
| From | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| Date | 2016-04-10 18:28 +0200 |
| Message-ID | <dmvd9oFq327U1@mid.individual.net> |
| In reply to | #12923 |
Am 10.04.2016 um 16:45 schrieb Peter Büttner: > Das es bei dir mit Brute force zu lange dauert kann natürlich auch > an 'schlecht Programmiert' liegen:-) (deinen Code schaute ich mir > nicht an). Bei brute force steigt der Rechenaufwand halt von Level zu Level um einen Faktor. Der ändert sich nicht, egal wie grausam man codiert. Und wenn ich meine Minimalbeispiele im Test anschaue, dann erreiche ich bei einer Geschwindigkeitssteigerund um Faktor 1000 immer noch keine Lösung realistischer Stellungen in realistischer Zeit. Ansonsten kann ich mir gut vorstellen, dass ich unter Effizienzgesichtspunkten „schlecht programmiert“ habe. Ich könnte mir gut vorstellen, dass Fehlerbehandlung im C-Stil über einen int-Rückgabewert schneller funktioniert als der etwas ... ausufernde Gebrauch von Exceptions. Deren Verwendung sauber durchzuziehen war aber Lernziel. Sollte ich je eine auf Effizienz getrimmte Fassung schreiben, werde ich das überdenken. lg QNo
[toc] | [prev] | [next] | [standalone]
| From | Wanja Gayk <brixomatic@yahoo.com> |
|---|---|
| Date | 2016-04-13 19:25 +0200 |
| Message-ID | <MPG.31789f5985a68ae9896b0@news.aioe.org> |
| In reply to | #12924 |
In article <dmvd9oFq327U1@mid.individual.net>, Christian H. Kuhn (qno- news@qno.de) says... > > Ansonsten kann ich mir gut vorstellen, dass ich unter > Effizienzgesichtspunkten ?schlecht programmiert? habe. Ich könnte mir > gut vorstellen, dass Fehlerbehandlung im C-Stil über einen > int-Rückgabewert schneller funktioniert als der etwas ... ausufernde > Gebrauch von Exceptions. Deren Verwendung sauber durchzuziehen war aber > Lernziel. Sollte ich je eine auf Effizienz getrimmte Fassung schreiben, > werde ich das überdenken. Ich glaube nicht, dass das das Problem ist, sondern bei derart harten Geschwindigkeitsproblemen solltest du den Flaschenhals a) im Algorithmus suchen (insb. bei Rekursion: Werden z.B. bereits gewonnene Erkentnisse verworfen und/oder neu berechnet, obwohl man sie sich merken kann?) oder b) in der Datenstruktur (z.B. du löscht immer Werte am Anfang einer ArrayList, das ist O(n) -> bei einer LinkedList ist removeFirst() nur O (1), z.B. du iterierst ohnehin immer durch eine Liste und ab und zu löscht du was an der aktuellen Position, dann ist LinkedList und Iterator#remove() besser statt ArrayList#remove(n) oder LinkedList#remove(n), oder z.B. die Suche in einem Ergebnis ist linear, dabei ist die Liste selten geschriebenm aber oft gelesen und eine binäre Suche ist schneller, oder vielleicht willst du auch eine HashMap, zb. ein HashSet, um zu checken, ob etwas schon vorhanden ist?) oder c) in der Speicherverwaltung - und zwar weniger im Erzeugen von vielen, kurzlebigen Objekten, sondern darin dem Garbage-Collector nicht genügend Speicher gegeben zu haben( -verbose:gc ), sodass es unnötig viele full garbage collections gibt. Der Overhead vom Exceptionhandling ist jedenfalls in 99.9999999999999% aller Fälle kein Problem. Aber wie immer: Wer nicht misst, liegt in der Regel falsch. Schau dur dazu am besten das Tool "JVisualVM" an und versuch dort einmal einmal mit dem Sampler und einmal mit dem Profiler deine Applikation zu vermessen und schau, wo die meiste Zeit drauf geht (Sampler und Profiler haben beide Vor- und Nachteile, der Sampler erwischt oft häufige sehr kurze Aufrufe nicht, der Profiler bläst ggf. kurze Aufrufe mit seinem eigenen Overhead auf). Download hier: https://visualvm.java.net/ Gruß, -Wanja- -- ..Alesi's problem was that the back of the car was jumping up and down dangerously - and I can assure you from having been teammate to Jean Alesi and knowing what kind of cars that he can pull up with, when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]
[toc] | [prev] | [next] | [standalone]
| From | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| Date | 2016-04-13 21:56 +0200 |
| Message-ID | <dn7mkmFu468U1@mid.individual.net> |
| In reply to | #12932 |
Hallo Wanja, Danke für die Hinweise. Am 13.04.2016 um 19:25 schrieb Wanja Gayk: > a) im Algorithmus suchen (insb. bei Rekursion: Werden z.B. bereits > gewonnene Erkentnisse verworfen und/oder neu berechnet, obwohl man sie > sich merken kann?) Zur Zeit sicher so. Ich suche bis Tiefe n. Wenn ich keine Lösung habe, suche ich bis Tiefe n+1, baue den Baum aber komplett neu auf. Ich müsste alle Stellungen in Tiefe n speichern und im nächsten Durchlauf dann bearbeiten. Spart viel Zeit, kostet viel Speicher. Werde ich in der nächsten Version probieren. > b) in der Datenstruktur (z.B. du löscht immer Werte am Anfang einer > ArrayList, das ist O(n) -> bei einer LinkedList ist removeFirst() nur O > (1), z.B. du iterierst ohnehin immer durch eine Liste und ab und zu > löscht du was an der aktuellen Position, dann ist LinkedList und > Iterator#remove() besser statt ArrayList#remove(n) oder > LinkedList#remove(n), oder z.B. die Suche in einem Ergebnis ist linear, > dabei ist die Liste selten geschriebenm aber oft gelesen und eine binäre > Suche ist schneller, oder vielleicht willst du auch eine HashMap, zb. > ein HashSet, um zu checken, ob etwas schon vorhanden ist?) Hm. Werde ich ausprobieren und messen müssen. Wo ich nur peek, pop und push brauche, verwende ich einen Stack<>, und da der von Vector<> erbt, kann ich beim Hashen auch mal eben durchiterieren. Zum Speichern schon gesehener Stellungen benutze ich je nachdem HashMap oder HashSet. Die ArrayList<>s habe ich aufgrund deines Posts mal mit LinkedList<>s ersetzt, weil ich tatsächlich hauptsächlich durchiteriere und nur gelegentlichst mal auf eine Index-Position zugreife. Allerdings ohne signifikanten Zeitvorteil. Werde ich mir nochmal genauer anschauen. > c) in der Speicherverwaltung - und zwar weniger im Erzeugen von vielen, > kurzlebigen Objekten, sondern darin dem Garbage-Collector nicht genügend > Speicher gegeben zu haben( -verbose:gc ), sodass es unnötig viele full > garbage collections gibt. Auch damit habe ich mal rumgespielt. Speicher bleibt bislang insgesamt unter 300 MB, -Xmx1g hat keine Zeitveränderung gezeigt. > Download hier: https://visualvm.java.net/ Das ist doch mal ein interessantes Werkzeug :-) Warum lernt man sowas nicht im Studium? Vielen Dank! lg QNo
[toc] | [prev] | [next] | [standalone]
| From | Wanja Gayk <brixomatic@yahoo.com> |
|---|---|
| Date | 2016-04-23 16:13 +0200 |
| Message-ID | <MPG.318596afa70f02789896b2@news.aioe.org> |
| In reply to | #12934 |
In article <dn7mkmFu468U1@mid.individual.net>, Christian H. Kuhn (qno-
news@qno.de) says...
> Die
> ArrayList<>s habe ich aufgrund deines Posts mal mit LinkedList<>s
> ersetzt, weil ich tatsächlich hauptsächlich durchiteriere und nur
> gelegentlichst mal auf eine Index-Position zugreife.
Dazu muss ich vielleicht etwas erklären:
Ein stumpfes list.remove(x) ist bei ArrayList und LinkedList etwa gleich
schnell - die eine verschwendet die Zeit beim Zugriff auf den Index, die
andere beim Kopieren der restlichen Elemente "nach links" um die Lücke
am gelöschten Index zu entfernen.
Bei einer LinkedList wird beim Löschen lediglich das nächste Objekt an
das vorherige geknüpft und das aktuelle Objekt ist damit nicht mehr
referenziert), während das Löschen aus einer ArrqaList bedeutet, dass
alle folgenden Positionen eine Position "nach links" kopiert werden
müssen. Dafpr muss die LinkesList der Kette ablaufen, bis es am
jeweiligen index ist.
Der Vorteil der LinkedList stellt sich also nur in einer recht
speziellen Situation ein, nämlich wenn du während des Iterierens löscht.
Iterator<X> it = arrayList.iterator();
while(it.hasNext()){ O(n)
if(canBeUsed(x)){
use(x);
}
if(mustBeDeleted(x)){
it.remove(); //ist O(n) für ArrayList
}
}
Iterator<X> it = linkedList.iterator();
while(it.hasNext()){ /O(n)
if(canBeUsed(x)){
use(x);
}
if(mustBeDeleted(x)){
it.remove(); //ist O(1) für LinkedList
}
}
Hier hat die ArrayList O(n*n) und die LinkedList O(n).
Gruß,
-Wanja-
--
..Alesi's problem was that the back of the car was jumping up and down
dangerously - and I can assure you from having been teammate to
Jean Alesi and knowing what kind of cars that he can pull up with,
when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]
[toc] | [prev] | [next] | [standalone]
| From | Wanja Gayk <brixomatic@yahoo.com> |
|---|---|
| Date | 2016-04-23 16:13 +0200 |
| Message-ID | <MPG.3185a0b7dd16d81a9896b4@news.aioe.org> |
| In reply to | #12934 |
In article <dn7mkmFu468U1@mid.individual.net>, Christian H. Kuhn (qno- news@qno.de) says... > Zur Zeit sicher so. Ich suche bis Tiefe n. Wenn ich keine Lösung habe, > suche ich bis Tiefe n+1, baue den Baum aber komplett neu auf. Ich müsste > alle Stellungen in Tiefe n speichern und im nächsten Durchlauf dann > bearbeiten. Spart viel Zeit, kostet viel Speicher. Werde ich in der > nächsten Version probieren. An der Stelle ist ein BloomFilter eine interessante Datenstruktur. Ein Bloomfilter kanndir mit Sicherheit sagen, dass er eine bytefolge noch nie gesehen hat, kann aber fälschlicherweise behaupten, er würde eine bytefolge schon kennen, auch wenn er sie noch nie gesehen hat. Kurz, er antwortet so: Filter, habe ich das schon geprüft? Sicher nicht! Filter, habe ich das schon geprüft? Wahrscheinlich ja. Weil ein Bloomfilter aber nur ein (oder mehrere) Bitfelder sind, deren Bits über mehrere hashes einer Bytefolge gesetzt werden, braucht er, verglichen mit einem HashSet wenig Speicher, hat aber eben die Unsicherheit, dass er behaupten kann "kenne ich schon", obwohl man es nie rein getan hat. Bzgl. dienes Problems kannst du also die Teilbäume, die keine Lösung enthoelten in einen BloomFilter schicken und den immer fragen: "Hey, kennst du den Teilbaum?" (war der Teilbaum ein Miserfolg?) und wenn der sagt: "Den kenne ich nicht!", weißt du, dass den Baum neu aufbauen und prüfen musst. In der Guava Bibliothek (https://github.com/google/guava ) gibt es eine Implementation für einen BloomFilter: Siehe javadoc: https://google.github.io/guava/releases/snapshot/api/docs/com/google/com mon/hash/BloomFilter.html Siehe Sourcecode: https://github.com/google/guava/blob/master/guava/src/com/google/common/ hash/BloomFilter.java Download: https://github.com/google/guava/releases/tag/v19.0 Gruß, -Wanja- -- ..Alesi's problem was that the back of the car was jumping up and down dangerously - and I can assure you from having been teammate to Jean Alesi and knowing what kind of cars that he can pull up with, when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-04-23 17:31 +0200 |
| Message-ID | <nfg4g6$11j$1@newsreader4.netcologne.de> |
| In reply to | #12952 |
Responding to Wanja Gayk: > In article <dn7mkmFu468U1@mid.individual.net>, Christian H. Kuhn (qno- > news@qno.de) says... > >> Zur Zeit sicher so. Ich suche bis Tiefe n. Wenn ich keine Lösung habe, >> suche ich bis Tiefe n+1, baue den Baum aber komplett neu auf. Ich müsste >> alle Stellungen in Tiefe n speichern und im nächsten Durchlauf dann >> bearbeiten. Spart viel Zeit, kostet viel Speicher. Werde ich in der >> nächsten Version probieren. > > An der Stelle ist ein BloomFilter eine interessante Datenstruktur. > Ein Bloomfilter kanndir mit Sicherheit sagen, dass er eine bytefolge > noch nie gesehen hat, kann aber fälschlicherweise behaupten, er würde > eine bytefolge schon kennen, auch wenn er sie noch nie gesehen hat. > > Kurz, er antwortet so: > Filter, habe ich das schon geprüft? Sicher nicht! > Filter, habe ich das schon geprüft? Wahrscheinlich ja. Den Hinweis verstehe ich in diesem Kontext nicht. Es gibt zum einen eine "Menge der aktuell weiter zu untersuchenden Stellungen" - eben Christians obenstehendes "alle Stellungen in Tiefe n", also die Queue in der Breitensuche. Da braucht man offenkundig die konkreten Stellungen selber, nicht nur die Information, ob Stellung x schon gesehen wurde. Zum anderen will man vermeiden, bereits untersuchte Stellungen noch einmal zu durchlaufen. Da bringt ein Bloomfilter aber auch nix. Wenn ich eine Stellung sicher nicht gesehen habe, muss ich sie untersuchen. Wenn ich eine Stellung wahrscheinlich schon gesehen habe, muss ich sie auch untersuchen, denn es könnte ja sein, dass sie doch nicht gesehen wurde, und dass es sich um die Stellung handelt, die zur (kürzesten oder gar einzigen) Lösung führt. Das war ja genau das Problem mit Christians initialem #hashCode()-Ansatz. (Ist ja auch nah verwandt.) Für die gesehenen Stellungen würde ich zunächst mal ein ordinäres HashSet verwenden. Wenn sich rausstellt, dass das tatsächlich in Speicherprobleme läuft, würde ich erst mal schauen, ob man die Repräsentation der Stellungen nicht kompakter hinbekommt. Nur, wenn da das Ende der Fahnenstange erreicht ist, würde ich für die gesehenen Stellungen eine kompaktere Alternativrepräsentation verwenden - das könnte z.B., wenn ich das richtig verstanden habe, Christians "bigHashCode" sein. Auf jeden Fall will man sicher sein, dass nicht gesehene Stellungen *immer* überprüft werden. Habe ich da was falsch verstanden oder übersehen? Viele Grüße, Patrick
[toc] | [prev] | [next] | [standalone]
| From | Wanja Gayk <brixomatic@yahoo.com> |
|---|---|
| Date | 2016-04-25 00:53 +0200 |
| Message-ID | <MPG.31876cabfd61f0ff9896b5@news.aioe.org> |
| In reply to | #12953 |
In article <nfg4g6$11j$1@newsreader4.netcologne.de>, Patrick Roemer (sangamon@netcologne.de) says... > >> Zur Zeit sicher so. Ich suche bis Tiefe n. Wenn ich keine Lösung habe, > >> suche ich bis Tiefe n+1, baue den Baum aber komplett neu auf. Ich müsste > >> alle Stellungen in Tiefe n speichern und im nächsten Durchlauf dann > >> bearbeiten. Spart viel Zeit, kostet viel Speicher. Werde ich in der > >> nächsten Version probieren. > > > > An der Stelle ist ein BloomFilter eine interessante Datenstruktur. > > Ein Bloomfilter kanndir mit Sicherheit sagen, dass er eine bytefolge > > noch nie gesehen hat, kann aber fälschlicherweise behaupten, er würde > > eine bytefolge schon kennen, auch wenn er sie noch nie gesehen hat. > > > > Kurz, er antwortet so: > > Filter, habe ich das schon geprüft? Sicher nicht! > > Filter, habe ich das schon geprüft? Wahrscheinlich ja. > > Den Hinweis verstehe ich in diesem Kontext nicht. Jetzt, wo ich den Post nochmal lese, muss ich dir recht geben, dass es wohl nicht ganz passt, weil er ja erst tiefer herab steigt, wenn die kürzere Tiefe nichts brachte und die Lösung möglicherweise weiter unten im Baum liegt. > Zum anderen will man vermeiden, bereits untersuchte Stellungen noch > einmal zu durchlaufen. Da bringt ein Bloomfilter aber auch nix. Wenn ich > eine Stellung sicher nicht gesehen habe, muss ich sie untersuchen. Wenn > ich eine Stellung wahrscheinlich schon gesehen habe, muss ich sie auch > untersuchen, denn es könnte ja sein, dass sie doch nicht gesehen wurde, > und dass es sich um die Stellung handelt, die zur (kürzesten oder gar > einzigen) Lösung führt. Das war ja genau das Problem mit Christians > initialem #hashCode()-Ansatz. (Ist ja auch nah verwandt.) Die Idee beim Filter war eher, dass Bäume, die schon als "tot" erkannt wurden, nicht neu durchlaufen werden müssen. Alles was nicht garantiert tot ist, enthält eine mögliche Lösung. Bei einem Baum (0 links, 1 rechts) 0000 (keine Lösung) 0001 (keine Lösung) 0010 (keine Lösung) 0011 (keine Lösung) Würde man sich folgende (Teil-)Bäume im Filter merken können: 0000 0001 0010 0011 000 001 00 Nehmen wir an, mit dem Wissen baue ich nun alle möglichen Bäume von Grund auf neu auf, so wird der Filter bei "00" sagen: "Kenne ich schon, ist tot, such weiter.", also kann man bei 01 starten und spart sich alle zuvor genannten Teilbäume. Aber dummerweise hatte ich übersehen, dass es eine Breitensuche ist, da wird halt nicht zuerst 0000 durchlaufen, dann 0001, dann 0010... (jetzt mal vereinfacht für eine maximale Tiefe von 4), insofern bringt das nix. > Habe ich da was falsch verstanden oder übersehen? Nein, ich glaube eher, ich habe etwas falsch verstanden. Gruß, -Wanja- -- ..Alesi's problem was that the back of the car was jumping up and down dangerously - and I can assure you from having been teammate to Jean Alesi and knowing what kind of cars that he can pull up with, when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]
[toc] | [prev] | [next] | [standalone]
| From | Wanja Gayk <brixomatic@yahoo.com> |
|---|---|
| Date | 2016-04-25 00:56 +0200 |
| Message-ID | <MPG.31876d82597e4b1e9896b6@news.aioe.org> |
| In reply to | #12955 |
In article <MPG.31876cabfd61f0ff9896b5@news.aioe.org>, Wanja Gayk (brixomatic@yahoo.com) says... > Nehmen wir an, mit dem Wissen baue ich nun alle möglichen Bäume von > Grund auf neu auf... (...) Und jetzt erkenne ich noch, dass es wohl ein wenig spät ist, weil das natürlich Unsinn ist. Gruß, -Wanja- -- ..Alesi's problem was that the back of the car was jumping up and down dangerously - and I can assure you from having been teammate to Jean Alesi and knowing what kind of cars that he can pull up with, when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-04-23 19:22 +0200 |
| Message-ID | <nfgb07$5lm$1@newsreader4.netcologne.de> |
| In reply to | #12952 |
Responding to Wanja Gayk: > In article <dn7mkmFu468U1@mid.individual.net>, Christian H. Kuhn (qno- > news@qno.de) says... > >> Zur Zeit sicher so. Ich suche bis Tiefe n. Wenn ich keine Lösung habe, >> suche ich bis Tiefe n+1, baue den Baum aber komplett neu auf. Ich müsste >> alle Stellungen in Tiefe n speichern und im nächsten Durchlauf dann >> bearbeiten. Spart viel Zeit, kostet viel Speicher. Werde ich in der >> nächsten Version probieren. [...] > Bzgl. dienes Problems kannst du also die Teilbäume, die keine Lösung > enthoelten in einen BloomFilter schicken und den immer fragen: "Hey, > kennst du den Teilbaum?" (war der Teilbaum ein Miserfolg?) und wenn der > sagt: "Den kenne ich nicht!", weißt du, dass den Baum neu aufbauen und > prüfen musst. Den Absatz hatte ich natürlich gekonnt überlesen. :) Ich verstehe es aber immer noch nicht. Abgesehen davon, dass der Ansatz mit der stufenweisen Tiefensuche an sich schon sehr fragwürdig ist: Was sind denn da die "Teilbäume, die keine Lösung enthalten"? Eine definitive Lösung hat bis hierher ja wohl keiner, sonst wären wir ja schon fertig. Also solche, die definitiv keine Lösung enthalten? Das wären dann solche, bei denen alle Pfade Tiefe <= n haben, weil an den Endpunkten/Blättern kein weiterer Zug mehr möglich ist? Die dürften bei diesem Spiel aber nur einen äußerst überschaubaren Bruchteil der Teilbäume ausmachen... Viele Grüße, Patrick
[toc] | [prev] | [next] | [standalone]
| From | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| Date | 2016-04-14 00:42 +0200 |
| Message-ID | <dn80blF210oU1@mid.individual.net> |
| In reply to | #12932 |
Am 13.04.2016 um 19:25 schrieb Wanja Gayk: > Der Overhead vom Exceptionhandling ist jedenfalls in 99.9999999999999% > aller Fälle kein Problem. Ich habe visualvm dann mal eingesetzt. Mann, habe ich gelacht. Je nachdem, ob ich dem Profiler oder dem Sampler glaube, verbringe ich 65–95% der Rechenzeit im Konstruktor von drei verschiedenen Exceptions, wobei zwei etwa gleich viel Zeit brauchen und die dritte ein Viertel davon. Und es sieht so aus, dass es tatsächlich die Aufrufe sind und weder super(String) noch die Erstellung des String. Die Exceptions werden bei der Überprüfung eines Zugs auf Legalität geworfen. Das betrifft hauptsächlich Züge in ein volles Glas und Züge auf einen Platz mit falschfarbigem Untermann, z.T. auch Züge mit gleichem Start und Ziel. Hm. Mal schauen, was sich da in der Zuggenerierung abfangen lässt. lg QNo
[toc] | [prev] | [next] | [standalone]
| From | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| Date | 2016-04-14 09:20 +0200 |
| Message-ID | <dn8ummF8ps7U1@mid.individual.net> |
| In reply to | #12935 |
Am 14.04.2016 um 00:42 schrieb Christian H. Kuhn:
> Am 13.04.2016 um 19:25 schrieb Wanja Gayk:
>> Der Overhead vom Exceptionhandling ist jedenfalls in 99.9999999999999%
>> aller Fälle kein Problem.
>
> Ich habe visualvm dann mal eingesetzt. Mann, habe ich gelacht. Je
> nachdem, ob ich dem Profiler oder dem Sampler glaube, verbringe ich
> 65–95% der Rechenzeit im Konstruktor von drei verschiedenen Exceptions,
> wobei zwei etwa gleich viel Zeit brauchen und die dritte ein Viertel
> davon. Und es sieht so aus, dass es tatsächlich die Aufrufe sind und
> weder super(String) noch die Erstellung des String.
>
> Die Exceptions werden bei der Überprüfung eines Zugs auf Legalität
> geworfen. Das betrifft hauptsächlich Züge in ein volles Glas und Züge
> auf einen Platz mit falschfarbigem Untermann, z.T. auch Züge mit
> gleichem Start und Ziel. Hm. Mal schauen, was sich da in der
> Zuggenerierung abfangen lässt.
Gigantisch. Alte Version: getMoveList() erzeugt die Liste der erlaubten
Züge, indem alle denkbaren Züge erzeugt und mit isLegalMove() überprüft
werden; in isLegalMove() werden dann die ganzen Exceptions geworfen. Die
erste Stellung aus Level 4 braucht dann 2270765 ms. Stattdessen:
Einhaltung der Größengrenzen ist durch die verschachtelten Schleifen
garantiert; die übrigen Fehlermöglichkeiten stehen als if (x || y || z)
{ continue; } drin. Reduktion auf 98558 ms. Ich bin begeistert.
Jetzt kommt noch der letzte Optimierungsschritt: Ich mache eigentlich
keine Breitensuche, sondern eine definiert abbrechende Tiefensuche. Mal
schauen, was ich da noch rauskitzle.
lg
QNo
[toc] | [prev] | [next] | [standalone]
| From | Christoph Schneegans <Christoph@Schneegans.de> |
|---|---|
| Date | 2016-04-14 18:47 +0200 |
| Message-ID | <dn9vteFh6thU1@mid.individual.net> |
| In reply to | #12935 |
Christian H. Kuhn schrieb:
> Ich habe visualvm dann mal eingesetzt. Mann, habe ich gelacht. Je
> nachdem, ob ich dem Profiler oder dem Sampler glaube, verbringe ich
> 65–95% der Rechenzeit im Konstruktor von drei verschiedenen Exceptions,
> wobei zwei etwa gleich viel Zeit brauchen und die dritte ein Viertel
> davon. Und es sieht so aus, dass es tatsächlich die Aufrufe sind und
> weder super(String) noch die Erstellung des String.
java.lang.Throwable.fillInStackTrace() macht typischerweise den
Löwenanteil aus. Wenn man den Stacktrace ohnehin nicht braucht,
erscheint mir sowas völlig legitim:
public class TracelessException
extends Exception
{
private static final long serialVersionUID = -9043029795604539423L;
public TracelessException()
{
super();
}
public TracelessException(final String message)
{
super(message);
}
@Override
@SuppressWarnings("sync-override")
public Throwable fillInStackTrace()
{
return this;
}
}
--
<http://schneegans.de/computer/safer/> · SAFER mit Windows
[toc] | [prev] | [next] | [standalone]
| From | Wanja Gayk <brixomatic@yahoo.com> |
|---|---|
| Date | 2016-04-23 16:13 +0200 |
| Message-ID | <MPG.31859c2ad1741b659896b3@news.aioe.org> |
| In reply to | #12935 |
In article <dn80blF210oU1@mid.individual.net>, Christian H. Kuhn (qno-
news@qno.de) says...
>
> Am 13.04.2016 um 19:25 schrieb Wanja Gayk:
> > Der Overhead vom Exceptionhandling ist jedenfalls in 99.9999999999999%
> > aller Fälle kein Problem.
>
> Ich habe visualvm dann mal eingesetzt. Mann, habe ich gelacht. Je
> nachdem, ob ich dem Profiler oder dem Sampler glaube, verbringe ich
> 65?95% der Rechenzeit im Konstruktor von drei verschiedenen Exceptions,
> wobei zwei etwa gleich viel Zeit brauchen und die dritte ein Viertel
> davon. Und es sieht so aus, dass es tatsächlich die Aufrufe sind und
> weder super(String) noch die Erstellung des String.
Das klingt ganz danach, als ob du die Exceptions nicht als "Ausnahme"
benutzt, sondern Mittel für den regulären Kontrollfluss. Wenn Exceptions
zur Regel werden, dann passt der Name "Exception" eigentlich nicht mehr.
Was du dort siehst, ist also in etwa so, als ob du ein extra
Rückgabeobjekt mit Stacktrace erzeugst, immer wenn du z.B. kein
Suchergebnis findest. Das ist eigentlich nicht das, wofür man eine
Exception nutzen sollte.
Eine Exception ist eigentlich immer eine Sonderbedingung, Beispiel:
Du hast ein Handelsprogramm, bei dem du checkst, ob die Ware auf Lager
ist und wenn ja, wird es dem Kunden abgeboten, der erteilt dann den
Auftrag die Ware vom Lager zu nehmen und ihm zu schicken. Eine Ausnahme
baust du für den Fall ein, dass zwischen dem Bestandscheck und dem
tatsächlichen Auftrag ein anderer Auftrag dazwischen kam, der die Ware
vom Lager nahm. Damit würde es beim Auftrag eine Art OutOfStockException
geben und du müsstest dem Kunden mitteilen: Sorry, zwischen unserem
Angebot und deinem Auftrag hat ein anderer Kunde das Zeug gekauft und
ihm anbieten das Zeug mit etwas Wartezeit trotzdem zu bestellen oder die
Transaktion abzubrechen.
Aber für so Sachen, wie eine Suche, wo sehr oft zu erwarten ist, dass du
nicht findest, was du suchst, ist eine Exception (Ausnahme!) nicht das
richtige Mittel.
Dort gibt man zum Beispiel sowas, wie ein "Optional" zurück, also:
public <X extends NamedItem> Optional<X> searchByName(Iterable<X> xs,
String name){
for(X x : xs){
if(x != null && Utils.equals(x.getName(), name)){
return Optional.of(x);
}
}
return Optional.empty();
}
Oder eben, wenn man den Konstruktor des Optionals umgehen muss, das
Objekt selbst oder null.
Gruß,
-Wanja-
--
..Alesi's problem was that the back of the car was jumping up and down
dangerously - and I can assure you from having been teammate to
Jean Alesi and knowing what kind of cars that he can pull up with,
when Jean Alesi says that a car is dangerous - it is. [Jonathan Palmer]
[toc] | [prev] | [next] | [standalone]
| From | "Christian H. Kuhn" <qno-news@qno.de> |
|---|---|
| Date | 2016-04-25 12:07 +0200 |
| Message-ID | <do68jjFl095U1@mid.individual.net> |
| In reply to | #12951 |
Am 23.04.2016 um 16:13 schrieb Wanja Gayk: > Das klingt ganz danach, als ob du die Exceptions nicht als "Ausnahme" > benutzt, sondern Mittel für den regulären Kontrollfluss. Jain. Der Grundgedanke ist schon der, dass Methoden mit korrekten Parametern aufgerufen werden; es sollte der Ausnahmefall sein, wenn das nicht passiert, und dann gibt es halt eine Exception zurück, die auch genau beschreibt, was los ist. In getMoveList() habe ich es dann übertrieben: Ich habe alle kombinatorisch möglichen Züge erzeugt und dann Exceptions werfen lassen. DAS war ein Mißbrauch des Mechanismus. Aktuell erzeuge ich nur erlaubte Züge in getMoveList(). Weil die Schnittstelle erlaubt, dass auch irgendwo Züge als Parameter übergeben werden, die nicht aus einer mit getMoveList() erzeugten Liste stammen, muss ich weiterhin eine Überprüfung von auszuführenden Zügen machen, und die arbeitet weiter mit Exceptions. Was mir gar nicht gefällt: Ich habe die Legalität an zwei Stellen codiert, die ich bei Änderungen beide anpassen muss. Alternativen zum Exception-Mechanismus gefallen mir alle nicht. Rückgabe boolean ist zu vage, da kann man nicht spezifizieren, was los ist. Rückgabe int (mit darin codierten Flags) ist C-Style, sowas von Achtziger und semantisch in komplexen Situationen nicht immer zu durchschauen, weil das Prinzip der Kapselung verletzt ist. > Dort gibt man zum Beispiel sowas, wie ein "Optional" zurück, Das kannte ich noch nicht, das schaue ich mir an. > Oder eben, wenn man den Konstruktor des Optionals umgehen muss, das > Objekt selbst oder null. Das bringt auch nicht mehr Information als boolean. lg Christian
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-04-25 17:38 +0200 |
| Message-ID | <nfldlt$ite$1@newsreader4.netcologne.de> |
| In reply to | #12958 |
Responding to Christian H. Kuhn: > Aktuell erzeuge ich nur erlaubte Züge in getMoveList(). Weil die > Schnittstelle erlaubt, dass auch irgendwo Züge als Parameter übergeben > werden, die nicht aus einer mit getMoveList() erzeugten Liste stammen, > muss ich weiterhin eine Überprüfung von auszuführenden Zügen machen, und > die arbeitet weiter mit Exceptions. Das ist ja auch völlig legitim. > Was mir gar nicht gefällt: Ich habe > die Legalität an zwei Stellen codiert, die ich bei Änderungen beide > anpassen muss. Wenn das in beiden Fällen ähnlicher Code sein sollte, ist das in der Tat ein Designfehler, der sich leicht beheben lassen sollte. Falls Du damit meinst, dass Du einmal "synthetischen" Code hast (in #getMoveList(), wo die Regeln implizit im Code sind, der die gültigen Züge erzeugt) und einmal "analytischen" (zum Prüfen der externen Eingaben, wo die Regeln explizit in Form von if/throw-Validierungen vorliegen) - das wird sich wohl kaum mit vertretbarem Aufwand vermeiden lassen und ist eigentlich gut verargumentierbar: Das eine ist die Implementierung eines Spielers, das andere die Implementierung des Spiels. Aber die Regeln an sich dürften sich ja eher selten ändern. Und dass man beide Stellen anpacken muss, wenn man z.B. eine andere Datenrepräsentation wählt - tough luck. Aber auch das sollte ja nicht ständig passieren. Viele Grüße, Patrick
[toc] | [prev] | [next] | [standalone]
| From | Patrick Roemer <sangamon@netcologne.de> |
|---|---|
| Date | 2016-04-25 22:36 +0200 |
| Message-ID | <nflv4p$vkq$1@newsreader4.netcologne.de> |
| In reply to | #12958 |
Responding to Stefan Ram:
> Du mußt Ausnahme nicht werfen, sondern kannst sie auch zurückgeben:
>
> java.lang.Exception toReciprocal()
> { if( this.getDouble() != 0 ){ this.set( 1 / this.getDouble() ); return null; }
> else return new DivisionByZeroException( this.getDouble() ); }
> ¯¯¯¯¯¯
Gibt es eigentlich einen Fachausdruck für sachlich korrekten Unfug? :)
Viele Grüße,
Patrick
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | de.comp.lang.java
csiph-web