Возьмите 2-мерную сетку и нарисуйте на ней несколько отрезков, чтобы представить зеркала. Теперь выберите точку для размещения теоретического лазера и угол, чтобы определить направление, на которое он указывает. Вопрос в следующем: если вы следуете по пути лазерного луча на определенном расстоянии, в какой точке координат вы находитесь?
Пример:
На этом изображении, L
является расположение лазера, t
является его угол (измеряется от положительной оси X), M1
, M2
, и M3
все сегменты линии зеркала, и E
является точкой на пути лазерного луча после того, как D = d1 + d2 + d3 + d4
блоков, начиная с L
.
Цель
Написать кратчайшую программу (в байтах) , который выводит E
данные L
, t
, D
и список зеркал.
(Используйте http://mothereff.in/byte-counter для подсчета байтов.)
Формат ввода
Вход будет поступать со стандартного ввода в формате:
Lx Ly t D M1x1 M1y1 M1x2 M1y2 M2x1 M2y1 M2x2 M2y2 ...
- Все значения будут плавающей точку , соответствующей это регулярное выражение:
[-+]?[0-9]*\.?[0-9]+
. - Между каждым числом всегда ровно один пробел.
- Требование кавычек вокруг ввода разрешено.
t
в градусах, но не обязательно в[0, 360)
диапазоне. (Если вы предпочитаете использовать радианы, просто скажите это в своем ответе.)D
может быть отрицательным, эффективно поворачивая лазер на 180 градусов.D
также может быть 0.- Там может быть как угодно много зеркал (включая их вообще).
- Порядок зеркал не должен иметь значения.
- Вы можете предположить, что ввод будет кратным 4 числам. например,
Lx Ly t
илиLx Ly t D M1x1
являются недействительными и не будут проверены. Нет ввода также является недействительным.
Схема выше может быть введена как:
1 1 430 17 4.8 6.3 6.2 5.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3
(Обратите внимание, что изображение было нарисовано от руки, и эти значения являются лишь приблизительными. Входные значения Мартина Бюттнера
1 1 430 17 4.8 5.3 6.2 4.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3
даст больше столкновений, хотя они не соответствуют эскизу.)
Выходной формат
Вывод должен идти в стандартный вывод в формате:
Ex Ey
Они также являются поплавками и могут быть в экспоненциальной форме.
Заметки
- Зеркала могут пересекаться друг с другом.
- Обе стороны зеркал являются отражающими.
- Луч может попасть в одно и то же зеркало много раз.
- Луч продолжается вечно.
Неопределенные случаи
Вы можете предположить, что случаи, когда
- лазер запускается на отрезке зеркальной линии
- лазерный луч достигает конечной точки зеркала
- лазерный луч попадает на пересечение между двумя зеркалами
не определены и не будут проверены. Ваша программа может сделать что угодно, если это произойдет, в том числе выдать ошибку.
бонус
Просто ради интереса, я буду награждать 200 баллов за наивысшую оценку, которая выводит графическое представление проблемы (вы даже можете написать интерактивный сценарий). Эти бонусные представления не требуют участия в игре и могут быть снисходительны к тому, как обрабатываются ввод и вывод. Они отличаются от фактических представлений о гольфе, но оба должны быть представлены в одном и том же ответе .
Примечание: хорошо подать только бонусный ответ, вы просто не будете принятым ответом. Чтобы быть принятым, вы должны точно следовать спецификации ввода / вывода (например, вывод включает только Ex Ey
изображения, а не изображения) и быть самым коротким.
Ответы:
Рубин, 327 байт
(прокрутите вниз)
Mathematica, бонусный ответ
Я сейчас собираюсь только для графического представления. Я мог бы портировать это на Руби позже и сыграть в гольф, если захочу.
Вы можете назвать это как
Это даст вам анимацию в Mathematica, а также экспортирует GIF (тот, что вверху для этого ввода). Для этого я немного расширил пример OP, чтобы сделать его немного интереснее.
Больше примеров
Трубка со слегка расходящимися стенками, но закрытым концом:
Равносторонний треугольник и начальное направление, почти параллельное одной из сторон.
Еще:
Рубин, гольф-ответ
По сути, это прямой перевод решения Mathematica на Ruby, плюс некоторая игра в гольф и проверка его соответствия критериям ввода / вывода.
источник
Python 3 (
421C 390C, 366C)Использовать
builtin.complex
как 2d вектор. ТакЧтобы обойти решение Ruby 368C, я нашел довольно компактный метод для расчета точечного отражения вдоль зеркала. А также использовал некоторую сложную алгебру, чтобы уменьшить количество символов. Их можно легко найти в некоголенном коде.
Вот версия для гольфа.
Ungolfed
Бонус: HTML, Coffeescript, настройка и расчет в реальном времени
То есть вы перетаскиваете любые конечные точки (или lazer, mirros), затем дорожка визуализируется. Он также поддерживает два типа ввода: тот, который описан в вопросе, и тот, который используется @Martin Büttner.
Масштабирование также регулируется автоматически.
Пока нет анимации. Возможно я улучшу это позже. Однако, перетаскивая белые точки, вы можете увидеть другой тип анимации. Попробуйте сами онлайн здесь , это смешно!
Весь проект можно найти здесь.
Обновить
Здесь я приведу интересный случай:
И результат:
источник
HTML JavaScript,
10543,+947+889Я исправил ошибку и убедился, что вывод соответствует спецификации вопроса. Веб-страница ниже имеет версию для игры в гольф, а также графическую бонусную версию. Я также исправил ошибку, указанную @Ray, которая спасла 58 символов. (Спасибо, Рэй.) Вы также можете запустить гольф-код в консоли JavaScript. (Сейчас я использую зеленый лазер мощностью 2 мВт.)
Гольф-код
вход
Выход
Вы можете проверить это здесь: http://goo.gl/wKgIKD
объяснение
Код на веб-странице прокомментирован. По сути, я рассчитываю пересечение лазера с каждым зеркалом, предполагая, что лазер и зеркала бесконечно длинные. Затем я проверяю, находится ли пересечение в пределах конечной длины зеркала и лазера. Затем я беру ближайший перекресток, перемещаю лазер в эту точку и продолжаю, пока лазер не пропустит все зеркала.
Очень веселый проект. Спасибо, что задали этот вопрос!
Читаемый код
источник
0 0 0.4 100 1 1 1 -1 1 -1 -1 -1 -1 -1 -1 1 -1 1 1 1
.Питон - 765
Хороший вызов. Это моё решение, которое получает вход от stdin и выводит на stdout. Используя пример @Martin Büttner:
Вот код для игры в гольф:
А вот и код ungolfed с бонусной фигурой
источник
sys.argv
это не stdin.Матлаб (388)
участок
Концепции
Точки отражения
Для расчета точек отражения нам нужно пересечь две прямые линии. Один с точкой p0 и вектором v, другой между двумя точками p1, p2. Таким образом, уравнение для решения (s, t - параметры): p0 + t v = s p1 + (1-s) * p2.
Параметр s является тогда барицентрической координатой зеркала, так что если 0
Зеркальное
Зеркальное отображение v довольно просто. Предположим, что || v || = || n || = 1 где n - нормальный вектор текущего зеркала. Тогда вы можете просто использовать формулу v: = v-2 ** n, где <,> - скалярное произведение.
Срок действия шага
При вычислении ближайшего «действительного» зеркала мы должны учитывать некоторые критерии, которые делают его действительным. Сначала точка пересечения зеркала должна находиться между двумя конечными точками, поэтому она должна быть 0
программа
Слегка поиграл в гольф (388)
источник