Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.comp.lang.java > #12917 > unrolled thread

Rekursion bricht nicht ab

Started by"Christian H. Kuhn" <qno-news@qno.de>
First post2016-04-08 23:28 +0200
Last post2016-04-25 21:42 +0200
Articles 20 on this page of 39 — 6 participants

Back to article view | Back to de.comp.lang.java


Contents

  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 →


#12917 — Rekursion bricht nicht ab

From"Christian H. Kuhn" <qno-news@qno.de>
Date2016-04-08 23:28 +0200
SubjectRekursion 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]


#12918

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-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]


#12922

From"Christian H. Kuhn" <qno-news@qno.de>
Date2016-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]


#12923

FromPeter Büttner <not_for_mail_peb@gmx.net>
Date2016-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]


#12924

From"Christian H. Kuhn" <qno-news@qno.de>
Date2016-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]


#12932

FromWanja Gayk <brixomatic@yahoo.com>
Date2016-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]


#12934

From"Christian H. Kuhn" <qno-news@qno.de>
Date2016-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]


#12950

FromWanja Gayk <brixomatic@yahoo.com>
Date2016-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]


#12952

FromWanja Gayk <brixomatic@yahoo.com>
Date2016-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]


#12953

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-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]


#12955

FromWanja Gayk <brixomatic@yahoo.com>
Date2016-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]


#12956

FromWanja Gayk <brixomatic@yahoo.com>
Date2016-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]


#12954

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-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]


#12935

From"Christian H. Kuhn" <qno-news@qno.de>
Date2016-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]


#12936

From"Christian H. Kuhn" <qno-news@qno.de>
Date2016-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]


#12939

FromChristoph Schneegans <Christoph@Schneegans.de>
Date2016-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]


#12951

FromWanja Gayk <brixomatic@yahoo.com>
Date2016-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]


#12958

From"Christian H. Kuhn" <qno-news@qno.de>
Date2016-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]


#12961

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-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]


#12965

FromPatrick Roemer <sangamon@netcologne.de>
Date2016-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