Invertire la polarità


12

Lo scopo di questa sfida è scrivere un programma che soddisfi le seguenti condizioni:

  • Il programma non è palindromico, o essenzialmente palindromico (nel senso che è possibile rimuovere i caratteri per renderlo un palindromo senza modificare gli effetti del programma).

  • Il programma non è un'involuzione (nel senso che non produce l'input originale quando viene eseguito sull'output)

  • Il programma a polarità inversa è l'inverso del programma normale; quindi quando il programma invertito viene eseguito sull'uscita del programma normale, restituisce l'input originale.

Cosa significa inversione di polarità ? Bene, differisce tra le lingue.

  • Per la maggior parte dei non-esolang, ciò significa invertire l'ordine delle sotto-operazioni in una singola operazione, invertire l'ordine degli argomenti e invertire il contenuto di elenchi / array / tuple / dizionari / stack / code / ecc. come invertire l'ordine dei blocchi di codice e delle linee autonome (ma non delle linee all'interno dei blocchi)

Esempi:

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)]

  • Per le lingue che hanno funzioni a 1 carattere (come Pyth, APL), è sufficiente invertire la stringa di istruzioni

  • Per esolang unidimensionali come BF, invertire le istruzioni o scambiare la polarità; gli scambi di polarità sono []-> {}, +-> -, --> +, >-> <, <-> >, .-> ,e ,-> .(ma non entrambi)

  • Per gli esolang bidimensionali come Befunge, è possibile eseguire una riflessione sugli assi X o Y o una diagonale, ruotare di 180 gradi o combinare una riflessione e una rotazione

Sono consentite operazioni commutative, ma non quelle palindromiche: 2*xva bene, ma x+xè male. La definizione di inversione di polarità è piuttosto ampia, ma usa il tuo giudizio su ciò che ha senso; l'obiettivo non è trovare la scappatoia più intelligente, ma trovare la soluzione più intelligente.

Questa è una gara di popolarità, quindi una scappatoia molto intelligente può essere popolare, ma cerca di mantenere lo spirito di questa sfida. Il vincitore verrà annunciato una volta che ci saranno almeno 10 soluzioni con almeno 1 voto, e c'è almeno una soluzione con più voti di quanti siano gli invii con almeno 1 voto; o tra 1 mese, a seconda dell'evento che si verifica per primo. Questa è la mia prima sfida, quindi cerca di essere onesto e dammi un feedback costruttivo, ma fammi anche sapere se questa è una sfida irragionevole o è in qualche modo erroneamente categorizzata o ambigua. Se hai domande su una lingua che non si adatta a nessuno dei buchi che ho esposto qui, commenta e mi piegherò alla volontà della comunità se c'è una forte protesta per un particolare chiarimento o cambio di regole.

AGGIORNARE

È passato esattamente 1 mese da quando è iniziato questo concorso (mi è capitato di controllarlo per caso, non sapendo di essere in tempo). Trattandosi di un concorso di popolarità, il vincitore (da una frana) è Pietu1998-Befunge . Anche se i componenti inferiori (l'invertitore di testo e l'alfabeto all'indietro) sono entrambi involuzioni, l'encoder / decodificatore non lo sono, quindi non vi sono problemi. Punti bonus (nella mia mente) per riuscire a scrivere "BEFUNGE" nel mezzo. Personalmente mi è piaciuta la novità della soluzione Theseus di Zgarb , perché la lingua sembra interessante (se limitata). Grazie a tutti per la partecipazione e, mentre il vincitore è stato scelto, lascio questo concorso completamente aperto e accolgo con favore i futuri contributi.


1
Cosa intendi con programma a polarità inversa è l' inverso del programma normale? L'output differisce in qualche modo?
Sp3000,

Esegue l'operazione inversa; quando il programma invertito viene eseguito sull'uscita del programma normale, restituisce l'input originale.
archaephyrryx,

Ci scusiamo per l'errore; Non ne avevo mai sentito parlare prima, e mi sembrava un po 'grottesco, quindi dovevo presumere che fosse un Esolang; Lo cambierò.
archaephyrryx,

1
Solo qualcosa che probabilmente dovrebbe essere specificato - è ()palindromico? Tecnicamente, è il contrario )(.
Sp3000,

1
Nell'esempio di Haskell perché l'argomento della funzione non è mischiato fino alla fine? I rovesci sono scelti in modo tale da preservare la sicurezza del tipo? Siamo autorizzati a scegliere alcuni dettagli dell'operazione di inversione di polarità?
John Dvorak,

Risposte:


41

Befunge

Whoa, quello era un lavoro, anche con l' editore che ho fatto per questa sfida. Ecco cosa ho ottenuto, un bel blocco 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

Fa un paio di cose, purtroppo solo per lettere minuscole.

Cosa fa

Se eseguito normalmente, esegue un codice Caesar sull'input.

abcxyz      -> bcdyza
exampletext -> fybnqmfufyu

Se capovolto in senso orizzontale, inverte la cifra. Questo è il requisito per la sfida, ma non finisce qui.

bcdyza      -> abcxyz
fybnqmfufyu -> exampletext

Se capovolto verticalmente , digita l'input con un alfabeto inverso. Questo può essere considerato l'approccio opposto alla cifra di Cesare.

abcxyz      -> zyxcba
exampletext -> vcznkovgvcg

Alla fine, quando ruotato di 180 gradi, inverte l'input. Ho la sensazione che debba essere il contrario di qualcosa (suggerimento: l'input).

abcxyz      -> zyxcba
exampletext -> txetelpmaxe

Come funziona

Il blocco è sostanzialmente costituito da quattro algoritmi semi-sovrapposti.

Codificatore di Cesare

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

Decodificatore di cifratura di Cesare (capovolto orizzontalmente)

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

Cifra alfabetica inversa (capovolta verticalmente)

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

Invertitore di testo (ruotato di 180 gradi)

v  <
~      
:>:#,_@
1^  <
>+ |$
   >^

2
Suppongo che Befunge abbia un leggero vantaggio qui, perché puoi sempre semplicemente usare il quadrante in alto a sinistra e ignorare completamente ciò che è nel resto del codice. Bel lavoro però!
Martin Ender,

1
Wow! DEVO votare questo, anche se ciò significa che devo scendere al terzo posto.
Level River St,

18

Brainfuck, 5

,+.-,

Forse per la prima volta in assoluto, Brainfuck produce una risposta competitiva sulla lunghezza del codice. Peccato che non sia una domanda da golf.

Immette un byte (carattere), lo incrementa e genera il risultato. La virgola alla fine è in attesa di un altro input, che se dato verrà ignorato. Non c'è nulla nelle specifiche sulla terminazione corretta: -) *

* (o sul fare qualcosa di utile con tutto il codice in entrambe le direzioni)

Risultati tipici (il secondo carattere se indicato viene ignorato).

Avanti: B->C

Invertire: B-> Ao C->B


11

Marbelous

Eccone uno semplice per iniziare. Legge un carattere da STDIN, lo incrementa e lo stampa.

--
]]
00
]]
++

Se lo ruotiamo di 180 ° (senza scambiare parentesi), o specchiamo nell'asse x, otteniamo

++
]]
00
]]
--

che legge un byte da STDIN e lo decrementa.

Puoi provarlo qui .

Potrei esaminare alcuni programmi Marbelous più complicati, ma sono sicuro che es1024 mi batterà. ;)

Spiegazione

La 00è un marmo con il valore 0 (arbitraria). I ]]dispositivi leggono un byte da STDIN, ovvero se un marmo li attraversa, il valore del marmo viene modificato nel byte letto. I dispositivi ++e --semplicemente aumentano o diminuiscono il valore di un marmo (mod 256) e lo lasciano cadere. Quando un marmo cade dal tabellone, il byte viene scritto su STDOUT.

Pertanto, i due dispositivi nella parte superiore vengono semplicemente ignorati perché il flusso di controllo non li raggiunge mai.


In alternativa, è possibile sostituire le tre file centrali con un singolo dispositivo di input.
overactor

@overactor O vuoi dire }0e usarlo come una sotto-scheda?
Martin Ender,

}0come input da riga di comando per essere precisi.
overactor

5

Marbelous

Questa scheda prende un argomento ( x) e ritorna (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 !! \\

Il mirroring delle celle lungo l'asse y comporterà una scheda che accetta un argomento ( y) e restituisce (101 * y + 8 * y) mod 256, che è l'inverso della prima scheda.

.. @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 /\

Prova questo qui . Le schede cilindriche e le librerie Includi devono essere entrambe controllate.

Esempio di input / output :

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

Si noti che Marbelous consente solo il passaggio di numeri interi positivi come argomenti e questi numeri interi vengono passati nel programma modulo 256 dall'interprete.

101è stato scelto per due motivi: è un numero primo (e ogni possibile input per questo programma si traduce in un output unico) e l'operazione inversa coinvolta 109, che è una distanza conveniente di 8 di distanza 101.

Breve spiegazione

La colonna che contiene le celle (dall'alto verso il basso) @0 >0 -- 65 @0gira la stessa su entrambe le schede e scorre i 101tempi prima di andare a destra. Su entrambi i lati del >0ramo è presente un diverso sincronizzatore; quale viene scelto dipende dal fatto che la scheda sia speculare o meno.

Su ciascun lato, in sincronia con il loop centrale, l'input viene ripetutamente sommato, ottenendo così 101*x mod 256. Sulla scheda al contrario, due copie dell'ingresso vengono anche spostate due volte a sinistra ( input * 4), quindi sommate e lasciate in un sincronizzatore.

Una volta terminato il ciclo centrale, i marmi sommati vengono inviati per la stampa, che si trova sul lato della scheda (a sinistra per la scheda originale, a destra per lo specchio). Dopo la stampa, !!viene raggiunta una cella che termina la scheda. Si noti che il ciclo che ha dato 101 * xcontinua a funzionare da solo fino al termine della scheda.

Dp stampa semplicemente il risultato come un numero decimale.


5

Teseo

Questo può essere considerato una scappatoia, ma mi piace la lingua, quindi ecco qui. Questo programma definisce una funzione fsui numeri naturali che mappa da 3n a 3n + 1 , 3n + 1 a 3n + 2 e 3n + 2 a 3n , per ogni 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

Teseo è un linguaggio reversibile con una sintassi simile a Haskell, in cui ogni funzione è invertibile (problemi di attualizzazione con non terminazione). È altamente sperimentale e progettato per scopi di ricerca. Il codice sopra definisce un tipo di dati per i numeri naturali e la funzione f. Dato un numero di input, lo fai corrispondere ad esso sul lato sinistro (corrisponde sempre n). Quindi guardi lo schema a destra. Se quel modello ha un'etichetta (quiiter), si procede a corrispondere al motivo sul lato sinistro e si assume nuovamente il valore corrispondente sul lato destro. Questo si ripete fino a quando non hai un valore senza etichetta sulla destra, e questo è il tuo output. I motivi a sinistra ea destra devono essere esaustivi e non sovrapposti (separatamente per ciascuna etichetta). Ora, per "invertire la polarità" di f, faccio quanto segue.

  • Scambia i due valori di ogni etichetta. Questo non cambia la semantica di f.
  • Scambia i lati destro e sinistro nel corpo della funzione. Questo definisce la funzione inversa della f progettazione .

Il risultato:

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

3

TR

a b

Esempio:

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

Solo un vero inverso nel dominio delle stringhe che non includono sia "a" che "b".


In realtà è necessario limitare il dominio un po 'di più. Ad esempio, se inizi con "bog", il tuo programma e il suo contrario danno "bog" -> "bog" -> "aog". Quindi qualsiasi stringa contenente 'b' è un problema (o contiene 'a', se si applica prima il programma inverso).
user19057

È possibile utilizzare tr abc bcacon la versione con polarità invertita tr acb cba.
Christian Sievers,

2

Un'altra risposta di Marbelous

La destra originale sposta l'ingresso della riga di comando (un valore di 8 bit), aggiungendo uno iniziale se un 1 si perde spostando. ( 0000 0001 -> 1000 0000)

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

Ruotando questa scheda di 180 ° (ma lasciando invariato il contenuto di ogni cella) Cambia il programma in modo che lasci i turni ( 1000 0000 -> 0000 0001)

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

Puoi provarlo qui . (dovrai attivare "Visualizza output come numeri decimali")

Spiegazione

Entrambi i programmi sono composti da due schede, la scheda principale (che ottiene l'input della riga di comando) e Sb. Diamo un'occhiata a entrambe le versioni della scheda madre, guardando solo le celle che possono essere raggiunte nel loro rispettivo orientamento (poiché i marmi in genere non possono andare verso l'alto e i dispositivi di input non sono in alto):

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

Quelle sono piuttosto semplici, entrambe prendono due copie dell'input (che prende il posto delle }0celle. L'originale <<inserisce una versione in un dispositivo di spostamento a sinistra, la versione capovolta lo mette in un dispositivo di spostamento a destra >>Questi eseguono uno spostamento di bit ma sfortunatamente scartano qualsiasi bit persi: è qui che Sbentrano in gioco le schede, controllano se spostando i bit il valore che vengono alimentati si tradurrà nella perdita di un bit e si restituirà un valore da aggiungere al risultato per contrastare il bit perso.

Ecco la parte rilevante della Sbscheda originale per il programma originale:

}0
^7
{0

Questo è incredibilmente facile, `^ 7 'controlla il valore del bit più significativo. Se questo è 1, l'esecuzione di uno spostamento a sinistra comporterebbe la perdita di questo bit. Quindi questa scheda emette il valore di questo bit come valore di 8 bit da aggiungere al risultato del bitshift.

Per la versione capovolta, Sbdeve guardare il bit meno significativo e tornare 128o 0, questo è un po 'più complicato:

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

Se il bit meno significativo (come testato da ^0) è 0, restituisce solo 0. Se è uno, ^0verrà emesso 1. Questo fallirà il test di uguaglianza con 0 =0e quindi sarà spinto verso destra. Quindi sottraggiamo 2 -2per ottenere 255, spostamento >>a sinistra per ottenere 127 ed eseguiamo un binario per non ~~ottenere 128 (avremmo anche potuto semplicemente aggiungerne uno ++per ottenere 128, ma dov'è il divertimento?)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.