Estou na posição (0, 0) de uma cidade bidimensional infinita, perfeitamente dividida em blocos centralizados em cada ponto da rede, alguns dos quais contêm edifícios. Uma construção em um determinado ponto (x, y) ocupa todo o quadrado com cantos opostos em (x-.5, y-.5) e (x + .5, y + .5) , incluindo sua borda. Um edifício é visível se houver algum segmento de linha de (0, 0) até um ponto no edifício que não cruze nenhum outro edifício.
Por exemplo, eu (o @
) posso ver 6 edifícios ( *
) na seguinte cidade:
*
*
*
*@
x**
* y
Não consigo ver o prédio marcado com um x
, em (-1, -1) porque está obstruído pelos dois adjacentes; ou aquele marcado com a y
em (3, -2) porque está obstruído pela borda do edifício (1, -1) .
Entrada
Uma sequência multilinha ou lista de linhas, opcionalmente preenchida com espaços em um retângulo. Ele conterá apenas:
- um único
@
(minha posição) - Espaços
*
, que representam edifícios.
Sempre haverá pelo menos um edifício e, portanto, pelo menos um edifício visível.
Resultado
O número de edifícios visíveis.
Casos de teste
*@
1
* *******
@ *
7
*****
**@**
*****
4
*
**
@ **
2
* *
* *
@
4
@
*
***
1
Obrigado a @Geobits pelo título .
Respostas:
Unidade + C #, 589 bytes
Esta é provavelmente a pior linguagem para se jogar código (leia-se: pior que Java), mas o Unity vem com muitos recursos úteis para esse desafio.
EDIT: perdeu alguns espaços, retorna o comprimento da lista, não o contador
Golfe:
Ungolfed:
Eu usei 3600 raycasts porque falha no quinto caso de teste com menos. Ainda pode falhar em casos de teste ainda maiores / mais precisos.
Infelizmente, as compilações de webgl e desktop parecem ter problemas, então tudo o que tenho é o código-fonte para testar no github .
fonte
read: worse than Java
Isso é 383 bytes mais curto que a solução Java!total+=1
portotal++
? Eu acho que outra maneira de salvar alguns personagens é criar o cubo do edifício e definir sua posição em uma declaração. Você não parece reutilizar acube
variável em nenhum lugar.GameObject b=GameObject.CreatePrimitive(PrimitiveType.Cube);b.transform.position=new Vector3(x,y);
. Eu não sei se é possível em C #, mas em Java alguém poderia escreverGameObject.CreatePrimitive(PrimitiveType.Cube).transform.position=new Vector3(x,y);
.Java 8 lambda,
15061002972942 caracteresEu queria vencer esse desafio, pois é muito interessante. O resultado
(pouco golfe)pode ser visto aqui:Claro que isso também existe na versão não-destruída:
Parece muito difícil, mas é muito mais fácil do que se possa pensar. Minha primeira idéia foi usar um algoritmo de interseção para verificar se uma linha da minha posição até o prédio pode ser feita sem nenhuma interseção. Para fazer isso, decidi usar o algoritmo de Cohen-Sutherland e desenhar linhas para todos os quatro cantos do edifício. Isso funcionou muito bem nos primeiros testes, mas o último falhou. Logo descobri que é um caso em que você não pode ver os cantos, mas parte de uma aresta. Então pensei em algum tipo de casting de raios como o @Blue fez. Afastei esse desafio, pois não obtive algum progresso. Então eu vi a resposta de Blue e a seguinte idéia simples veio à minha mente: Cada construção bloqueia algum ângulo em que nada mais pode ser visto. Eu só preciso acompanhar o que pode ser visto e o que já está escondido por outros edifícios. É isso aí!
O algoritmo funciona da seguinte maneira: determina o edifício com a menor distância para a pessoa. Então imaginamos quatro linhas traçadas da pessoa para os cantos do edifício. Dois deles têm um valor extremo: o ângulo mínimo e máximo em que o edifício pode ser visto. Nós os tomamos como um intervalo e os comparamos com outros edifícios dos quais sabemos que podem ser vistos (nenhum no começo). Os intervalos podem se sobrepor, incluir um ao outro ou não tocar em nada. Comparo os intervalos e recebo novos intervalos do edifício que não estão ocultos pelos edifícios visíveis. Se ainda restar algo depois de compará-lo com os prédios à vista, o prédio também será visível. Adicionamos o intervalo de ângulo restante à lista de intervalos para comparar e começar com o próximo edifício com a próxima distância mais longa.
Às vezes, os intervalos podem se sobrepor de maneira que eu acabe com um intervalo de 0 graus. Esses intervalos serão filtrados para não adicionar por engano um prédio que nem seja visível.
Espero que alguém tenha entendido essa explicação :)
Eu sei que esse código não é muito jogado, vou fazer isso o mais rápido possível.Essa foi uma tarefa realmente desafiadora. Você achou que havia encontrado uma solução que funcionasse, mas ainda está longe. Eu acho que essa solução funciona muito bem. Não é muito rápido, mas pelo menos funciona;) Obrigado por esse quebra-cabeça!
Atualizar
Encontrei tempo para jogar a coisa toda em uma única função, que pode ser transformada em uma lambda. Todas as funções foram chamadas apenas uma vez e, portanto, podem ser colocadas em um método. Mudei de listas para conjuntos, pois isso salva alguns caracteres adicionais. As declarações foram reunidas. As comparações foram reunidas e os caracteres foram substituídos pelo seu valor ASCII. O intervalo de comparação pode ser expresso como muitos ternários. Alguns truques aqui e ali para evitar expressões longas como Double.NEGATIVE_INFINITY. Sempre que possível, são feitas atribuições em linha. Para economizar um pouco mais, passei de comparar os ângulos em graus para comparar os radianos. Toda a mudança salvou mais de 500 caracteres, espero que tudo fique abaixo de 1000;)
Removai os genéricos sempre que possível e reduzi a comparação de retorno criando uma matriz de um elemento e verifiquei seu valor. Também substituí o Double.NEGATIVE_INFINITY por PI2 e -PI2, pois esses são os limites superior e inferior dos ângulos. Agora, finalmente, tem menos de 1000 caracteres!
Mesclei os loops para encontrar a localização das pessoas e o iterador da construção para salvar alguns caracteres. Infelizmente, isso exige que tiremos o retorno do loop e ainda utilizemos uma pausa, mas desta vez sem um rótulo. I fundiu
max
edistanceSquared
emin
enewDistanceSquared
como eles não são necessários ao mesmo tempo. Eu mudeiInteger.MAX_VALUE
para2e31-1
. Também criei uma constantehalf = 0.5
que é usada para calcular os cantos do edifício. Isso é mais curto na versão golfed. No geral, salvamos outros 30 caracteres!fonte