Комп'ютерний шифр


14

Вступ:

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


Комп'ютерний шифр розшифрує даний текст на "випадкові" групи символів даної length. Якщо така група містить цифру, вона буде використовувати цю цифру для індексації до власної групи для шифрованого символу. Якщо в групі немає жодної цифри, це означає, що використовується перший символ.

Наприклад, скажімо, що ми хочемо розшифрувати текст this is a computer cipherзаданою довжиною 5. Це потенційний вихід (зверніть увагу: цифри 1-індексовано у наведеному нижче прикладі):

t     h     i     s     i     s     a     c     o     m     p     u     t     e     r     c     i     p     h     e     r       (without spaces of course, but added as clarification)
qu5dt hprit k3iqb osyw2 jii2o m5uzs akiwb hwpc4 eoo3j muxer z4lpc 4lsuw 2tsmp eirkr r3rsi b5nvc vid2o dmh5p hrptj oeh2l 4ngrv   (without spaces of course, but added as clarification)

Візьмемо кілька прикладів, як пояснити, як розшифрувати групу:

  • qu5dtЦя група містить цифру 5, так що (1-індексований) п'ятий символ цієї групи є символ , який використовується для розшифрованого тексту: t.
  • hpritЦя група не містить цифр, тому перший символ цієї групи неявно використовуються для розшифрованого тексту: h.
  • osyw2: Ця група містить цифру 2, так що (1-індексований) другий символ цієї групи є символ , який використовується для розшифрованого тексту: s.

Виклик:

Враховуючи ціле число lengthі рядок word_to_encipher, виведіть випадкову шифровану рядок, як описано вище.

Вам потрібно лише розшифрувати дані lengthта word_to_encipher, тому не потрібно також створювати програму / функцію розшифровки. Однак, я можу зробити завдання 2 для розшифровки в майбутньому.

Правила виклику:

  • Можна припустити, що lengthволя буде в діапазоні [3,9].
  • Ви можете припустити, що word_to_encipherбуде містити лише букви.
  • Ви можете використовувати як малі, так і великі великі регістри (будь ласка, вкажіть, який саме ви використовували у своїй відповіді).
  • Ваші результати, кожна група та позиції цифр у групі (якщо вони є) повинні бути однаково випадковими . Отже, всі випадкові букви алфавіту мають однаковий шанс виникнення; положення зашифрованого листа в кожній групі має однаковий шанс виникнення; і позиція цифри має однаковий шанс виникнення (за винятком випадків, коли це перший символ і немає жодної цифри; і, очевидно, він не може бути на тому ж самому місці, що і зашифрований символ).
  • Також вам дозволяється використовувати 0-індексовані цифри замість 1-індексованих. Будь ласка, вкажіть, який із двох ви використали у своїй відповіді.
  • Цифра 1(або 0коли 0-індексований) ніколи не буде присутній у висновку. Тому b1ndhне є дійсною групою для шифрування символу 'b'. Тим НЕ менше, b4tbwє дійсним, де 4зашифровує bна 4 - м (1-індексованого) положенні, а також інші символи b, t, wє випадковими (який по збігу також містить b). Інші можливі дійсні групи length5 , щоб зашифрувати символ «B» є: abcd2, ab2de, babbk, hue5bі т.д.

Загальні правила:

  • Це , тому найкоротша відповідь у байтах виграє.
    Не дозволяйте мовам з кодовим гольфом відштовхувати вас від публікації відповідей з мов, що не кодують гольф. Спробуйте придумати якомога коротшу відповідь на "будь-яку" мову програмування.
  • Для вашої відповіді застосовуються стандартні правила з правилами вводу / виводу за замовчуванням , тому вам дозволяється використовувати STDIN / STDOUT, функції / метод із відповідними параметрами та повним програмами типу повернення. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду (тобто TIO ).
  • Також настійно рекомендується додавати пояснення до своєї відповіді.

Тестові приклади:

Input:
 Length:           5
 Word to encipher: thisisacomputercipher
Possible output:
 qu5dthpritk3iqbosyw2jii2om5uzsakiwbhwpc4eoo3jmuxerz4lpc4lsuw2tsmpeirkrr3rsib5nvcvid2odmh5phrptjoeh2l4ngrv

Input:
 Length:           8
 Word to encipher: test
Possible output:
 ewetng4o6smptebyo6ontsrbtxten3qk

Input:
 Length:           3
 Word to encipher: three
Possible output:
 tomv3h2rvege3le

2
Як означає "рівномірний"
l4m2

@ l4m2 Що є рівний шанс для будь-якого виходу. Отже, всі випадкові букви алфавіту мають однаковий шанс виникнення; положення зашифрованого листа в кожній групі має однаковий шанс виникнення; і позиція цифри має однаковий шанс виникнення (за винятком випадків, коли це перший символ і немає цифри, а також не на тій же позиції, що і зашифрований символ).
Кевін Круїссен

Так abcd2, ab2de, babbkвсе ж? Також b1akkдіє?
l4m2

@ l4m2 Так, всі три можливі виходи, що шифрують символ "b". Щодо того, b1akkя б сказав, що ні. Відредагуйте його в описі завдання, щоб уточнити. Якщо перший символ є зашифрованим, жодна цифра не повинна бути присутнім.
Кевін Круїссен

1
Наприклад, коли довжина = 3, char = "a"; Форма "a??"має 676 можливих результатів, але "1a?", "?a1", "2?a", "?2a", має only104 результати. Отже, якщо я намагаюся вибрати один результат з усіх цих 780 результатів, розподіл "положення зашифрованого письма" становить 13: 1: 1, а не 1: 1: 1. І я вважав би це так, як працює "рівномірно випадковий".
tsh

Відповіді:


3

Піт, 22 байти

smsXWJOQXmOGQJdO-UQJJz

Спробуйте в Інтернеті.

Використовується малі та нульові показники.

Пояснення

Дуже простий алгоритм.

                           Implicit: read word in z
                           Implicit: read number in Q
 m                   z     For each char d in z:
      OQ                     Choose a number 0..Q-1
     J                       and call it J.
         m  Q                Make an array of Q
          OG                 random letters.
        X     d              Place d in this string
             J               at position J.
    W                        If J is not 0,
   X                J        place J in this string
               O             at a random position from
                 UQ          0..Q-1
                -  J         except for J.
  s                          Concatenate the letters.
s                          Concatenate the results.

5

Perl 6 , 125 байт

->\n{*.&{S:g{.}=(65..90)>>.chr.roll(n).join.subst(/./,$/,:th($!=roll 1..n:)).subst(/./,$!,:th($!-1??(^n+1$!).roll!!n+1))}}

Спробуйте в Інтернеті!

Здійснює введення та вихід великими літерами. Приймає вхід викришений, як f(n)(string). Використовує 1 індексацію.

Пояснення:

->\n{*.&{ ...  }}   # Anonymous code block that takes a number n and returns a function
     S:g{.}=        # That turns each character of the given string into
                          .roll(n)      # Randomly pick n times with replacement
            (65..90)>>.chr              # From the uppercase alphabet
                                  .join # And join
            .subst(                         ) # Then replace
                   /./,  ,:th($!=roll 1..n:)  # A random index (saving the number in $!)
                       $/               # With the original character
            .subst(                )    # Replace again
                   /./,$!,:th( ... )    # The xth character with $!, where x is:
                           $!-1??          # If $! is not 1
                                 (^n+1$!).roll       # A random index that isn't $!
                                               !!n+1  # Else an index out of range

4

Пітон 2 , 187 177 176 156 154 148 байт

lambda l,s:''.join([chr(choice(R(65,91))),c,`n`][(j==n)-(j==i)*(n>0)]for c in s for n,i in[sample(R(l),2)]for j in R(l))
from random import*
R=range

Спробуйте в Інтернеті!

Використовуються великі літери та 0-індексовані цифри.

-3 байти, завдяки Кевіну Крейсейну


@KevinCruijssen Спасибі :)
TFeld

Що sample(R(l),2)[::1|-(random()<.5)]означає?
l4m2

@ l4m2 Він бере 2 числа від range(l)та переміщує їх. Але, мабуть, зразок не гарантує замовлення, тому він не потрібний :)
TFeld

Ви не можете видалити круглі дужки навколо (j==i)*(n>0)? Перемноження має перевагу оператора над відніманням, чи не так?
Кевін Круїссен

1
@KevinCruijssen Так, я забув їх видалити, коли у мене виникли проблеми
TFeld


3

R , 134 132 123 байт

function(S,n,s=sample)for(k in utf8ToInt(S)){o=k+!1:n
P=s(n,1)
o[-P]=s(c(P[i<-P>1],s(17:42,n-1-i,T)))+48
cat(intToUtf8(o))}

Спробуйте в Інтернеті!

Бере великі літери.

Пояснення старого коду (переважно той самий підхід):

function(S,n){s=sample				# alias
K=el(strsplit(S,""))				# split to characters
o=1:n						# output array
for(k in K){					# for each character in the string
P=s(n,1)					# pick a Position for that character
o[-P]=						# assign to everywhere besides P:
      s(					# a permutation of:
	c(P[i<-P>1],				# P if it's greater than 1
		s(letters,n-1-i,T)))		# and a random sample, with replacement, of lowercase letters
o[P]=k						# set k to position P
cat(o,sep="")}}					# and print

2

Java (JDK) , 193 байт

s->n->s.flatMap(c->{int a[]=new int[n],i=n,x=0;for(;i-->0;)a[i]+=Math.random()*26+97;a[i+=Math.random()*n+1]=c;x+=Math.random()*~-n;if(i>0)a[x<i?x:x+1]=48+i;return java.util.Arrays.stream(a);})

Спробуйте в Інтернеті!

  • Індекс заснований на 0.
  • Цей запис використовує IntStream(отриманий через String::chars) як вхід, а також число та повертає інше IntStream.
  • Касти з doubleдо intне потрібні через +=злом.

2

Japt , 29 байт

;£=VöJ;CöV hUÎX hUÅÎUÎ?UÎs:Cö

Спробуйте в Інтернеті!

Нульова індексація.

Пояснення:

;                                :Set C = [a...z]
 £                               :For each character of the input:
  =VöJ;                          : Get two different random indexes from [0,length)
       CöV                       : Get 5 random letters
           hUÎX                  : Replace one at random with the character from the input
                hUÅÎ             : Replace a different random character with:
                    UÎ?          :  If the input character was not placed at 0:
                       UÎs       :   The index of the input character
                          :      :  Otherwise:
                           Cö    :   A random letter
                                 :Implicitly join back to a string

2

C, 115 байт

g(_,n)char*_;{int i=rand(),j=i%~-n,k=0;for(i%=n;k<n;k++)putchar(k-i?!i|i<k^k-j?rand()%26+97:48+i:*_);*++_&&g(_,n);}

Спробуйте в Інтернеті!

0-індексований, малий регістр.

Трохи неозорений і розширений:

g(char*_,int n) {
    int i = rand(), j = i%(n-1), k = 0;
    for(i = i%n; k<n; k++)
        putchar(k!=i ? i!=0 || k==j + (k>i)
                          ? rand()%26 + 'A'
                          : i + '0')
                    : *_);
    if (*++_!=0) g(_,n);
}

Код повинен бути досить простим. Два рандеми i, jзгенеровані за один rand()виклик, гарні як незалежні, оскільки gcd ( n, ~-n) = 1 і RAND_MAXвеликий.


1
Ласкаво просимо до PPCG! :)
Shaggy

1

Чисто , 256 байт

import StdEnv
s::!Int->Int
s _=code {
ccall time "I:I"
ccall srand "I:I"
}
r::!Int->Int
r _=code {
ccall rand "I:I"
}
$n|s 0<1#k=map\e.r e rem n
=flatten o map\c.hd[map(\i|i==x=c=toChar if(i==y&&x>0)(x+48)(r i rem 26+97))[0..n-1]\\x<-k[0..]&y<-k[0..]|x<>y]

Спробуйте в Інтернеті!

Вибір:

  • випадковий x(положення символу в сегменті)
  • випадковий, yякий не дорівнює x(позиція цифри у відрізку)
  • випадкова мала літера для кожної позиції, не дорівнює xі не дорівнює, yякщо не дорівнює xнулю

1

JavaScript, 134 байти

l=>w=>w.replace(/./g,c=>eval("for(s=c;!s[l-1]||s[t?t-1||9:0]!=c;t=s.replace(/\\D/g,''))s=(p=Math.random()*36**l,p-p%1).toString(36)"))

Спробуйте в Інтернеті!

Ця відповідь рівномірно вибрала кодований рядок з усіх можливих кодованих рядків. Тож більш можливо зробити кодований лист як перший.


1

C # (Visual C # Interactive Compiler) , 171 байт

s=>n=>{var r=new Random();return s.SelectMany(c=>{int i=r.Next(n),j=r.Next(n-1);j+=j<i?0:1;return new int[n].Select((_,k)=>(char)(i==k?c:j==k&i>0?i+49:r.Next(26)+97));});}

Спробуйте в Інтернеті!

Пояснення ...

// s is the input string
// n is the input length
s=>n=>{
  // we need to create an instance
  // of Random and use throughout
  var r=new Random();
  // iterate over s, each iteration
  // returns an array... flatten it
  return s.SelectMany(c=>{
    // i is the position of the letter
    // j is the position of the number
    int i=r.Next(n), j=r.Next(n-1);
    // ensure i and j are different
    j+=j<i?0:1;
    // create an iterable of size n
    return new int[n]
      // iterate over it with index k
      .Select((_,k)=>(char)(
        // return the letter
        i==k?c:
        // return the number
        j==k&i>0?i+49:
        // return a random letter
        r.Next(26)+97)
      );
  });
}

1

Вугілля деревне , 35 30 байт

NθFS«≔‽θη≔∧η‽Φθ⁻κηζFθ≡κζIηηι‽β

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. 0-індексований. Пояснення:

Nθ

Введіть довжину.

FS«

Введіть слово та петлю над символами.

≔‽θη

Виберіть випадкову позицію для розшифрованої літери.

≔∧η‽Φθ⁻κηζ

Виберіть іншу випадкову позицію для цифри, за винятком випадків, коли літера знаходиться в положенні 0, і в цьому випадку цифру також поставте в позицію 0.

Fθ≡κ

Обведіть один раз за кожний вихідний символ і увімкніть положення.

ζIη

Якщо це позиція цифри, тоді виведіть позицію розшифрованої літери.

ηι

Але якщо це положення розшифрованої літери, тоді виведіть лист. Це має перевагу над позицією цифри, оскільки вугілля приймає останній запис, якщо кілька випадків комутації мають одне значення.

‽β

Інакше виведіть випадкову літеру.


0

05AB1E , 26 байт

ε²Ý¨Ω©A.r²£Šǝ®Āi®²Ý¨®KΩǝ]J

0-індексований.

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

ε            # Map over the characters of the first (implicit) input-string:
 ²Ý¨         #  Create a list in the range [0, second input)
    Ω        #  Get a random item from this list
     ©       #  Store it in the register (without popping)
 A           #  Push the lowercase alphabet
  .r         #  Shuffle it
    ²£       #  Leave only the first second input amount of characters
      Š      #  Triple swap, so the stack order becomes:
             #  random index; random string; map-character
       ǝ     #  Insert the map-character at this random index into the random string
 ®Āi         #  If the random index was NOT 0:
    ®        #   Push the random index
    ²Ý¨      #   Push the list in the range [0, second input) again
       ®K    #   Remove the random index from this list
         Ω   #   Get a random item from this list
          ǝ  #   Insert the first random index at the second random index into the string
]            # Close both the if-else and map
 J           # Join all strings together (and output implicitly)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.