Двоичное шифрование


11

Это основано на xkcd # 153 .

Создайте программу или именованную функцию, которая принимает 2 параметра, каждый из которых является строкой или списком или массивом байтов или символов. Второй параметр будет содержать только символы, взятые из lrfu(или эквивалентных байтов ASCII). Его следует интерпретировать как последовательность инструкций, которые должны выполняться над битовой последовательностью, представленной первым параметром.

Выполняемая обработка должна быть эквивалентна следующей:

  1. Преобразуйте первый параметр в одну цепочку битов, сформированную путем объединения битов каждого символа (интерпретируемых как один из 7-битного ASCII, 8-битного расширенного ASCII или стандартного кодирования Unicode). Например, если первый параметр, "AB"то это будет один из 10000011000010(7-битный), 0100000101000010(8-битный или UTF-8) 00000000010000010000000001000010или 01000001000000000100001000000000(UTF-16 в двух порядковых номерах) и т. Д.
  2. Для каждого символа во втором параметре по порядку выполните соответствующую инструкцию:
    • lвращает цепочку битов влево. Например 10000011000010становится 00000110000101.
    • rвращает правую цепочку. Например 10000011000010становится 01000001100001.
    • fпереворачивает (или инвертирует) каждый бит в цепочке битов. Например 10000011000010становится 01111100111101.
    • uменяет цепочку битов Например 10000011000010становится 01000011000001.
  3. Преобразуйте цепочку битов в строку ASCII, которая использует один символ на бит. Например 10000011000010становится "10000011000010". Это связано с тем, что не всем наборам 7/8 битов назначен символ.

Пример (в Python):

>>> f("b", "rfu")
01110011

Он превращается "b"в свое 8-битное двоичное представление ASCII 01100010, поворачивает его вправо ( 00110001), переворачивает каждый бит ( 11001110) и переворачивает его ( 01110011).

гибкость

Другие символы могут быть использованы вместо символов l, r, fи u, но они должны быть четко документированы.

Табло

Спасибо @Optimizer за создание следующего фрагмента кода. Для использования нажмите «Показать фрагмент кода», прокрутите вниз и нажмите «► Выполнить фрагмент кода».


3
Каким может быть второй параметр? Это может быть "rrfrburb"? Кроме того, когда кто-то сдвигает или меняет биты, делает ли он это для каждой отдельной буквы или для строки в целом? Чем больше тестов, тем яснее.
xnor

1
Вы имеете в виду сдвиг или поворот? левое смещение в C приведет к потере самого левого бита, а самый правый бит станет равным нулю. Для смены прав на число без знака происходит обратное. Для числа со знаком я не уверен, существует ли универсально определенное поведение для того, что сдвигается для отрицательных чисел (это 0 или 1?). В любом случае, при смене информация всегда теряется, что не так. для поворота.
Уровень Река Сент


2
@flawr, я не думаю, что это будет иметь какое-либо преимущество по сравнению с существующей способностью поиска 'xkcd'
Питер Тейлор

1
@KSFT Я думаю, мне придется сказать нет. Сделайте это строкой, присоединившись к нему.

Ответы:


1

CJam, 34 32 байта

1l+256b2b1>l{~"11W:mm%!<>">4%~}/

Он использует следующие символы для инструкций:

0: left rotation
1: right rotation
2: reverse
3: flip

Ввод осуществляется из STDIN со словом в первой строке и строкой инструкции во второй строке.

Проверьте это здесь.

объяснение

Чтобы получить битовую строку, нужно просто интерпретировать коды символов как цифры числа с базовым 256 (и получить его представление с базовым 2). Хитрость заключается в том, что последнее базовое преобразование не дополнит результат нулями слева. Поэтому я добавляю начальную 1 к начальному входу, а затем снова разделяю эту 1 в двоичном представлении. В качестве примера, если входные данные есть ab, я превращаю их в массив [1 'a 'b]и интерпретирую их как base-256 (символы автоматически преобразуются в коды символов), то есть 90466и в base-2, то есть [1 0 1 1 0 0 0 0 1 0 1 1 0 0 0 1 0]. Теперь, если я просто уберу это лидерство, 1у меня будет поток битов, который я ищу.

Вот что делает эта часть кода:

1l+256b2b1>

Теперь я читаю список инструкций и выполняю блок для каждого символа в строке инструкций:

l{...}/

Первое , что нужно сделать , это оценить характер и действительные целые числа 0, 1, 2или 3. Теперь настоящая магия гольфа ... в зависимости от инструкции, я хочу запустить небольшой фрагмент кода, который реализует операцию:

Integer:  Code  Operation
0         1m<   "Left rotation";
1         1m>   "Right rotation";
2         W%    "Reverse";
3         :!    "Flip each bit";

Я мог бы сохранить их в массиве блоков и выбрать правильный блок для запуска, но кодирование их в строку на самом деле короче:

"11W:mm%!<>">4%~

Во-первых, я использую целочисленную ассоциацию с инструкцией, чтобы вырезать начало строки. Так что для левого вращения строка не изменяется, для правого вращения первый символ отбрасывается и так далее. Затем я выбираю каждый четвертый символ в строке, начиная с первого, с помощью 4%. Обратите внимание, как четыре фрагмента кода распределены по всей строке. Наконец, я просто оцениваю строку как код ~.

Битовая строка печатается автоматически в конце программы.


Почему, 1m<а не (+? Вы работаете над массивом, а не над числом, не так ли?
Питер Тейлор

@ Питер, хорошо, спасибо. Я исправлю это позже.
Мартин Эндер

2

CJam, 34 байта

Еще один подход в CJam.

1l+256b2b1>l_S/,1&@f=_,,@f{W%~}\f=

Вводимый текст находится в первой строке, а инструкции - во второй.

Инструкции:

)        Rotate left.
(        Rotate right.
 (space) Flip.
~        Reverse.

1
Это довольно умно. Позор, который f~не реализован, не так ли? ;)
Мартин Эндер

2

Пиф 33

jku@[+eGPG+tGhG_Gms!dG)sHwsmjCk2z

Область применения:

0    : rotate right
1    : rotate left
2    : reverse order
3    : flip values

Pyth GitHub

Попробуйте это онлайн здесь.

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

AbC
0321

Объяснение:

                                    : z=input() (implicit)
jk                                  : join("", ...)
  u@[                 )sHw          : reduce(select from [...] the value at int(H), input(), ...)
     +eGPG                          : [ G[-1] + G[:1],
          +tGhG                     : G[1:] + G[1],
               _G                   : G[::-1],
                 ms!dG              : map(lambda d: int(not(d)), G) ]
                          smjCk2z   : first arg = sum(map(lambda k:convert_to_base(ord(k),2),z)

Кое-что, что я не мог втиснуть: Pyth reduceавтоматически использует Gдля предыдущего значения и Hдля следующего значения.


Потерять ваше прикосновение? Всего на 1 байт короче, чем CJam?
Оптимизатор

@ Оптимизатор На самом деле, я могу победить, используя те же инструкции. Но я не думал, что это будет правильно, потому что в задании говорится: « Вместо них можно использовать и другие буквыlrfu , но они должны быть четко задокументированы». (выделение мое)
Мартин Эндер

1

Скала - 192

def f(i:String,l:String)=(i.flatMap(_.toBinaryString).map(_.toInt-48)/:l){
case(b,'l')⇒b.tail:+b.head
case(b,'r')⇒b.last+:b.init
case(b,'f')⇒b.map(1-_)
case(b,'u')⇒b.reverse}.mkString

1

Matlab (166 байт)

Это использует буквы abcdвместо lrfuсоответственно.

function D=f(B,C)
D=dec2bin(B,8)';
D=D(:);
g=@circshift;
for c=C
switch c-97
case 0
D=g(D,-1);
case 1
D=g(D,1);
case 2
D=char(97-D);
case 3
D=flipud(D);
end
end
D=D';

Некоторые приемы, используемые здесь для экономии места:

  • Использование abcdбукв позволяет мне вычитать 97один раз, а затем письма стали 0, 1, 2, 3. Это экономит место в switch- caseпунктах.
  • Определение circshiftв качестве однобуквенной анонимной функции также экономит место, так как используется дважды.
  • Поскольку Dсостоит из '0'и '1'символов (ASCII коды 48и 49), утверждение D=char(97-D)соответствует инверсии между '0'и '1'значениями. Обратите внимание, что это не 97имеет ничего общего с тем, что указано выше.
  • Комплексно-сопряженная транспозиция 'используется вместо транспонирования .'.

0

Питон 2 - 179

b="".join([bin(ord(i))[2:]for i in input()])
for i in input():b=b[-1]+b[:-1]if i=="r"else b[1:]+b[0]if i=="l"else[str("10".find(j))for j in b]if i=="f"else b[::-1]
print"".join(b)

0

C #, 418 байт

using System;using System.Collections.Generic;using System.Linq;class P{string F(string a,string o){var f=new Dictionary<char,Func<string,IEnumerable<char>>>{{'l',s=>s.Substring(1)+s[0]},{'r',s=>s[s.Length-1]+s.Substring(0,s.Length-1)},{'u',s=>s.Reverse()},{'f',s=>s.Select(c=>(char)(97-c))}};return o.Aggregate(string.Join("",a.Select(c=>Convert.ToString(c,2).PadLeft(8,'0'))),(r,c)=>new string(f[c](r).ToArray()));}}

отформатирован:

using System;
using System.Collections.Generic;
using System.Linq;

class P
{
    string F(string a, string o)
    {
        // define string operations
        var f = new Dictionary<char, Func<string, IEnumerable<char>>>
        {
            {'l', s => s.Substring(1) + s[0]},
            {'r', s => s[s.Length - 1] + s.Substring(0, s.Length - 1)},
            {'u', s => s.Reverse()},
            {'f', s => s.Select(c => (char) (97 - c))}
        };
        // for each operation invoke f[?]; start from converted a
        return o.Aggregate(
            // convert each char to binary string, pad left to 8 bytes and join them
            string.Join("", a.Select(c => Convert.ToString(c, 2).PadLeft(8, '0'))),
            // invoke f[c] on result of prev operation
            (r, c) => new string(f[c](r).ToArray())
        );
    }
}

0

J, 164

([: >@:}. (([: }. >&{.) ; >@:{.@:>@:{. 128!:2 >@:}.)^:({.@:$@:>@:{.))@:(>@:((<;._1 ' 1&|."1 _1&|."1 -. |."1') {~ 'lrfu' i. 0&({::)@:]) ; ;@:([: (8$2)&#: a. i. 1&({::)))

отформатирован:

nextop=:([: }. >&{.)
exec=: (>@:{.@:>@:{.) apply"1 >@:}.
times=: ({.@:$@:>@:{.)
gapply=: [: >@:}. (nextop ; exec)^:(times) f.

tobin=: ;@:([: (8#2)&#:(a.i.1&{::))
g=:'1&|.';'_1&|.';'-.';'|.'
tog =:  g {~ ('lrfu' i. 0&{::@:])
golf=: gapply @: (>@:tog;tobin)  f.

пример

golf ('rfu';'b')
0 1 1 1 0 0 1 1


golf ('lruuff';'b')
0 1 1 0 0 0 1 0

(8#2)#: 98
0 1 1 0 0 0 1 0

golf ('lruuff';'AB')
0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0

tobin '';'AB'
0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0

0

JavaScript (E6), 163 167

Полностью используя гибкость ввода, именованная функция с 2 параметрами массива.

  • Первый параметр, массив байтов, соответствующих 7-битным кодам символов
  • Второй параметр, массив байтов, соответствующих символам ascii 'F', 'L', 'R', 'U' -> 70, 76, 82, 85

Функция возвращает символьную строку, состоящую из '1' и '0'

F=(a,s,r='')=>
  a.map(c=>r+=(128|c).toString(2).slice(-7))-
  s.map(c=>a=c<71?a.map(c=>1-c):c<77?a.concat(a.shift):c<83?[a.pop(),...a]:a.reverse(),a=[...r])
  ||a.join('')

Пример f("b", "rfu") перевода на F([98],[82,70,85]), результат0111001

Обратите внимание, что использование символьных строк намного длиннее в JavaScript! Количество байт 186

F=(a,s,r='')=>
  [for(c of a)r+=(128|c.charCodeAt()).toString(2).slice(-7)]-
  [for(c of(a=[...r],s))a=c<'G'?a.map(c=>1-c):c<'M'?a.concat(a.shift):c<'S'?[a.pop(),...a]:a.reverse()]
  ||a.join('')

Пример F("b", "RFU") , результат 0111001снова


0

Рубин, 151

f=->i,s{s.chars.inject(i.unpack("B*")[0]){|a,c|
a.reverse! if c==?u
a.tr!"01","10" if c==?f
a<<a.slice!(1..-1) if c==?l
a<<a.slice!(0..-2) if c==?r
a}}

Довольно просто. Зацикливает персонажей sи выполняет действие для любого из них.


0

Python 2, 142

j="".join
f=lambda S,I:reduce(lambda s,i:[s[1:]+s[0],s[-1]+s[:-1],s[::-1],j([`1^int(c)`for c in s])][int(i)],I,j([bin(ord(c))[2:]for c in S]))

Аналогично моему подходу к ответу на Pyth: я строю список всех строк и индексирую в нем, основываясь на значении строки инструкции, которую я перебираю с помощью метода Reduce.

Область применения:

0  ->  Rotate left
1  ->  Rotate right
2  ->  Reverse order
3  ->  Invert bits
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.