Invierta la polaridad

12

El objetivo de este desafío es escribir un programa que satisfaga las siguientes condiciones:

  • El programa no es palindrómico, o esencialmente palindrómico (lo que significa que es posible eliminar caracteres para convertirlo en un palíndromo sin cambiar los efectos del programa).

  • El programa no es una involución (lo que significa que no produce su entrada original cuando se ejecuta en su salida)

  • El programa de polaridad inversa es el inverso del programa normal; entonces, cuando el programa invertido se ejecuta en la salida del programa normal, devuelve la entrada original.

¿Qué significa polaridad inversa ? Bueno, difiere entre idiomas.

  • Para la mayoría de los que no son esolangs, esto significa revertir el orden de las suboperaciones en una sola operación, revertir el orden de los argumentos y revertir el contenido de listas / matrices / tuplas / diccionarios / pilas / colas codificadas, etc. como invertir el orden de los bloques de código y las líneas independientes (pero no las líneas dentro de los bloques)

Ejemplos:

Haskell : x`mod`y-> y`mod`x; zipWith ((*3).(+)) [1,2,3] [4,5,6]->zipWith ((+).(*3)) [6,5,4] [3,2,1]

Python : 2**3-> 3**2; for x,y in [(1,2),(3,4),(5,6)]->for y,x in [(6,5),(4,3),(2,1)]

  • Para los idiomas que tienen funciones de 1 carácter (como Pyth, APL), simplemente invierta la cadena de instrucciones

  • Para esolangs unidimensionales como BF, invierta las instrucciones o cambie la polaridad; los intercambios de polaridad son []-> {}, +-> -, --> +, >-> <, <-> >, .-> ,y ,-> .(pero no ambos)

  • Para esolangs bidimensionales como Befunge, puede realizar una reflexión a través de los ejes x o y o una diagonal, rotar 180 grados o hacer una combinación de una reflexión y una rotación

Las operaciones conmutativas están permitidas, pero las palindrómicas no lo están: 2*xestá bien, pero x+xes malo. La definición de una inversión de polaridad es bastante laxa, pero use su juicio sobre lo que tiene sentido; el objetivo no es encontrar la escapatoria más inteligente, sino encontrar la solución más inteligente.

Este es un concurso de popularidad, por lo que una escapatoria muy inteligente puede ser popular, pero trate de mantenerse dentro del espíritu de este desafío. El ganador se anunciará una vez que haya al menos 10 soluciones con al menos 1 voto a favor, y haya al menos una solución con más votos a favor que los que presenten al menos 1 voto a favor; o en 1 mes, lo que ocurra primero. Este es mi primer desafío, así que trate de ser justo y darme comentarios constructivos, pero también avíseme si este es un desafío irrazonable o de alguna manera está mal clasificado o es ambiguo. Si tiene preguntas sobre un idioma que no encaja en ninguno de los casilleros que he establecido aquí, comente y me doblegaré a la voluntad de la comunidad si hay una fuerte protesta por una aclaración particular o cambio de reglas.

ACTUALIZAR

Ha pasado exactamente 1 mes desde que se inició este concurso (por casualidad lo revisé por casualidad, sin saber que realmente estaba a tiempo). Como se trata de un concurso de popularidad, el ganador (por un deslizamiento de tierra) es Pietu1998-Befunge . Aunque los componentes inferiores (el inversor de texto y el alfabeto hacia atrás) son ambas involuciones, el codificador / decodificador no lo son, por lo que no hay ningún problema allí. Puntos de bonificación (en mi opinión) por lograr escribir "BEFUNGE" en el medio. Personalmente, me gustó la novedad de la solución Theseus de Zgarb , porque el lenguaje se ve genial (si está restringido). Gracias a todos por participar, y aunque el ganador ha sido elegido, dejo este concurso completamente abierto, y les doy la bienvenida a futuras presentaciones.

Archaephyrryx
fuente
1
¿Qué quiere decir con el programa de polaridad inversa es el inverso del programa normal? ¿La salida difiere de alguna manera?
Sp3000
Realiza la operación inversa; cuando el programa invertido se ejecuta en la salida del programa normal, devuelve la entrada original.
archaephyrryx
Lo siento por el error; No lo había escuchado antes, y me pareció un poco grotesco, así que debo haber asumido que era un Esolang; Voy a cambiar eso
archaephyrryx
1
Algo que probablemente debería especificarse: ¿es ()palindrómico? Técnicamente, lo contrario es )(.
Sp3000
1
En el ejemplo de Haskell, ¿por qué el argumento de la función no se baraja hasta el final? ¿Se eligen los reveses de tal manera que se conserve la seguridad del tipo? ¿Se nos permite elegir algunos detalles de la operación de inversión de polaridad?
John Dvorak

Respuestas:

41

Befunge

Whoa, ese fue un trabajo, incluso con el editor que hice para este desafío. Esto es lo que obtuve, un bonito bloque de 11x12:

v$,g6<6g,$v
v,$ _^_ $,v
1W>v\B\v>L1
~T+:1E1:-O~
+F00-F-02L+
>:|6gUg6|:>
{a@>^N^>@z`
>1+|@G$| +>
:^9< E<  ^1
~>7^@_,#:>:
 xD>65 ^=P~
v,-\+**<  v

Hace un par de cosas, lamentablemente solo para letras minúsculas.

Que hace

Cuando se ejecuta normalmente, realiza un cifrado César en la entrada.

abcxyz      -> bcdyza
exampletext -> fybnqmfufyu

Cuando se voltea horizontalmente, invierte dicho cifrado. Este es el requisito para el desafío, pero no termina aquí.

bcdyza      -> abcxyz
fybnqmfufyu -> exampletext

Cuando se voltea verticalmente , cifra la entrada con un alfabeto inverso. Esto puede considerarse el enfoque opuesto al cifrado César.

abcxyz      -> zyxcba
exampletext -> vcznkovgvcg

Finalmente, cuando se gira 180 grados, invierte la entrada. Tengo la sensación de que tiene que ser al revés de algo (pista: la entrada).

abcxyz      -> zyxcba
exampletext -> txetelpmaxe

Cómo funciona

El bloque consiste básicamente en cuatro algoritmos semi-superpuestos.

Codificador de cifrado César

v$,g6<
v,$ _^
1 >v\
~ +:1
+ 00-
>:|6g
{a@>^

Decodificador de cifrado César (volteado horizontalmente)

v$,g6<
v,$ _^
1 >v\
~ -:1
+ 20-
>:|6g
`z@>^

Invertir alfabeto cifrado (volteado verticalmente)

v,-\+**<
   >65 ^
~>7^
:^9<
>1+|@
   >^

Inversor de texto (girado 180 grados)

v  <
~      
:>:#,_@
1^  <
>+ |$
   >^
PurkkaKoodari
fuente
2
Supongo que Befunge tiene una ligera ventaja aquí, porque siempre puedes usar el cuadrante superior izquierdo e ignorar por completo lo que hay en el resto del código. Buen trabajo sin embargo!
Martin Ender
1
¡Guauu! Tengo que votar esto, a pesar de que eso significa que baje al tercer lugar.
Level River St
18

Brainfuck, 5

,+.-,

Posiblemente por primera vez, Brainfuck produce una respuesta que es competitiva en cuanto a la longitud del código. Es una pena que no sea una pregunta de código de golf.

Introduce un byte (carácter), lo incrementa y genera el resultado. La coma al final está esperando otra entrada, que si se da será ignorada. No hay nada en la especificación sobre la terminación adecuada: -) *

* (o sobre hacer algo útil con todo el código en ambas direcciones)

Resultados típicos (se ignora el segundo carácter si se da).

Adelante: B->C

Reverso: B-> Ao C->B

Level River St
fuente
11

Maravilloso

Aquí hay uno simple para comenzar. Lee un carácter de STDIN, lo incrementa e imprime.

--
]]
00
]]
++

Si giramos esto 180 ° (sin intercambiar paréntesis), o lo reflejamos en el eje x, obtenemos

++
]]
00
]]
--

que lee un byte de STDIN y lo disminuye.

Puedes probarlo aquí .

Podría buscar algunos programas Marbelous más complicados, pero estoy seguro de que es1024 me convencerá. ;)

Explicación

El 00es una canica con valor 0 (que es arbitrario). Los ]]dispositivos leen un byte de STDIN, es decir, si una canica cae a través de ellos, el valor de la canica cambia al byte leído. Los dispositivos ++y --simplemente incrementan o disminuyen el valor de una canica (mod 256) y la dejan caer. Cuando una canica se cae del tablero, el byte se escribe en STDOUT.

Por lo tanto, los dos dispositivos en la parte superior simplemente se ignoran porque el flujo de control nunca los alcanza.

Martin Ender
fuente
Alternativamente, puede reemplazar sus tres filas centrales por un solo dispositivo de entrada.
Overactor
@overactor ¿O quieres decir }0y usarlo como una placa base?
Martin Ender
}0como entrada de línea de comando para ser precisos.
overactor
5

Maravilloso

Este tablero toma un argumento ( x) y devuelve (101 * x) mod 256.

.. @5 .. }0 }0 @1 .. @0 .. @2 .. 
.. /\ Dp << \\ .. &0 >0 &1 .. .. 
!! @3 .. << }0 .. \/ -- \/ .. }0 
@4 .. .. &0 @1 /\ &0 65 &1 /\ @2 
/\ Dp .. @4 .. .. @3 @0 @5 !! \\

Reflejar las celdas a lo largo del eje y dará como resultado un tablero que toma un argumento ( y) y devuelve (101 * y + 8 * y) mod 256, que es el inverso del primer tablero.

.. @2 .. @0 .. @1 }0 }0 .. @5 ..
.. .. &1 >0 &0 .. \\ << Dp /\ ..
}0 .. \/ -- \/ .. }0 << .. @3 !!
@2 /\ &1 65 &0 /\ @1 &0 .. .. @4
\\ !! @5 @0 @3 .. .. @4 .. Dp /\

Prueba esto aquí . Los tableros cilíndricos y las bibliotecas de inclusión deben estar marcados.

Ejemplo de entrada / salida :

Original Board:      Mirrored Board:
Input   Output       Input    Output
025     221          221      025
042     146          146      042
226     042          042      226

Tenga en cuenta que Marbelous solo permite pasar enteros positivos como argumentos, y el intérprete pasa estos enteros al módulo 256 del programa.

101fue elegido por dos razones: es un primo (y cada entrada posible a este programa da como resultado una salida única), y la operación inversa involucrada 109, que está a una distancia conveniente de 8 de distancia 101.

Breve explicacion

La columna que contiene las celdas (de arriba a abajo) se @0 >0 -- 65 @0ejecuta igual en ambos tableros, y se repite varias 101veces antes de dirigirse hacia la derecha. A cada lado de la >0rama hay un sincronizador diferente; cuál es el elegido depende de si el tablero está reflejado o no.

En cada lado, en sincronización con el bucle central, la entrada se suma repetidamente, obteniéndose así 101*x mod 256. En el tablero invertido, dos copias de la entrada también se desplazan un poco dos veces a la izquierda ( input * 4), luego se suman y se dejan en un sincronizador.

Una vez que finaliza el bucle central, las canicas resumidas se envían para su impresión, que se encuentra en el costado del tablero (izquierda para el tablero original, derecha para espejo). Después de imprimir, !!se alcanza una celda, terminando el tablero. Tenga en cuenta que el bucle que dio 101 * xcontinúa ejecutándose por sí mismo hasta que se termina la placa.

Dp simplemente imprime el resultado como un número decimal.

es1024
fuente
5

Teseo

Esto puede considerarse como un vacío legal, pero me gusta el lenguaje, así que aquí va. Este programa define una función fen números naturales que asigna 3n a 3n + 1 , 3n + 1 a 3n + 2 y 3n + 2 a 3n , para cada n .

data Num = Zero | Succ Num

iso f :: Num <-> Num
  | n                          <-> iter $ Zero, n
  | iter $ m, Succ Succ Succ n <-> iter $ Succ m, n
  | iter $ m, Succ Succ Zero   <-> back $ m, Zero
  | iter $ m, Succ Zero        <-> back $ m, Succ Succ Zero
  | iter $ m, Zero             <-> back $ m, Succ Zero
  | back $ Succ m, n           <-> back $ m, Succ Succ Succ n
  | back $ Zero, n             <-> n
  where iter :: Num * Num
        back :: Num * Num

Theseus es un lenguaje reversible con una sintaxis similar a la de Haskell, donde cada función es invertible (descartando problemas con la no terminación). Es altamente experimental y está diseñado para fines de investigación. El código anterior define un tipo de datos para números naturales y la función f. Dado un número de entrada, puede emparejarlo con el patrón en el lado izquierdo (siempre coincide n). Luego miras el patrón de la derecha. Si ese patrón tiene una etiqueta (aquíiter), procede a hacer coincidir el patrón en el lado izquierdo y nuevamente toma el valor correspondiente en el lado derecho. Esto se repite hasta que tenga un valor sin etiquetar a la derecha, y esa es su salida. Los patrones de la izquierda y de la derecha deben ser exhaustivos y no superpuestos (por separado para cada etiqueta). Ahora, para "revertir la polaridad" de f, hago lo siguiente.

  • Cambia los dos valores de cada etiqueta. Esto no cambia la semántica de f.
  • Cambie los lados derecho e izquierdo en el cuerpo de la función. Esto define la función inversa de f by design .

El resultado:

iso f :: Num <-> Num
  | iter $ n, Zero             <-> n
  | iter $ n, Succ m           <-> iter $ Succ Succ Succ n, m
  | back $ Zero, m             <-> iter $ Succ Succ Zero, m
  | back $ Succ Succ Zero, m   <-> iter $ Succ Zero, m
  | back $ Succ Zero, m        <-> iter $ Zero, m
  | back $ Succ Succ Succ n, m <-> back $ n, Succ m
  | n                          <-> back $ n, Zero
  where iter :: Num * Num
        back :: Num * Num
Zgarb
fuente
3

tr

a b

Ejemplo:

$ echo "apple" | tr a b
bpple
$ echo "bpple" | tr b a
apple

Solo un inverso verdadero en el dominio de cadenas que no incluye 'a' y 'b'.

histocrat
fuente
En realidad, necesita restringir el dominio un poco más que eso. Por ejemplo, si comienza con "bog", su programa y su reverso dan "bog" -> "bog" -> "aog". Entonces, cualquier cadena que contenga 'b' es un problema (o que contiene 'a', si aplica el programa inverso primero).
user19057
Puede usar tr abc bcacon la versión de polaridad invertida tr acb cba.
Christian Sievers
2

Otra respuesta maravillosa

La derecha original desplaza la entrada de la línea de comando (un valor de 8 bits), agregando uno principal si un 1 se pierde al cambiar. ( 0000 0001 -> 1000 0000)

{0 ..
~~ ..
>> {0
-2 =0
.. ^0
\/ }0
}0 Sb
<< ..
\\ ..
:Sb
// ..
Sb >>
}0 ..
^7 }0
{0 \/

Girando este tablero 180 ° (pero dejando el contenido de cada celda igual) Cambia el programa para que quede desplazado ( 1000 0000 -> 0000 0001)

\/ {0
}0 ^7
.. }0
>> Sb
.. //
:Sb
.. \\
.. <<
Sb }0
}0 \/
^0 ..
=0 -2
{0 >>
.. ~~
.. {0

Puedes probarlo aquí . (deberá activar 'Mostrar salida como números decimales')

Explicación

Ambos programas consisten en dos tableros, el tablero principal (que obtiene la entrada de la línea de comandos) y Sb. Echemos un vistazo a ambas versiones de la placa principal, solo mirando las celdas a las que se puede llegar en su orientación respectiva (ya que las canicas generalmente no pueden ir hacia arriba y los dispositivos de entrada no están en la parte superior):

original:      flipped:
   }0          }0
}0 Sb          .. }0
<< ..          >> Sb
\\ ..          .. //

Esos son tableros bastante sencillos, ambos toman dos copias de la entrada (que toman el lugar de las }0celdas. El original introduce una versión en un dispositivo de desplazamiento a la izquierda, <<la versión invertida lo coloca en un dispositivo de desplazamiento a la derecha. >>Estos realizan un desplazamiento de bits pero desafortunadamente descartan bits perdidos. Aquí es donde Sbentran las tablas, comprueban si el desplazamiento de bits del valor al que se alimenta dará como resultado que se pierda un bit y devolverá un valor que se agregará al resultado para contrarrestar el bit perdido.

Aquí está la parte relevante de la Sbplaca original para el programa original:

}0
^7
{0

Este es increíblemente fácil, '^ 7' verifica el valor del bit más significativo. Si este es 1, realizar un desplazamiento a la izquierda provocaría la pérdida de este bit. Por lo tanto, esta placa genera el valor de este bit como un valor de 8 bits que se agregará al resultado del desplazamiento de bits.

Para la versión invertida, Sbtiene que mirar el bit menos significativo y regresar 128o 0, esto es un poco más complicado:

}0
^0 ..
=0 -2
{0 >>
.. ~~
.. {0

Si el bit menos significativo (según lo probado por ^0) es 0, solo devuelve 0. Si es uno, ^0saldrá 1. Esto fallará la prueba de igualdad 0 =0y, por lo tanto, se empujará hacia la derecha. Luego restamos 2 -2para obtener 255, desplazamiento >>a la izquierda para obtener 127 y realizar un binario ~~para no obtener 128 (también podríamos simplemente haber agregado uno ++para obtener 128, pero ¿dónde está la diversión en eso?)

overactor
fuente