Розв’яжіть діагональну трансформацію Берроса-Уілера


11

Вступ

У цьому виклику ви вирішите діагональні перетворення Берроу-Уілера. Ось загальний огляд того, що таке діагональна трансформація Берроса-Уілера. Щоб кодувати повідомлення, спочатку ви повинні гарантувати, що воно має непарну довжину (тобто 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, аргументи програми або параметри функції та декодує її за допомогою цього методу.

Вимоги

Перша програма / функція

  • Введення одного рядка, використовуючи будь-який метод, перерахований вище.
  • Повинно кодувати рядок, використовуючи діагональний стиль перетворення Берроуса-Уілера.

Друга програма / функція

  • Введення одного рядка, використовуючи будь-який метод, перерахований вище.
  • Потрібно розшифрувати рядок, використовуючи діагональний стиль перетворення Burrow-Wheeler.

Обмеження

  • Ви не можете використовувати будь-які вбудовані або зовнішні функції, які виконують це завдання.
  • Стандартні лазівки заборонені.
  • Обидві програми / функції повинні бути однаковою мовою.

Оцінка балів

Це кодовий гольф, тому найкоротша програма в байтах виграє.

Якщо мені потрібно додати більше інформації, залиште коментар!


2
Чи потрібно перетворювати вхідний рядок парної довжини в непарну довжину?
Оптимізатор

5
Це не перетворення Бурроу-Уілера.
FUZxxl

3
Перетворення Берроуса-Уілера відрізняється тим, що масив усіх обертів сортується лексикографічно перед тим, як взяти останні елементи.
FUZxxl

@Optimizer не обов’язково.
GamrCorps

Відповіді:


12

CJam, (4 + 8 =) 12 байт

Програма кодування:

q2/z

Спробуйте його онлайн тут

Програма декодування:

q_,2/)/z

Спробуйте його онлайн тут

Як (точніше, навіщо) вони працюють :

Перетворення Діагональних Бурроу-Уіллера - це в основному кожен інший символ струни, з обгортанням з кінця. Якщо ми розглянемо String як 2D матрицю з 2 стовпців, вона просто зводиться до прийняття перетворення матриці. Приклад:

Hello World

Представлена ​​у вигляді 2D матриці як

He
ll
o 
Wo
rl
d

Тепер, просто прочитавши стовпець мудро, дайте:

HloWrdel ol

Яка трансформація Берроуз-Вілер.

Розшифровка - це просто зворотний процес, запишіть рядок як дворядну 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

Python 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

(Навколишні дужки не враховуються в рахунок, оскільки вони не є частиною визначення функції.)

Дякуємо FUZxxl за покращення в 3 байти.

Тепер добре показано, що обидві функції є зворотними, оскільки перша займає символи з позицій, визначених списком, #|2*i.@#а друга функція впорядковує символи, використовуючи той самий список, як впорядкування.

Спробуйте його онлайн тут.


Перші з них можуть бути зроблені в 10 символів , а також: {~#|2*i.@#.
FUZxxl

@FUZxxl Дякую, оновлено. Тепер відношення між двома функціями показано дійсно добре.
randomra

3

Pyth - 5 + 11 = 16 байт

Я помітив візерунок! ~ Чи щасливий танець ~ Перетворення просто насправді просто перебирає струну, підбираючи всі інші елементи. Він працює лише на дивні, оскільки в іншому випадку він ніколи не отримає половину елементів. Це еквівалентно обертанню 2 широкої матриці.

Кодер:

%2*2z

Крок нарізки Python не крутиться навколо, тому я повторив рядок.

%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 Я майже впевнений, що він повинен мати лише рядки непарної довжини. Це було на початку опису.
Мальтісен

На жаль, вибачте. : S
FryAmTheEggman

2

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

Додатковий +1 у балі - для -r варіант sed. Припускаються вхідні рядки непарної довжини.

Кодер:

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

JavaScript 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 байт.
Ісмаїл Мігель

Дякую, але це говорить, щоб написати 2 функції, і я не думаю, що це буде рахувати.
NinjaBearMonkey

Це ще 2 функції. Правила не визначають імена та способи доступу до функцій. Це говорить лише про те, що ви повинні використовувати 2 функції.
Ісмаїл Мігель

1
@IsmaelMiguel Тепер, коли я замислююся над цим, я думаю, що анонімні функції дозволені самі собою, тому використання цього рятує мені ще більше байтів.
NinjaBearMonkey

Я радий, що ви скоротили кількість байтів.
Ісмаїл Мігель
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.