Соревнование
Самый короткий код за счет символов для ввода двумерного представления доски и вывода «истина» или «ложь» в соответствии с вводом .
Доска изготовлена из 4 видов плиток:
# - A solid wall
x - The target the laser has to hit
/ or \ - Mirrors pointing to a direction (depends on laser direction)
v, ^, > or < - The laser pointing to a direction (down, up, right and left respectively)
Есть только один лазер и только одна цель . Стены должны образовывать сплошной прямоугольник любого размера, в котором лазер и мишень находятся внутри. Стены внутри «комнаты» возможны.
Лазерный луч снимает и движется от его источника в направлении, куда он указывает. Если лазерный луч падает на стену, он останавливается. Если лазерный луч попадает в зеркало, он отражается на 90 градусов в направлении, на которое указывает зеркало. Зеркала являются двусторонними, то есть обе стороны являются «отражающими» и могут отражать луч двумя способами. Если лазерный луч попадает в сам лазер ( ^v><
), он рассматривается как стена (лазерный луч разрушает луч, и поэтому он никогда не попадет в цель).
Контрольные примеры
Входные данные: ########## # / \ # # # # \ Икс# #> / # ########## Вывод: правда Входные данные: ########## # vx # # / # # / # # \ # ########## Вывод: ложный Входные данные: ############# # # # #> # # # # # # # Икс # # # # ############# Вывод: ложный Входные данные: ########## # / \ / \ / \ # # \\ // \\\ # # // \ / \ / \\ # # \ / \ / \ / Х ^ # ########## Вывод: правда
Количество кодов включает в себя ввод / вывод (то есть полную программу).
источник
Ответы:
Perl,
166160 символовPerl,
251248246222214208203201193190180176173170166 -> 160 символов.На момент окончания конкурса у Solution было 166 ударов, но А. Рекс нашел пару способов сбрить еще 6 персонажей:
Первая строка загружает ввод в
%t
таблицу доски, где$t{99*i+j}
находится символ в строке i , столбце j . Затем,он ищет элементы
%t
для символа, который соответствует> ^ <
илиv
, и одновременно устанавливает$d
значение между 0 и 3, которое указывает начальное направление лазерного луча.В начале каждой итерации в основном цикле мы обновляем,
$d
если луч в настоящее время находится на зеркале. XOR'ing на 3 дает правильное поведение для\
зеркала, а XOR'ing на 1 дает правильное поведение для/
зеркала.Затем текущая позиция
$r
обновляется в соответствии с текущим направлением.Мы назначаем символ в текущей позиции, чтобы
$_
удобно использовать операторы сопоставления.Продолжайте, если мы на пустом месте или зеркальный символ. В противном случае мы завершаем работу,
true
если мы находимся на target ($_ =~ /x/
) и вfalse
противном случае.Ограничение: может не работать при проблемах с более чем 99 столбцами. Это ограничение может быть снято за счет еще 3 символов,
источник
s!.!$t{$s++}=$&!ge,$s=$r+=99for<>;
, изменить%d=split//,.." to
% d = .. = ~ /./ g, and change
grep {..}% t` наgrep..,%t
Perl, 177 символов
Первый разрыв строки может быть удален; два других являются обязательными.
Объяснение:
Если движущийся вправо луч попадает в {пустое пространство, наклонное зеркало, наклонное зеркало}, то он становится {движущимся вправо пучком, движущимся вниз пучком}. Инициализируйте
$/
по пути - к счастью, «6» не является допустимым входным символом.Прочитайте доску в
$_
.$s
является символом того, на чем сейчас сидит луч. Поскольку лазерный излучатель следует рассматривать как стену, для начала установите его в качестве стены.Если лазерный луч направлен в любую сторону, кроме правой, поверните его символ, а затем поверните всю доску на место (также поворачивая символы для зеркал). Это поворот на 90 градусов влево, который достигается путем реверсирования рядов при транспонировании строк и столбцов, с немного излишним
s///e
побочным эффектом. В гольф-коде tr написано в форме,y'''
которая позволяет мне пропустить обратную косую черту.Прекратите с правильным сообщением, если мы поразим цель или стену.
Если перед лазером пустое пространство, двигайтесь вперед. Если перед лазером есть зеркало, двигайтесь вперед и вращайте луч. В любом случае, поместите «сохраненный символ» обратно в старое местоположение луча и поместите только что перезаписанное в сохраненный символ.
Повторите до конца.
{...;redo}
на два символа меньшеfor(;;){...}
и на три меньшеwhile(1){...}
.источник
C89 (209 знаков)
объяснение
Этому чудовищу, вероятно, будет трудно следовать, если вы не понимаете C. Просто предупреждение.
Этот маленький макрос проверяет,
*p
равен ли текущий символ ( ) тому, чтоa
находится в символьной форме (*#a
). Если они равны, установите вектор движения наb
(m=b
), отметьте этого персонажа как стену (*p=1
) и установите в качестве начальной точки текущее местоположение (q=p
). Этот макрос включает в себя «еще» часть.Объявите некоторые переменные. *
q
текущее местоположение источника света. *G
это игровое поле в виде одномерного массива. *p
текущее местоположение чтения при заполненииG
. *w
ширина доскиОчевидно
main
.m
переменная, хранящая вектор движения (Это параметр дляmain
оптимизации.)Перебирайте все символы, заполняя
G
используяp
. ПропуститьG[0]
в качестве оптимизации (не нужно тратить впустую написание символовp
в третьей частиfor
).Используйте вышеупомянутый макрос для определения лазера, если это возможно.
-1
и1
соответствуют слева и справа соответственно и-w
иw
вверх и вниз.Если текущий символ является маркером конца строки (ASCII 10), установите ширину, если она еще не была установлена. Пропущенный
G[0]
позволяет нам писатьw=p-G
вместоw=p-G+1
. Кроме того, это завершает?:
цепочку изM
.Переместить свет на вектор движения.
Отразите вектор движения.
Если это стена или
x
, выйдите с соответствующим сообщением (m=0
завершает цикл). В противном случае ничего не делать (noop;m=m
)источник
g.c:3: declaration expected
:(puts
декларации помогло, но не настолько, чтобы довести ее до 170. 209 довольно хорошо, поэтому, я думаю, я оставлю это на этом. Спасибо за помощь ребята. Я очень ценю это. =] (Что-нибудь, чтобы свергнуть этих колдунов Perl!)Могу поспорить, что люди ждали этого в течение НЕСКОЛЬКО времени. (Что ты имеешь в виду, вызов закончен, и никого больше не волнует?)
Вот ... я представляю решение в
Befunge-93!
Он весит 973 символа (или 688, если вы достаточно благотворительны, чтобы игнорировать пробелы, которые используются только для форматирования и ничего не делают в реальном коде).
Предостережение : я недавно написал свой собственный интерпретатор Befunge-93 на Perl, и, к сожалению, это все, что у меня действительно было время, чтобы протестировать его. Я достаточно уверен в его правильности в целом, но у него может быть странное ограничение в отношении EOF: поскольку
<>
оператор Perl возвращает undef в конце файла, это обрабатывается как 0 в числовом контексте. Для реализаций на основе Си, где EOF имеет другое значение (скажем, -1), этот код может не работать.объяснение
Если вы не знакомы с синтаксисом и операцией Befunge, проверьте здесь .
Befunge - это стековый язык, но есть команды, позволяющие записывать символы в код Befunge. Я пользуюсь этим в двух местах. Сначала я копирую весь ввод на доску Befunge, но расположил пару строк ниже фактического написанного кода. (Конечно, это никогда не видимо, когда код выполняется.)
Другое место рядом с верхним левым:
В этом случае область, которую я выделил выше, - это место, где я храню пару координат. Первый столбец в средней строке - это место, где я храню x-координату для текущей «позиции курсора»; во втором столбце хранится координата y; следующие два столбца предназначены для хранения координат x и y источника лазерного луча, когда он найден; и последний столбец (с символом «а» в нем) в конечном итоге перезаписывается, чтобы содержать текущее направление луча, которое, очевидно, изменяется при трассировке пути луча.
Программа начинается с размещения (0,27) в качестве начальной позиции курсора. Затем ввод читается по одному символу за раз и помещается в позицию курсора; Символы новой строки просто приводят к увеличению координаты y, а координаты x возвращаются к 0, точно так же, как реальный возврат каретки. В конечном счете интерпретатор читает undef, и это значение 0 символов используется, чтобы сигнализировать об окончании ввода и перейти к этапам итерации лазера. Когда читается символ лазера [<> ^ v], он также копируется в хранилище памяти (над символом «a»), а его координаты копируются в столбцы слева.
Конечным результатом всего этого является то, что весь файл в основном копируется в код Befunge, немного ниже фактического пройденного кода.
После этого местоположение луча копируется обратно в позиции курсора, и выполняется следующая итерация:
Если на это будет достаточно спроса, я постараюсь указать, где именно в коде все это выполняется.
источник
F #, 36 строк, очень читабельный
Хорошо, просто чтобы получить ответ там:
Образцы:
источник
Golfscript - 83 символа (коллаж из мейджеров и страджеров)
Новая строка только для упаковки
Golfscript - 107 символов
Новая строка просто для ясности
Как это устроено.
Первая строка определяет исходное местоположение и направление.
Вторая линия поворачивается, когда лазер попадает в зеркало.
источник
353 символа в рубине:314277 символов сейчас!Хорошо, 256 символов в Ruby, и теперь я готов. Хороший круглый номер, чтобы остановиться на. :)247 символов Я не могу остановиться.223203201 символ в рубинеС пробелами:
Немного переработано:
источник
ch
вC
или любой другой 1 полукокса буквы , чтобы сохранить 2 символов!i++
(вместоi+=1
)?питон
294277253240232 символов, включая переводы строки:(первый символ в строках 4 и 5 - это табуляция, а не пробелы)
Я забыл, что в Python даже есть дополнительные точки с запятой.
Как это устроено
Основная идея этого кода заключается в использовании комплексных чисел для представления позиций и направлений. Ряды представляют собой воображаемую ось, увеличивающуюся вниз. Столбцы являются реальной осью, увеличивающейся вправо.
l='>v<^';
список лазерных символов. Порядок выбирается так, чтобы индекс символа направления лазера соответствовал степени sqrt (-1)x={'/':'^<v>','\\':'v>^<',' ':l};
таблица преобразований, определяющая, как меняется направление, когда луч покидает разные плитки. Плитка - это ключ, а новые направления - это значения.b=[1];
держит доску. Первый элемент равен 1 (оценивается как true), поэтому цикл while будет запущен хотя бы один раз.r=p=0
r
текущий номер строки на входе,p
текущая позиция лазерного луча.while b[-1]:
прекратить загрузку данных платы, когда raw_input возвращает пустую строкуb+=[raw_input()];r+=1
добавить следующую строку ввода на доску и увеличить счетчик строкfor g in l:
угадать каждое направление лазера по очередиc=b[r].find(g)
установите в столбце местоположение лазера или -1, если он не находится на линии (или указывает в другом направлении)if-1<c:p=c+1j*r;d=g
если мы нашли лазер, то установите текущее положениеp
и направлениеd
.d
это один из символов вl
После загрузки платы в
b
текущее положениеp
и направлениеd
были установлены таковые из лазерного источника.while' '<d:
пробел имеет более низкое значение ASCII, чем любой из символов направления, поэтому мы используем его как флаг остановки.z=l.find(d);
индекс текущего направления char вl
строке.z
позже используется как для определения нового направления луча с помощьюx
таблицы, так и для увеличения позиции.p+=1j**z;
увеличить позицию, используя степень i. Например,l.find('<')==2
-> i ^ 2 = -1, который переместился бы влево на один столбец.c=b[int(p.imag)][int(p.real)];
читать символ в текущей позицииd=x.get(c,' '*4)[z]
ищите новое направление для луча в таблице преобразования. Если текущий символ не существует в таблице, тогда установитеd
пробел.print'#'<c
выведите false, если мы остановились на чем-то кроме цели.источник
p+=1j**z
: Это мило.Это
естьбыл прямым портом решения Брайана на C # 3, минус консоль взаимодействия. Это не вход в задачу, так как это не полная программа, мне просто интересно, как некоторые из конструкций F #, которые он использовал, могли быть представлены в C #.Изменить: После некоторых экспериментов, следующий довольно подробный код поиска:
был заменен более компактным кодом LINQ to Objects:
источник
F #, 255 символов (и все же довольно читабельно!):
Хорошо, после ночного отдыха я значительно улучшила это:
Давайте поговорим об этом построчно.
Во-первых, отбросьте все входные данные в большой одномерный массив (двумерные массивы могут быть плохими для гольф-кода; просто используйте одномерный массив и добавьте / вычтите ширину одной строки к индексу для перемещения вверх / вниз по линии).
Затем мы вычисляем 'w', ширину входной строки и 'c', начальную позицию, индексируя в нашем массиве.
Теперь давайте определим функцию «next» «n», которая принимает текущую позицию «c» и направление «d», которое равно 0,1,2,3 для вверх, влево, вправо, вниз.
Индекс-эпсилон 'e' и 's-new-direction-if-we-we-hit-slash' s 'вычисляются таблицей. Например, если текущее направление 'd' равно 0 (вверх), то первый элемент таблицы говорит "-w, 2", что означает, что мы уменьшаем индекс на w, и если мы коснемся косой черты, новое направление равно 2 (право).
Теперь мы вернемся к следующей функции 'n' с (1) следующим индексом ("c + e" - current plus epsilon) и (2) новым направлением, которое мы вычисляем, посмотрев вперед, чтобы увидеть, что находится в массиве в эта следующая клетка. Если заглядывающий символ - косая черта, новое направление - «s». Если это обратная косая черта, новое направление - 3 с (наш выбор кодировки 0123 делает эту работу). Если это пробел, мы просто продолжаем двигаться в том же направлении «д». И если это любой другой символ «c», то игра заканчивается, выводя «true», если char был «x», и false в противном случае.
Для начала мы вызываем рекурсивную функцию 'n' с начальной позицией 'c' и начальным направлением (которое выполняет начальное кодирование направления в 0123).
Я думаю, что я все еще могу побрить еще несколько персонажей, но я очень доволен этим (а 255 - неплохое число).
источник
Взвешивание в 18203 символов - это решение Python, которое может:
Это все еще нужно привести в порядок, и я не знаю, диктует ли 2D физика, что луч не может пересекать сам себя ...
Скрипт bash для отображения отчетов об ошибках цвета:
Юнитесты, используемые в разработке:
источник
Рубин, 176 символов
Я использовал простой конечный автомат (как большинство плакатов), ничего особенного. Я просто продолжал сокращать его, используя каждый трюк, который только мог придумать. Побитовое XOR, используемое для изменения направления (сохраняемое как целое число в переменной
c
), стало большим улучшением по сравнению с условиями, которые я имел в более ранних версиях.У меня есть подозрение, что код, который увеличивается
x
иy
может быть сокращен. Вот часть кода, которая выполняет приращение:Изменить : мне удалось немного сократить вышеупомянутое:
Текущее направление лазера
c
сохраняется следующим образом:Код полагается на этот факт для увеличения
x
иy
на правильное значение (0, 1 или -1). Я попытался переставить, какие числа отображаются в каждом направлении, в поисках схемы, которая позволила бы мне выполнить побитовую манипуляцию для увеличения значений, потому что у меня появилось неприятное ощущение, что оно будет короче арифметической версии.источник
C # 3.0
259 символов
Чуть более читабельно:
Основная трата символов заключается в поиске ширины карты и расположения лазерного источника. Есть идеи как сократить это?
источник
while(1)
C + ASCII, 197 знаков:
Это решение C предполагает набор символов ASCII, что позволяет нам использовать трюк с зеркалом XOR. Это также невероятно хрупко - например, все строки ввода должны быть одинаковой длины.
Он преодолевает отметку в 200 символов - но, черт возьми, вы еще не победили эти решения Perl!
источник
Golfscript (83 символа)
Привет, Гнибблер!
источник
Питон - 152
Читает ввод из файла с именем "L"
Для чтения из stdin замените первую строку на эту
Если вам нужна строчная истина / ложь, измените последнюю строку на
источник
True
наtrue
иFalse
наfalse
? ;-)D<5
» на «печать D <5»? Или мне чего-то не хватает?JavaScript - 265 символов
Обновление IV - Вероятность того, что это будет последний раунд обновлений, удалось сохранить еще пару символов, переключившись на цикл выполнения и переписав уравнение движения.
Обновление III - благодаря предложению strager относительно удаления Math.abs () и помещения переменных в глобальное пространство имен, что в сочетании с некоторой перестановкой назначений переменных, уменьшило код до 282 символов.
Обновление II - Еще несколько обновлений в коде, чтобы убрать использование! = -1, а также улучшенное использование переменных для более длительных операций.
Обновление - когда закончено и внесены некоторые изменения путем создания ссылки на функцию indexOf (спасибо LiraNuna!) И удаления ненужных скобок.
Я впервые играю в гольф кода, поэтому я не уверен, насколько лучше это может быть, любая обратная связь приветствуется.
Полностью свернутая версия:
Оригинальная версия с комментариями:
Веб-страница для тестирования:
источник
index != -1
сindex > 0
пожалуйста! (Надеюсь, никто не помещает лазер в верхнем левом углу, поэтому0
не будет возвращен. =]) Вы можете связыватьvar
операторы или вообще избавляться от них (помещая переменные в глобальное пространство имен). Я думаюMath.abs(m)==1
можно заменить наm==-1|m==1
. Можноmovement = ...; location += movement
оптимизировать доlocation += movement =
?function(a){return g.indexOf(a)}
может быть замененоfunction(a)g.indexOf(a)
в последних версиях JavaScript.Дом Зеркала
Не факт, что вступление в испытание, но я написал игру, основанную на этой концепции (не так давно).
Он написан на Scala с открытым исходным кодом и доступен здесь :
Это делает немного больше; имеет дело с цветами и различными типами зеркал и устройств, но версия 0.00001 сделала именно то, что просит этот вызов. Я потерял эту версию, и она так или иначе не была оптимизирована для подсчета символов.
источник
c (K & R) 339 необходимых символов после дополнительных предложений от Страгера.
Мой физик отметил, что операции распространения и отражения не зависят от времени, поэтому эта версия отбрасывает лучи от цели и проверяет, не прибыл ли лазерный излучатель.
Остальная часть реализации очень прямолинейна и более или менее точно взята из моих более ранних усилий.
Сжатый:
Несжатый (МОГ):
Нет проверки ввода, и неправильный ввод может отправить его в бесконечный цикл. Работает правильно с вводом не более 99 на 99. Требуется компилятор, который будет связывать стандартную библиотеку, не включая заголовки. И я думаю, что я закончил, Стрэджер заставил меня биться значительно, даже с его помощью.
Я скорее надеюсь, что кто-то продемонстрирует более тонкий способ выполнить задачу. В этом нет ничего плохого, но это не глубокая магия.
источник
=0
использовать глобальные переменные, поскольку они по умолчанию инициализируются в 0. Замените символьные константы их эквивалентами в десятичном виде. Используйте>0
вместо того,!=EOF
чтобы проверять EOF (и\0
). Вы, вероятно, можете удалить#define
часть кода,case
как я сделал сif
. Нет необходимости в экстра\n
вputs
качествеputs
должен напечатать строку в любом случае.for(;;)
короче чемwhile(1)
. Надеюсь это поможет. =]"There is no input validation"
- Там не должно быть никаких. Чтобы упростить игру в гольф, предполагается, что ввод всегда будет «чистым», если не указано иное.Рубин - 146 символов
источник
PostScript , 359 байт
Первая попытка, много возможностей для улучшения ...
источник
Хаскелл,
395391383361339 символов (оптимизировано)Все еще использует общий конечный автомат, а не что-нибудь умное:
Читаемая версия:
источник
Я верю в повторное использование кода, я бы использовал один из ваших кодов в качестве API :).
32 символа \ o / ... wohoooo
источник
C ++: 388 символов
( 318 без заголовков)
Как это устроено:
Сначала читаются все строки, затем лазер найден. Следующее будет оцениваться до
0
тех пор, пока лазерная стрелка еще не найдена, и то же время назначеноx
горизонтальному положению.Затем мы смотрим, в каком направлении мы нашли, и сохраняем его
i
. Четные значенияi
сверху / слева («убывающие») и нечетные значения снизу / справа («возрастающие»). В соответствии с этим понятиемd
(«направление») иr
(«ориентация») установлены. Мы индексируем массив указателейz
с ориентацией и добавляем направление к целому числу, которое мы получаем. Направление меняется только в том случае, если мы попали в косую черту, но оно остается неизменным, когда мы попадаем в обратную косую черту. Конечно, когда мы ударяем по зеркалу, мы всегда меняем ориентацию (r = !r
).источник
Groovy @ 279 персонажей
источник
C #
1020 символов.1088 символов (добавлен ввод с консоли).925 символов (рефакторированные переменные).875 символов (удален избыточный инициализатор словаря; изменен на двоичный и операторы)
Сделал пункт, чтобы не смотреть на кого-либо еще перед публикацией. Я уверен, что это может быть немного LINQ. И весь метод FindLaser в читаемой версии кажется мне ужасно подозрительным. Но это работает, и уже поздно :)
Обратите внимание, что читаемый класс включает дополнительный метод, который распечатывает текущую арену при движении лазера.
Читаемая версия (не совсем финальная версия для гольфа, но та же предпосылка):
источник
Perl 219
Мой Perl версия
392342 символов (я должен был обработать случай луча удара лазера):Update , спасибо Hobbs за напоминание мне
tr//
, теперь 250 символов:Обновление , удаление
m
вm//
, изменяя двеwhile
петли принесенной немного сбережений; теперь требуется только одно место.(
L:it;goto L
такой же длины какdo{it;redo}
):Я побрился, но с некоторыми из них он
едва ликонкурирует, хотя и поздно.Это выглядит немного лучше, как:
Ну ... Честно говоря, это должно быть само собой разумеющимся, если вы понимаете, что
@b
это массив массивов символов в каждой строке и можете читать простые выражения иtr
операторы.источник
$_=$s;tr/^v<>/<>^v/
и$_=$s;tr/v^<>/<>^v/
соответственно. Кроме того, вам не нужноm
вm//
.$_=$s;tr/v^></<>^v/;
if m/.../
которые могутif/.../
сохранить два символа в поп.y///
вместо того,tr///
чтобы сохранить два символа.F # - 454 (или около того)
Немного опоздал к игре, но не могу удержаться от публикации моей 2-й попытки.
Обновление изменено незначительно. Теперь правильно останавливается, если передатчик попал. Удержал идею Брайана для IndexOfAny (позор, эта строка настолько многословна). На самом деле мне не удалось выяснить, как заставить ReadToEnd возвращаться из консоли, поэтому я беру это на веру ...
Я рад этому ответу, как будто он довольно короткий, он все еще довольно читабелен.
источник