Полуобратная двоичная строка


12

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

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

Реализуйте такую ​​функцию f как можно меньше байтов.

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

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

  • Результатом одного применения 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]

Ungolfed:

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.