Реалізуйте цей ключовий шифр


13

Реалізуйте цей ключовий шифр

Мета

Використовуйте алгоритм (пояснений у розділі Алгоритм) для реалізації певного шифру.

Програма повинна зчитувати вхід з STDIN або найближчого доступного еквівалента, використовувати алгоритм для генерації шифротексту та ключа.

Шифротекст і ключ будуть записані в STDOUT або найближчий доступний еквівалент. Дозволений будь-який формат, доки він видає шифротекст і ключ.

Алгоритм

Перетворіть символи в рядку у відповідні значення ASCII. Наприклад:

Hello -> 72 101 108 108 111

Далі вам потрібно буде згенерувати ключ до тих пір, як рядок із випадковими числами в діапазоні 0-9.

Hello -> 62841

Додайте цілі числа у послідовності випадкових чисел до значень ASCII рядка. У наведених вище прикладах 72 стали б 78, а 101 - 104.

72 + 6 = 78, 101 + 2 = 103, 108 + 8 = 116, etc

Далі конвертуйте нові значення назад у символи. У наведених вище прикладах текст Helloстав Ngtpp.

Приклади

(Це просто приклади того, як може виглядати вихід. Вихід може і змінюватись.)

Hello World

Lfrlu)_supg
41606984343

This will be encoded

Zhjs$~koo gj$iuhofgj
60104723305544750226

Правила

  • Можна припустити, що вхід буде містити лише символи в діапазоні az, AZ та пробілах.
  • Подання повинні бути повноцінними програмами або функціями.
  • Подання будуть оцінені в байтах.
  • Стандартні лазівки заборонені.
  • Це код-гольф, тому найкоротший код виграє.

(Це одна з моїх перших проблем: якщо з цим щось не так, сміливо скажіть, як я міг би це покращити.)


5
Цей виклик мені добре виглядає, за винятком пари думок. 1. Чи дозволена функція замість повної програми? Пов'язане запитання: чи можна повернути значення замість друкованих? 2. Ви сказали, що preferably with the format (ciphertext)\n(key)."бажані функції" та код гольфу не дуже добре поєднуються. Вам слід зробити це обов'язковим або дозволити інші формати виводу. 3. Чи потрібно друкувати ключ без пробілів? Що з друком у форматі списку, наприклад [0, 5, 2, ...]?
Джеймс

Чи може ключ мати провідні нулі?
TheBikingViking

1
Хороший перший виклик, але я не дуже впевнений у строгому форматі вводу-виводу. Зазвичай функції дозволяються, і зазвичай відповіді можна прочитати з одного з прийнятих методів вводу-виводу. Сюди входить виведення масиву з елементами
Downgoat

1
Чи потрібно створювати цифри ключа при рівномірному розподілі?
Денніс

1
Ага ... 101 + 2 - 103, а не 104. :-)
YetiCGN

Відповіді:


5

Желе , 12 9 байт

⁵ṁX€’Ṅ+OỌ

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

Як це працює

⁵ṁX€’Ṅ+OỌ  Main link. Argument: s (string)

⁵             Set the return value to 10.
 ṁ            Mold; create an array of 10's with the length of s.
  X€          Pseudo-randomly pick a integer between 1 and 10, for each 10.
    ’         Decrement, so the integers fall in the range [0, ..., 9].
     Ṅ        Print the key, as an array, followed by a linefeed.
      +O      Add the integers to the ordinals (code points) of s.
        Ọ     Unordinal; convert back to characters.

5

Python 3, 130 байт

Дякуємо @Rod за вказівку на помилку

from random import*
def f(x):l=10**len(x);k=str(randint(0,l-1)+l)[1:];print(''.join(chr(ord(i)+int(j))for i,j in zip(x,k))+'\n'+k)

Функція, яка приймає введення через аргумент як рядок і друкує в STDOUT.

Як це працює

from random import*  Import everything from the random module
def f(x):            Function with input string x
l=10**len(x)         Define l for later use as 10^length(x)
randint(0,l-1)+l     Generate a random integer in the range [0, l-1] and add l, giving a
                     number with l+1 digits...
k=str(...)[1:]       ...convert to a string and remove the first character, giving a key of
                     length l that can include leading zeroes, and store in k
for i,j in zip(x,k)  For each character pair i,j in x and k:
chr(ord(i)+int(j))    Find the UTF-8 code-point (same as ASCII for the ASCII characters),
                      add the relevant key digit and convert back to character
''.join(...)         Concatenate the characters of the ciphertext
print(...+'\n'+k)    Add newline and key, then print to STDOUT

Спробуйте це на Ideone


ваш генератор ключів не генерує ключі, починаючи з 0. збільшуючи межі в 10 разів і видаляючи першу цифру, слід виправити: m=10**len(x);k=str(randint(m,m*10))[1:];і ви навіть збережете байт у процесі c:
Rod

@Rod Дякуємо за вказівку на помилку. Однак це не врятує жодних байтів, оскільки randintце інклюзивно, це означає, що вам потрібно буде зробити m*10-1. Я щойно придумав спосіб виправити це за тим самим числом байтів.
TheBikingViking


3

Власне, 17 байт

;`X9J`M;(O¥♂cΣ@εj

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

Пояснення:

;`X9J`M;(O¥♂cΣ@εj
;                  dupe input
 `X9J`M            for each character in input copy:
  X9J                discard the character, push a random integer in [0, 9]
       ;           duplicate the offset array
        (O         bring input to top of stack, ordinal array
          ¥♂c      pairwise addition with offset array, turn each ordinal into a character
             Σ     concatenate
              @εj  concatenate the copy of the offset array


2

MATL, 13 байт

"10r*]v!kGy+c

Вихід виглядає приблизно так:

9 5 8 2 1
Qjtnp

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

Пояснення:

"    ]          % For each character:
 10             % Push a 10 onto the stack
   r            % Push a random float in [O, 1)
    *           % Multiply. This essentially the same thing as pushing a number in [0, 10)
      v!k       % Join all of these together, and take the floor
         G      % Push the input again
          y     % Duplicate the array of random numbers
           +    % And add these together. Since MATL treats strings as an array of chars, we don't need to explicitly convert types
            c   % Display as string

Я не впевнений, чи це правильний формат ...
Leaky Nun

@Laaky Nun Я трохи змінив правила.
m654

@ m654 Де ти сказав, що між значеннями можуть бути пробіли?
Leaky Nun

@LeakyNun Спочатку було правило проти них, але я його усунув.
m654

1
Гарна ідея використовувати цикл. Це насправді коротше, ніж версія з декількома входами rабоYr
Луїс Мендо

2

PowerShell v2 +, 79 77 байт

param($n)-join(($x=[char[]]$n|%{0..9|Random})|%{[char]($_+$n[$i++])});-join$x

Бере введення $n, перебирає цикл на кожен символ і отримує Randomелемент з 0..9кожної ітерації. Зберігає ці числа (як масив) у $x. Труби, що масив, в інший цикл. Кожна ітерація, приймає поточний елемент $_, додає його до позиційного символу, вирізаного із $n(неявного відтворення char-to-int), після чого повторно відтворює як [char]. Залишає це на трубопроводі. Це інкапсульовано в паренах і -joinразом, щоб утворити слово. Це залишилося на конвеєрі. Крім того, номер $xтакож -joinредагується разом і залишається на конвеєрі. Вони неявно друкуються з а Write-Outputв кінці виконання, що призводить до того, що вони за замовчуванням друкуються новим рядком.

Приклад

PS C:\Tools\Scripts\golfing> .\implement-this-key-cipher.ps1 'Hello World!'
Lhoot(Yt{mf"
433358259121

2

C #, 252 247 245 232 216 байт

Розмір досить поганий порівняно з іншими рішеннями, але все-таки ...

using System;using System.Linq;class p{static void Main(){var c="";var i=Console.ReadLine();var r=new Random();for(int b=0;b++<i.Count();){int d=r.Next(10);Console.Write((char)(i[b]+d));c+=d;}Console.Write("\n"+c);}}

Це моя друга відповідь на кодовий гольф, і я досить початківець, розглядаючи C #, тому я вдячний би почути, як скоротити її :)

Безголівки:

using System;
using System.Linq;

class p
{
    static void Main()
    {
        var c = "";
        var i = Console.ReadLine();
        var r = new Random();
        for (int b = 0; b++ < i.Count();)
        {
            int d = r.Next(10);
            Console.Write((char)(i[b] + d));
            c += d;
        }
        Console.Write("\n" + c);
    }
}
  • Збережено 5 байт завдяки @FryAmTheEggman
  • Збережено 2 байти завдяки @theLambGoat
  • Збережено 7 байт, видаливши staticз класу p
  • Збережено 24 байти завдяки @milk

1
Хитрість полягає в тому, щоб не порівнювати з іншими мовами;) Я не особливо добре розбираюся в C # golf, але чи можете ви зробити b++<i.Count()і залишити третій пункт порожнім? Крім того, я не думаю, що вам не потрібна нова лінія, тому останній дзвінок WriteLineможе бути Writeзамість цього.
FryAmTheEggman

Я також не добре розбираюся в C #, але я думаю, ви можете перемістити = r.Next (10) до декларації d і зберегти на наборі дужок у записі. Або випадковий вибір не повертає int, тому ви не можете цього зробити?
theLambGoat

Я думаю, що я можу це зробити, дозвольте перевірити
Том Дудлер

Ви можете замінити типи на var. тобто var c=замість того, string c=щоб голити кілька байт.
молоко

Чому б не залишити результат у Console.ReadLine()вигляді рядка? i.Lengthкоротше i.Count(), вам не знадобиться System.Linq. рядок має індексатор char. Також об'єкти створення нових випадковий в петлі менше байт: new Random().Next(10).
молоко

2

CJam, 11 байт

Nq{Amr_o+}/

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

Як це працює

N            Push a linefeed on the stack.
 q           Read all input from STDIN and push it on the stack.
  {      }/  For each character in the input:
   Amr       Pseudo-randomly pick an integer in [0 ... 9].
      _o     Print a copy.
        +    Add the integer to the character.
             (implicit) Print the linefeed, followed by the modified characters.

2

05AB1E , 18 17 байт

vžh.RDyÇ+ç`?}J¶?,

Пояснення

v           }      # for each char in input
 žh.RD             # push 2 copies of a random number in [0..9]
      yÇ+          # add 1 copy to the current chars ascii value
         ç`?       # convert to char, flatten and print
             J     # join stack (which contain the digits of the key)
              ¶?,  # print a newline followed by the key

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


2

Python 3, 112 байт

c - функція, яка повертає зашифрований текст та ключ

from random import*
c=lambda t:map(''.join,zip(*[(chr(a+b),str(b))for a,b in((ord(i),randint(0,9))for i in t)]))

Ось код, який робить те саме і трохи читабельніший

def encrypt(text):
    # keep the codes of the letters in the input and a random key
    # that will be used later to encrypt this letter
    letter_and_key = ((ord(letter),randint(0,9)) for letter in text)

    # encrypt the letter and keep the key used as a string
    output_and_key = [(chr(letter_code+key), str(key))
                      for letter_code, key in letter_and_key]

    # At this point the values are kept in the format:
    # [(firstletter, firstkey), (secondletter, secondkey), ...]

    # to reorder the list to be able to output in the format "text key"
    text, key = map(''.join, zip(*output_and_key))

    # same as print(*output_and_key)
    return text, key

Вихід:

>>> text, key = c('Hello World')
>>> print(text, key, sep='\n')
Liuot#`oylk
44935390707

Ласкаво просимо на цей сайт!
Джеймс

1

PHP, 63 86 82 байт

Редагувати: забув надрукувати ключ ...

Дякую Алексу Хованському, що врятував мені 4 байти.

for(;$i<strlen($a=$argv[1]);$s.=$r)echo chr(ord($a[$i++])+$r=rand(0,9));echo"
$s";

Введення задається через аргумент командного рядка. Бере кожен символ у рядку і додає до свого ASCII-коду випадковий int від 0-9, а потім перетворює код назад в ASCII. До кожного додається випадкове число $s, яке друкується в кінці.


Вам також потрібно роздрукувати ключ.
Олексій Хованський

Ви можете помістити $s.=$rпісля 2-го півтора в цикл for, економлячи байт, тому що ви можете скинути його тривалість. Тоді ваш цикл буде лише одним твердженням, щоб ви могли вирізати обгорткові дужки, заощадивши ще 2 байти. Потім в кінці ви можете помістити $sвсередину цитованого рядка, зберігаючи .оператора на ще один байт. :)
Олексій Хованський

@AlexHowansky: Це дуже правда. Спасибі
Ділова кішка

1

J, 32 байти

<@:e,:~[:<[:u:3&u:+e=.[:?[:$&10#

еквівалент пітона:

from random import randint
def encrypt(message):
    rand_list = list(map(lambda x: randint(0, 9), range(len(message))))
    return (''.join(list(map(lambda x,y: chr(x+y), rand_list, map(ord, message)))), rand_list)


0

Perl, 65 байт

for(split'',$ARGV[0]){$;.=$a=int rand 9;$b.=chr$a+ord}say"$b\n$;"

Мені потрібно було деякий час, щоб зрозуміти, як отримати вхід без нового рядка наприкінці. Приймає це як аргумент командного рядка


У вашого рішення є деякі проблеми. Введення не зчитується із форми STDIN, $;не починається порожнім, тому він друкує старий вміст, а rand ніколи не може генерувати 9. Їх легко виправити, а використання STDIN зробить ваш код коротшим :-)
Ton Hospel

@TonHospel Зазвичай вимоги до вводу є невисокими, а аргументи є прийнятними над STDIN, і в той час, коли введення даних від STDIN коротше, необхідність видалення нового рядка з нього робить його довшим. І хоча rand генерує числа <9, метод методу Perl
обводить

Вимоги щодо введення зазвичай є невисокими, але тут цього не було. Отримання нон нового рядка з STDIN легко: <>=~/./g. І ні, intв perl скорочується до 0, він не округлюється. perl -wle 'print int 8.6'Виходи8
Тон Євангелія

0

Python 2, 84 99 байт

def f(x):y=`id(x)**len(x)`[1:len(x)+1];return''.join(map(chr,[ord(a)+int(b)for a,b in zip(x,y)])),y

Використовує id()значення рядка для генерації випадкових чисел.

Спробуй це


Ви повинні вивести ключ, а також шифротекст.
TheBikingViking

@TheBikingViking не знаю, як я це пропустив. Подяка - зафіксовано
атласолог

Я думаю, що це також має ту саму проблему, що і попередня версія моєї відповіді Python; він ніколи не виробляє ключі з провідними нулями.
TheBikingViking

@TheBikingViking Виправлено знову
атласолог

змінити map(chr,[ord(a)+int(b)for a,b in zip(x,y)])на map(lambda x,y:chr(ord(x)+int(y)),x,y)? що має щось врятувати
ljeabmreosn

0

Сенва , 74 байти

Ось найкоротша програма, яку я зробив:

2'(`>0.>{@}0'{v}2-2'0,{@}1'{v}0'{+}{'}9%+{^}{1-}1'"{+}{~}>$10.~0'2+"0,-:>$

Невелике пояснення? (Примітка: BM означає Back-memory ):

// === Input and informations storing ===

2'  // Go to the 3rd cell (the two first will be used to store informations)
(   // Ask the user for a string (it will be stored as a suite of ASCII codes)
`   // Go the end of the string
>   // Make a new cell
0.  // Put a 0 to mark the end of the string
>   // Make a new cell, here will be stored the first random number
{@} // Store its adress in BM
0'  // Go to the 1st cell
{v} // Paste the adress, now the 1st cell contains the adress of the first random number
2-  // Subtract 2 because the string starts at adress 2 (the 3rd cell)
2'  // Go to the 3rd cell (where the string begins)

// === String encryption and displaying ===

0,  // While the current cell doesn't contain 0 (while we didn't reach the string's end)
  {@}  // Store the character's adress into the memory
  1'   // Go to the 2nd cell
  {v}  // Paste the value, now the 1st cell contains the adress of the current char
  0'   // Go to the 1st cell
  {+}  // Add the adress of the first random number to the current char adress
  {'}  // Go to this adrses
  9%+  // A random number between 0 and 10
  {^}  // Store this number in BM
  {1-} // Decrease BM (random number between 0 and 9)
  1'   // Go to the 1st cell
  "    // Go to the adress pointed by the cell (the adress of the current char)
  {+}  // Add it to the random number value
  {~}  // Display it as an ASCII character
  >    // Go to the next cell (the next character)
$   // End of the loop
10. // Set the new line's ASCII code into the current cell (which is now useless, so it can be overwritten)
~   // Display the new line
0'  // Go to the first cell
2+  // Add 2 to the adress, because we are not in the string loop : we cancel the 2 substraction
"   // Go to the pointed adress (the first random number's one)

// === Display the random numbers ===

0,  // While we didn't reach the end of the random numbers suite
    // That was why I stored numbers between 1 and 10, the first equal to 0 will be the end of the suite
  - // Decrease it (number between 0 and 9)
  : // Display the current random number as an integer
  > // Go to the next cell (the next number)
$ // End of the loop

Це здається більшим зараз, правда: p? Можливо, цей код можна оптимізувати, але на даний момент це найкоротше, що я знайшов.


0

C #, 174 байти

using static System.Console;class b{static void Main(){var c=new System.Random();var d="\n";foreach(var e in ReadLine()){var f=c.Next(10);Write((char)(e+f));d+=f;}Write(d);}}

Безголівки:

using static System.Console;

class b
{
    static void Main()
    {
        var c = new System.Random();
        var d = "\n";

        foreach (var e in ReadLine())
        {
            var f = c.Next(10);
            Write((char)(e + f));
            d += f;
        }

        Write(d);
    }
}

Досить прямо, насправді.


0

Perl 6: 55 або 70 байт

Як анонімна функція, яка приймає параметр рядка і повертає список з двох рядків (54 символи, 55 байт) :

{my @n=^9 .roll(.ords);(.ords Z+@n)».chr.join,@n.join}

Як програма, яка читає з STDIN і записує в STDOUT (69 символів, 70 байт) :

my @a=get.ords;my @n=^9 .roll(@a);say (@a Z+@n)».chr.join;say @n.join
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.