Trifid Cipher (без ключевого слова)

19

Вступление:

У меня есть множество разных шифров, которые хранятся в документе, который я однажды скомпилировал в детстве, я выбрал несколько из тех, которые, по моему мнению, лучше всего подходили для испытаний (не слишком тривиально и не слишком сложно), и превратил их в задачи. Большинство из них все еще находятся в песочнице, и я пока не уверен, опубликую ли я их всех или только несколько. Вот второй ( Компьютерный Шифр был первым, который я отправил).


Для Trifid Cipher (без использования ключевого слова) алфавит (и дополнительный подстановочный знак) разделен на три таблицы 3 на 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  

Текст, который мы хотим зашифровать, является первым символом за символом, закодированным в числах столбца строки таблицы. Например, текст this is a trifid cipherстановится:

        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

Затем мы помещаем все подряд один за другим в таблице выше группами по три:

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

И они преобразуются обратно в символы, используя те же таблицы:

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

Стоит отметить, что значение input-length должно быть взаимно простым с 3. Таким образом, если длина кратна 3, мы добавляем один или два конечных пробела, чтобы длина input больше не была кратна 3.

Вызов:

Получив строку sentence_to_encipher, зашифруйте ее, как описано выше.

Вам нужно только шифровать данные sentence_to_encipher, поэтому не нужно создавать программу / функцию дешифрования. Тем не менее, я мог бы сделать вызов части 2 для расшифровки в будущем (хотя у меня есть ощущение, что это тривиально / похоже на процесс шифрования).

Правила соревнований:

  • Вы можете предполагать, что sentence_to_encipherзавещание будет содержать только буквы и пробелы.
  • Вы можете использовать либо строчные, либо прописные буквы (укажите, какой из них вы использовали в своем ответе).
  • Вы можете добавить один или два завершающих пробела, когда длина ввода равна 3, чтобы больше не быть кратным 3.
  • Ввод / вывод является гибким. И вход, и выход могут быть строкой, списком / массивом / потоком символов и т. Д.

Основные правила:

  • Это , поэтому выигрывает самый короткий ответ в байтах.
    Не позволяйте языкам кода-гольфа отговаривать вас от публикации ответов на языках, не относящихся к кодексу. Попробуйте придумать как можно более короткий ответ для «любого» языка программирования.
  • Стандартные правила применяются к вашему ответу с правилами ввода / вывода по умолчанию , поэтому вам разрешено использовать STDIN / STDOUT, функции / метод с правильными параметрами и типом возврата, полные программы. Ваш звонок.
  • По умолчанию лазейки запрещены.
  • Если возможно, добавьте ссылку с тестом для вашего кода (например, TIO ).
  • Кроме того, добавление объяснения для вашего ответа настоятельно рекомендуется.

Тестовые случаи:

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)
Кевин Круйссен
источник
3
Я прочитал это как "без клавиатуры ". Это будет восхитительный вызов!
Корт Аммон - Восстановить Монику
1
Почему длина входа должна быть взаимно проста с 3? Я не понимаю, как это имеет значение здесь.
Фонд Моники Иск
Требование взаимной простоты не обязательно для того, чтобы заставить шифр работать, но оно делает его немного более безопасным, так как группы из трех цифр не совпадают с разделением строк в исходном списке цифр.
Спарр
@NicHartley Вы действительно правы, что даже если вход делится на 3, вы все равно можете транспонировать таблицу. У меня изначально не было этого правила в Песочнице, но кто-то сказал мне, что Википедия для Trifid показывает, что нужно добавить один или два пробела, чтобы сделать шифрование немного более безопасным. Поэтому я добавил его как часть задачи, чтобы сделать его более синхронизированным со страницей Википедии (кроме ключевого слова, которое я удалил).
Кевин Круйссен
1
@KevinCruijssen Я ... действительно не понимаю, как это сделало бы его более безопасным (если что-то, если ввод не определенной длины, сделало бы его менее безопасным, как вы могли догадаться, что последний символ кодирует пространство), но я согласен, что поддержание описания шифра здесь в соответствии с Википедией является хорошей идеей. Спасибо за объяснение!
Фонд Моника иск

Ответы:

6

Желе , 29 26 25 байт

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

Попробуйте онлайн!

Как это устроено

⁶Ø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.
Деннис
источник
Я никогда не знаю правил о побочных эффектах ... но договоренность ;L3ḍƊ¡⁶µ⁶Øa;3ṗ¤,ðṚyZFs3⁸yможет покончить с тем, µесли это приемлемо для 24.
Джонатан Аллан
У нас слабый консенсус ( + 6 / -1 ), что это разрешено, так что спасибо!
Деннис
Вывод кажется неверным. Я не думаю, что добавленное пространство "прилипает".
Деннис
6

Древесный уголь , 39 байт

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

Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:

≔               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
Нил
источник
6

Python 2 , 180 176 174 165 163 байта

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

Попробуйте онлайн!

Ввод может быть верхним или нижним. Вывод в верхнем регистре

TFeld
источник
6

Pyth, 34 33 байта

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

Полная программа. Ввод ожидается в нижнем регистре, вывод - массив символов. Попробуйте онлайн здесь или проверьте все тестовые примеры сразу здесь .

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

Альтернативное 34-байтовое решение: sm@+G;id3csCm.[03jx+G;d3+W!%lz3zd3- вместо +27 и tail, используется .[03для заполнения от 0 до длины 3. Может быть 33, если ведущий sотброшен.

Редактировать: сохранил байт, отбросив ведущий, так sкак символьные массивы верны

Sok
источник
5

Рубин , 153 145 138 131 байт

->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}}

Попробуйте онлайн!

Быстрый и наивный подход, работает со строчными буквами. Входы и выходы массивов символов.

Кирилл Л.
источник
4

Java (JDK) , 192 байта

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;}

Попробуйте онлайн!

Очень наивный подход. Принимает нижний регистр в char[]качестве входных данных , но выводит String.

Пояснения

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
}

кредиты

Оливье Грегуар
источник
1
Два небольших Integer.valueOfByte.valueOfR+=c<26?(char)(c+97):' ';R+=(char)(c<26?c+97:32);
поля для гольфа
1
202 байта
Кевин Круйссен
4

R 145 байтов

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

Попробуйте онлайн!

Ввод / вывод в виде строк; добавляет один пробел Странное повторение в [,3:1]том, что естественная индексация массива R несколько отличается.

Giuseppe
источник
Черт, ты побил меня более чем на 200 байтов. Я всегда впечатлен твоим кодированием, @Giuseppe. Я даже не должен пытаться иногда
Sumner18
1
@ Sumner18 хорошо, спасибо! Я обычно стараюсь пропустить день или два, прежде чем отвечать на вызовы, так как знаю, что сейчас здесь много других игроков в гольф R, но я не смог устоять перед этим, так как увидел его в Песочнице. Вы всегда можете подпрыгнуть идеи для игры в гольф от нас в R гольф чате . :-)
Джузеппе
3
@ Sumner18 также нет ничего постыдного в том, чтобы пытаться и терпеть неудачу, мое первое представление здесь было ужасным, и я только поправился! Пожалуйста, продолжайте писать, я думаю, что всегда хорошо получать отзывы, чтобы вы могли улучшить :-)
Джузеппе
3

APL + WIN, 102 байта

⎕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←⎕)↓' '])]]

Объяснение:

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  

Пример снимка экрана тестового примера:

⎕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  
Грэхем
источник
Не могли бы вы добавить скриншот (одного или нескольких) тестовых случаев? Я знаю, что версия WIN APL недоступна на TIO, но я все же хотел бы увидеть какую-то проверку, так как я едва знаю, как интерпретировать код APL, просто читая его, не говоря уже о проверке его без запуска. :)
Кевин Круйссен
Не совсем уверен, как это сделать, но вот как это будет выглядеть. Я добавлю что-то к записи выше
Грэм
Обычно я могу использовать Dyalog Classic в TIO, но в этом случае его атомный вектор находится в другом порядке, поэтому индексация не будет работать.
Грэм
3

SAS, 305 байт

Сытное «богатство» для этого чудовища SAS. Было много случайного форматирования строк, и я думал, что смогу избежать этого; Я уверен, что есть лучшие способы сделать это.

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;

Ввод вводится на новых строках после выписки карт, например:

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

Выводит набор данных, содержащий выходные данные в переменной f, вместе с набором вспомогательных переменных / значений массива.

введите описание изображения здесь

Ungolfed / объяснение:

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
Джош Эллер
источник
3

JavaScript (Node.js) ,  146 141 139  136 байт

Ввод / вывод в нижнем регистре.

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``

Попробуйте онлайн!

комментарии

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
источник
Я думаю, что вы уже объясняли это однажды, но как (o=...,++i)%3снова работает в JS? Является (o,i)ли кортеж или что-то еще, и оба внутренних целых числа преобразуются в их модуль-3? Как Java-разработчик, это все еще немного смущает меня, чтобы увидеть (a,b)%c. Хороший ответ, хотя! Мне нравится, как вы конвертируете каждую третью цифру, а затем удаляете первые два нулевых байта. +1 от меня.
Кевин Круйссен
2
@KevinCruijssen Цитирование MDN : «Оператор запятой оценивает каждый из своих операндов (слева направо) и возвращает значение последнего операнда. » Таким образом, модуль применяется только к ++i.
Арнаулд
3

05AB1E , 25 байтов

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

Поскольку никто еще не опубликовал ответ 05AB1E, я решил опубликовать собственное решение. Теперь я вижу, что это очень похоже на ответ @ Dennis ♦ 'Jelly , хотя я и придумал его самостоятельно, прежде чем опубликовать задание.

Ввод в виде строки, вывод в виде списка символов. Добавляет один пробел, если длина делится на 3.

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

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"]
Кевин Круйссен
источник
3

Japt , 42 байта

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

Попробуйте онлайн!

В основе этого ответа лежит удаленный ответ Шегги, но он никогда не возвращался для обработки входных данных длины, кратной 3, так что это фиксированная версия .

Объяснение:

;                                 #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
Камил Дракари
источник
3

C # (интерактивный компилятор Visual C #) , 178 байт

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;}

Попробуйте онлайн!

Менее гольф ... Это все еще сбивает с толку :)

// 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
источник