Ich befinde mich an der Position (0, 0) einer unendlichen zweidimensionalen Stadt, die perfekt in Blöcke unterteilt ist, die an jedem Gitterpunkt zentriert sind, von denen einige Gebäude enthalten. Ein Gebäude an einem bestimmten Punkt (x, y) nimmt das gesamte Quadrat mit gegenüberliegenden Ecken bei (x-.5, y-.5) und (x + .5, y + .5) einschließlich seiner Begrenzung ein. Ein Gebäude ist sichtbar, wenn es ein Liniensegment von (0, 0) zu einem Punkt im Gebäude gibt, der kein anderes Gebäude schneidet.
Zum Beispiel kann ich (die @
) 6 Gebäude ( *
) in der folgenden Stadt sehen:
*
*
*
*@
x**
* y
Ich kann das Gebäude, das mit einem x
, bei (-1, -1) markiert ist, nicht sehen , da es von den beiden angrenzenden Gebäuden blockiert wird. oder die mit einem y
bei (3, -2) markierte , weil sie durch den Rand des (1, -1) Gebäudes blockiert ist.
Eingang
Eine mehrzeilige Zeichenfolge oder Liste von Zeilen, die optional mit Leerzeichen in einem Rechteck aufgefüllt werden. Es wird nur enthalten:
- eine einzelne
@
(meine Position) - Räume
*
, die Gebäude darstellen.
Es wird immer mindestens ein Gebäude geben und daher mindestens ein sichtbares Gebäude.
Ausgabe
Die Anzahl der sichtbaren Gebäude.
Testfälle
*@
1
* *******
@ *
7
*****
**@**
*****
4
*
**
@ **
2
* *
* *
@
4
@
*
***
1
Vielen Dank an @Geobits für den Titel .
Antworten:
Einheit + C #, 589 Bytes
Dies ist wahrscheinlich die schlechteste Sprache, in der man Codegolf spielen kann (lesen Sie: schlechter als Java), aber Unity bietet viele hilfreiche Funktionen für diese Herausforderung.
BEARBEITEN: Einige Leerzeichen verpasst, Länge der Liste zurückgegeben, kein Zähler
Golf gespielt:
Ungolfed:
Ich habe 3600 Raycasts verwendet, weil es den 5. Testfall mit niedrigerem nicht schafft. Bei noch größeren / genaueren Testfällen kann es immer noch scheitern.
Leider scheinen sowohl Webgl- als auch Desktop-Builds zu brechen. Ich habe also nur den Quellcode, mit dem ich auf Github testen kann .
quelle
read: worse than Java
Das sind 383 Bytes weniger als bei der Java-Lösung!total+=1
mittotal++
? Ich denke, eine andere Möglichkeit, einige Zeichen zu speichern, besteht darin, den Würfel des Gebäudes zu erstellen und seine Position in einer Anweisung festzulegen. Sie scheinen diecube
Variable nirgendwo wiederzuverwenden .GameObject b=GameObject.CreatePrimitive(PrimitiveType.Cube);b.transform.position=new Vector3(x,y);
. Ich weiß nicht, ob es in C # möglich ist, aber in Java könnte manGameObject.CreatePrimitive(PrimitiveType.Cube).transform.position=new Vector3(x,y);
stattdessen schreiben .Java 8 Lambda,
15061002972942 ZeichenIch wollte diese Herausforderung bestehen, da sie sehr interessant ist. Das Ergebnis
(nicht sehr golfen)ist hier zu sehen:Natürlich gibt es das auch in der ungolfed Version:
Es sieht also sehr schwierig aus, ist aber viel einfacher als man denkt. Meine erste Idee war, mit einem Kreuzungsalgorithmus zu prüfen, ob eine Linie von meiner Position zum Gebäude ohne Kreuzungen hergestellt werden kann. Zu diesem Zweck habe ich mich für den Cohen-Sutherland-Algorithmus entschieden und Linien zu allen vier Ecken des Gebäudes gezogen. Dies hat bei den ersten Tests ziemlich gut funktioniert, aber der letzte ist fehlgeschlagen. Ich habe schnell herausgefunden, dass man die Ecken nicht sehen kann, sondern nur einen Teil einer Kante. Also dachte ich über eine Art Raycasting nach, wie es @Blue gemacht hat. Ich habe diese Herausforderung weggeräumt, da ich keine Fortschritte gemacht habe. Dann sah ich die Antwort von Blue und die folgende einfache Idee kam mir in den Sinn: Jedes Gebäude blockiert einen Winkel, in dem nichts anderes zu sehen ist. Ich muss nur verfolgen, was zu sehen ist und was bereits von anderen Gebäuden verborgen wird. Das ist es!
Der Algorithmus funktioniert wie folgt: Er ermittelt das Gebäude mit der geringsten Entfernung zur Person. Dann stellen wir uns vier Linien vor, die von der Person zu den Ecken des Gebäudes gezogen werden. Zwei davon haben einen extremen Wert: Der minimale und maximale Winkel, in dem das Gebäude gesehen werden kann. Wir nehmen sie als eine Reihe und vergleichen sie mit anderen Gebäuden, von denen wir wissen, dass sie zu sehen sind (keine am Anfang). Die Bereiche können sich überlappen, sich gegenseitig einschließen oder sich überhaupt nicht berühren. Ich vergleiche die Bereiche und erhalte einige neue Bereiche des Gebäudes, die von den sichtbaren Gebäuden nicht verborgen werden. Wenn nach dem Vergleich mit den sichtbaren Gebäuden noch etwas übrig ist, kann das Gebäude auch angezeigt werden. Wir fügen den verbleibenden Winkelbereich der Liste der Bereiche hinzu, die mit dem nächsten Gebäude mit der nächstgrößeren Entfernung verglichen und mit diesem begonnen werden sollen.
Manchmal überlappen sich die Bereiche so, dass ich einen Bereich von 0 Grad erhalte. Diese Bereiche werden gefiltert, um nicht versehentlich ein Gebäude hinzuzufügen, das nicht einmal sichtbar ist.
Ich hoffe jemand hat diese erklärung verstanden :)
Ich weiß, dass dieser Code nicht sehr gut ist. Ich mache das so schnell wie möglich.Das war eine wirklich herausfordernde Aufgabe. Sie dachten, Sie hätten eine Lösung gefunden, die funktioniert, sind aber noch weit entfernt. Ich denke, diese Lösung funktioniert ziemlich gut. Es ist nicht sehr schnell, aber es funktioniert zumindest;) Danke für das Rätsel!
Aktualisieren
Ich fand die Zeit, das Ganze in eine einzige Funktion zu verwandeln, die sich so in einen Lambda verwandeln lässt. Alle Funktionen wurden nur einmal aufgerufen und können somit in einer Methode zusammengefasst werden. Ich habe von Listen zu Sets gewechselt, da hierdurch einige zusätzliche Zeichen eingespart werden. Die Erklärungen wurden zusammengestellt. Die Vergleiche wurden zusammengestellt und die Zeichen durch ihren ASCII-Wert ersetzt. Der Bereichsvergleich kann als viele Ternären ausgedrückt werden. Hier und da ein paar Tricks, um lange Ausdrücke wie Double.NEGATIVE_INFINITY zu verhindern. Wo möglich werden Inline-Zuordnungen vorgenommen. Um etwas mehr zu sparen, habe ich vom Winkelvergleich in Grad auf den Bogenmaßvergleich umgestellt. Die ganze Änderung sparte über 500 Zeichen, ich hoffe, dass ich alles unter 1000 bekomme;)
Ich habe die Generika entfernt und den Rückgabevergleich verkürzt, indem ich ein Array mit einem Element erstellt und stattdessen dessen Wert überprüft habe. Ich habe auch Double.NEGATIVE_INFINITY durch PI2 und -PI2 ersetzt, da dies die oberen und unteren Grenzen der Winkel sind. Jetzt ist es endlich unter 1000 Zeichen lang!
Ich habe die Schleifen zum Finden des Orts der Person und des Gebäude-Iterators zusammengeführt, um einige Zeichen zu speichern. Leider müssen wir dafür den Return aus der Schleife verschieben und trotzdem eine Pause verwenden, diesmal jedoch ohne Label. Ich habe
max
unddistanceSquared
undmin
und zusammengeführt,newDistanceSquared
da sie nicht gleichzeitig benötigt werden. Ich wechselteInteger.MAX_VALUE
zu2e31-1
. Außerdem habe ich eine Konstante erstellthalf = 0.5
, mit der die Ecken des Gebäudes berechnet werden. Dies ist in der Golfversion kürzer. Insgesamt haben wir weitere 30 Zeichen gespeichert!quelle