Inverter metade da string binária

12

Esta é uma pergunta de acompanhamento para minha pergunta Puzzling.SE : Perguntei se há uma função f mapeando seqüências de caracteres booleanas para seqüências de caracteres booleanas, de modo que f (f (b)) = reverse (b) para todas as seqüências de entrada b . (Por reverso , quero dizer a função que reverte a ordem dos bits.)

O link acima contém uma resposta positiva, com prova, do ótimo f '' , mas você pode ponderar a questão antes de procurar.

Implemente essa função f no menor número de bytes possível.

  • Você pode ler a entrada de STDIN ou usar um argumento de função; e escreva a sequência de resultados em STDOUT ou retorne-a.

  • De qualquer maneira, você pode trabalhar com cordas reais de dois bytes distintas ou personagens de sua escolha (dizer 0e 1, ou \x00e \x01), ou com matrizes / listas de truthy e valores Falsas . Escolha dois valores e fique com eles, no entanto.

  • O resultado de uma única aplicação de f deve ser uma string binária: nenhuma resposta boba como b -> if b starts with 'x' then reverse(b[1:]) else 'x' + b...

  • Sua função deve ser total ; em particular, a entrada pode ser a sequência vazia, ou um pouco longa, etc. Não há limite superior para o comprimento da sequência.

  • Também deve ser puro : não mantenha nenhum estado global entre chamadas de função; a sequência de entrada deve determinar completamente a sequência de saída.

Lynn
fonte
A saída pode ter um comprimento diferente da entrada?
Luis Mendo
Certo! (Na verdade, caso contrário, o desafio é comprovadamente impossível.)
Lynn
Tem que trabalhar para cadeias de comprimento um ou zero?
CalculatorFeline
Sim; a função tem que ser total. Eu esclareci isso na pergunta!
Lynn
1
Relacionado.
Martin Ender

Respostas:

7

Python 2, 64 69 bytes

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)

Ele encontra o período da string, ou seja, o mínimo ptal que sé uma string de comprimento prepetido nvezes (eu encontrei um método de golfe no SO). Então, se nfor ímpar, adiciona mais uma repetição do período. Se nfor par, remove uma repetição do período e a reverte.

Agradecemos ao @ Sp3000 por ajudar a implementar o mapeamento de funções entre 1 <-> 2, 3 <-> 4, etc.

feersum
fonte
... Quando o código não protegido será atualizado?
CalculatorFeline
@CatsAreFluffy Não tenho planos de modificar o código não-limitado, pois ele usa a mesma idéia com apenas uma diferença trivial. O inglês, por outro lado, está atualizado.
feersum 8/03/16
2

Perl, 49 47 bytes

Inclui +2 para -lp

Baseado no algoritmo muito bom do @ feersum

Execute com entrada no STDIN, por exemplo

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

halfreverse.pl:

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

Explicação

/^               $/         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
Ton Hospel
fonte
Como funciona??
CalculadoraFeline