Представьте себе следующий сценарий: вы играете в линейные корабли с другом, но решили обмануть. Вместо того, чтобы перемещать корабль после того, как он стреляет туда, где раньше был ваш корабль, вы решаете вообще не размещать никаких кораблей. Вы говорите ему, что все его выстрелы - промахи, пока невозможно разместить корабли таким образом.
Вы должны написать функцию или полную программу, которая каким-то образом принимает 3 аргумента: размер поля, список размеров кораблей и список снимков.
Поле боя
Одним из заданных параметров является размер платы. Поле битвы - это квадрат клеток, а данный параметр - просто одна сторона квадрата.
Например, ниже приведена доска размером 5.
Координаты в поле указываются в виде двухкомпонентной строки: буква, за которой следует число. Вы можете положиться на буквы в каком-то конкретном случае.
Буква обозначает столбец, цифра обозначает строку ячейки (индексируется 1). Например, на изображении выше выделенная ячейка обозначена "D2"
.
Поскольку в нем всего 26 букв, поле не может быть больше, чем 26x26.
Суд
Корабли представляют собой прямые линии из 1 или более блоков. Количество кораблей указывается в списке, где первый элемент - количество кораблей с 1 ячейкой, второй - количество кораблей с 2 ячейками и так далее.
Например, список [4,1,2,0,1]
создаст следующий набор кораблей:
Находясь на поле битвы, корабли не могут пересекаться или даже касаться друг друга. Даже с углами. Однако они могут касаться краев поля.
Ниже вы можете увидеть пример правильного размещения корабля:
Вы можете предположить, что для данного набора кораблей всегда есть место на пустой доске заданного размера.
Выход
Если такие размещения кораблей существуют, вы должны вывести любое из них.
Программа должна вывести разделенную новой строкой матрицу символов ascii любого из трех типов - один для обозначения пустой ячейки, один - для фрагмента корабля и один - для ячейки, помеченной как «пропущенные». Другие символы не должны выводиться.
Например,
ZZ@Z
\@@Z
@\\Z
\Z\\
(В этом примере я определил @
пустую ячейку, \
пропущенную и Z
отправленную часть)
Если такого размещения не существует, программа / функция должна вернуться без вывода чего-либо.
вход
Если вы решите создать полноценную программу, вам нужно будет указать, как вводятся списки, некоторые могут проходить через аргументы, некоторые через stdin.
Это код-гольф , выигрывает наименьшее количество персонажей.
Пример не оптимизированного для игры в гольф решения можно найти здесь.
Compile with -std=c99
, первый аргумент - размер доски, остальные аргументы - размеры корабля. Список снимков, разделенных новой строкой, указан на stdin. Пример:
./a 4 1 1 1 <<< $'A2\nA4\nB3\nC3\nC4\D4'
источник
26x26
? Я набросал решение, основанное на регулярных выражениях и рекурсии, и оно становится чрезвычайно медленным = непригодным для полей более чем6x6
. Либо я делаю что-то очень глупое, либо отсутствие ответов означает, что у других тоже нет успеха.10x10
с4,3,2,1
ком- плектОтветы:
GolfScript, 236 символов
Ввод дан на STDIN. Первая строка содержит размер и количество кораблей, каждая следующая строка - координаты одного выстрела.
Пример:
Я думал, что у этой задачи также должен быть хотя бы один ответ на GolfScript. В конце это стало очень неприличным из-за используемого алгоритма, который предпочитает производительность по сравнению с краткостью.
Аннотированный код:
источник
SWI-Пролог,
536441 1 байт1 конец строки UNIX, последняя новая строка не учитывается
Версия со всеми удаленными оптимизациями ( 441 байт):
Поскольку код изменен для уменьшения количества байтов, он больше не будет принимать список снимков с дубликатами.
Версия с базовой оптимизацией, полностью отлаженная ( 536 → 506 байт)
Я реализую некоторые базовые проверки (необходимо подсчитать количество корабельных блоков ), чтобы ускорить выполнение кода в явно невозможных случаях. Код также невосприимчив к дублированию в списке кадров до сих пор.
Ниже (несколько) читаемая версия с подробными комментариями:
Формат запроса:
Пример запроса (используя образец в вопросе):
источник
Matlab - 536 символов
Обновлено: гораздо меньшее форматирование вывода, некоторые пробелы удалены.
Обновлено: добавлена версия для игры в гольф
Обновлено: добавлена прокомментированная версия, уменьшена версия для гольфа на ~ 100 символов
Вот версия для гольфа.
Вот несколько примеров.
Большая линия с 'kron' (в нижней части кода без гольфа) - моя любимая часть. Он записывает «1» во все местоположения на карте, которые соседствуют с данной позицией. Вы видите, как это работает? Он использует тензорное произведение Кронекера, умножение матриц и индексирует карту как линейный массив ...
источник
Python, 464 символа
Вход (стандартный):
Выход:
Работает с использованием целых чисел, содержащих растровые изображения различных функций:
источник
[::-1]
она заставляет его сначала попробовать самый длинный корабль. Он также возвращается, как только находит корабль, который не может установить.Python, 562 символа, -8 с ужасным выводом, +4? для вызова Bash
Примечание: уровни отступа: пробел, табуляция, табуляция + пробел, табуляция + табуляция и табуляция + табуляция + пробел. Это экономит несколько символов от использования только пробелов.
Использование и пример :
Принимает данные из аргументов командной строки. Выводит пробел как пробел, выстрел как
.
и@
как часть корабля:Когда неразрешимо, ничего не печатает:
2>X
Заключается в подавление сообщения об ошибке , поскольку выход из программы пути бросать исключение. Не стесняйтесь добавлять штраф +4, если сочтете справедливым. В противном случае я должен был бы сделать это,try: ... except:0
чтобы подавить его, что в любом случае потребовало бы больше символов.Я также могу печатать выходные данные в виде чисел (
0
,1
и2
) сбривать 8 символов, но эстетики значения I.Пояснение :
Я представляю доску в виде списка целых чисел с размером 2 больше, чем входные данные, чтобы избежать необходимости выполнять проверку границ.
0
представляет пустое пространство,1
выстрел и2
корабль. Я бегу по списку снимковQ
и отмечаю все снимки. Я конвертирую список кораблей в явный списокX
кораблей, например,[4, 0, 2, 0, 1]
становится[5, 3, 3, 1, 1, 1, 1]
. Тогда это простой алгоритм обратного отслеживания: в порядке убывания размера, попытайтесь разместить корабль, а затем попытайтесь разместить остальные корабли. Если это не работает, попробуйте следующий слот. Как только это удается, список кораблейX
становится пустым, и доступX[0]
вызывает исключение, которое выходит из программы. Остальное просто тяжелый гольф (изначально было 1615 символов).источник
Perl,
455 447 437 436 422418Отступ:
Я ожидаю, что это может быть продолжено (например, с помощью
eval<>
предварительно отформатированного ввода, поскольку я вижу, что все в порядке (?)), А также некоторые другие вещи (50$
символов? Нет, они останутся).Скорость, как я говорил ранее, может быть проблемой (от мгновенной (см. Пример ниже) до очень-очень длинной), в зависимости от того, где находится решение в дереве рекурсии, но пусть это будет вопрос устаревания используемого оборудования. Я сделаю оптимизированную версию позже, с рекурсией и 2-3 другими очевидными трюками.
Он запускается так, 3 линии передаются через STDIN:
~
это океан (художественное решение, не правда ли),o
это иx
есть корабли и выстрелы. Первые 5 строк получают ввод и готовят наше «поле битвы».$N
это размер,@S
развернутый массив кораблей (например,1 1 1 1 2 3 3 5
как указано выше) , и он переходит к следующей итерации. И так далее.$f
строка, представляющая поле битвы (строки с конкатенацией строк). Далее идет рекурсивная подпрограмма, которая ожидает текущее состояние поля боя и список оставшихся кораблей. Он проверяет слева направо, сверху вниз и пытается расположить каждый корабль в каждой позиции, как по горизонтали, так и по вертикали (см. «Спелые для оптимизации», но это будет позже). Горизонтальный корабль является очевидной заменой регулярного выражения, вертикальный - немного более хитрым - побитовая манипуляция строк для замены в столбце. В случае успеха (H, V или оба), новые недоступные позиции отмечены!
Редактировать: ОК, вот 594- байтовая (без отступа) версия, которая на самом деле пытается быть полезной (то есть быстрой) - оптимизирована в меру моих возможностей, при этом все еще применяя те же методы - рекурсию (хотя и сделано «вручную») и регулярные выражения. Он поддерживает «стек» -
@A
- массив состояний, которые стоит исследовать. «Состояние» - это 4 переменные: текущая строка поля битвы, индекс, с которого следует начинать попытки разместить корабли, ссылка на массив оставшихся кораблей и индекс следующего корабля, который нужно попробовать. Изначально существует одно «состояние» - начало пустой строки, все корабли. При совпадении (H или V, см. Выше) текущее состояние передается для последующего исследования, обновленное состояние (с размещенным кораблем и отмеченными недоступными позициями) передается и блок перезапускается. Когда конец строки поля битвы достигнут без успеха,@A
исследуется следующее доступное состояние из (если таковое имеется).Другие оптимизации: не перезапускать с самого начала строки, пытаться сначала разместить большие корабли, не проверять корабли того же размера, если предыдущий потерпел неудачу в той же позиции, + возможно что-то еще (например, без
$&
переменных и т. Д.).,
OTOH, это все еще берет навсегда для невозможного случая
6 5 4 3 2 1
в примере выше. Возможно, практическая версия должна выйти немедленно, если общий тоннаж корабля превышает вместимость поля боя.источник
Решение C #
источник
size=1 ships={1} moves={"A1"}
.Ява, 1178
Да, слишком долго.
Ungolfed:
Sample-Input
Sample-выход
С
O
пропущенный выстрел#
Корабль-часть_
снимай здесь дальше ;-)Смотрите на ideone.com
Обработка ввода ожидает пробелы вокруг чисел /
;
и не будет работать иначе.Сначала я ставлю большие корабли, потому что у них меньше мест, куда можно пойти. Если вы хотите переключиться на малые первый можно заменить
pop()
наremove(0)
иpush(s)
на ,add(0,s)
даже заменив только один из двух должен еще привести к действующей программе.Если вы позволите судам касаться друг друга,
g(int,int)
функция может быть значительно упрощена или удалена.источник