Моя «клавіатура» мене нудить за допомогою ключів! Допоможіть мені знайти мінімальний натискання клавіш


13

Кредити @ Agawa001 для придумують з цим питанням.

Пояснення

У моєї нової "клавіатури" є лише 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.
  • Потім ви виведете / роздрукуєте мінімальну кількість натискань клавіш, необхідних для створення цього номера, використовуючи вищевказаний метод.

Тестові шафи

Оскільки перегрупування +або -запуски дає однакове число, для кожної такої групи перерахована лише найдавніша лексикографічна послідовність.

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 тестовими випадками (включаючи мою).
Ерік Аутгольфер

@ ΈρικΚωνσταντόπουλος Додано 12 тестових випадків з незначною модифікацією (оскільки +++++--це також альтернатива, але я її зняв, ++-++++оскільки це рівнозначно ++++-++). У мене є ще один випадок, який я хотів би додати пізніше, якщо хтось придумає ефективне рішення, якщо мені вдасться його створити.
Sp3000

@ Sp3000 Я не хотів ++-++++видаляти. Також це було МОЕ редагування, а не ВАШ.
Ерік Аутгольфер

@ ΈρικΚωνσταντόπουλος Перераховано лише 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; інші рядки перетинають всі можливі бінарні рядки, поки не буде знайдено той, чий результат дорівнює аргументу.

@Laaky врятував три байти!


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.

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 - це тестові випадки, на які посилається, по порядку.
Ерік Аутгольфер

1

Пітон, 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

Редагувати: Leaky Nun поголив п'ять байтів.


s/m,t,l,h=0,0,0,[]/m=t=l=0,h=[]/
Лина монашка

s/while m!=n/while m-n/
Лина монашка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.