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


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 Я немного изменил правила.
m654

@ m654 Где вы сказали, что между значениями могут быть пробелы?
Утренняя монахиня

@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 к 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);}}

Это мой второй ответ на Codegolf, и я довольно новичок в рассмотрении C #, поэтому я хотел бы услышать, как сделать его короче :)

Ungolfed:

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 и сохранить набор скобок при записи. Или random не возвращает int, поэтому вы не можете этого сделать?
theLambGoat

Я думаю, что я могу сделать это, позвольте мне проверить
Том Doodler

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

Почему бы не оставить результат в Console.ReadLine()виде строки? i.Lengthкороче i.Count(), вам не понадобится System.Linq. Строка имеет индексатор символов. Также объекты создания новых случайный в петле меньше байт: 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";

Ввод осуществляется через аргумент командной строки. Берет каждый символ в строке и добавляет случайный int от 0-9 к своему ASCII-коду, а затем преобразует код обратно в ASCII. К каждому случайному числу добавляется $s, который печатается в конце.


Вам также необходимо распечатать ключ.
Алекс Ховански

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

@AlexHowansky: Это очень верно. Спасибо
Деловая Кошка

1

J, 32 байта

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

эквивалент Python:

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$;"

Мне потребовалось некоторое время, чтобы понять, как получить ввод без новой строки в конце. Принимает это как командную строку arg


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

@TonHospel Обычно требования к вводу невелики, и аргументы приемлемы по сравнению с STDIN, и хотя ввод данных из STDIN короче, необходимость удаления новой строки из него делает его длиннее. И хотя rand генерирует числа <9, метод Perl int округляет, а не полы, поэтому что угодно> = 8.5 должно заканчиваться как 9
theLambGoat

Входные требования обычно невелики, но здесь это не так. Получение нон новой строки из 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,-:>$

Небольшое объяснение? (Примечание: БМ означает 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);}}

Ungolfed:

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.