이진 암호화


11

이것은 xkcd # 153을 기반으로 합니다.

2 개의 매개 변수를 갖는 프로그램 또는 명명 된 함수를 작성하십시오. 각 매개 변수는 문자열 또는 바이트 또는 문자의 목록 또는 배열입니다. 두 번째 매개 변수에는 문자 lrfu(또는 동등한 ASCII 바이트) 만 사용됩니다. 첫 번째 매개 변수로 표시되는 비트 시퀀스에서 수행되는 일련의 명령으로 해석되어야합니다.

수행되는 처리는 다음과 같아야합니다.

  1. 첫 번째 매개 변수를 각 문자의 비트를 연결하여 형성된 단일 비트 열로 변환하십시오 (7 비트 ASCII, 8 비트 확장 ASCII 또는 표준 유니 코드 인코딩 중 하나로 해석 됨). 첫 번째 변수 인 경우 예 "AB"다음이 중 하나가 될 것이다 10000011000010(7 비트) 0100000101000010(8 비트 또는 UTF-8) 00000000010000010000000001000010또는 01000001000000000100001000000000(UTF-16에서 두 endian을) 등
  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이됩니다. 부호없는 숫자를 오른쪽으로 이동하면 반대가 발생합니다. 부호가있는 숫자의 경우 음수로 이동되는 항목에 대해 보편적으로 정의 된 동작이 있는지 확실하지 않습니다 (0 또는 1입니까?) 어느 쪽이든, 이동이 수행 될 때 정보가 항상 손실됩니다. 회전합니다.
레벨 리버 St


2
@flawr, 나는 그것이 'xkcd'
Peter Taylor

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 표현을 얻는 것입니다. 까다로운 것은 후자의 기본 변환이 결과를 왼쪽에 0으로 채우지 않는다는 것입니다. 따라서 초기 입력에 선행 1을 추가 한 다음 이진 표현에서 1을 다시 분리합니다. 예를 들어, 입력이 ab이면 배열로 바꾸고 [1 'a 'b]base-256 (문자는 자동으로 문자 코드로 변환 됨), 즉 90466base-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<아니라 (+? 숫자가 아닌 배열을 작업하고 있습니까?
피터 테일러

@ 피터 오, 고마워. 나중에 고칠 게요.
Martin Ender 2019

2

CJam, 34 바이트

CJam의 또 다른 접근법.

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

입력 텍스트는 첫 번째 줄에 있고 지침은 두 번째 줄에 있습니다.

명령:

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

1
이것은 꽤 영리합니다. f~아직 구현되지 않은 수치심이 아닌가? ;)
Martin Ender 2016 년

2

피스 33

jku@[+eGPG+tGhG_Gms!dG)sHwsmjCk2z

용도 :

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

피 티스 깃 허브

여기에서 온라인으로 사용해보십시오.

이것은 문자열을 첫 번째 인수로 사용하고 명령 문자열을 두 번째 인수로 사용하는 프로그램입니다. 온라인 버전에서는 다음과 같이 문자열을 개행으로 구분해야합니다.

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다음 값을 사용합니다.


당신의 터치를 잃어버린? CJam보다 1 바이트 더 짧은?
Optimizer

@Optimizer 사실, 같은 지침을 사용하여 이길 수 있습니다. 그러나 도전 과제에 "다른 문자 가 대신 사용될 수 lrfu있지만 명확하게 문서화되어야 "하기 때문에 이것이 유효하지 않다고 생각했습니다 . (강조 광산)
Martin Ender

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 코드 4849) 문 D=char(97-D)사이의 반전에 대응을 '0'하고 '1'값. 이것은 97위에서 언급 한 것과 관련이 없습니다.
  • transpose '대신 complex-conjugate transpose 가 사용됩니다 .'.

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

자바 스크립트 (E6), 163167

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

참고 자바 스크립트에 너무 긴 문자열을 사용! 바이트 수 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

파이썬 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.