Предположим, что вы натягиваете нитки Froot Loops для ожерелья, браслета, шнурка или чего-то еще. Есть 6 цветов контура: г - е изд, о диапазоне, у ellow, г Reen, б LUE и р urple. Вы хотите, чтобы ваша прядь начиналась с красного в самом левом углу, а цикл в порядке радуги шел вправо, заканчиваясь фиолетовым. То есть вы хотите сделать так, чтобы ваша нить могла быть представлена строкой, roygbp
повторенной несколько раз (возможно, 0).
Проблема в том, что вы уже натянули петли, а не в каком-то определенном порядке. Какие петли следует есть, а не есть, чтобы вы могли максимизировать количество правильных циклов радуги, идущих слева направо, с самой первой красной петлей и самой последней фиолетовой петлей?
Напишите программу или функцию, которая принимает произвольную строку символов roygbp
и печатает или возвращает строку одинаковой длины с e
тем, чтобы вместо циклов есть и n
вместо циклов не есть.
Например, если ваша нить Froot Loop выглядела как
вход будет
gorboypbgbopyroybbbogppbporyoygbpr
и, пройдя слева направо, мы можем найти 3 полных roygbp
последовательности радуги, но некоторые петли нужно съесть. Таким образом, результат будет
eenenneennenennneeeeneennenennnnne
в результате получается идеальная 3-х тактная цепь:
Если на входе нет полных циклов радуги, то на выходе будут все e
, и цепь заканчивается без петель. например, вход proygb
имеет выход eeeeee
. И наоборот, proygbp
имеет выход ennnnnn
.
Можно предположить, что все входные цепи имеют хотя бы одну петлю.
Самый короткий код в байтах побеждает.
r
или можетoygbproygbpr
также претендовать?Ответы:
Pyth, 31 байт
Невероятно неэффективно, объяснение скоро будет.
yUlz
генерирует все возможные подмножества всех возможных индексовz
(вход) в порядке. Например, если входabc
:Затем
hf!
находит первыйT
в приведенном выше списке такой, что:jk.DzT"roygbp"k
является ложным..D
берет строку и список индексов и удаляет элементы этих индексов. Так и.D"abcd",1 3
есть"ac"
. Так как.D
возвращает список (что не должно иметь место, это будет исправлено в будущих версиях Pyth), я используюjk
(k
is""
), чтобы объединить его обратно в строку.:_"roygbp"k
Часть заменяет каждый экземпляр цикла с пустой строкой.Поскольку пустая строка имеет значение false, в приведенных выше параграфах объясняется, как найти наименьший набор индексов, необходимый для употребления, чтобы получить строку, состоящую только из циклов.
:*lz\n_\e
затем превращает этот список индексов вnnnneeennene
строку.источник
Гексагония ,
920722271 байтВы говорите, шесть разных видов фруктовых петель? Вот для чего была создана Гексагония.
Ладно не было О боже, что я сделал для себя ...
Этот код теперь является шестиугольником с длиной стороны 10 (он начался в 19). Вероятно, это может быть еще немного, возможно, даже до размера 9, но я думаю, что моя работа здесь выполнена ... Для справки, в источнике 175 действующих команд, многие из которых являются потенциально ненужными зеркалами (или были добавлены для отмены). команда с пути пересечения).
Несмотря на кажущуюся линейность, код на самом деле двумерный: Hexagony преобразует его в правильный шестиугольник (который также является допустимым кодом, но все пробелы в Hexagony являются необязательными). Вот развернутый код во всем его ... ну, я не хочу сказать "красота":
объяснение
Я даже не буду пытаться объяснить все запутанные пути выполнения в этой версии игры в гольф, но алгоритм и общий поток управления идентичны этой версии без правил, которую, возможно, будет легче изучить для действительно любопытных после того, как я объясню алгоритм:
Честно говоря, в первом абзаце я шутил только наполовину. Тот факт, что мы имеем дело с циклом из шести элементов, на самом деле очень помог. Модель памяти Hexagony представляет собой бесконечную гексагональную сетку, где каждое ребро сетки содержит целое число произвольной точности со знаком, инициализированное в ноль.
Вот схема расположения памяти, которую я использовал в этой программе:
Длинный прямой бит слева используется как строка
a
с нулем в конце произвольного размера, связанная с буквой r . Пунктирные линии на других буквах представляют собой структуру такого же типа, каждая из которых повернута на 60 градусов. Первоначально указатель памяти указывает на край, обозначенный 1 , обращенный на север.Первый линейный бит кода устанавливает внутреннюю «звезду» ребер в буквы,
roygbp
а также устанавливает начальное ребро так1
, чтобы мы знали, где цикл заканчивается / начинается (междуp
иr
):После этого мы снова на краю с надписью 1 .
Теперь общая идея алгоритма такова:
e
на краю надпись с надписью ? , потому что пока цикл не завершен, мы должны предположить, что нам придется съесть и этого персонажа. После этого мы переместимся по кольцу к следующему персонажу в цикле.e
в ? граничит сn
s, потому что теперь мы хотим, чтобы этот цикл оставался на цепочке. Затем мы переходим к печати кода.e
иn
). Затем мы ищем 1 ребро (чтобы пропустить остаток потенциально неполного цикла), а затем перейдем к печати кода.e
для каждого символа. Тогда он движется к ? край, связанный с персонажем. Если оно отрицательное, мы просто завершаем программу. Если оно положительное, мы просто печатаем его и переходим к следующему символу. Как только мы завершим цикл, мы вернемся к шагу 2.Еще одна вещь, которая может быть интересной, - это то, как я реализовал строки произвольного размера (потому что я впервые использую неограниченную память в Hexagony).
Представьте себе , что мы в каком - то момент , когда мы по- прежнему читаем символы для г (так что мы можем использовать схему как есть) и а [0] и 1 уже заполнены с персонажами (все северо-запад от них по - прежнему равен нулю ). Например, возможно, мы только что прочитали первые два символа ввода в эти края и теперь читаем a .
og
y
Новый персонаж читается в краю. Мы используем ? край, чтобы проверить, равен ли этот символ
r
. (Здесь есть хитрый трюк: гексагония может легко различать только положительное и не положительное, поэтому проверка на равенство с помощью вычитания раздражает и требует как минимум двух ветвей. Но все буквы меньше, чем в 2 раза, поэтому мы можем сравнить значения, взяв по модулю, который даст только ноль, если они равны.)Поскольку
y
отличается отr
, мы перемещаем (немаркированный) край слева в и копируемy
туда. Теперь мы перемещаемся дальше по шестиугольнику, каждый раз копируя символ на одно ребро дальше, пока у нас не появитсяy
край напротив in . Но теперь в [0] уже есть символ, который мы не хотим перезаписывать. Вместо этого мы «таскать»y
вокруг следующего шестиугольника и проверить с 1 . Но там тоже есть персонаж, поэтому мы идем дальше с шестигранником. Теперь [2] по-прежнему равен нулю, поэтому мы копируемy
внутрь. Указатель памяти теперь перемещается назад вдоль строки к внутреннему кольцу. Мы знаем, когда достигли начала строки, потому что (немаркированные) ребра между a [i] равны нулю, тогда как ? положительно.Это, вероятно, будет полезной техникой для написания нетривиального кода в Hexagony в целом.
источник
Гексагония , 169 байт
Я был вдохновлен ответом Мартина Бюттнера (это тоже его esolang) и решил, что я могу сделать это в размере 8 (я уверен, что это возможно и в размере 7, но это очень сложно. Я уже провел четыре дня без Остановись на этом.)
Выложены шестиугольно:
Программа фактически не использует
#
инструкцию, поэтому я использовал этот символ, чтобы показать, какие ячейки на самом деле не используются. Кроме того, каждая неоперативная ячейка, проходящая только в одном направлении, является зеркалом (например,_
если проходить горизонтально), поэтому вы знаете, что все.
символы перемещаются более чем в одном направлении.объяснение
В начале мы выполняем последовательность инструкций
r''o{{y''g{{b''p"")"
. Они немного разбросаны по всему коду, потому что я сжал их после того, как написал все остальное. Я использую]
для переключения на указатель на следующую инструкцию несколько раз; таким образом я могу по существу телепортироваться в другой угол шестиугольника. Вся остальная часть программы выполняется указателем команды № 3.Теперь память выглядит следующим образом: важные ребра помечены именами, которые я буду использовать в этом объяснении:
Помеченные края означают следующее:
in
: Мы используем этот край для хранения символа, который мы читаем из STDIN.%
: Мы используем это ребро для выполнения операции по модулю над символом, считанным из STDIN (in
) и текущим «действительным» символом (r
,o
и т. Д.), Что будет,0
если они равны. Я украл этот трюк из ответа Мартина Бюттнера, но остальная часть программы другая.#
: Пока мы читаем «недопустимые» символы (то есть цвета, которые нам нужны), мы увеличиваем этот край. Таким образом, этот край запоминает, сколькоe
s нам нужно вывести позже.r?
: Всегда,0
за исключением того, где находитсяr
(красная) часть. Это говорит нам, когда мы завершили цикл.Программа протекает так:
#
. В противном случае переходите к следующему сегменту памяти по часовой стрелке.r?
он положительный, мы совершили целую революцию. Сделайте полный раунд и выведите#
e
s и 1n
на сегмент. Это устанавливает каждый#
обратно0
. (Объектe
помещается на немаркированном ребре, но для этогоn
мы неправильно присваиваем#
ребро, которое впоследствии мы установили,0
используя*
(умножение), что работает, потому что мы знаем, что все%
ребра в это время равны нулю.)#
+1e
с, пока не вернетесь кr?
положительному положению, затем выйдите.После полного запуска память выглядит примерно следующим образом в конце. Вы заметите ребра, содержащие
101
(код ASCIIe
); один изin
ребер-1
(EOF); все#
ребра в 0; и указатель памяти заканчивается на положительномr?
фронте.источник
Сетчатка ,
1488579 байтВы можете запустить это из одного исходного файла с
-s
флагом интерпретатора.объяснение
Давайте сначала разберемся с простыми вещами:
Добавляется
#roygbp
в конец строки, которую мы будем использовать для динамического вычисления цикла букв.Следующий (длинный) шаг определяет, какие циклы сохранить, и заменяет их
n
. Мы немного посмотрим, как это работает.Это избавляет от нашего помощника по поиску в конце строки.
Это заменяет все символы, которые не были заменены на втором шаге
e
, завершив преобразование.Теперь вернемся ко второму шагу.
Базовая структура использует трюк, который я обнаружил несколько месяцев назад для замены выбранных символов в глобальном сопоставлении:
где
...
соответствует произвольно сложному шаблону. Это соответствует символу, который должен быть заменен,.
и затем начинает просмотр сзади (который вы должны читать справа налево). Взгляд назад захватывает все, вплоть до соответствующего персонажа, в группуprefix
. Затем он переключается на просмотр вперед , который теперь начинается с начала строки и может содержать сложный шаблон. После символа, который мы хотим заменить в этом шаблоне, мы помещаем необязательный вид сзади , который проверяет, соответствует лиprefix
группа здесь. Если это так, он захватывает пустую строку вflag
группа. Если это не так, потому что это необязательно, это не влияет на состояние движка регулярных выражений и игнорируется. Наконец, после успешного сопоставления заглядывания остается только\k<flag>
конец в конце, который соответствует, только если флаг был установлен в некоторой точке во время вычисления.Теперь давайте немного развернем длинное регулярное выражение, используя именованные группы и режим свободного доступа:
Я надеюсь, что вы узнаете общий план сверху, поэтому нам нужно только взглянуть на то, что я заполнил
...
.Мы хотим захватить следующего персонажа в цикле в группу
char
. Мы делаем это, также запоминая строку с#
текущего символа вcycle
. Чтобы получить следующий символ, мы используем поиск для поиска#
. Теперь мы пытаемся сопоставитьcycle
и затем сопоставить следующий символ вchar
. Обычно это будет возможно, если толькоchar
не последний символp
. В этом случае\k<cycle>
будет соответствовать весь остаток строки, и не останется символа для вводаchar
. Таким образом, движок возвращает назад, опускает обратную ссылкуcycle
и просто соответствует первому символуr
.Теперь у нас есть следующий символ в цикле
char
, мы ищем следующее возможное вхождение этого символа с.*?\k<char>
. Это символы, которые мы хотим заменить, поэтому мы ставимprefix
чек после него. Эти шаги (поиск следующегоchar
в цикле, поиск следующего вхождения, установка флага, если это необходимо) теперь просто повторяются с помощью+
.Это на самом деле все, что нужно для нахождения циклической подпоследовательности, но мы также должны убедиться, что мы заканчиваем на
p
. Это довольно легко: просто проверить , что значение в настоящее время хранится вchar
матчах сp
в конце строки с.*\k<char>$
. Это также гарантирует, что наша строка поиска не будет использована для завершения неполного цикла, потому что нам нужен трейлингp
для этой проверки.источник
Python 2
133 130 126121 байтПервый цикл получает циклы, а второй удаляет неполный цикл
Сохранено 3 байта благодаря JF и 5 из DLosc
источник
r
иn
как это:r=n=''
?R=r.count
не работает , как строки являются неизменными , такR
это''.count
даже тогда , когдаr
изменяется.Perl 5,
7665 байтЩепотка чистых неразбавленных регулярных выражений.
Сначала находит то, что не следует есть. То, что осталось, можно съесть.
Контрольная работа
источник
[^o]*
т. Д. Вы можете использовать.*?
(не жадный квантификатор)?\s
вместо класса\n
отрицательных символов первой версии.r(.*?)o(.*?)y(.*?)g(.*?)b(.*?)p
n$1n$2n$3n$4n$5n
[^n\s]
e
(4 файла, 57 байт).Луа, 101 байт
Творчески использует шаблоны Lua; Я думаю, что это интересный подход.
Он заменяет все не съеденные символы на «*», заменяет все буквенно-цифровые символы на «e», а затем заменяет все «*» на «n».
источник
Javascript (ES6), 118
Скрипка проверена в Firefox. Я слышал, что Chrome поддерживает функции стрелок, но я еще не проверял это в Chrome.
Ungolfed:
источник
...
пока еще не обозначенГоук, 96
Создает шаблон поиска
"([^r]*)r([^o]*)o([^y]*)y([^g]*)g([^b]*)b([^p]*)p"
и замены"\\1n\\2n\\3n\\4n\\5n\\6n"
. После этой замены он объявляет всю еду («е»), которая не является частью полной радуги.Эта комбинация автоматически гарантирует, что во время этой операции раны не будут повреждены, и в конце не появятся оторванные радуги.
источник
Pyth, 42 байта
Попробуйте онлайн: демонстрация
источник
CJam, 41 байт
Подход грубой силы, который пробует все варианты еды / не есть и выбирает тот, который приводит к самому длинному, действительному ожерелью.
Попробуйте онлайн в интерпретаторе CJam .
источник
CJam, 50 байтов
Попробуйте онлайн
Это немного дольше, чем некоторые другие материалы, но это очень эффективно с линейной сложностью. Он просматривает входную строку и сопоставляет символы один за другим.
Основная часть алгоритма на самом деле довольно компактна. Около половины кода предназначено для удаления неполного цикла в конце.
источник
C90, 142-146 байт (до 119 в зависимости от)
Работает в линейное время, чтобы эффективно съесть те фруктовые петли, которые не могут быть частью красивой радуги. Затем постпроцесс убивает любой частичный цикл в конце.
Вот четыре версии:
Версия 1 (146 байт), вызов с
[name] [string]
:main(int a,char**b){char*v=b[1],*s="roygbp",i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';while(k-->0)v[--i]='e';puts(v);}
Версия 2 (142 байта), вызывать с помощью
[name] [string] [rainbow order]
:main(int a,char**b){char*v=b[1],*s=b[2],i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';while(k-->0)v[--i]='e';puts(v);}
Это позволяет вам определять свой собственный порядок радуги с любыми цветами, которые вы хотите, если они не являются
n
илиe
. Это на самом деле делает код короче!Версия 3 (123 байта), назовите как версию 1:
main(int a,char**b){char*v=b[1],*s="roygbp",i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';puts(v);}
эта дает вам как можно больше вашей радуги! Незавершенные следы радуги обещают! Мы не должны их есть!
Версия 4 (119 байт), вызов как версия 2:
main(int a,char**b){char*v=b[1],*s=b[2],i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';puts(v);}
То же, что и версия 3, но ТИПЫ РАДУГИ МОРА!
Небольшое ограничение: машина должна иметь подписанные символы (общий случай), а строка должна быть довольно короткой. Выводит трейлинг
\n
для ясности.Версия 1 является единственным, который четко передает требования, хотя версия 2 спорно. Версии 3 и 4 являются менее правильной (но все же забавной) интерпретацией вопроса.
источник
Pyth, 38 байт
Я знаю, что это значительно дольше, чем ответ orlp, но этот работает за линейное время: о)
Попробуйте это здесь .
Вкратце, эта программа заменяет все символы после последнего 'p' пробелами, а затем выполняет итерацию по каждому символу в результирующей строке. Если символ является следующим в последовательности «roygbp», выведите «n», в противном случае выведите «e».
Я изо всех сил пытался найти более короткий способ обработки входной строки.
_>_zJ
в частности, чувствует себя неловко, но<Jz
не дает нужную строку когдаJ == 0
, т.е. когда ввод заканчивается буквой 'p'.источник
Haskell, 138 байт
g
Является ли.источник
f
иz
как инфикс:'n'%'n'='n'
и т. Д. Кроме того, некоторые скобки в определенииg
могут быть удалены с помощью$
.Javascript (ES6),
8582 байтаПравило «ожерелье должно заканчиваться пурпуром» изначально было большим препятствием, увеличивая мой счет с 66 до 125, но я нашел более короткий путь (к счастью!).
Объяснение:
Этот код перебирает каждый символ на входе и заменяет каждый с помощью
r
илиe
с этой логикой:p
И, а персонаж следующий в радуге, оставьте его (замените его наn
).e
).Ungolfed:
Предложения приветствуются!
источник
Python 2, 254 байта
Loops!
Извините за каламбур. :П
источник