Мой «брелок» мне скучно! Помогите найти минимальные нажатия клавиш

13

Кредиты @ Agawa001 за этот вопрос.

объяснение

Мой новый "keybore" имеет только 2 кнопки, а именно +и -.

Номер в памяти начинается с 0.

Каждое последовательное нажатие +или -будет увеличивать / уменьшать память в течение того времени, сколько раз оно было нажато последовательно.

Поэтому, если вы нажмете +4 раза, в первый раз он добавляет 1, во второй раз он добавляет 2, в третий раз он добавляет 3, в четвертый раз он добавляет 4, давая вам 10(десять).

Теперь, если вы нажмете - 3 раза, первый раз вычитает 1, второй раз 2, третий раз 3, оставив вас с 4(четыре).

TL; DR

Учитывая строку + и -, делите ее при каждом изменении символа. Затем каждая результирующая строка из m +символов добавляет номер m-го треугольника, а каждая строка из n- символов вычитает n-й номер треугольника.

Прохождение

Теперь, если вы все еще не понимаете, я покажу вам, как +++--+--создает 1.

Program   | Counter | Memory
----------------------------
          |  0      | 0
+         | +1      | 1
++        | +2      | 3
+++       | +3      | 6
+++-      | -1      | 5
+++--     | -2      | 3
+++--+    | +1      | 4
+++--+-   | -1      | 3
+++--+--  | -2      | 1

задача

  • В качестве входных данных вы будете принимать положительное целое число, либо в качестве функционального аргумента, либо из STDIN.
  • Затем вы выведете / распечатаете минимальное количество нажатий клавиш, необходимое для создания этого числа, используя метод выше.

Testcases

Так как перестановка прогонов +или -дает одно и то же число, для каждой такой группы указана только самая ранняя лексикографическая последовательность.

Input | Output | Possible corresponding sequences
-------------------------------------------------
    4 |      5 | -+++-
    6 |      3 | +++
    9 |      5 | ++++-
   11 |      7 | +++-+++
   12 |      7 | +++++--, ++++-++
   19 |      8 | -++++++-
   39 |     12 | +++++++++---
   40 |     13 | +++++++++---+, ++++++++-+++-
   45 |      9 | +++++++++
   97 |     20 | ++++++++++++++--+---, +++++++++++++-++++--, ++++++++++++-++++++-
  361 |     34 | ++++++++++++++++++++++++++-+++-+++

Дополнительные ресурсы

счет

Это . Самое короткое решение в байтах побеждает.

Дрянная Монахиня
источник
9
Означает ли это ... у вас скучно?
Busukxuan
Я думаю, что вы в порядке с 10 тестовыми случаями сейчас (включая мой).
Эрик Outgolfer
@ ΈρικΚωνσταντόπουλος 12 тестовых примеров были добавлены с небольшой модификацией (так как +++++--это тоже альтернатива, но я удалил, ++-++++так как это эквивалентно ++++-++). У меня все еще есть еще один случай, который я хотел бы добавить позже, если кто-нибудь придумает эффективное решение, если мне удастся его сгенерировать.
Sp3000
@ Sp3000 я не хотел ++-++++удалять. Кроме того, это была МОЯ редакция, а не ВАША.
Эрик Outgolfer
@ ΈρικΚωνσταντόπουλος В списке только 1 решение из каждого набора эквивалентных решений - я думал, что если бы были перечислены все минимальные решения, тестовые случаи были бы излишне длинными (есть 6 решений для 40 и 17 решений для 97). Я прошу прощения, если это намерение не было ясным. Кроме того, вы пропали +++++--(или, что то же самое --+++++), поэтому я почувствовал необходимость редактировать в первую очередь.
Sp3000

Ответы:

2

Python 2, 119 байт

def g(n,i=0,s=''):
 c=x=t=0
 for d in s:C=int(d)*2-1;t=(c==C)*t+1;c=C;x+=c*t
 return(x==n)*len(s)or g(n,i+1,bin(i)[3:])

Очень медленный подход грубой силы. Третья строка вычисляет оценку строки x; другие строки перебирают все возможные двоичные строки, пока не будет найдена та, чья оценка равна аргументу.

@Leaky сохранил три байта!

Линн
источник
s/x==n and len/(x==n)*len/
Утренняя монахиня
Это может сэкономить несколько байтов, чтобы избавиться от них, sи просто использовать повторное деление, например так:def f(n): \n while n>0:print n%2;n/=2
Leaky Nun
2

Pyth, 25 байт

ffqyQ.as-Mc*RhdY2{s.pM./T

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

Это крайне неэффективно и не хватает памяти для f(n)≥ 11. Он рассчитывает f(22)= 10 примерно за 10 секунд на моем ноутбуке.

объяснение

  • Начиная с 1, перебирайте числа T. ( f)
    • Генерация всех разделов T. ( ./T)
    • Генерация всех перестановок тех. ( .pM)
    • Свести список. ( s)
    • Унифицируйте список. ( {) Этот шаг можно удалить, но он делает код намного быстрее.
    • Фильтрация полученных перестановок разделов: ( f)
      • Умножьте каждый номер dраздела ( *R) отдельно плюс один ( hd). Это дает двойное число, чтобы сложить / вычесть результат.
      • Разделите список на части длиной 2. ( c2)
      • Вычтите любое второе число в этих частях из второго числа. ( -M)
      • Подведите итоги. Это дает двойное полученное число, если перестановка разбиения интерпретировалась как число сложений, затем вычитаний и т. Д.
      • Возьмите абсолютное значение. ( .a) Если результат был отрицательным, замена сложений и вычитаний дает положительный результат.
      • Проверьте, равен ли результат двойному входу. ( qyQ) В этом случае перестановка разделов верна, верните ее.
    • Если фильтр возвращал какие-либо результаты, было найдено решение длины T. Вернуться и распечатать T.
PurkkaKoodari
источник
2

MATL , 43 29 байт

E:"@TFEqZ^!"@Y'tQ**s]vGE=a?@.

Это нехватка памяти и времени. Онлайн-компилятор может обрабатывать только до ввода 45.

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

Вот модифицированная версия со всеми тестовыми примерами до 40(это занимает почти минуту в онлайн-компиляторе).

объяснение

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

E:       % Range [1 2 ... 2*N] where N is implicit input. The required sequence length is
         % less than 2*N, so this is enough
"        % For each
  @      %   Push current value: length of sequence
  TFEq   %   Push array [1 -1]
  Z^     %   Cartesian power. Gives all possible sequences of 1, -1 of that length
  !      %   Transpose. Each sequence is now a row
  "      %   For each sequence
    @    %     Push current sequence
    Y'   %     Run-length decoding: Pushes an array of values 1 and -1, and then an
         %     array of run-lengths
    tQ*  %     Duplicate, add 1, multiply. Gives twice the triangular number for each run
    *    %     Multiply element-wise by 1 or -1 to produce correct sign
    s    %     Sum of array. This is the number produced by the current sequence
  ]      %   End for
  v      %   Concatenate all numbers into an array
  GE=a   %   True if any of those numbers equals twice the input
  ?      %   If so
    @    %     Push current sequence length. This is the final result
    .    %     Break loop
         %   End if
         % End for
         % Implicit display
Луис Мендо
источник
@ Sp3000 Я тоже добавил один, так что, для справки, 4, 6, 9 и 19 - тестовые примеры, упомянутые по порядку.
Эрик Outgolfer
1

Python, 105 100 байт

Использует неэффективный поиск в ширину.

def k(n):
 m=t=l=0;h=[]
 while m-n:o=1-2*(t>0);(m,t,l),*h=h+[(m+t-o,t-o,l+1),(m+o,o,l+1)]
 return l
  • h список используется в качестве очереди
  • m значение последовательности в начале списка
  • t последний добавленный номер m
  • l длина последовательности, которая сгенерировала m
  • o +/- 1, знак напротив знака t

Редактировать: Дрянная Монахиня побрила пять байтов.

RootTwo
источник
s/m,t,l,h=0,0,0,[]/m=t=l=0,h=[]/
Утренняя монахиня
s/while m!=n/while m-n/
Утренняя монахиня