대각선 굴레-휠러 변환을 해결


11

소개

이 도전에서 당신은 대각선 Burrows-Wheeler 변환을 해결할 것입니다. 다음은 대각선 Burrows-Wheeler 변환의 일반적인 개요입니다. 메시지를 인코딩하려면 먼저 메시지 길이가 홀수임을 보장해야합니다 (예 : 5, 7, 9 등). 그런 다음, 격자를 만들기 nn하는 경우, n메시지의 길이입니다. 첫 번째 행은 원본 메시지입니다. 그 뒤의 각 행은 그 위의 행이지만 첫 번째 문자가 뒤로 이동하면서 1 문자 왼쪽으로 이동했습니다. 예를 들면 다음과 같습니다.

Hello World
ello WorldH
llo WorldHe
lo WorldHel
o WorldHell
 WorldHello
WorldHello 
orldHello W
rldHello Wo
ldHello Wor
dHello Worl

그런 다음 NW에서 SE 대각선으로 각 문자를 가져 와서 새 문자열에 넣으십시오.

Hello World  H
ello WorldH  l
llo WorldHe  o
lo WorldHel  W
o WorldHell  r
 WorldHello  d
WorldHello   e
orldHello W  l
rldHello Wo  (space)
ldHello Wor  o
dHello Worl  l

인코딩 된 메시지는 HloWrdel ol입니다. 디코딩하려면 먼저 인코딩 된 메시지의 길이를 취하고 1을 더한 다음 2로 나눕니다 x. 이 번호를 호출 할 수 있습니다. 이제 x첫 글자부터 시작하여 각 글자는 x마지막 글자 다음에 반복됩니다. 예를 들면 다음과 같습니다.

H   l   o   W   r   d   e   l     o   l
1   

Then...

H   l   o   W   r   d   e   l     o   l
1                       2

And again...

H   l   o   W   r   d   e   l     o   l
1   3                   2

Until you get...

H   l   o   W   r   d   e   l       o   l
1   3   5   7   9  11   2   4   6   8  10

이제 문자를 올바른 순서로 다시 정렬하십시오 Hello World!

도전

두 가지 프로그램, 기능 또는 각각 하나를 작성해야합니다. 그러나 둘 다 동일한 언어를 사용해야합니다. 첫 번째 프로그램은 STDIN, 프로그램 인수 또는 함수 매개 변수를 통해 문자열을 입력으로 받아이 메소드를 사용하여 인코딩 합니다. 두 번째 프로그램은 STDIN, 프로그램 인수 또는 함수 매개 변수를 통해 문자열을 입력으로 받아 들여이 메소드를 사용하여 디코딩 합니다.

요구 사항

첫 번째 프로그램 / 기능

  • 위에 나열된 방법을 사용하는 단일 문자열 입력
  • 대각선 Burrows-Wheeler 변환 스타일을 사용하여 문자열을 인코딩해야합니다.

두 번째 프로그램 / 기능

  • 위에 나열된 방법을 사용하는 단일 문자열 입력
  • 대각선 Burrows-Wheeler 변환 스타일을 사용하여 문자열을 디코딩해야합니다.

제약

  • 이 작업을 수행하는 내장 또는 외부 기능을 사용할 수 없습니다.
  • 표준 허점은 허용되지 않습니다.
  • 두 프로그램 / 기능 모두 동일한 언어로되어 있어야합니다.

채점

이것은 코드 골프이므로 바이트 단위의 가장 짧은 프로그램이 이깁니다.

더 많은 정보를 추가해야한다면 의견을 남겨주세요!


2
짝수 길이의 입력 문자열을 홀수 길이로 변환해야합니까?
Optimizer

5
이것은 Burrows-Wheeler 변형이 아닙니다.
FUZxxl

3
Burrows-Wheeler 변환은 마지막 항목을 가져 오기 전에 모든 회전 배열이 사전 순으로 정렬된다는 점에서 다릅니다.
FUZxxl

@Optimizer 필요하지 않습니다.
GamrCorps

답변:


12

CJam, (4 + 8 =) 12 바이트

인코딩 프로그램 :

q2/z

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

디코딩 프로그램 :

q_,2/)/z

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

그들이 어떻게 작동하는지 (또는 오히려 왜) :

Diagonal Burrows-Wheeler 변환은 기본적으로 문자열의 다른 모든 문자이며 끝에서 줄 바꿈됩니다. 문자열을 2 열의 2D 행렬로 취급하면 행렬 변환으로 간단히 요약됩니다. 예:

Hello World

2D 매트릭스로 표현

He
ll
o 
Wo
rl
d

이제 열을 현명하게 읽으면 다음과 같이하십시오.

HloWrdel ol

Burrows-Wheeler 변환입니다.

디코딩은 단순히 프로세스의 반대이며 문자열을 2 행 2D 행렬로 쓰고 열을 현명하게 읽습니다.

코드 확장 :

인코더 :

q          "Read the input";
 2/        "divide it into sub arrays of 2 characters";
   z       "Take transform";

디코더 :

q_,        "Read the input, take copy and get length of copy";
   2/      "Divide the length by 2";
     )/    "Increment and split the input into two rows";
       z   "Take transform";

7

파이썬 2, 61 바이트

E=lambda x:x[::2]+x[1::2]
D=lambda y:(-~len(y)/2*y)[::len(y)/2+1]

E암호화하고 D해독합니다. 나는 계산 아니에요 E=D=점수합니다.

해독은 문자열 길이의 절반이 반올림 n되는 모든 문자를 n감 쌉니다. 이유는이 반전이 있다는 것입니다 2n역함수 그렇게 매일 복용, 문자열의 길이를 모듈로하는 n모든 복용 번째 문자 반전 2차를.

단일 기능을 사용할 수 있다면 44 바이트를 할 수 있습니다

def F(x,b):n=1+len(x)**b>>b;return(n*x)[::n]

를 암호화 때 b입니다 False때 해독 b입니다 True. 식은 1+len(x)**b>>b입니다 [2,len(x)/2+1][b].


4

J, 10 + 10 = 20

   ({~#|2*i.@#) 'Hello World'
HloWrdel ol

   (/:#|2*i.@#) 'HloWrdel ol'
Hello World

(주위 괄호는 함수 정의의 일부가 아니므로 점수에 포함되지 않습니다.)

3 바이트 개선을 위한 FUZxxl 에 감사합니다 .

이제 첫 #|2*i.@#번째 함수는 목록에 의해 정의 된 위치에서 문자를 가져 오고 두 번째 함수는 순서와 동일한 목록을 사용하여 문자를 다시 정렬하므로 두 함수는 역함을 알 수 있습니다.

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


첫 번째는 10 자로도 가능합니다 : {~#|2*i.@#.
FUZxxl

@FUZxxl 감사합니다. 이제 두 기능 간의 관계가 정말 훌륭하게 표시됩니다.
randomra

3

Pyth-5 + 11 = 16 바이트

패턴이 나타났습니다! ~ 행복한 춤을 추세 요 ~ 변형은 단지 다른 모든 요소를 ​​고르는 현을 통해 반복됩니다. 그렇지 않으면 요소의 절반을 얻지 않기 때문에 홀수에서만 작동합니다. 이것은 2 와이드 매트릭스를 회전시키는 것과 같습니다.

인코더 :

%2*2z

파이썬의 단계 슬라이싱은 반복되지 않으므로 문자열을 반복했습니다.

%2      Take every other elements
 *2z    Double input string

디코더 :

K/hlz2%K*Kz

다시 스텝 슬라이싱을위한 랩 어라운드가 없습니다.

K/hlz2       K=length of (input+1)/2
%K           Every kth element
 *Kz         From K*the input

@FryAmTheEggman 나는 홀수 길이의 문자열 만 가져야한다고 확신합니다. 설명의 시작 부분에있었습니다.
Maltysen

앗 미안 해요. : S
FryAmTheEggman

2

GNU sed -r, (20 + 104 + 1) = 125

점수에서 추가 +1은 -r 옵션을 사용하는 것입니다. 홀수 길이 입력 문자열이 가정됩니다.

인코더 :

s/.*/&&/
s/(.)./\1/g
  • 입력 문자열을 두 배로
  • 모든 홀수 (1부터 계산)를 삭제

디코더 :

디코더는 :임시 마커 문자로 사용하므로 입력 문자열에 표시되면 정의되지 않은 동작이 발생합니다. 입력 문자열이 95 ASCII 문자로 제한되는 경우 이러한 마커를 ASCII 범위를 벗어난 것으로 바꿀 수 있습니다 (예 : BEL 0x7).

s/.*/:&:/
:l;s/:(.)(.+)(.):/\1:\2:\3/;tl
s/:(.*)/\1:/
:m;s/(.)(.*):(.?)(.*):(.*)/\2:\4:\5\1\3/;tm
s/://g
  • :입력 문자열의 시작과 끝에 마커를 넣 습니다.
  • 제 셔플 :순방향 및 제 :때까지 한 번에 하나의 역방향 문자 :마커 중간 문자 양쪽있다
  • 첫 번째를 제거하고 "A : B :"를 남기고 끝에 :다른 :것을 추가 하십시오. 여기서 A는 일반 텍스트 입력에서 홀수 문자로 구성된 문자열이고 B는 짝수 문자로 구성된 문자열입니다.
  • :평문 입력을 다시 어셈블하기 위해 마지막에 A와 B의 문자를 리플 링하십시오.
  • 남은 :마커를 제거

2

자바 스크립트 ES6, 41 + 49 = 90 바이트

엔코더

(t=>t.replace(/./g,(_,o)=>t[o*2%t.length]))('Hello World')

디코더

(t=>t.replace(/./g,(_,o)=>t[-~(l=t.length)/2*o%l]))('HloWrdel ol')

이들은 익명 함수이므로 전체 함수 정의이므로 괄호 안의 코드 만 계산합니다. 아래의 스 니펫으로 사용해보십시오. (ES5를 사용하도록 수정)


이건 [t=>t.replace(/./g,(_,o)=>t[o*2%t.length]),t=>t.replace(/./g,(_,o)=>t[(1+(l=t.length))/2*o%l])]어때요? 당신처럼 사용 [...][0]('encode string')하고 [...][1]('decode string'). 이것이 불가능하다는 말은 없습니다! 그리고 당신은 1 바이트를 저장합니다.
Ismael Miguel

고마워, bu는 2 개의 함수를 작성한다고 말하지만 이것이 중요하지 않다고 생각합니다.
NinjaBearMonkey

그것은 여전히 ​​2 가지 기능입니다. 규칙은 기능에 액세스하는 이름이나 방법을 지정하지 않습니다. 단지 두 가지 기능을 사용해야한다고 말합니다.
Ismael Miguel

1
@IsmaelMiguel 이제 그것에 대해 생각하기 때문에 익명 함수가 스스로 허용된다고 생각하므로 더 많은 바이트를 절약 할 수 있습니다.
NinjaBearMonkey

바이트 수를 줄이면 기쁩니다.
Ismael Miguel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.