У меня есть музыкальная шкатулка с ручным управлением, которая может сыграть серию из четырех нот. Когда я поворачиваю рукоятку, она дергает одну из четырех струн, в зависимости от положения рукоятки и направления поворота. Когда рукоятка поворачивается на север, коробка (с ее рядами, пронумерованными от 1 до 4) выглядит следующим образом:
1 | 2
|
O
4 3
Оттуда я могу повернуть рукоятку по часовой стрелке, чтобы сорвать строку № 2 и направить рукоятку на восток:
1 2
O---
4 3
В качестве альтернативы, я мог бы также повернуть рукоятку против часовой стрелки с севера, чтобы сыграть на струне № 1 и закончить рукояткой, указывающей на запад:
1 2
---O
4 3
Таким образом, в любой момент времени коробка может сыграть одну из двух нот: следующую ноту, имеющуюся в направлении по часовой стрелке, или следующую ноту в направлении против часовой стрелки.
Вызов
Ваша задача состоит в том, чтобы написать программу или функцию, которая принимает непустую строку значений нот (т. Е. 1
Через цифры 4
) и определяет, возможно ли воспроизвести эту последовательность нот на музыкальной шкатулке. Получите достоверный или ложный результат, указывающий на воспроизводимость или неиграбельность ввода.
Некоторые заметки:
На входе не делается никаких предположений о начальной стартовой позиции. Входные данные
214
(начиная с востока и двигаясь строго против часовой стрелки) и234
(начиная с севера и двигаясь строго по часовой стрелке) и оба действительны.Кривошип может свободно двигаться в любом направлении после каждой ноты. Серия одной и той же ноты возможна (например,
33333
), перемещаясь вперед и назад по одной струне. Серия1221441
идеально подходит для игры (начиная с запада, двигаясь по часовой стрелке на два шага, затем против часовой стрелки на три шага, затем по часовой стрелке на два шага).
образцы
Некоторые true
случаи:
1
1234
1221
3333
143332
22234
2234
22214
1221441
41233
Некоторые false
случаи:
13 (note 3 is never available after note 1)
1224 (after `122`, the crank must be north, so 4 is not playable)
121 (after `12` the crank is east; 1 is not playable)
12221 (as above, after `1222` the crank is east)
43221
источник
Ответы:
Pyth,
3027 байтовВот идея:
Кривошип всегда находится в полуцелом положении
c
. На каждом шаге мы отражаем его в целочисленной позицииn
, установивc = 2*n-c
. Еслиn
он действителен,c
изменяется на ± 1 mod 8. Еслиn
недействителен,c
изменяется на ± 3 mod 8. Мы кумулятивно сокращаем входные данные, чтобы собрать все значенияc
, а затем посмотрим, все ли примечания действительны Мы делаем это для каждого начального значенияc
, потому что оно короче, чем проверка только тех, которые примыкают к первой ноте.отформатирован:
Тестовый пакет .
источник
CJam,
3431 байтСделал это на моем телефоне, поэтому мне придется выложить объяснение позже.Вывод не пустой, если правдивый.Попробуй это онлайн | Тестирование
объяснение
Новый код немного меняет макет:
Четные числа соответствуют положениям строки, а нечетные числа соответствуют положениям кривошипа.
Вот что происходит:
Затем стопка автоматически печатается в конце. Любые возможные конечные позиции будут на выходе, например, для входа
1
- выход31
, что означает, что кривошип может заканчиваться лицом влево или вверх.Если бы только CJam имел фильтр с дополнительным параметром ...
Изменить: временно откат, пока я убедить себя, что этот 29-байт работает:
источник
Haskell,
93 8887 байтЭто приводит к анонимной функции, которая принимает строку и возвращает логическое значение. Тестовый набор здесь.
объяснение
Идея заключается в том , что лямбда на праве отображает номер
a
на[[a,a+1],[a+1,a]]
, из двух возможных «ходов» , которые имеют рукоятку над этим номером, в соответствии со следующей схемой:Сначала мы выполняем главную анонимную функцию,
mapM((...).read.pure)
которая преобразует каждый символ в целое число, применяет к нему указанную лямбду и выбирает один из двух ходов, возвращая список всех полученных последовательностей ходов. Затем мы проверяем, обладает ли какая-либо из этих последовательностей свойством того, что второе число каждого хода равно первому числу следующего по модулю 4, что означает, что это физически возможная последовательность. Чтобы сделать это, мыzip
каждый перемещаем последовательность со своейtail
, проверяем условие дляall
пар и проверяем, соответствует лиany
последовательностьTrue
.источник
Сетчатка, 50 байт
Я думаю, что это работает?
Попробуй это здесь.
источник
Сетчатка ,
127109 байтЭто печатает
0
или1
, соответственно.Попробуйте онлайн! (Это слегка измененная версия, которая помечает все совпадения на входе вместо печати
0
или1
.)Я пытался придумать элегантный алгоритм, но мои первые несколько попыток не смогли обойти возврат ... и реализация обратного отслеживания раздражает ... поэтому я использовал язык, который выполняет возврат для меня, где мне просто нужно кодировать правильное решение. К сожалению, кодировка довольно многословна и довольно избыточна ... Я уверен, что это можно сократить.
В то время как я пытаюсь выяснить что-то более аккуратное, если кто-то хочет разобраться, как это работает, вот несколько более читаемая версия:
И вот подсказка:
источник
MATL ,
5755 байтПри этом используется текущая версия (10.2.1) , которая является более ранней, чем эта проблема.
РЕДАКТИРОВАТЬ (17 января 2017 г.): из-за изменений в языке
v
необходимо заменить на&v
иtL3$)
наY)
(кроме того, могут быть сделаны некоторые другие улучшения ). Следующая ссылка включает в себя эти две модификацииПопробуйте онлайн!
объяснение
Это основано на двух моих любимых инструментах для игры в гольф: грубая сила и свертка .
Код определяет путь, по которому следует кривошип, в терминах координат
0.5
и1.5
т. Д. Каждое число указывает положение кривошипа между нотами. Сначала код строит массив путей со всеми возможными путями, которые начинаются с первой ноты входной строки. Каждый путь является столбцом в этом массиве. Это грубая сила .Из этого массива путей получается массив заметок , где каждый столбец представляет собой реализуемую последовательность проигрываемых нот. Например, перемещение из позиции
0.5
в1.5
производит примечание1
. Это состоит в том, чтобы взять среднее между позициями и затем применить операцию по модулю 4. Скользящее среднее вдоль каждого столбца выполняется с двухмерной сверткой .Наконец, программа проверяет, совпадает ли какой-либо столбец массива примечаний с вводом.
источник
Пиф, 43
Тестирование
Это, вероятно, очень пригодный для игры в гольф, а также не оптимальный алгоритм для игры в гольф (я предполагаю, что перечисление всех путей будет короче?) ... В любом случае, если вы обнаружите какую-либо ошибку в алгоритме, пожалуйста, дайте мне знать, я думаю, что он должен работать, но я раньше ошибался!
Я объясню мой алгоритм на примере ввода
1221
. Эта программа отображает первые цифры против их наследников, так как:[[1,2],[2,2],[2,1]]
. Тогда он получает их различие мод4
(Pyth получает результат , который соответствует знаку правого аргумента%
, так что это всегда положительно)[3,0,1]
. Тогда результаты расщепляются на0
и2
вычитается из каждого из них:[[1],[-1]]
.Теперь, когда настройка завершена, мы создаем список
[-1,1,-1...]
и его отрицание[1,-1,...]
, одинаковой длины с полученным ранее массивом. Затем для каждого из этих списков выполните поэтапное вычитание между элементами списка и списком, сгенерированным на предыдущем шаге. Затем, если любой из результатов содержит только пустые списки, мы выводим true.источник
1221221
и1221441
?1221221
имеет значение false и в1221441
целом дает значение true, но, насколько я понимаю, вы хотите получить результат после этого шага в алгоритме? Если это так , это дает: от[3, 0, 1, 3, 0, 1]
до[[3], [1, 3], [1]]
и[3, 0, 1, 1, 0, 3]
до[[3], [1, 1], [3]]
. Дайте мне знать, если вы хотите что-то еще объяснить :)[[1], [-1, 1], [-1]]
и[[1], [-1, -1], [1]]
отсюда, вы можете увидеть, что первый не имеет списков, которые чередуются между-1
и в1
то время как другой список, давая окончательный результат. Алгоритм немного тупой, но в основном он отображает изменения направления0
и направления, а+/-1
затем проверяет, что переходы не сделаны и направления имеют смысл.Matlab,
279180 байтДовольно ленивое решение, но самое короткое, что мне удалось придумать. Я создал специальную матрицу: когда вы кодируете состояние сборщика и последнюю строку, которая должна быть извлечена, он возвращает вектор, который кодирует новую позицию сборщика и была ли вообще возможна предыдущая сборка . Теперь мы просто зациклим все ноты с двух возможных начальных позиций и посмотрим, приведет ли одна из них к воспроизводимой мелодии. Возможно, можно играть в гольф намного больше.
Расширенный и объясненный источник:
источник
ES6,
104100 байтРедактировать: 4 байта сохранены благодаря @DigitalTrauma.
Это полное переписывание, так как мой предыдущий подход был ошибочным.
Я начинаю с сокращения всех серий цифр до 1 или 2 в зависимости от того, было ли в серии нечетное или четное число. Затем я ищу все незаконные комбинации:
13|24|31|42
(противоположные стороны)3[24]{2}1
как3221
и3441
являются незаконными4xx2
,1xx3
и2xx4
гдеx
либо из недостающих цифр(.).\1
как вещи,121
которые являются незаконными (111
было сокращено до1
ранее)Если нет недопустимых пар или «троек», тогда вся строка является допустимой (доказательство по индукции оставлено в качестве упражнения, потому что здесь поздняя ночь).
Я попытался упростить
3[24]{2}1|1[24]{2}3
использование отрицательного прогнозного утверждения, но оно оказалось длиннее.источник
f("1122") => true
@DigitalTraumaf("1221221")
выводит неправильный ответ, поэтому мне придется переосмыслить.[24][24]
в гольф,(2|4)\1
но я не проверил адекватно. Прости за это.[24][24]
в гольф[24]{2}
?JavaScript (ES6), 80 байт
объяснение
i%4
текущее положение кривошипа:Отступы и комментарии
Контрольная работа
источник
|
работает в этом случае?(x.map(...),v)
. Это работает, потому что массив, которыйmap
возвращает, приводится к0
и0|v == v
.Lua ,
146 142 108 162 159 149 144 135 132 118113 байтовВозвращает истину или ложь, если строка чисел находится в диапазоне от 1 до 4. (Не обрабатывает никаких данных или выходит за пределы диапазона.
Просто отслеживает, каким было последнее движение, и проверяет, является ли это движение разворотом последнего движения (IE, 121 или 12221) или если перемещение на расстояние более чем возможно.
РЕДАКТИРОВАТЬ 1 :
Сохранено 6 байтов. Я забыл, что
if (int) then
возвращает истину, если int не ноль.Таким образом:
изменения к:
Также сэкономлено несколько байтов путем реструктуризации.
РЕДАКТИРОВАТЬ 2 :
Я медленно выясняю это. Я читал документацию здесь: http://www.lua.org/pil/ И одна из наиболее полезных страниц для игры в гольф - http://www.lua.org/pil/3.3.html.
В частности, это очень полезно:
Для меня это означает, что я могу пойти дальше и удалить свое объявление для q ( которое изначально было установлено в 0 ), так как оно будет рассматриваться как «ложное» до тех пор, пока оно не будет установлено. Таким образом, я сохраню еще несколько байтов через это.
Еще одна вещь, о которой стоит упомянуть, хотя я ее не использую, это то, что если вы хотите поменять местами значения в Lua, вы можете просто обойтись
a,b=b,a
без временной переменной.РЕДАКТИРОВАТЬ 3
Итак, благодаря некоторой умной реконструкции, а также новой функции, я сократил число байтов еще на 9.
Лучший режим для получения ввода
Если вам нужно прочитать список чисел и выполнить операции с ними по одному, вы можете использовать:
По сравнению с вашей альтернативой, использующей string: sub, вы можете увидеть значение для гольфа (или общего использования):
Функции реструктуризации или строки
Во-вторых, если у вас есть несколько объявлений в одной строке и одно из значений является функцией, или у вас есть условие, в котором вы сравниваете число с результатом функции, подобной этой:
реструктурировав его так, чтобы закрывающая скобка была последним символом в условии или объявлении, вы можете вырезать символ следующим образом:
Условия возврата, которые равны True или False вместо «True» или «False»
Я нашел полузабавный способ сократить мой счетчик байтов еще больше. Если вам нужно вернуть true или false, вы можете вернуть оператор, равный true или false, который содержит меньше символов, чем сами «true» или «false».
Например, сравните:
Для того, чтобы:
источник
121
должен вывести false.MATL, 49 байтов (неконкурентный 1 )
1. В ответе (ab) используется менее строгая индексация более новых версий MATL, и он не сработал бы во время публикации этого запроса.
Попробуйте онлайн! ,
Я видел эту проблему на Best of PPCG 2016 и подумал, что это может использовать мой любимый оператор :
Или
diff
в MATLAB / Octave (я буду свободно использовать терминологию MATLAB / Octave в моем объяснении, поскольку людям легче читать). Эта команда вычисляет поэлементную разницу в векторе или, в данном случае, в массиве символов.Для этой проблемы различия демонстрируют интересную закономерность. Обратите внимание, что
Для разностного паттерна (игнорируя
1-4
переход на данный момент) это означает, чтоЯ реализовал это, для каждого массива, найдя первый ноль. Я обрезаю ноль и умножаю все элементы после него на
-1
. Для конечного результата это означает, что все элементы должны иметь одинаковый знак. Конечно, есть небольшая проблема-3
равных+1
и2
вообще не разрешенных. Я решил это, взяв объединение множества результата с[1 -3]
, и проверив, имеет ли он размер 2 (то есть, никакие запрещенные элементы не «вошли» в множество через объединение). Повторите для[-1 3]
и убедитесь, что либо (или оба, в случае ввода длины 1) верно.источник
M
, в прошлый раз, когда я попробовал это, это работало не так, как ожидалось, поэтому я просто проигнорировал это в настоящее время. Правильно ли сказать , что это должно быть ,3M
потому что тогда я получаю ввод не)
, не:
ноq
(пропуск ,w
как это не нормальная функция)?w
пропускается, потому что это не нормальная функция. Нормальные функции, не требующие ввода, тоже будут пропущеныPython (3,5)
160151150 байтРекурсивное решение
Безголовый без лямбды
Я поворачиваю всю коробку вместо рукоятки. Положение кривошипа находится между первым и вторым символом строки c. Мне нужно проверить все начальное положение кривошипа.
Трюк использовать для поворота строки
Обычный способ поворота строки в python (
s[i:]+s[:i]
) тоже должен повторять как индекс, так и строку. В этом случае я дублирую строку и обрезаю первые символы.Контрольные примеры
источник
3"[i:]) for
.Python 2 , 65 байт
Попробуйте онлайн!
источник
JavaScript (ES2015),
1109515 байтов, сохраненных Нилом! Оригинальная версия ungolfed:
Тесты: https://jsbin.com/cuqicajuko/1/edit?js,console
источник
(s,d)=>(h=s[0],t=s.slice(1),g=t[0],!g||(d?g==h?p(t,-d):g%4==(h-d)%4&&p(t,d):p(s,1)||p(s,-1)))
Машинный код Тьюринга, 395 байтов
Попробуйте онлайн!
Это в основном государственный подход:
a
,b
,c
Иd
является «неопределившимся государством» , которые происходят только в началеN
,E
,S
, ИW
являются «решившие государства», очевидно , стоя наN
Орт,E
аст,S
outh иW
ЭСТа.источник
Чт, 203 байта
Я не могу думать о том, как играть в гольф дальше.
Если последовательность нот возможна, будет выводиться конечное направление, в противном случае вывод будет пустым.
источник
Пролог (SWI) , 117 байт
Определяет предикат,
p
который преуспевает на воспроизводимых входных данных (заданных в виде списка целых чисел) и терпит неудачу на неиграбельных. Попробуйте онлайн!объяснение
a
определяет отношение смежности между примечаниемN
и положением кривошипаP
. Мы определяем положение p между нотами p и p + 1 . Таким образом, позиция смежна с примечанием,N
еслиN
(P=N
); или жеN=1,P=4
); или же!
) и позиция равнаN-1
(P is N-1
).m
берет список заметок и пытается сгенерировать список позиций, которые будут воспроизводить эти заметки.A
является ли только что сыграннаяB
нота;X
текущее положение кривошипа,Y
следующее положение кривошипа. Ход действителен, еслиa(A,X)
);a(B,X)
);a(B,Y)
); а такжеX\=Y
).Если все это верно, рекурсивно. Если мы успешно перейдем к какой-либо одной ноте (
m([_],_)
), последовательность нот будет воспроизводимой.Для этого вопроса нам важно только, существует ли последовательность ходов, поэтому мы определяем,
p
чтобы вызыватьm
и отбрасывать сгенерированный список положений кривошипа.Посмотрите версию без игры и проверьте все контрольные примеры здесь .
источник