Напівповернення двійкового рядка


12

Це додаткове запитання до мого питання Puzzling.SE : Я запитав, чи є функція f відображення булевих рядків до булевих рядків, щоб f (f (b)) = reverse (b) для всіх вхідних рядків b . (Під зворотним значенням я маю на увазі функцію, яка змінює порядок бітів.)

Наведене вище посилання містить позитивну відповідь із підтвердженням великої f '' , але ви, можливо, захочете задуматися над питанням перед тим, як шукати.

Реалізуйте таку функцію f якомога менше байтів.

  • Ви можете або прочитати вхід з STDIN, або взяти аргумент функції; або або запишіть рядок результатів в STDOUT, або поверніть його.

  • У будь-якому випадку, ви можете працювати з фактичними рядками з двох різних байтів або символів на ваш вибір (скажімо, 0і 1, або \x00і \x01), або з масивами / списками правдивих і хибних значень . Виберіть два значення та дотримуйтесь цих.

  • Результатом одного застосування f повинен бути сам двійковий рядок: жодних дурних відповідей, як b -> if b starts with 'x' then reverse(b[1:]) else 'x' + b...

  • Ваша функція повинна бути загальною ; зокрема, вхідним може бути порожній рядок або один біт довжиною тощо. Немає верхньої межі для довжини рядка.

  • Він також повинен бути чистим : не зберігайте жодного глобального стану між викликами функцій; рядок введення повинен повністю визначати вихідний рядок.


Чи може вихід має іншу довжину, ніж вхідний?
Луїс Мендо

Звичайно! (Насправді, інакше виклик неможливо.)
Лін

Чи повинен він працювати для рядків довжиною один або нуль?
CalculatorFeline

Так; функція повинна бути тотальною. Я це уточнив у питанні!
Лінн

Відповіді:



7

Python 2, 64 69 байт

def f(s):p=(s+s).find(s,1);return[s[~p::-1],s+s[:p]][len(s)/p%2]

Безголівки:

def f(s):
    p = (s+s).find(s,1)
    n = len(s)/p
    return s[:p][::1|n%-2] * -~(n-1^1)

Це знаходить період рядка, тобто мінімальний, pтакий, що sє рядком довжини pповторених nразів (я знайшов метод гофри на SO). Тоді, якщо nце не дивно, додається ще одне повторення періоду. Якщо nпарне число, воно видаляє одне повторення періоду і відміняє його.

Завдяки @ Sp3000 допомагає реалізувати відображення функцій між 1 <-> 2, 3 <-> 4 тощо.


... Коли буде оновлений код, який не використовується для перегляду?
CalculatorFeline

@CatsAreFluffy У мене немає плану змінювати код, який не використовується, оскільки він використовує ту саму ідею лише з дрібницею. Англійська мова, з іншого боку, є сучасною.
feersum

2

Perl, 49 47 байт

Включає +2 для -lp

На основі дуже приємного алгоритму @ feersum

Виконати з введенням на STDIN, наприклад

perl -lp halfreverse.pl <<< "101001"

halfreverse.pl:

/^(.+?)((\1\1?)*)$/;$_=$3eq$1?reverse$2:$_.$1

Пояснення

/^               $/         Match the complete input string
  (.+?)                     Non-greedy match. Try only one digit at the start,
                            if that doesn't work try 2, then 3 etc. The string
                            being tried is remembered in backreference \1
       ((\1\1?)*)           Try to repeat \1 as many times as possible but
                            prefer in groups of 2. Fall back to only 1 at the
                            end of the string if the trailing part has an odd
                            number of \1 (so the total count is even)

   $3eq$1                   So the last match $3 equals the first match $1
         ?                  if and only if the total count is even
          reverse$2         If total count is even drop the first instance of
                   :        \1 and reverse
                    $_.$1   If total count is odd extend $_ by one instance
$_=                         Assign result

Як це працює??
CalculatorFeline
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.