Trifid Cipher (sin palabra clave)

19

Introducción:

Tengo un montón de cifrados diferentes almacenados en un documento que una vez compilé cuando era niño, elegí algunos de los que pensé que eran más adecuados para los desafíos (no demasiado triviales y no demasiado difíciles) y los transformé en desafíos. La mayoría de ellos todavía están en la caja de arena, y todavía no estoy seguro de si los publicaré todos, o solo unos pocos. Aquí está el segundo ( Computer Cipher fue el primero que publiqué).


Para el Trifid Cipher (sin usar una palabra clave), el alfabeto (y un comodín adicional) se divide en tres tablas de 3 por 3:

table 1:     table 2:     table 3:
 |1 2 3       |1 2 3       |1 2 3
-+-----      -+-----      -+-----
1|a b c      1|j k l      1|s t u
2|d e f      2|m n o      2|v w x
3|g h i      3|p q r      3|y z  

Un texto que queremos cifrar es el primer carácter por carácter codificado en números de tabla-fila-columna. Por ejemplo, el texto se this is a trifid cipherconvierte en:

        t h i s   i s   a   t r i f i d   c i p h e r
table:  3 1 1 3 3 1 3 3 1 3 3 2 1 1 1 1 3 1 1 2 1 1 2
row:    1 3 3 1 3 3 1 3 1 3 1 3 3 2 3 2 3 1 3 3 3 2 3
column: 2 2 3 1 3 3 1 3 1 3 2 3 3 3 3 1 3 3 3 1 2 2 3

Luego colocamos todo uno tras otro fila por fila en la tabla de arriba en grupos de tres:

311 331 331 332 111 131 121 121 331 331 313 133 232 313 332 322 313 313 132 333 313 331 223

Y esos se transforman de nuevo en personajes usando las mismas tablas:

s   y   y   z   a   g   d   d   y   y   u   i   q   u   z   w   u   u   h       u   y   o

Una cosa a tener en cuenta, la longitud de entrada debe ser coprime a 3. Entonces, si la longitud es un múltiplo de 3, agregamos uno o dos espacios finales para que la longitud de entrada ya no sea un múltiplo 3.

Desafío:

Dada una cadena sentence_to_encipher, cifrarla como se describe anteriormente.

Solo tiene que cifrar dado el sentence_to_encipher, por lo que no es necesario crear un programa / función de descifrado también. Sin embargo, podría hacer un desafío de la parte 2 para descifrar en el futuro (aunque tengo la sensación de que es trivial / similar al proceso de cifrado).

Reglas de desafío:

  • Puede suponer sentence_to_encipherque solo contendrá letras y espacios.
  • Puede usar minúsculas o mayúsculas (indique cuál ha utilizado en su respuesta).
  • Puede elegir agregar uno o dos espacios finales cuando la longitud de entrada es 3 para que ya no sea un múltiplo de 3.
  • I / O es flexible. Tanto la entrada como la salida pueden ser una cadena, una lista / matriz / secuencia de caracteres, etc.

Reglas generales:

  • Este es el , por lo que la respuesta más corta en bytes gana.
    No permita que los lenguajes de código de golf lo desalienten de publicar respuestas con idiomas que no sean de código. Trate de encontrar una respuesta lo más breve posible para 'cualquier' lenguaje de programación.
  • Las reglas estándar se aplican a su respuesta con las reglas de E / S predeterminadas , por lo que puede usar STDIN / STDOUT, funciones / método con los parámetros adecuados y programas completos de tipo retorno. Tu llamada.
  • Las lagunas predeterminadas están prohibidas.
  • Si es posible, agregue un enlace con una prueba para su código (es decir, TIO ).
  • Además, se recomienda agregar una explicación para su respuesta.

Casos de prueba:

Input:            "this is a trifid cipher"
Output:           "syyzagddyyuiquzwuuh uyo"

Input:            "test"
Output:           "utbk"

Input:            "output"
Possible outputs: "rrvgivx" (one space) or "rrzcc lr" (two spaces)

Input:            "trifidcipher"
Possible output:  "vabbuxlzz utr" (one space) or "vabbyzv rx ie " (two spaces)
Kevin Cruijssen
fuente
3
Lo leí como "sin teclado ". ¡Ese iba a ser un desafío delicioso!
Cort Ammon - Restablece a Monica el
1
¿Por qué la longitud de la entrada debe ser coprime a 3? No veo cómo eso importa aquí.
Fondo de la demanda de Mónica
El requisito coprime no es necesario para que el cifrado funcione, pero lo hace un poco más seguro al garantizar que los grupos de tres dígitos no se alineen con las divisiones de fila de la lista de dígitos inicial.
Sparr
@NicHartley De hecho, tienes razón en que incluso si la entrada es divisible por 3, aún puedes transponer la tabla. Inicialmente no tenía esa regla en el Sandbox, pero alguien me dijo que Wikipedia para Trifid muestra que debería agregar uno o dos espacios para hacer que el cifrado sea un poco más seguro. Así que lo agregué como parte del desafío y para que esté más sincronizado con la página de Wikipedia (aparte de la palabra clave que eliminé).
Kevin Cruijssen
1
@KevinCruijssen I ... realmente no veo cómo eso lo haría más seguro (en todo caso, forzar que la entrada no sea de cierta longitud lo haría menos seguro, ya que podría adivinar que el último carácter está codificando un espacio), pero estoy de acuerdo en que mantener la descripción del cifrado aquí en línea con Wikipedia es una buena idea. ¡Gracias por la explicación!
Financia la demanda de Mónica el

Respuestas:

6

Jalea , 29 26 25 bytes

⁶Øa;3ṗ¤,©Ṛy;⁶$L3ḍƊ¡ZFs3®y

Pruébalo en línea!

Cómo funciona

⁶Øa;3ṗ¤,©Ṛy;⁶$L3ḍƊ¡ZFs3®y  Main link. Argument: s (string)

⁶                          Set the return value to space.
 Øa;                       Append it to "a...z".
    3ṗ¤                    Yield the third Cartesian power of [1, 2, 3].
       ,©                  Pair the results and store the pair in the register.
                           The register now holds
                           [[[1, 1, 1], ..., [3, 3, 3]], ['a', ... ,'z', ' '].
         Ṛ                 Reverse the outer array.
           ;⁶$             Append a space to s...
              L3ḍƊ¡        if the length is divisible by 3.
          y                Transliterate according to the mapping to the left.
                   ZFs3    Zip/transpose, flatten, split into chunks of length 3.
                       ®y  Transliterate according to the mapping in the register.
Dennis
fuente
Nunca conozco las reglas sobre salidas de efectos secundarios ... pero el acuerdo ;L3ḍƊ¡⁶µ⁶Øa;3ṗ¤,ðṚyZFs3⁸ypuede eliminar µsi es aceptable para 24.
Jonathan Allan
Tenemos un consenso débil ( + 6 / -1 ) de que esto está permitido, ¡así que gracias!
Dennis
La salida parece ser incorrecta. No creo que el espacio adjunto se "pegue".
Dennis
6

Carbón , 39 bytes

≔E⁺θ× ¬﹪Lθ³⌕βιθ⭆⪪E⁺÷θ⁹⁺÷θ³θ﹪鳦³§⁺β ↨³ι

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

≔               Assign
   θ            Input string
  ⁺             Concatenated with
                Literal space
    ×           Repeated
         θ      Input string
        L       Length
       ﹪        Modulo
          ³     Literal 3
      ¬         Logical not
 E              Mapped over characters
             ι  Current character
           ⌕    Position found in
            β   Lowercase alphabet
              θ To variable

     θ                      List of positions
    ÷                       Vectorised integer divide by
      ⁹                     Literal 9
   ⁺                        Concatenated with
         θ                  List of positions
        ÷                   Vectorised integer divide by
          ³                 Literal 3
       ⁺                    Concatenated with
           θ                List of positions
  E                         Map over values
             ι              Current value
            ﹪               Modulo
              ³             Literal 3
 ⪪                          Split into
                ³           Groups of 3
⭆                           Map over groups and join
                   β        Lowercase alphabet
                  ⁺         Concatenated with
                            Literal space
                 §          Cyclically indexed by
                       ι    Current group
                     ↨      Converted from
                      ³     Base 3
                            Implicitly print
Neil
fuente
6

Python 2 , 180 176 174 165 163 bytes

lambda s:''.join(chr(32+(33+a*9+3*b+c)%59)for a,b,c in zip(*[iter(sum(zip(*[(c/9,c/3%3,c%3)for c in map(o,s+' '[len(s)%3:])]),()))]*3))
o=lambda c:(ord(c)%32-1)%27

Pruébalo en línea!

La entrada puede ser superior o inferior. La salida es mayúscula

TFeld
fuente
6

Pyth, 34 33 bytes

m@+G;id3csCmtj+27x+G;d3+W!%lz3zd3

Programa completo La entrada se espera en minúsculas, la salida es una matriz de caracteres. Pruébelo en línea aquí , o verifique todos los casos de prueba a la vez aquí .

m@+G;id3csCmtj+27x+G;d3+W!%lz3zd3   Implicit: z=input(), d=" ", G=lowercase alphabet
                           lz       Length of z
                          %  3      The above, mod 3
                        W!          If the above != 3...
                       +      zd    ... append a space to z
           m                        Map the elements of the above, as d, using:
                  +G;                 Append a space to the lowercase alphabet
                 x   d                Find the 0-based index of d in the above
              +27                     Add 27 to the above
             j        3               Convert to base 3
            t                         Discard first element (undoes the +27, ensures result is 3 digits long)
          C                         Transpose the result of the map
         s                          Flatten
        c                       3   Split into chunks of length 3
m                                   Map the elements of the above, as d, using:
     id3                              Convert to decimal from base 3
 @+G;                                 Index the above number into the alphabet + space
                                    Implicit print

Solución alternativa de 34 bytes: sm@+G;id3csCm.[03jx+G;d3+W!%lz3zd3- en lugar de +27 y cola, se usa .[03para rellenar con 0 a longitud 3. Puede ser 33 si sse cae el inicio.

Editar: guardado un byte al soltar los principales scomo matrices de caracteres son salida válida

Sok
fuente
5

Rubí , 153 145 138 131 bytes

->a{a<<" "if a.size%3<1;a.map{|c|[(b=(c.ord%32-1)%27)/9,b%9/3,b%3]}.transpose.join.scan(/.{3}/).map{|x|((x.to_i(3)+65)%91+32).chr}}

Pruébalo en línea!

Un enfoque rápido e ingenuo, funciona con texto en minúsculas. Entradas y salidas de matrices de caracteres.

Kirill L.
fuente
4

Java (JDK) , 192 bytes

s->{String T="",R=T,C=T,r=T;for(int c:s){c-=c<33?6:97;T+=c/9;R+=c%9/3;C+=c%3;}for(var S:(s.length%3<1?T+2+R+2+C+2:T+R+C).split("(?<=\\G...)"))r+=(char)((Byte.valueOf(S,3)+65)%91+32);return r;}

Pruébalo en línea!

Enfoque muy ingenuo. Toma minúsculas char[]como entrada pero emite a String.

Explicaciones

s->{                                       // char[]-accepting lambda
 String T="",                              //  declare variables Table as an empty string,
        R=T,                               //                    Row as an empty string,
        C=T,                               //                    Column as an empty string,
        r=T;                               //                    result as an empty string.
 for(int c:s){                             //  for each character
  c-=c<33?6:97;                            //   map each letter to a number from 0 to 25, space to 26.
  T+=c/9;                                  //   append the table-value to Table
  R+=c%9/3;                                //   append the row-value to Row
  C+=c%3;                                  //   append the column-value to Column
 }                                         //
 for(var S:                                //  For each token of...
     (s.length%3<1?T+2+R+2+C+2:T+R+C)      //    a single string out of table, row and column and take the space into account if the length is not coprime to 3...
      .split("(?<=\\G...)"))               //    split every 3 characters
  r+=(char)((Byte.valueOf(S,3)+65)%91+32); //   Parses each 3-characters token into a number, using base 3,
                                           //  and make it a letter or a space
 return r;                                 //  return the result
}

Créditos

Olivier Grégoire
fuente
1
Dos campos de golf pequeñas: Integer.valueOfa Byte.valueOfy R+=c<26?(char)(c+97):' ';aR+=(char)(c<26?c+97:32);
Kevin Cruijssen
1
202 bytes
Kevin Cruijssen
4

R , 145 bytes

function(s,K=array(c(97:122,32),rep(3,3)))intToUtf8(K[matrix(arrayInd(match(c(utf8ToInt(s),32[!nchar(s)%%3]),K),dim(K))[,3:1],,3,byrow=T)[,3:1]])

Pruébalo en línea!

E / S como cadenas; agrega un espacio La extraña repetición de [,3:1]es porque la indexación de matriz natural de R es algo diferente.

Giuseppe
fuente
Dang, me ganaste más de 200 bytes. Siempre estoy impresionado por tu codificación, @Giuseppe. No debería siquiera se moleste en tratar veces
Sumner18
1
@ Sumner18 bien, gracias! Por lo general, trato de dejar pasar un día o dos antes de responder a los desafíos, ya que sé que hay muchos otros golfistas R aquí ahora, pero no pude resistirme a este desde que lo vi en el Sandbox. Usted es siempre bienvenido a intercambiar ideas para jugar al golf fuera de nosotros en la sala de chat R golf . :-)
Giuseppe
3
@ Sumner18 tampoco es vergonzoso intentarlo y llegar a ser breve, mi primera presentación aquí fue horrible y ¡solo he mejorado! Continúa publicando, creo que siempre es bueno recibir comentarios para que puedas mejorar :-)
Giuseppe
3

APL + WIN, 102 bytes

⎕av[n[c⍳(⊂[2]((⍴t),3)⍴,⍉⊃(c←⊂[2]c,(,⍉9 3⍴c←9/⍳3),[1.1]27⍴⍳3)[(⎕av[n←(97+⍳26),33])⍳t←t,(3|⍴t←⎕)↓' '])]]

Explicación:

t←t,(3|⍴t←⎕)↓' ' Prompts for input and applies coprime condition

(⎕av[n←(97+⍳26),33]⍳ Indices of characters in APL atomic vector 

c←⊂[2]c,(,⍉9 3⍴c←9/⍳3),[1.1]27⍴⍳3) Create a matrix of table, row column for 27 characters

⊂[2]((⍴t),3)⍴,⍉⊃ Extract columns of c corresponding to input and re-order

c⍳ Identify Column indices of re-ordered columns

⎕av[.....] Use indices back in atomic vector to give enciphered text  

Ejemplo de captura de pantalla del caso de prueba:

⎕av[n[c⍳(⊂[2]((⍴t),3)⍴,⍉⊃(c←⊂[2]c,(,⍉9 3⍴c←9/⍳3),[1.1]27⍴⍳3)[(⎕av[n←(97+⍳26),33])⍳t←t,(3|⍴t←⎕)↓' '])]]
⎕:
'output'
rrvgivx  
Graham
fuente
¿Le importaría agregar una captura de pantalla de (uno o varios de) los casos de prueba? Sé que la versión WIN APL no está disponible en TIO, pero todavía me gustaría ver algún tipo de verificación, ya que apenas sé cómo interpretar el código APL con solo leerlo, y mucho menos verificarlo sin ejecutarlo. :)
Kevin Cruijssen
No estoy muy seguro de cómo hacerlo, pero así es como se vería. Agregaré algo a la entrada de arriba
Graham
Normalmente puedo usar Dyalog Classic en TIO, pero en este caso su vector atómico está en un orden diferente, por lo que la indexación no funcionará.
Graham
3

SAS, 305 bytes

Un caluroso 'oof' para esta monstruosidad SAS. Hay muchos formatos de cadena aleatorios que pensé que podría evitar entrar en esto; Estoy seguro de que hay mejores formas de hacer algo de esto.

data;input n:&$99.;n=tranwrd(trim(n)," ","{");if mod(length(n),3)=0then n=cats(n,'{');f=n;l=length(n);array a(999);do i=1to l;v=rank(substr(n,i,1))-97;a{i}=int(v/9);a{i+l}=mod(int(v/3),3);a{i+l*2}=mod(v,3);end;f='';do i=1to l*3by 3;f=cats(f,byte(a{i}*9+a{i+1}*3+a{i+2}+97));end;f=tranwrd(f,"{"," ");cards;

La entrada se ingresa en las nuevas líneas después del extracto de las tarjetas, así:

data;input n:&$99.;n=tranwrd(trim(n)," ","{");if mod(length(n),3)=0then n=cats(n,'{');f=n;l=length(n);array a(999);do i=1to l;v=rank(substr(n,i,1))-97;a{i}=int(v/9);a{i+l}=mod(int(v/3),3);a{i+l*2}=mod(v,3);end;f='';do i=1to l*3by 3;f=cats(f,byte(a{i}*9+a{i+1}*3+a{i+2}+97));end;f=tranwrd(f,"{"," ");cards;
this is a trifid cipher
test
output
trifidcipher

Emite un conjunto de datos que contiene la salida en la variable f, junto con un grupo de variables auxiliares / valores de matriz.

ingrese la descripción de la imagen aquí

Sin golf / explicación:

data;
input n : & $99.; /* Read a line of input, maximum 99 characters */

n=tranwrd(trim(n)," ","{"); /* Replace spaces with '{' (this is the ASCII character following 'z', so it makes it easy to do byte conversions, and lets us not have to deal with spaces, which SAS does not like) */
if mod(length(n),3)=0then n=cats(n,'{'); /* If length of n is not coprime with 3, add an extra "space" to the end */

f=n; /* Set output = input, so that the string will have the same length */
l=length(n);    /* Get the length of the input */
array a(999);   /* Array of values to store intermediate results */

do i = 1 to l; /* For each character in the input... */
    v = rank(substr(n,i,1))-97; /* Get the value of the current character, from 0-26 */

    a{i}=int(v/9);          /* Get the table of the current character and store at appropriate index, from 0-2  */
    a{i+l}=mod(int(v/3),3); /* Get the row of the current character, from 0-2 */
    a{i+l*2}=mod(v,3);      /* Get the column of the current character, from 0-2  */
end;

f='';

do i = 1 to l*3 by 3; /* For each character in the output... */
    f=cats(f,byte(a{i}*9+a{i+1}*3+a{i+2}+97)); /* Convert values back from base 3 to base 10, and convert back into ASCII value */
end;

f = tranwrd(f,"{"," "); /* Replaces our "spaces" with actual spaces for final output */

/* Test cases */
cards;
this is a trifid cipher
test
output
trifidcipher
Josh Eller
fuente
3

JavaScript (Node.js) ,  146 141 139  136 bytes

I / O está en minúsculas.

s=>'931'.replace(/./g,d=>Buffer(s.length%3?s:s+0).map(c=>(o=(c>48?c-16:26)/d%3+o*3%27|0,++i)%3?0:(o+97)%123||32),i=o=0).split`\0`.join``

Pruébalo en línea!

Comentado

s =>                       // s = input string
  '931'.replace(/./g, d => // for each digit d = 9, 3 and 1:
    Buffer(                //   create a buffer from:
      s.length % 3 ?       //     if the length of s is coprime with 3:
        s                  //       the original input string
      :                    //     else:
        s + 0              //       the input string + an extra '0'
    )                      //
    .map(c =>              //   for each ASCII code c from this Buffer:
      ( o =                //     update o:
        ( c > 48 ?         //       if c is neither a space nor the extra '0':
            c - 16         //         yield c - 16 (which gives 81 .. 106)
          :                //       else:
            26             //         this is the 26th character (space)
        ) / d % 3 +        //       divide by d and apply modulo 3
        o * 3 % 27 | 0,    //       add o * 3, apply modulo 27, coerce to integer
        ++i                //       increment i
      ) % 3 ?              //     if i mod 3 is not equal to 0:
        0                  //       yield 0 (NUL character)
      :                    //     else:
        (o + 97) % 123     //       convert o to the ASCII code of the output letter
        || 32              //       or force 32 (space) for the 26th character
    ),                     //   end of map()
    i = o = 0              //   start with i = o = 0
  ).split`\0`.join``       // end of replace(); remove the NUL characters
Arnauld
fuente
Creo que ya lo has explicado antes, pero ¿cómo (o=...,++i)%3funciona de nuevo en JS? ¿Es (o,i)una tupla o algo así, y ambos enteros internos se convierten a su módulo-3? Como desarrollador de Java, todavía me confunde un poco ver (a,b)%c. Buena respuesta sin embargo! Me gusta cómo convierte cada tercer dígito y luego elimina los dos primeros bytes nulos. +1 de mi parte
Kevin Cruijssen
2
@KevinCruijssen Citando MDN : "El operador de coma evalúa cada uno de sus operandos (de izquierda a derecha) y devuelve el valor del último operando " . Por lo tanto, el módulo solo se aplica a ++i.
Arnauld
3

05AB1E , 25 bytes

g3Öð׫SAð«3L3㩇ø˜3ô®Að«‡

Como nadie publicó una respuesta 05AB1E todavía, pensé que publicaría mi propia solución. Ahora veo que es muy similar a @ Dennis ♦ 'Respuesta de Jelly , a pesar de que se me ocurrió de forma independiente antes de publicar el desafío.

Entrada como cadena, salida como una lista de caracteres. Agrega un espacio si la longitud es divisible por 3.

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

g3Ö         # Check if the length of the (implicit) input is divisible by 3
            # (results in 1 for truthy or 0 for falsey)
            #  i.e. "out" → 1
            #  i.e. "test" → 0
   ð×       # Repeat a space that many times
            #  i.e. 1 → " "
            #  i.e. 0 → ""
     «      # And append it to the (implicit) input
            #  i.e. "out" and " " → "out "
            #  i.e. "test" and "" → "test"
      S     # Then make the string a list of characters
            #  i.e. "out " → ["o","u","t"," "]
            #  i.e. "test" → ["t","e","s","t"]
A           # Push the lowercase alphabet
 ð«         # Appended with a space ("abcdefghijklmnopqrstuvwxyz ")
   3L       # Push list [1,2,3]
     3ã     # Cartesian repeated 3 times: [[1,1,1],[1,1,2],...,[3,3,2],[3,3,3]]
       ©    # Save that list of triplets in the registry (without popping)
           # Transliterate, mapping the letters or space to the triplet at the same index
            #  i.e. ["o","u","t"," "] → [[2,2,3],[3,1,3],[3,1,2],[3,3,3]]
            #  i.e. ["t","e","s","t"] → [[3,1,2],[1,2,2],[3,1,1],[3,1,2]]
ø           # Zip, swapping all rows/columns
            #  i.e. [[2,2,3],[3,1,3],[3,1,2],[3,3,3]] → [[2,3,3,3],[2,1,1,3],[3,3,2,3]]
            #  i.e. [[3,1,2],[1,2,2],[3,1,1],[3,1,2]] → [[3,1,3,3],[1,2,1,1],[2,2,1,2]]
 ˜          # Flatten the list
            #  i.e. [[2,3,3,3],[2,1,1,3],[3,3,2,3]] → [2,3,3,3,2,1,1,3,3,3,2,3]
            #  i.e. [[3,1,3,3],[1,2,1,1],[2,2,1,2]] → [3,1,3,3,1,2,1,1,2,2,1,2]
  3ô        # Split it into parts of size 3
            #  i.e. [2,3,3,3,2,1,1,3,3,3,2,3] → [[2,3,3],[3,2,1],[1,3,3],[3,2,3]]
            #  i.e. [3,1,3,3,1,2,1,1,2,2,1,2] → [[3,1,3],[3,1,2],[1,1,2],[2,1,2]]
®           # Push the triplets from the registry again
 Að«        # Push the lowercase alphabet appended with a space again
           # Transliterate again, mapping the triplets back to letters (or a space)
            # (and output the result implicitly)
            #  i.e. [[2,3,3],[3,2,1],[1,3,3],[3,2,3]] → ["r","v","i","x"]
            #  i.e. [[3,1,3],[3,1,2],[1,1,2],[2,1,2]] → ["u","t","b","k"]
Kevin Cruijssen
fuente
3

Japt , 42 bytes

;Êv3 ?UpS:U
m!bS=iC)®+27 ì3 ÅÃÕc ò3 £SgXì3

Pruébalo en línea!

El núcleo de esta respuesta proviene de una respuesta eliminada de Shaggy, pero nunca regresó para manejar entradas de longitud divisible por 3, por lo que esta es una versión fija .

Explicación:

;                                 #Set C to the string "abcdefghijklmnopqrstuvwxyz"

 Ê                                #Get the length of the input
  v3 ?                            #If it is divisible by 3:
      UpS                         # Add a space
         :U                       #Otherwise don't add a space
                                  #Store the result in U

   S=iC)                          #Set S to C plus a space
m                                 #For each character in U:
 !bS                              # Get the position of that character in S
        ®        Ã                #For each resulting index:
             ì3                   # Convert to base 3
         +27    Å                 # Including leading 0s up to 3 places
                  Õ               #Transpose rows and columns
                   c              #Flatten
                     ò3           #Cut into segments of length 3
                        £         #For each segment:
                           Xì3    # Read it as a base 3 number
                         Sg       # Get the letter from S with that index
Kamil Drakari
fuente
3

C # (compilador interactivo de Visual C #) , 178 bytes

s=>{int[]a={9,3,1},b=(s.Length%3>0?s:s+0).Select(c=>c<97?26:c-97).ToArray();s="";for(int i=0,k,l=b.Length;i<l*3;s+=(char)(k>25?32:97+k))k=a.Sum(p=>b[i%l]/a[i++/l]%3*p);return s;}

Pruébalo en línea!

Menos golf ... Sigue siendo confuso :)

// s is an input string
s=>{
  // powers of 3
  int[]a={9,3,1},
  // ensure the length of s is coprime to 3
  // and convert to numbers from 0-26
  b=(s.Length%3>0?s:s+0).Select(c=>c<97?26:c-97).ToArray();
  // reset s to collect result
  s="";
  // main loop
  for(
    // i is the main index variable
    // k is the value of the encoded character
    // l is the length
    int i=0,k,l=b.Length;
    // i continues until it is 3x the length of the string
    i<l*3;
    // convert k to a character and append
    s+=(char)(k>25?32:97+k)
  )
    // compute the trifid
    // (this is the confusing part :)
    k=a.Sum(p=>b[i%l]/a[i++/l]%3*p);
  // return the result
  return s;
}
dana
fuente