Этот вопрос основан на головоломке «Башни с номерами» (также известной как «Небоскребы»), в которую можно играть онлайн . Ваша цель - найти решение головоломки и определить подсказки - количество башен, видимых вдоль каждого ряда и столбца. Это код гольф, поэтому побеждает меньше байтов.
Как работает Towers
Решением головоломки Towers является латинский квадрат - n*n
сетка, в которой каждая строка и столбец содержит перестановку чисел, 1
проходящих через n
. Пример для n=5
:
4 3 5 2 1
5 4 1 3 2
1 5 2 4 3
2 1 3 5 4
3 2 4 1 5
Каждая строка и столбец помечены подсказкой на каждом конце, как:
2 3 1 4 5
v v v v v
2 > 4 3 5 2 1 < 3
1 > 5 4 1 3 2 < 4
2 > 1 5 2 4 3 < 3
3 > 2 1 3 5 4 < 2
3 > 3 2 4 1 5 < 1
^ ^ ^ ^ ^
2 2 2 2 1
Каждый ключ представляет собой число от 1
до , n
который говорит вам , сколько башен вы «видите» , глядя вдоль строки / столбца из этого направления, если эти номера рассматриваются как башни с этой высотой. Каждая башня блокирует более короткие башни позади нее. Другими словами, башни, которые вы можете видеть, - это те, которые выше, чем любая башня до них.
Например, давайте посмотрим на первый ряд.
2 > 4 3 5 2 1 < 3
Он имеет подсказку 2
слева, потому что вы можете увидеть 4
и 5
. В 4
преграждает 3
из поля зрения и 5
блокирует все остальное. Справа вы можете увидеть 3
башни: 1
, 2
и 5
.
Требования к программе
Напишите программу или функцию, которая принимает сетку чисел и выводит или печатает подсказки, двигаясь по часовой стрелке сверху слева.
вход
n*n
Latin-квадрат с 2<=n<=9
.
Формат гибкий. Вы можете использовать любую структуру данных, которая представляет собой сетку или список, содержащий цифры или цифры. Вам может потребоваться разделитель между строками или вообще без разделителя. Некоторые возможности - это список, список списков, матрица, разделенная токеном строка, например
43521 54132 15243 21354 32415,
или строка без пробелов.
Вы не даны n
как часть ввода.
Выход
Верните или распечатайте подсказки, начиная сверху слева и по часовой стрелке. Итак, сначала верхние подсказки читаются вправо, затем правые подсказки читаются вниз, затем нижние подсказки читаются влево, левые подсказки читаются вверх.
Это было бы 23145 34321 12222 33212
для предыдущего примера
2 3 1 4 5
v v v v v
2 > 4 3 5 2 1 < 3
1 > 5 4 1 3 2 < 4
2 > 1 5 2 4 3 < 3
3 > 2 1 3 5 4 < 2
3 > 3 2 4 1 5 < 1
^ ^ ^ ^ ^
2 2 2 2 1
Как и для ввода, вы можете использовать список, строку или любую упорядоченную структуру. Четыре «группы» могут быть разделены или нет, во вложенной или плоской структуре. Но формат должен быть одинаковым для каждой группы.
Пример тестовых случаев:
(Ваш формат ввода / вывода не должен быть таким же, как эти.)
>> [[1 2] [2 1]]
[2 1]
[1 2]
[2 1]
[1 2]
>> [[3 1 2] [2 3 1] [1 2 3]]
[1 2 2]
[2 2 1]
[1 2 3]
[3 2 1]
>> [[4 3 5 2 1] [5 4 1 3 2] [1 5 2 4 3] [2 1 3 5 4] [3 2 4 1 5]]
[2 3 1 4 5]
[3 4 3 2 1]
[1 2 2 2 2]
[3 3 2 1 2]
>> [[2 6 4 1 3 7 5 8 9] [7 2 9 6 8 3 1 4 5] [5 9 7 4 6 1 8 2 3] [6 1 8 5 7 2 9 3 4] [1 5 3 9 2 6 4 7 8] [3 7 5 2 4 8 6 9 1] [8 3 1 7 9 4 2 5 6] [9 4 2 8 1 5 3 6 7] [4 8 6 3 5 9 7 1 2]]
[4 2 2 3 3 3 3 2 1]
[1 3 3 2 2 2 2 3 3]
[4 3 2 1 2 3 3 2 2]
[3 1 2 4 3 3 2 2 5]
Для вашего удобства вот те же тесты в формате плоской строки.
>> 1221
21
12
21
12
>> 312231123
122
221
123
321
>> 4352154132152432135432415
23145
34321
12222
33212
>> 264137589729683145597461823618572934153926478375248691831794256942815367486359712
422333321
133222233
432123322
312433225
≢¨∪¨↓⌈\(⍉⍪⌽⍪⍉∘⌽∘⊖⍪⊖)
Python 2, 115 байт
Там очень много листания списков происходит там.
Принимает ввод как вложенный список (например, вызов с
T([[4,3,5,2,1],[5,4,1,3,2],[1,5,2,4,3],[2,1,3,5,4],[3,2,4,1,5]])
). Выход представляет собой единый плоский список.Ungolfed:
Альтернатива 115:
Я понятия не имею, почему это работает с пониманием списка, но бросает
NameError
с определенным пониманием ...Слишком долго, но если кому-то интересно - да, это возможно до лямбды!
Pyth , 25 байт
Обязательный порт Pyth.
Введите список через STDIN, например
[[4, 3, 5, 2, 1], [5, 4, 1, 3, 2], [1, 5, 2, 4, 3], [2, 1, 3, 5, 4], [3, 2, 4, 1, 5]]
.Попробуйте онлайн ... это то, что я бы сказал, но, к сожалению, из соображений безопасности онлайн-переводчик запрещает использование eval во вложенных скобках.
JcQ5V4=J_CJ~Yml{meS<dhkUd_J)Y
Вместо этого попробуйте обходной код и введите его в виде сплюснутого списка[4, 3, 5, 2, 1, 5, 4, 1, 3, 2, 1, 5, 2, 4, 3, 2, 1, 3, 5, 4, 3, 2, 4, 1, 5]
.(Спасибо @isaacg, который помог гольфу несколько байтов)
источник
<
и>
являются односторонними операторами срезов, так что:d0hk
их можно превратить в<dhk
.U
на коллекцию входов так же, какUl
, так чтоUld
можно превратить вUd
.CJam,
2927 байтВвод как
Выходной как
Как это работает
Основная идея состоит в том, чтобы код работал вдоль строк и вращал сетку против часовой стрелки 4 раза. Чтобы подсчитать башни, я поднимаю каждую башню настолько, чтобы она не имела «визуального различия» (то есть, не меняйте ее, если она видна, или тяните ее на ту же высоту башни перед это), а потом я считаю разные высоты.
источник
APL, 44
Проверено здесь.
источник
J, 35 символов
Пример:
Попробуй это здесь.
источник
Хаскелл, 113
источник
Mathematica,
230 120 116 163110 байтИспользование:
источник
a[[y]][[x]]
естьa[[y,x]]
. И использованиеArray
может быть короче, чемTable
.JavaScript,
335264256213Оценка в консоли JavaScript браузера (я использовал Firefox 34.0, похоже, не работает в Chrome 39 ??). Тест с:
Вот текущее воплощение неопрятного кода - становится все труднее следовать:
Я намеренно не смотрел ни на один из других ответов, я хотел посмотреть, смогу ли я что-нибудь решить сам. Мой подход состоял в том, чтобы сгладить входные массивы в одномерный массив и предварительно вычислить смещения строк со всех четырех направлений. Затем я использовал shift вправо, чтобы проверить, была ли следующая башня ложной, и если это так, то увеличить счетчик для каждого ряда.
Я надеюсь, что есть много способов улучшить это, возможно, не предварительно рассчитать смещения, а вместо этого использовать какое-то переполнение / модуль по входному массиву 1D? И, возможно, объединить мои циклы, получить более функциональный, дедуплицирующий.
Мы ценим любые предложения!
Обновление № 1 : прогресс, у нас есть технологии! Мне удалось избавиться от предварительно рассчитанных смещений и сделать их встроенными с помощью троичных операторов, соединенных вместе. Также удалось избавиться от моего оператора if и преобразовать циклы for в whiles.
Обновление № 2 : Это довольно неприятно; нет вечеринки с пиццей для меня. Я полагал, что функционирование и использование рекурсии уменьшат количество байтов, но мои первые несколько попыток закончились увеличением на целых 100 символов! В отчаянии я старался использовать функции жирных стрелок ES6, чтобы по-настоящему сократить его. Затем я занялся заменой логических операторов арифметическими и удалением паренов, точек с запятой и пробелов, где только мог. Я даже перестал объявлять свои переменные и загрязнил глобальное пространство имен своими локальными символами. Грязный, грязный. После всех этих усилий я побил свой результат в обновлении № 1 на целых 8 символов, до 256. Блин!
Если бы я применил те же безжалостные оптимизации и трюки ES6 к своей функции обновления №1, я бы побил этот показатель на милю. Я могу сделать обновление № 3, просто чтобы посмотреть, как это будет выглядеть.
Обновление № 3 : Оказывается, что у рекурсивного подхода с толстой стрелой было гораздо больше жизни, мне просто нужно было работать с двумерным вводом напрямую, а не сглаживать его и лучше использовать области замыкания. Я переписал вычисления смещения внутреннего массива дважды и получил ту же оценку, так что этот подход может быть близок к минимальному!
источник
Только на Java
352350325 байт ...Ввод как
43521 54132 15243 21354 32415
Вывод как:
23145343211222233212
Отступ:
Любые советы будут с благодарностью!
источник
for
цикламиfor(;i<n;i++)
чтобыfor(;++i<n;)
и инициализироватьi
в-1
. Тогда используйте это, чтобы делать вещи. Вы можете сделать то же самое с другим циклом тоже.a[i].charAt(j)-'0'
вместо явного разбора. Это также не требует разделителей во входных данных (делает формат ввода более похожим на формат вывода).for
-loops вы всегда можете вставить что-то полезное в часть «приращение цикла». Это делает код более неясным и удаляет одну точку с запятой. Например:for(j=n;j-->0;System.out.print(c))
.Python 2 - 204 байта
Это, вероятно, действительно плохой гольф. Я думал, что проблема была интересной, поэтому я решил заняться этим, не глядя на чье-либо решение. Когда я набираю это предложение, мне еще предстоит взглянуть на ответы на этот вопрос. Я не удивлюсь, если кто-то еще сделал более короткую программу на Python;)
Пример ввода / вывода
При желании вы можете включить пробел в поле ввода. Честно говоря, где угодно. Пока это возможно
eval()
, это будет работать.объяснение
Единственная интересная часть этой программы - первая строка. Он определяет функцию,
f(l)
которая сообщает вам, сколько башен можно увидеть подряд, а остальная часть программы просто применяет эту функцию к каждой возможной позиции.При вызове он находит длину
l
и сохраняет ее в переменнойn
. Затем он создает новую переменнуюk
с этим довольно чудовищным пониманием списка:Это не так уж плохо, когда вы ломаете это. С тех пор
n==len(l)
, все, чтоif
только что представляетl
. Однако, используяif
мы можем удалить некоторые элементы из списка. Мы создаем список с([0]+list(l))
, который просто «l
с0
добавлением в начало» (игнорируйте вызовlist()
, это только там, потому что иногдаl
это генератор, и мы должны убедиться, что это на самом деле список здесь).l[c]
попадает в окончательный список, только если он больше, чем([0]+list(l))[c]
. Это делает две вещи:l[c]
становитсяc+1
. Мы эффективно сравниваем каждый элемент с элементом слева от него. Если оно больше, это видно. В противном случае он будет скрыт и удален из списка.[0]+
чушь и просто по сравнениюl[c]
сl[c-1]
, Python бы сравнить первую башню до последнего (вы можете индекса в список с конца с-1
,-2
и т.д.), поэтому если последняя башня была выше , чем Во-первых, мы получили бы неправильный результат.Когда все сказано и сделано,
l
содержит некоторое количество башен иk
содержит каждую из тех, которая не короче своего непосредственного соседа слева. Если ни один из них не был (например, дляf([1,2,3,4,5])
), тоl == k
. Мы знаем, что ничего не осталось сделать и вернутьn
(длина списка). Еслиl != k
это означает, что на этот раз была удалена хотя бы одна из башен, и, возможно, еще многое предстоит сделать. Итак, мы вернемсяf(k)
. Боже, я люблю рекурсию. Интересно, чтоf
всегда повторяется на один уровень глубже, чем это строго «необходимо». Когда список, который будет возвращен, генерируется, функция не имеет возможности узнать это сначала.Когда я начал писать это объяснение, длина этой программы составляла 223 байта. Объясняя вещи, я понял, что есть способы сохранить персонажей, поэтому я рад, что напечатал это! Самый большой пример - это то, что
f(l)
изначально он был реализован как бесконечный цикл, который был разорван во время вычислений, прежде чем я понял, что рекурсия сработает. Это просто говорит о том, что первое решение, о котором вы думаете, не всегда будет лучшим. :)источник
Матлаб,
(123)(119)используется так:
C #, до 354 ...
Другой подход, чем в TheBestOne.
источник
\n
вместо новых строк, я просто заменил их пробелами, поэтому код запускается сразу, когда кто-то копирует его. И я позволил себе удалить последнийend
(который закрывает функцию, которая не нужна), которая сохраняет дополнительные 4 символа, я надеюсь, что все было в порядке =)end
хотя,