Half-reverse una cadena binaria

12

Esta es una pregunta de seguimiento a mi pregunta de Puzzling.SE : pregunté si hay una función f que asigne cadenas booleanas a cadenas booleanas, de modo que f (f (b)) = reversa (b) para todas las cadenas de entrada b . (Por reversa , me refiero a la función que invierte el orden de los bits).

El enlace anterior contiene una respuesta positiva, con prueba, por la gran f '' , pero es posible que desee reflexionar sobre la pregunta antes de buscar.

Implemente dicha función f en la menor cantidad de bytes posible.

  • Puede leer la entrada de STDIN o tomar un argumento de función; y escribe la cadena de resultado en STDOUT o la devuelve.

  • De cualquier manera, puede trabajar con cadenas reales de dos bytes distintos o caracteres de su elección (digamos 0y 1, o \x00y \x01), o con matrices / listas de valores de verdad y falsedad . Sin embargo, elija dos valores y quédese con ellos.

  • El resultado de una sola aplicación de f debe ser una cadena binaria en sí misma: no hay respuestas tontas como b -> if b starts with 'x' then reverse(b[1:]) else 'x' + b...

  • Tu función debe ser total ; en particular, la entrada puede ser la cadena vacía, o un bit de largo, etc. No hay límite superior para la longitud de la cadena.

  • También debe ser puro : no mantenga ningún estado global entre llamadas a funciones; la cadena de entrada debe determinar completamente la cadena de salida.

Lynn
fuente
¿Puede la salida tener una longitud diferente a la entrada?
Luis Mendo
¡Seguro! (De hecho, de lo contrario, el desafío es probablemente imposible.)
Lynn
¿Tiene que funcionar para cadenas de longitud uno o cero?
CalculatorFeline
Si; La función tiene que ser total. ¡He aclarado esto en la pregunta!
Lynn
1
Relacionado.
Martin Ender

Respuestas:

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]

Sin golf:

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

Esto encuentra el período de la cadena, es decir, el mínimo ptal que ses una cadena de longitud prepetida nveces (encontré un método de golf en SO). Entonces, si nes extraño, agrega una repetición más del período. Si nes par, elimina una repetición del período y lo invierte.

Gracias a @ Sp3000 por ayudarnos a implementar la asignación de funciones entre 1 <-> 2, 3 <-> 4, etc.

Feersum
fuente
... ¿Cuándo se actualizará el código no protegido?
CalculatorFeline
@CatsAreFluffy No tengo planes de modificar el código no golfizado, ya que usa la misma idea con solo una diferencia trivial. El inglés, por otro lado, está actualizado.
feersum
2

Perl, 49 47 bytes

Incluye +2 para -lp

Basado en el muy buen algoritmo de @feersum

Ejecutar con entrada en STDIN, p. Ej.

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

halfreverse.pl:

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

Explicación

/^               $/         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
fuente
¿¿Como funciona??
CalculatorFeline