Я нахожусь в положении (0, 0) бесконечного двумерного города, который идеально разделен на блоки, центрированные в каждой точке решетки, некоторые из которых содержат здания. Здание в определенной точке (x, y) занимает весь квадрат с противоположными углами в точках (x -.5, y-.5) и (x + .5, y + .5) , включая его границу. Здание является видимым, если существует некоторый отрезок от (0, 0) до точки в здании, которая не пересекает никакое другое здание.
Например, я (the @
) могу видеть 6 зданий ( *
) в следующем городе:
*
*
*
*@
x**
* y
Я не вижу здание, помеченное знаком x
, в (-1, -1), потому что оно закрыто двумя соседними с ним; или тот, который отмечен символом y
at (3, -2), потому что он закрыт краем здания (1, -1) .
вход
Многострочная строка или список строк, необязательно дополненный пробелами в прямоугольник. Он будет содержать только:
- сингл
@
(моя позиция) - пространства
*
, которые представляют собой здания.
Всегда будет хотя бы одно здание и, следовательно, хотя бы одно видимое здание.
Выход
Количество видимых зданий.
Контрольные примеры
*@
1
* *******
@ *
7
*****
**@**
*****
4
*
**
@ **
2
* *
* *
@
4
@
*
***
1
Спасибо @Geobits за название .
Ответы:
Unity + C #, 589 байт
Вероятно, это худший язык для игры в гольф (читай: хуже, чем на Java), но Unity предлагает множество полезных функций для решения этой задачи.
РЕДАКТИРОВАТЬ: пропустил пару пробелов, возвращает длину списка, а не счетчик
Golfed:
Ungolfed:
Я использовал 3600 raycast, потому что он не прошел 5-й тестовый случай с более низким. Это все еще может потерпеть неудачу для еще больших / более точных тестовых случаев.
К сожалению, как webgl, так и настольные сборки, похоже, ломаются, поэтому все, что у меня есть, это исходный код для тестирования на github .
источник
read: worse than Java
Это на 383 байта короче, чем решение Java!total+=1
сtotal++
? Я думаю, что другой способ сохранить некоторые символы - это создать куб здания и установить его положение в одном выражении. Кажется, вы нигде не используете этуcube
переменную.GameObject b=GameObject.CreatePrimitive(PrimitiveType.Cube);b.transform.position=new Vector3(x,y);
. Я не знаю, возможно ли это в C #, но в Java можно было бы написатьGameObject.CreatePrimitive(PrimitiveType.Cube).transform.position=new Vector3(x,y);
вместо этого.Java 8 лямбда,
15061002972942 знаковЯ хотел побить этот вызов, так как он очень интересный. Результат
(не очень удачный)можно увидеть здесь:Конечно, это также существует в негольфированной версии:
Так что это выглядит очень сложно, но это намного проще, чем можно подумать. Моя первая идея состояла в том, чтобы использовать некоторый алгоритм пересечения, чтобы проверить, можно ли провести линию от моей позиции до здания без каких-либо пересечений. Для этого я решил использовать алгоритм Коэна-Сазерленда и рисовать линии для всех четырех углов здания. Это сработало довольно хорошо для первых тестов, но последний провалился. Вскоре я обнаружил, что это тот случай, когда вы видите не углы, а часть края. Так что я подумал о каком-то лучевом отбрасывании, как это сделал @Blue. Я отложил этот вызов, так как не получил никакого прогресса. Затем я увидел ответ Блю, и мне пришла в голову следующая простая идея: каждое здание блокирует некоторый угол, в котором больше ничего не видно. Мне просто нужно следить за тем, что можно увидеть и что уже скрыто другими зданиями. Это оно!
Алгоритм работает следующим образом: он определяет здание с наименьшим расстоянием до человека. Затем мы представляем четыре линии, проведенные от человека к углам здания. Два из них имеют экстремальное значение: минимальный и максимальный угол обзора здания. Мы берем их в качестве диапазона и сравниваем их с другими зданиями, о которых мы знаем, что их можно увидеть (ни одного в начале). Диапазоны могут перекрываться, включать друг друга или вообще не касаться. Я сравниваю диапазоны и получаю новые диапазоны зданий, которые не скрыты видимыми зданиями. Если после сравнения зданий и сооружений в поле зрения остается что-то, здание также можно увидеть. Мы добавляем оставшийся диапазон углов в список диапазонов для сравнения и начинаем со следующего здания со следующим более длинным расстоянием.
Иногда диапазоны могут перекрываться таким образом, что я получаю диапазон 0 градусов. Эти диапазоны будут отфильтрованы, чтобы по ошибке не добавить здание, которое даже нельзя просмотреть.
Я надеюсь, что кто-то понял это объяснение :)
Я знаю, что этот код не очень хороший, я сделаю это как можно скорее.Это была действительно сложная задача. Вы думали, что нашли решение, которое работает, но вместо этого вы все еще далеко. Я думаю, что это решение работает довольно хорошо. Это не очень быстро, но, по крайней мере, это работает;) Спасибо за эту загадку!
Обновить
Я нашел время для игры в гольф в единую функцию, которую можно превратить в лямбду. Все функции были вызваны только один раз и поэтому могут быть объединены в один метод. Я переключился со списков на наборы, так как это сохраняет некоторые дополнительные символы. Декларации были составлены. Сравнения были собраны вместе, и символы были заменены на значение ascii. Диапазон сравнения можно выразить как множество троичных. Некоторые приемы для предотвращения длинных выражений типа Double.NEGATIVE_INFINITY были сделаны. Где возможно встроенные назначения сделаны. Чтобы сэкономить немного больше, я переключился со сравнения углов в градусах на сравнение радианов. Все изменения сэкономили более 500 символов, но я надеюсь получить все до 1000, хотя;)
Я удалил обобщения, где это было возможно, и сократил возвращаемое сравнение, создав массив из одного элемента и проверив его значение. Я также заменил Double.NEGATIVE_INFINITY на PI2 и -PI2, так как это верхняя и нижняя границы углов. Теперь это наконец менее 1000 символов!
Я объединил циклы поиска местоположения людей и итератор здания, чтобы сохранить некоторые символы. К сожалению, это требует, чтобы мы переместили возврат из цикла и все еще использовали разрыв, но на этот раз без метки. Я слил
max
иdistanceSquared
и такmin
и такnewDistanceSquared
как они не требуются одновременно. Я изменилсяInteger.MAX_VALUE
на2e31-1
. Также я создал константу,half = 0.5
которая используется для вычисления углов здания. Это короче в версии для гольфа. В целом мы сохранили еще 30 символов!источник