Çapraz Burrows-Wheeler dönüşümünü çözme


11

Giriş

Bu meydan okumada çapraz Burrows-Wheeler dönüşümlerini çözeceksiniz. İşte köşegen Burrows-Wheeler dönüşümünün ne olduğuna genel bir bakış. Bir mesajı kodlamak için önce mesajın tek uzunlukta olduğunu garanti etmelisiniz (yani 5, 7, 9 vb.). Sonra, bir ızgara yapmak ntarafından nnerede, nmesajın uzunluğudur. İlk satır orijinal mesajdır. Bundan sonraki her satır, üstündeki satırdır, ancak ilk karakter arkaya hareket ederek 1 karakter sola kaydırılmıştır. Örneğin:

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

Sonra NW to SE diyagonalindeki her harfi alıp yeni bir dizeye koyuyorsunuz:

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

Kodlanmış mesajınız HloWrdel ol. Kod çözmek için önce kodlanmış mesajın uzunluğunu alın, 1 ekleyin ve 2'ye bölün x. Bu numarayı çağıralım . Artık biliyoruz ki x, ilk harften başlayarak, her harf xsondan sonra dönüyor. Örneğin:

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

Şimdi harfleri doğru sırayla yeniden düzenleyin Hello World!

Meydan okuma

Zorluğunuz iki program, fonksiyon ya da her birinden birini yazmaktır. Ancak, her ikisi de aynı dili kullanmalıdır. İlk program bir dizeyi STDIN, program bağımsız değişkenleri veya işlev parametreleri aracılığıyla girdi olarak kabul eder ve bu yöntemi kullanarak kodlar . İkinci program, bir dizeyi STDIN, program bağımsız değişkenleri veya işlev parametreleri aracılığıyla girdi olarak kabul eder ve bu yöntemi kullanarak kodunu çözer .

Gereksinimler

İlk Program / İşlev

  • Yukarıda listelenen herhangi bir yöntemi kullanan tek bir dize girişi.
  • Dizeyi çapraz Burrows-Wheeler dönüşüm stili kullanarak kodlamalıdır.

İkinci Program / İşlev

  • Yukarıda listelenen herhangi bir yöntemi kullanan tek bir dize girişi.
  • Çapraz bir Burrows-Wheeler dönüşüm stili kullanarak dizginin kodunu çözmelidir.

Kısıtlamalar

  • Bu görevi gerçekleştiren yerleşik veya harici işlevleri kullanamazsınız.
  • Standart boşluklara izin verilmez.
  • Her iki program / fonksiyon da aynı dilde olmalıdır.

puanlama

Bu kod golf, bayt en kısa program kazanır.

Daha fazla bilgi eklemem gerekirse, bir yorum bırakın!


2
Hatta uzunluk giriş dizesini tek bir uzunluğa dönüştürmek zorunda mıyız?
Doktor

5
Bu bir Burrows-Wheeler dönüşümü değil.
FUZxxl

3
Bir Burrows-Wheeler dönüşümü farklıdır, çünkü son dönüşleri almadan önce tüm rotasyonların dizisi sözlükbilimsel olarak sıralanır.
FUZxxl

@Optimizer gerekli değildir.
GamrCorps

Yanıtlar:


12

CJam, (4 + 8 =) 12 bayt

Kodlama programı:

q2/z

Buradan çevrimiçi deneyin

Kod çözme programı:

q_,2/)/z

Buradan çevrimiçi deneyin

Nasıl (veya daha doğrusu, neden) çalışıyorlar :

Diagonal Burrows-Wheeler dönüşümü, temelde, sondan sararak dizenin diğer her karakteridir. String'i 2 sütunlu bir 2D matris olarak ele alırsak, sadece matrisin dönüşümünü almak için kaynar. Misal:

Hello World

2D matris olarak

He
ll
o 
Wo
rl
d

Şimdi, sadece sütun akıllıca okumak, vermek:

HloWrdel ol

Burrows-Wheeler dönüşümü budur.

Kod çözme işlemi sürecin tersidir, dizeyi 2 satır 2D matris olarak yazın ve sütunları akıllıca okuyun.

Kod genişletme :

Encoder:

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

dekoder:

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 bayt

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

Eşifreleri Dçözer. Ben saymam E=ve D=puan için.

Şifre çözme, nkarakter ndizisinin etrafına sarılarak , dize uzunluğunun yarısı yuvarlanır. Bunun nedeni, bu gibi ters çevirir olmasıdır 2ve ninversleri yüzden her alarak dize uzunluğunu modulo olan nher alarak inci karakter tersine çevirir 2nd tane.

Tek bir işlev kullanılmasına izin verildiyse, 44 bayt yapabilirim

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

Şifreler zaman bolduğu Falseve ne zaman çözer bolduğunu True. İfade 1+len(x)**b>>beşittir [2,len(x)/2+1][b].


4

J, 10 + 10 = 20

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

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

(Çevreleyen parantezler, işlev tanımının bir parçası olmadığı için skora dahil edilmez.)

3 baytlık iyileştirme için FUZxxl için teşekkürler .

Şimdi, iki fonksiyonun, liste tarafından tanımlanan konumlardan karakterleri alırken #|2*i.@#ve ikinci fonksiyon, siparişleri ile aynı listeyi kullanarak karakterleri geri düzenlerken , iki fonksiyonun tersine döndüğü güzel bir şekilde gösterilmiştir .

Burada çevrimiçi deneyin.


İlki yanı 10 karakter yapılabilir: {~#|2*i.@#.
FUZxxl

@FUZxxl Teşekkürler, güncellendi. Şimdi, iki fonksiyon arasındaki ilişki gerçekten güzel bir şekilde gösteriliyor.
randomra

3

Pyth - 5 + 11 = 16 bayt

Bir desen fark ettim! ~ Mutlu dans yapar ~ Dönüşüm sadece gerçekten tüm diğer unsurları toplamak dize döngü. Aksi takdirde hiçbir zaman elemanların yarısını alamayacağı için sadece garip çalışır. Bu, 2 geniş bir matrisin döndürülmesine eşdeğerdir.

Encoder:

%2*2z

Python'un adım dilimleme etrafında dönmez, bu yüzden dizeyi tekrarladım.

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

dekoder:

K/hlz2%K*Kz

Yine adım dilimleme için sargı yok.

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

@FryAmTheEggman Sadece garip uzunluklu dize alması gerekiyor eminim. Açıklamanın başlangıcındaydı.
Maltysen

Ayy üzgünüm. : S
FryAmTheEggman

2

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

Skordaki ekstra +1, -r seçeneğinin ayarlanması içindir. Tek uzunluklu giriş dizeleri varsayılır.

Encoder:

s/.*/&&/
s/(.)./\1/g
  • Giriş dizesini ikiye katlayın
  • Her tek (1'den sayarak) karakteri düşür

dekoder:

Kod çözücü :geçici bir işaretçi karakteri olarak kullanılır, bu nedenle giriş dizesinde görünürse, tanımlanmamış davranış elde edersiniz. Giriş dizesi 95 ASCII karakteriyle sınırlandırılmışsa, bu işaretçileri değiştirmek için ASCII aralığının dışında bir şeyle (örneğin BEL 0x7) değiştirilebilir.

s/.*/:&:/
:l;s/:(.)(.+)(.):/\1:\2:\3/;tl
s/:(.*)/\1:/
:m;s/(.)(.*):(.?)(.*):(.*)/\2:\4:\5\1\3/;tm
s/://g
  • :İşaretleyicileri giriş dizesinin başına ve sonuna koyun
  • İşaretçiler orta karakterin her iki tarafı olana kadar her seferinde ilk :ileri ve ikinci :geri bir :karakteri karıştırın
  • İlkini kaldırın ve sonuna "A: B:" ifadesini bırakarak sonuna :bir tane :daha ekleyin ; burada A düz metin girişinden tek karakterlerden oluşan dize ve B çift karakterlerden oluşan dizedir
  • :Düz metin girişini yeniden birleştirmek için sondan sonra A ve B karakterlerini birleştirin
  • Kalan :işaretleri kaldırın

2

JavaScript ES6, 41 + 49 = 90 bayt

Encoder

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

şifre çözücü

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

Bunlar anonim işlevlerdir, bu yüzden tüm fonksiyon tanımı olduğundan sadece parantez içindeki kodu sayıyorum. Aşağıdaki snippet ile deneyin: (ES5 kullanmak üzere değiştirildi)


Buna ne dersin [t=>t.replace(/./g,(_,o)=>t[o*2%t.length]),t=>t.replace(/./g,(_,o)=>t[(1+(l=t.length))/2*o%l])]? Sen gibi kullanabilirsiniz [...][0]('encode string')ve [...][1]('decode string'). Bunun yapılamayacağını söyleyen hiçbir şey yok! Ve 1 bayt tasarruf edersiniz.
Ismael Miguel

Teşekkürler, bu 2 fonksiyon yazmayı söylüyor ve bunun önemli olacağını düşünmüyorum.
NinjaBearMonkey

Bu hala 2 işlev. Kurallar, adlara veya işlevlere erişim yollarını belirtmez. Sadece 2 işlevi kullanmanız gerektiğini söylüyor.
Ismael Miguel

1
@IsmaelMiguel Şimdi düşündüğüme göre, anonim işlevlerin kendilerine izin verdiğini düşünüyorum, bu yüzden bunu kullanmak daha fazla bayt kazandırıyor.
NinjaBearMonkey

Bayt sayısını azalttığınıza sevindim.
Ismael Miguel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.