Может ли моя музыкальная шкатулка с 4 нотами сыграть эту песню?


51

У меня есть музыкальная шкатулка с ручным управлением, которая может сыграть серию из четырех нот. Когда я поворачиваю рукоятку, она дергает одну из четырех струн, в зависимости от положения рукоятки и направления поворота. Когда рукоятка поворачивается на север, коробка (с ее рядами, пронумерованными от 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  

Может ли ввод быть строкой, включающей кавычки?
Луис Мендо

@ LuisMendo Конечно, я позволю - мне интересен твой алгоритм, не заставляющий тебя прыгать через обручи, чтобы получить ввод. В любом случае, существует неофициальное согласие сообщества, что в целом все нормально: ввод строки с или без «»?
Апсиллерс

1
Я этого не знал. Спасибо за ссылку!
Луис Мендо

1
@AJMansfield Нет, решения должны учитывать произвольное количество циклов. Конечно, если какой-то ввод приводит к тому, что ваш код превышает лимит в интерпретаторе вашего языка или в памяти вашего компьютера, это нормально (поскольку он просто ограничен тем, сколько физической памяти у вас есть или ваш переводчик позволяет), но ваше решение не должно накладывать дополнительных ограничений. на сколько или сколько раз заводит рукоятку.
Апсиллеры

1
Эта задача выиграла категорию Не так просто, как кажется в Best of PPCG 2016. К сожалению, мы не можем давать награды за вызовы, но Згарб написал вызов в вашу честь . Поздравляем!
Мартин Эндер

Ответы:


9

Pyth, 30 27 байтов

f!-aVJ.u%-ysYN8zTtJ,1 7cR2T

Вот идея:

 1.5  1  0.5

  2       0

 2.5  3  3.5

Кривошип всегда находится в полуцелом положении c. На каждом шаге мы отражаем его в целочисленной позиции n, установив c = 2*n-c. Если nон действителен, cизменяется на ± 1 mod 8. Если nнедействителен, cизменяется на ± 3 mod 8. Мы кумулятивно сокращаем входные данные, чтобы собрать все значения c, а затем посмотрим, все ли примечания действительны Мы делаем это для каждого начального значения c, потому что оно короче, чем проверка только тех, которые примыкают к первой ноте.

отформатирован:

f
  ! -
      aV J .u
              % -
                  y s Y
                  N
                8
              z
              T
         t J
      ,
        1 
        7
  cR2 T

Тестовый пакет .


18

CJam, 34 31 байт

8,q{~2*f{_@-_zF8b&,@@+8,=*}0-}/

Сделал это на моем телефоне, поэтому мне придется выложить объяснение позже. Вывод не пустой, если правдивый.

Попробуй это онлайн | Тестирование

объяснение

Новый код немного меняет макет:

2    3    4

1    .    5

0/8  7    6

Четные числа соответствуют положениям строки, а нечетные числа соответствуют положениям кривошипа.

Вот что происходит:

8,           Create the range [0 1 .. 7] of possible starting positions
             We can leave the string positions [0 2 4 6] in since it doesn't matter
q{ ... }/    For each character in the input...
  ~2*          Evaluate as integer and double, mapping "1234" -> [2 4 6 8]
  f{ ... }     Map over our possible current crank positions with the string
               position as an extra parameter
    _@-          Calculate (string - crank), giving some number in [-7 ... 7]
    _z           Duplicate and absolute value
    F8b          Push 15 base 8, or [1 7]
    &,           Setwise intersection and get length. If (string - crank) was in
                 [-7 -1 1 7] then the move was valid and this evaluates to 1, otherwise 0
    @@+          Calculate ((string - crank) + string)
    8,=          Take modulo 8, giving the new crank position. x%y in Java matches the
                 sign of x, so we need to do ,= (range + index) to get a number in [0 .. 7]
    *            Multiply the new crank position by our previous 0 or 1
  0-           Remove all 0s, which correspond to invalid positions

Затем стопка автоматически печатается в конце. Любые возможные конечные позиции будут на выходе, например, для входа 1- выход 31, что означает, что кривошип может заканчиваться лицом влево или вверх.

Если бы только CJam имел фильтр с дополнительным параметром ...


Изменить: временно откат, пока я убедить себя, что этот 29-байт работает:

8,q{~2*f{_@-_7b1#@@+8,=|}W-}/

37
Каждый раз, когда кто-то отвечает на каком-то сложном языке, таком как cjam, и говорит «сделал это на моем телефоне», я умираю немного внутри
Деннис ван Гилс

2
Вероятно, он имел в виду, что текст выводился с помощью телефона, но это было сделано в его голове.
Нельсон

7

Haskell, 93 88 87 байт

any(all(\(a,b:c)->1>mod(a!!1-b)4).(zip=<<tail)).mapM((\a->[[a,a+1],[a+1,a]]).read.pure)

Это приводит к анонимной функции, которая принимает строку и возвращает логическое значение. Тестовый набор здесь.

объяснение

Идея заключается в том , что лямбда на праве отображает номер aна [[a,a+1],[a+1,a]], из двух возможных «ходов» , которые имеют рукоятку над этим номером, в соответствии со следующей схемой:

  1 (2) 2

(1/5)  (3)

  4 (4) 3

Сначала мы выполняем главную анонимную функцию, mapM((...).read.pure)которая преобразует каждый символ в целое число, применяет к нему указанную лямбду и выбирает один из двух ходов, возвращая список всех полученных последовательностей ходов. Затем мы проверяем, обладает ли какая-либо из этих последовательностей свойством того, что второе число каждого хода равно первому числу следующего по модулю 4, что означает, что это физически возможная последовательность. Чтобы сделать это, мы zipкаждый перемещаем последовательность со своей tail, проверяем условие для allпар и проверяем, соответствует ли anyпоследовательность True.



6

Сетчатка , 127 109 байт

^((1|2)|(2|3)|(3|4)|(4|1))((?<2-5>1)|(?<5-2>1)|(?<3-2>2)|(?<2-3>2)|(?<4-3>3)|(?<3-4>3)|(?<5-4>4)|(?<4-5>4))*$

Это печатает 0или 1, соответственно.

Попробуйте онлайн! (Это слегка измененная версия, которая помечает все совпадения на входе вместо печати 0или 1.)

Я пытался придумать элегантный алгоритм, но мои первые несколько попыток не смогли обойти возврат ... и реализация обратного отслеживания раздражает ... поэтому я использовал язык, который выполняет возврат для меня, где мне просто нужно кодировать правильное решение. К сожалению, кодировка довольно многословна и довольно избыточна ... Я уверен, что это можно сократить.

В то время как я пытаюсь выяснить что-то более аккуратное, если кто-то хочет разобраться, как это работает, вот несколько более читаемая версия:

^
(
    (?<a>1|2)
  | (?<b>2|3)
  | (?<c>3|4)
  | (?<d>4|1)
)
(
    (?<a-d>1) | (?<d-a>1)
  | (?<b-a>2) | (?<a-b>2)
  | (?<c-b>3) | (?<b-c>3)
  | (?<d-c>4) | (?<c-d>4)
)*
$

И вот подсказка:

1  a  2

d  O  b

4  c  3

6

MATL , 57 55 байт

1t_hjnZ^!t1tL3$)2_/wvG1)UGnl2$Ov+Ys.5tv3X53$Y+4X\G!U=Aa

При этом используется текущая версия (10.2.1) , которая является более ранней, чем эта проблема.

РЕДАКТИРОВАТЬ (17 января 2017 г.): из-за изменений в языкеv необходимо заменить на &vи tL3$)на Y)(кроме того, могут быть сделаны некоторые другие улучшения ). Следующая ссылка включает в себя эти две модификации

Попробуйте онлайн!

объяснение

Это основано на двух моих любимых инструментах для игры в гольф: грубая сила и свертка .

Код определяет путь, по которому следует кривошип, в терминах координат 0.5и 1.5т. Д. Каждое число указывает положение кривошипа между нотами. Сначала код строит массив путей со всеми возможными путями, которые начинаются с первой ноты входной строки. Каждый путь является столбцом в этом массиве. Это грубая сила .

Из этого массива путей получается массив заметок , где каждый столбец представляет собой реализуемую последовательность проигрываемых нот. Например, перемещение из позиции 0.5в 1.5производит примечание 1. Это состоит в том, чтобы взять среднее между позициями и затем применить операцию по модулю 4. Скользящее среднее вдоль каждого столбца выполняется с двухмерной сверткой .

Наконец, программа проверяет, совпадает ли какой-либо столбец массива примечаний с вводом.

1t_h        % row array [1, -1]
j           % input string
nZ^!        % Cartesian power of [1, -1] raised to N, where "N" is length of string
t           % duplicate
1tL3$)      % extract first row
2_/         % divide by -2
wv          % attach that modified row to the top of Cartesian power array
G1)U        % first character of input string converted to number, "x"
Gnl2$O      % column array of N-1 zeros, where N is length of input
v           % concat vertically into column array [x;0;0...;0]
+           % add with singleton expansion
Ys          % cumulative sum along each column. Each column if this array is a path
.5tv        % column array [.5;.5]
3X5         % predefined string 'same' (for convolution)
3$Y+        % 2D convolution of path array with [.5;.5]
4X\         % modified modulo operation. This gives note array with values 1,2,3,4
G!U         % column array of input string characters converted to numbers
=Aa         % true if any column of the note array equals this

5

Пиф, 43

Km-R2sMdc`M%R4-VJjQTtJ`0|Fm!s-VKdCm_B^_1dlK

Тестирование

Это, вероятно, очень пригодный для игры в гольф, а также не оптимальный алгоритм для игры в гольф (я предполагаю, что перечисление всех путей будет короче?) ... В любом случае, если вы обнаружите какую-либо ошибку в алгоритме, пожалуйста, дайте мне знать, я думаю, что он должен работать, но я раньше ошибался!

Я объясню мой алгоритм на примере ввода 1221. Эта программа отображает первые цифры против их наследников, так как: [[1,2],[2,2],[2,1]]. Тогда он получает их различие мод 4(Pyth получает результат , который соответствует знаку правого аргумента %, так что это всегда положительно) [3,0,1]. Тогда результаты расщепляются на 0и 2вычитается из каждого из них: [[1],[-1]].

Теперь, когда настройка завершена, мы создаем список [-1,1,-1...]и его отрицание [1,-1,...], одинаковой длины с полученным ранее массивом. Затем для каждого из этих списков выполните поэтапное вычитание между элементами списка и списком, сгенерированным на предыдущем шаге. Затем, если любой из результатов содержит только пустые списки, мы выводим true.


Что вы подразумеваете под "результаты делятся на 0"? В частности, что вы получите за 1221221и 1221441?
Нил

1
@Neil 1221221имеет значение false и в 1221441целом дает значение true, но, насколько я понимаю, вы хотите получить результат после этого шага в алгоритме? Если это так , это дает: от [3, 0, 1, 3, 0, 1]до [[3], [1, 3], [1]]и [3, 0, 1, 1, 0, 3]до [[3], [1, 1], [3]]. Дайте мне знать, если вы хотите что-то еще объяснить :)
FryAmTheEggman

Я думаю, что я более запутан, чем раньше, поэтому не могли бы вы закончить эти два примера, чтобы объяснить, как достигаются (правильные) результаты?
Нил

1
@Neil Конечно, нет проблем :) Оттуда мы делаем вычитание, чтобы получить: [[1], [-1, 1], [-1]]и [[1], [-1, -1], [1]]отсюда, вы можете увидеть, что первый не имеет списков, которые чередуются между -1и в 1то время как другой список, давая окончательный результат. Алгоритм немного тупой, но в основном он отображает изменения направления 0и направления, а +/-1затем проверяет, что переходы не сделаны и направления имеют смысл.
FryAmTheEggman

О, так что мне не хватало того, что каждый разделенный список должен состоять из одного и того же значения, и эти значения должны чередоваться. Спасибо!
Нил

4

Matlab, 279 180 байт

o=eye(4);a=input('')-'0';M=[o,o(:,[4,1:3]);o(:,[2:4,1:4,1])];x=2;for p=[a(1),mod(a(1),4)+1];for k=a;i=find(M*[o(:,k);o(:,p)]>1);if i;p=mod(i-1,4)+1;else;x=x-1;break;end;end;end;x>0

Довольно ленивое решение, но самое короткое, что мне удалось придумать. Я создал специальную матрицу: когда вы кодируете состояние сборщика и последнюю строку, которая должна быть извлечена, он возвращает вектор, который кодирует новую позицию сборщика и была ли вообще возможна предыдущая сборка . Теперь мы просто зациклим все ноты с двух возможных начальных позиций и посмотрим, приведет ли одна из них к воспроизводимой мелодии. Возможно, можно играть в гольф намного больше.

Расширенный и объясненный источник:

o=eye(4);
a=input('')-'0';

% encoding of plucker/notes
%      1
%   1     2
%4           2
%   4     3
%      3
%

M=[...
%12 3 4 1 2 3 4 <
1,0,0,0,0,1,0,0; %1  k = current note
0,1,0,0,0,0,1,0; %2  
0,0,1,0,0,0,0,1; %3  
0,0,0,1,1,0,0,0; %4  
0,0,0,1,0,0,0,1; %1  p = current position of plucker
1,0,0,0,1,0,0,0; %2
0,1,0,0,0,1,0,0; %3
0,0,1,0,0,0,1,0];%4
% the vector we multiply with this matrix has following structure,
% the k-th and the p+4 th entries are 1, the rest 0
% when we multiply this vecotr with this matrix, we get a vector with an
% entry of value 2 IF this is a valid move ( mod(positionOfThe2 -1,4)+1 is
% the position of the plucker now)
% or only entries less than 2 it is impossible
x=2;  %number of "chances" to get it right
for p=[a(1),mod(a(1),4)+1] %check both starting values;
    for k=a;                %loop throu the notes
        size(M);

        c = M * [o(:,k);o(:,p)];
        i=find(c>1);               %did we find a 2?
        if i;
           p=mod(i-1,4)+1;         %if yes, valid move
        else;
            x=x-1;                 %if no, invalid, 
            break;
        end 
    end
end
x=x>0 %if we failed more than once, it is not possible

4

ES6, 104 100 байт

s=>!/13|24|31|42|3[24]{2}1|4[13]{2}2|1[24]{2}3|2[13]{2}4|(.).\1/.test(s.replace(/(.)(\1\1)+/g,"$1"))

Редактировать: 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@DigitalTrauma
Конор О'Брайен

@ C'O'Bʀɪᴇɴ Я не вижу в этом ничего плохого. С другой стороны, я понял, что f("1221221")выводит неправильный ответ, поэтому мне придется переосмыслить.
Нил

Всегда хорошо включить набор тестов, «43221» не удается: jsbin.com/vafitotequ/1/edit?js,console
Павло

@Pavlo Ой, я бы играл [24][24]в гольф, (2|4)\1но я не проверил адекватно. Прости за это.
Нил

Вы можете играть [24][24]в гольф [24]{2}?
Цифровая травма

2

JavaScript (ES6), 80 байт

s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r

объяснение

i%4 текущее положение кривошипа:

    1 (i%4 == 1) 2   

(i%4 == 0) (i%4 == 2)

    4 (i%4 == 3) 3   

Отступы и комментарии

s=>
  [r=0,1,2,3].map(i=> // i = crank position, test for i starting at 0 to 3, r = result
    [...s].map(n=>    // for each note n
      n-1-i%4?        // if n is not at the position after i
        n%4-i%4?      // if n is not at the position before i
          v=0         // set the result of this test to invalid
        :i+=3         // else i-- (+3 used because i%4 would break for negative values)
      :i++,           // else i++
      v=1             // v = result of test, initialise to 1 (valid)
    )
    |v?r=1:0          // if the test returned true, set the result to true
  )
  |r                  // return the result

Контрольная работа

var solution = s=>[r=0,1,2,3].map(i=>[...s].map(n=>n-1-i%4?n%4-i%4?v=0:i+=3:i++,v=1)|v?r=1:0)|r
<input type="text" value="1221441" oninput="result.textContent=solution(this.value)" />
<pre id="result"></pre>


Красиво сделано. Не могли бы вы объяснить, как |работает в этом случае?
Павло

1
@pavlo Спасибо. Это более короткий способ написания (x.map(...),v). Это работает, потому что массив, который mapвозвращает, приводится к 0и 0|v == v.
user81655

2

Lua , 146 142 108 162 159 149 144 135 132 118 113 байтов

z,q,s=0,0,io.read()for i in s:gmatch'.'do t=i-z if 2==math.abs(t)or t==q then return''end q=-t z=i end return 2>1

Возвращает истину или ложь, если строка чисел находится в диапазоне от 1 до 4. (Не обрабатывает никаких данных или выходит за пределы диапазона.

Просто отслеживает, каким было последнее движение, и проверяет, является ли это движение разворотом последнего движения (IE, 121 или 12221) или если перемещение на расстояние более чем возможно.

РЕДАКТИРОВАТЬ 1 :

Сохранено 6 байтов. Я забыл, что if (int) thenвозвращает истину, если int не ноль.

Таким образом:

if t~=0 then

изменения к:

if t then

Также сэкономлено несколько байтов путем реструктуризации.

РЕДАКТИРОВАТЬ 2 :

Я медленно выясняю это. Я читал документацию здесь: http://www.lua.org/pil/ И одна из наиболее полезных страниц для игры в гольф - http://www.lua.org/pil/3.3.html.

В частности, это очень полезно:

Как и управляющие структуры, все логические операторы считают false и nil ложными, а все остальное - истинными.

Для меня это означает, что я могу пойти дальше и удалить свое объявление для q ( которое изначально было установлено в 0 ), так как оно будет рассматриваться как «ложное» до тех пор, пока оно не будет установлено. Таким образом, я сохраню еще несколько байтов через это.

Еще одна вещь, о которой стоит упомянуть, хотя я ее не использую, это то, что если вы хотите поменять местами значения в Lua, вы можете просто обойтись a,b=b,a без временной переменной.

РЕДАКТИРОВАТЬ 3

Итак, благодаря некоторой умной реконструкции, а также новой функции, я сократил число байтов еще на 9.

Лучший режим для получения ввода

Если вам нужно прочитать список чисел и выполнить операции с ними по одному, вы можете использовать:

for x in string:gmatch('.') do
    print(x) --This is our number
end

По сравнению с вашей альтернативой, использующей string: sub, вы можете увидеть значение для гольфа (или общего использования):

for x=1,string:len() do
    print(string:sub(x,x)) --This is our number
end

Функции реструктуризации или строки

Во-вторых, если у вас есть несколько объявлений в одной строке и одно из значений является функцией, или у вас есть условие, в котором вы сравниваете число с результатом функции, подобной этой:

x,y,z=io.read(),0,0 print('test')

if math.abs(x)==2 then

реструктурировав его так, чтобы закрывающая скобка была последним символом в условии или объявлении, вы можете вырезать символ следующим образом:

y,z,x=0,0,io.read()print('test') --Notice no space

if 2==math.abs(x)then --If we put the '2' first in the conditional statement, we can now remove a space character

Условия возврата, которые равны True или False вместо «True» или «False»

Я нашел полузабавный способ сократить мой счетчик байтов еще больше. Если вам нужно вернуть true или false, вы можете вернуть оператор, равный true или false, который содержит меньше символов, чем сами «true» или «false».

Например, сравните:

return true
return false

Для того, чтобы:

return 2>1
return 1>2

121должен вывести false.
lirtosiast

Ах, неважно. Понимаю.
Скоро

Возможно, вам будет интересно добавить некоторые из этих советов Lua в Tips для игры в гольф в Lua, если вы их там еще не видите.
Апсиллеры

2

MATL, 49 байтов (неконкурентный 1 )

1. В ответе (ab) используется менее строгая индексация более новых версий MATL, и он не сработал бы во время публикации этого запроса.

dt~aX`tt~f1)q:)w3MQJh)_ht~a]tT-3hX|n2=wT_3hX|n2=+

Попробуйте онлайн! ,

Я видел эту проблему на Best of PPCG 2016 и подумал, что это может использовать мой любимый оператор :

d

Или diffв MATLAB / Octave (я буду свободно использовать терминологию MATLAB / Octave в моем объяснении, поскольку людям легче читать). Эта команда вычисляет поэлементную разницу в векторе или, в данном случае, в массиве символов.

Для этой проблемы различия демонстрируют интересную закономерность. Обратите внимание, что

Изменение направления должно означать, что нота играется дважды .

Для разностного паттерна (игнорируя 1-4переход на данный момент) это означает, что

Изменение входа diff(input)должно иметь нечетное число нулей между ними. И наоборот, знак не может меняться после четного числа нулей.


Я реализовал это, для каждого массива, найдя первый ноль. Я обрезаю ноль и умножаю все элементы после него на -1. Для конечного результата это означает, что все элементы должны иметь одинаковый знак. Конечно, есть небольшая проблема -3равных +1и 2вообще не разрешенных. Я решил это, взяв объединение множества результата с [1 -3], и проверив, имеет ли он размер 2 (то есть, никакие запрещенные элементы не «вошли» в множество через объединение). Повторите для [-1 3]и убедитесь, что либо (или оба, в случае ввода длины 1) верно.

d                                % Difference of input
 t~a                             % Check if any element equals 0
    X`                     t~a]  % Start while loop, ending in the same check
       t~                           % Get a new vector, logical negated to find zeroes.
          f1)                       % Find the position of the first zero. 
      t         q:)                 % Decrement by 1, to index all elements before that zero.
                   w3MQJh)          % Push the result of 'find', but increment to get all elements after.
                         _h         % Multiply the second half by -1, and concatenate horizontally.

  T-3hX|n2=                      % Check if set union with [1 -3] is size 2
 t        wT_3hX|n2=             % Check if set union with [-1 3] is size 2
                    +            % Logical OR. 

@ LuisMendo Спасибо. Мне действительно нужно читать M, в прошлый раз, когда я попробовал это, это работало не так, как ожидалось, поэтому я просто проигнорировал это в настоящее время. Правильно ли сказать , что это должно быть , 3Mпотому что тогда я получаю ввод не ), не :но q(пропуск , wкак это не нормальная функция)?
Sanchises

Да, точно. wпропускается, потому что это не нормальная функция. Нормальные функции, не требующие ввода, тоже будут пропущены
Луис Мендо,

2

Python (3,5) 160 151 150 байт

Рекурсивное решение

def f(s):g=lambda s,c:s==''or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])if s==''or s[0]in c[:2]else 0;return any([g(s,"1234123"[i:])for i in range(4)])

Безголовый без лямбды

def f(s):
    def g(s,c):
        if s=='' or s[0] in c[:2] :
            return s=='' or g(s[1:],(c[:4]*2)[(s[0]==c[0])*2+1:])
        else:
            return False
    return any([g(s,"1234123"[i:]) for i in range(4)])

Я поворачиваю всю коробку вместо рукоятки. Положение кривошипа находится между первым и вторым символом строки c. Мне нужно проверить все начальное положение кривошипа.

Трюк использовать для поворота строки

Обычный способ поворота строки в python ( s[i:]+s[:i]) тоже должен повторять как индекс, так и строку. В этом случае я дублирую строку и обрезаю первые символы.

(c*2)                        # duplicate the string
     [(s[0]==c[0])*2+1       # test that return 1 if firsts characters match 3 instead 
                      :]     
                        [:4] # crop again to have a 4 characters string

Контрольные примеры

[f(i) for i in ["1", "1234", "1221", "3333", "143332", "22234", "2234", "22214", "1221441", "41233", "13", "1224", "121", "12221", "43221"]]
[True, True, True, True, True, True, True, True, True, True, False, False, False, False, False]

1
Вы можете удалить место в 3"[i:]) for.
Эрик Outgolfer

@EriktheOutgolfer спасибо, я удалил его.
Эрван


1

JavaScript (ES2015), 110 95

p=(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)))

15 байтов, сохраненных Нилом! Оригинальная версия ungolfed:

p = (s, d) => {
  h = s[0]
  t = s.substr(1)

  if (!t[0]) return true
  if (!d) return p(s, 1) || p(s, -1)
  if (t[0] == h) return p(t, d*-1)
  if (t[0] == (h-d > 4 ? 1 : h-d || 4)) return p(t, d)

  return false
}

Тесты: https://jsbin.com/cuqicajuko/1/edit?js,console


1
Сохранено 17 байт:(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)))
Нейл

Тем не менее, не такой короткий, как ответ @ user81655.
Нил

1

Машинный код Тьюринга, 395 байтов

0 1 _ r a
0 2 _ r b
0 3 _ r c
0 4 _ r d
a 1 _ r a
a 2 _ r E
a 3 _ r h
a 4 _ r S
b 1 _ r W
b 2 _ r b
b 3 _ r S
b 4 _ r h
c 1 _ r h
c 2 _ r N
c 3 _ r c
c 4 _ r W
d 1 _ r N
d 2 _ r h
d 3 _ r E
d 4 _ r d
N 1 _ r W
N 2 _ r E
N _ _ r r
N * _ r h
E 2 _ r N
E 3 _ r S
E _ _ r r
E * _ r h
S 3 _ r E
S 4 _ r W
S _ _ r r
S * _ r h
W 4 _ r S
W 1 _ r N
W _ _ r r
W * _ r h
h _ 0 r halt
h * _ r h
r _ 1 r halt

Попробуйте онлайн!

Это в основном государственный подход:

  • Начальное состояние 0.
  • a, b, cИ dявляется «неопределившимся государством» , которые происходят только в начале
  • N, E, S, И Wявляются «решившие государства», очевидно , стоя на NОрт, Eаст, South и WЭСТа.

1

Чт, 203 байта

Я не могу думать о том, как играть в гольф дальше.

0::=:::
>11::=>1
>22::=>2
>33::=>3
>44::=>4
>12::=b
>21::=d
>14::=c
>41::=a
>23::=c
>32::=a
>34::=d
>43::=b
a1::=d
a2::=b
b2::=a
b3::=c
c3::=b
c4::=d
d4::=c
d1::=a
a<::=~n
b<::=~e
c<::=~s
d<::=~w
::=
>0<

Если последовательность нот возможна, будет выводиться конечное направление, в противном случае вывод будет пустым.


1

Пролог (SWI) , 117 байт

a(N,P):-P=N;N=1,P=4,!;P is N-1.
m([A,B|C],[X,Y|Z]):-a(A,X),a(B,X),a(B,Y),X\=Y,m([B|C],[Y|Z]).
m([_],_).
p(N):-m(N,_).

Определяет предикат, pкоторый преуспевает на воспроизводимых входных данных (заданных в виде списка целых чисел) и терпит неудачу на неиграбельных. Попробуйте онлайн!

объяснение

aопределяет отношение смежности между примечанием Nи положением кривошипа P. Мы определяем положение p между нотами p и p + 1 . Таким образом, позиция смежна с примечанием, Nесли

  • это равно N( P=N); или же
  • примечание 1 и позиция 4 ( 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и отбрасывать сгенерированный список положений кривошипа.

Посмотрите версию без игры и проверьте все контрольные примеры здесь .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.