Je suis à la position (0, 0) d'une ville bidimensionnelle infinie, qui est parfaitement divisée en blocs centrés à chaque point du réseau, dont certains contiennent des bâtiments. Un bâtiment à un certain point (x, y) occupe la place entière avec des coins opposés en (x-0,5, y-0,5) et (x + 0,5, y + 0,5) , y compris sa bordure. Un bâtiment est visible s'il existe un segment de ligne allant de (0, 0) à un point du bâtiment qui ne coupe aucun autre bâtiment.
Par exemple, je (le @
) vois 6 bâtiments ( *
) dans la ville suivante:
*
*
*
*@
x**
* y
Je ne vois pas le bâtiment marqué d'un x
, à (-1, -1) car il est obstrué par les deux adjacents; ou celui marqué d'un y
at (3, -2) car il est obstrué par le bord du bâtiment (1, -1) .
Contribution
Une chaîne multiligne, ou liste de lignes, éventuellement complétée par des espaces dans un rectangle. Il ne contiendra que:
- un seul
@
(ma position) - Les espaces
*
, qui représentent des bâtiments.
Il y aura toujours au moins un bâtiment, et donc au moins un bâtiment visible.
Production
Le nombre de bâtiments visibles.
Cas de test
*@
1
* *******
@ *
7
*****
**@**
*****
4
*
**
@ **
2
* *
* *
@
4
@
*
***
1
Merci à @Geobits pour le titre .
Réponses:
Unity + C #, 589 octets
C'est probablement le pire langage pour faire un golf de code (lire: pire que Java), mais Unity est livré avec beaucoup de fonctionnalités utiles pour ce défi.
EDIT: manque quelques espaces, renvoie la longueur de la liste, pas le compteur
Golfé:
Non golfé:
J'ai utilisé 3600 raycasts car il échoue au 5ème cas de test avec inférieur. Il peut encore échouer pour des cas de test encore plus grands / plus précis.
Malheureusement, les versions webgl et desktop semblent ne pas fonctionner, donc tout ce que j'ai est le code source avec lequel tester sur github .
la source
read: worse than Java
C'est 383 octets de moins que la solution Java!total+=1
avectotal++
? Je pense qu'une autre façon de sauver certains personnages est de créer le cube du bâtiment et de définir sa position dans une seule déclaration. Vous ne semblez pas réutiliser lacube
variable n'importe où.GameObject b=GameObject.CreatePrimitive(PrimitiveType.Cube);b.transform.position=new Vector3(x,y);
. Je ne sais pas si c'est possible en C # mais en Java on pourrait écrire à laGameObject.CreatePrimitive(PrimitiveType.Cube).transform.position=new Vector3(x,y);
place.Java 8 lambda,
15061002972942 caractèresJe voulais battre ce défi, car il est très intéressant. Le résultat
(pas très golfique)peut être vu ici:Bien sûr, cela existe également dans la version non golfée:
Cela semble donc très difficile, mais c'est beaucoup plus facile qu'on ne pourrait le penser. Ma première idée a été d'utiliser un algorithme d'intersection pour vérifier si une ligne de ma position au bâtiment peut être faite sans intersection. Pour ce faire, j'ai décidé d'utiliser l'algorithme de Cohen-Sutherland et de tracer des lignes aux quatre coins du bâtiment. Cela a plutôt bien fonctionné pour les premiers tests, mais le dernier a échoué. J'ai vite découvert que c'est un cas où vous ne pouvez pas voir les coins mais une partie d'un bord. J'ai donc pensé à une sorte de lancer de rayons comme le faisait @Blue. J'ai mis ce défi de côté, car je n'avais pas progressé. Puis j'ai vu la réponse de Blue et l'idée simple suivante m'est venue à l'esprit: chaque bâtiment bloque un angle dans lequel rien d'autre ne peut être vu. J'ai juste besoin de garder une trace de ce qui peut être vu et de ce qui est déjà caché par d'autres bâtiments. C'est ça!
L'algorithme fonctionne comme suit: Il détermine le bâtiment avec la plus petite distance à la personne. Ensuite, nous imaginons quatre lignes tracées de la personne aux coins du bâtiment. Deux d'entre eux ont une valeur extrême: l'angle minimum et maximum sous lequel le bâtiment peut être vu. Nous les prenons comme une gamme et les comparons avec d'autres bâtiments dont nous savons qu'ils peuvent être vus (aucun au début). Les plages peuvent se chevaucher, s'inclure ou ne pas se toucher du tout. Je compare les plages et j'obtiens de nouvelles plages du bâtiment qui ne sont pas cachées par les bâtiments visibles. S'il reste quelque chose après l'avoir comparé aux bâtiments en vue, le bâtiment est également visible. Nous ajoutons la plage d'angles restante à la liste des plages à comparer et commençons par le bâtiment suivant avec la distance plus longue suivante.
Parfois, les plages peuvent se chevaucher d'une manière que je me retrouve avec une plage de 0 degrés. Ces plages seront filtrées pour ne pas ajouter par erreur un bâtiment qui n'est même pas visible.
J'espère que quelqu'un a compris cette explication :)
Je sais que ce code n'est pas beaucoup joué, je vais le faire dès que possible.C'était une tâche vraiment difficile. Vous pensiez avoir trouvé une solution qui fonctionne, mais vous êtes encore loin. Je pense que cette solution fonctionne plutôt bien. Ce n'est pas très rapide mais au moins ça marche;) Merci pour ce puzzle!
Mise à jour
J'ai trouvé le temps de jouer au golf en une seule fonction, qui peut donc être transformée en lambda. Toutes les fonctions n'ont été appelées qu'une seule fois et peuvent donc être regroupées dans une seule méthode. Je suis passé de listes à ensembles car cela enregistre quelques caractères supplémentaires. Les déclarations ont été rassemblées. Les comparaisons ont été rassemblées et les caractères ont été remplacés par leur valeur ascii. La plage de comparaison peut être exprimée en nombre de ternaires. Quelques astuces ici et là pour empêcher les expressions longues comme Double.NEGATIVE_INFINITY ont été effectuées. Dans la mesure du possible, des affectations en ligne sont effectuées. Pour économiser un peu plus, je suis passé de la comparaison des angles en degrés à la comparaison des radians. L'ensemble du changement a sauvé plus de 500 caractères, j'espère tout de même moins de 1000;)
J'ai supprimé les génériques dans la mesure du possible et raccourci la comparaison de retour en créant un tableau à un élément et en vérifiant sa valeur à la place. J'ai également remplacé le Double.NEGATIVE_INFINITY par PI2 et -PI2 car ce sont les limites supérieures et inférieures des angles. Maintenant, c'est enfin moins de 1000 caractères!
J'ai fusionné les boucles pour trouver l'emplacement des personnes et l'itérateur du bâtiment pour enregistrer certains personnages. Malheureusement, cela nous oblige à sortir le retour de la boucle et à utiliser toujours une pause, mais cette fois sans étiquette. J'ai fusionné
max
etdistanceSquared
etmin
etnewDistanceSquared
comme ils ne sont pas requis en même temps. J'ai changéInteger.MAX_VALUE
pour2e31-1
. J'ai également créé une constantehalf = 0.5
qui est utilisée pour calculer les coins du bâtiment. C'est plus court dans la version golfée. Dans l'ensemble, nous avons enregistré 30 autres caractères!la source