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


11

소개

이 도전에서 당신은 대각선 Burrows-Wheeler 변환을 해결할 것입니다. 다음은 대각선 Burrows-Wheeler 변환의 일반적인 개요입니다. 메시지를 인코딩하려면 먼저 메시지 길이가 홀수임을 보장해야합니다 (예 : 5, 7, 9 등). 그런 다음, 격자를 만들기 n로 n하는 경우, 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감 쌉니다. 이유는이 반전이 있다는 것입니다 2및 n역함수 그렇게 매일 복용, 문자열의 길이를 모듈로하는 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.