Verimli hatasız * kodlama [kapalı]


20

Görev

İyi bilindiği gibi, Dünya üzerinde bilinen tüm canlıların genetik materyali DNA'da kodlanmıştır; dört nükleotit adenin, timin, sitozin ve guanin kullanılarak. (Genellikle ATGC tarafından temsil edilir).

Tüm genomu depolamak isteyen bir biyoinformatik, elbette bunu ASCII olarak saklamak istemez, çünkü her seçim sadece iki bitle temsil edilebilir!

Şartname

Göreviniz kabul etmeyi seçerseniz, ASCII temsilini ikili temsile ve geri dönüştürmek için bir çift program, işlev veya yöntem yazmaktır; temsil Aolarak b00, Tyanı b01, Gsıra b10ve Cşekilde b11(bundan sonra "birim").

Ayrıca, her baytın yüksek bitleri bayttaki birim sayısını içermelidir, bu da her baytın bir üçlüyü temsil etmesini sağlar.

Örneğin: "GATTACCA"olur b11 100001 b11 010011 b10 1100xx.

ASCII'den ikili girişe boşluklar, sekmeler ve yeni satırlar göz ardı edilmelidir. Setinde olmayan herhangi bir karakter [ \r\n\tATGC]bir hatadır ve yok sayılabilir veya işlemeyi sonlandırabilir.

İkili - ASCII girişinde, iki yüksek biti olan baytlar b00yok sayılabilir.

ASCII çıkışı boşluk içerebilir; ancak hiçbir zaman ikili girişin boyutunun artı bir bayt uzunluğunun 4 katından fazla olmamalı ve bir satırsonu ile bitmemelidir.

İkili çıktı isteğe bağlı sayıda b00xxxxxx"kontrol" baytı içerebilir ; ancak ASCII girişinden asla daha uzun olmamalıdır.

Her dönüşüm programı keyfi uzunluk girişini desteklemelidir; ve kodlamayı veya kod çözmeyi yaklaşık doğrusal zamanda tamamlamalıdır.

Bükülme

Ne yazık ki, bu görevi yerine getirdiğiniz biyoinformatik için, bir şekilde sizi kişisel ama belki de küçük bir düzeyde haksızlığa uğrattı.

Belki kız kardeşinle bir kez dışarı çıktı ve onu bir daha asla aramadı. Belki de köpeğinin kuyruğuna bastı. Ayrıntılar gerçekten önemli değil.

Önemli olan geri ödeme şansınız olması!

Ayrıntılar

Her dönüşüm küçük bir hata oranı getirmelidir; işlenen on bin ila bir milyon birimde bir hata emrinde.

Bir hata aşağıdakilerden biri olabilir:

  • Çoğaltma hataları: "GAT TAC CA"olur"GAT TAA CCA"
  • Silme hataları: "GAT TAC CA"olur"GAT TAC A"
  • Çeviri hataları: "GAT TAC CA"olur"GTA TAC CA"
  • Üçlü kopyalar: "GAT TAC CA"olur"GAT TAC TAC CA"
  • Üçlü kaymalar: "GAT TAC CA"olur"TAC GAT CA"
  • Üçlü dönüşler: "GAT TAC CA"olur"GAT CAT CA"

Bu hatalar elbette koddan hemen belli olmamalıdır; ve girdinin uzunluğuna bakılmaksızın; dönüşüm en az bir hata içermelidir.

Aynı girişlere sahip iki çalışma mutlaka aynı çıkışları üretmemelidir.

Numara

Aşağılık biyoinformatik, orta derecede yetkin bir kodlayıcıdır; ve bazı yapılar otomatik olarak keşfedilecek ve şu şekilde yasaklanacak:

  • Rand (), random () veya / dev / urandom veya / dev / random (veya dil eşdeğeri ne olursa olsun) gibi rasgele sayı üreteçlerine yapılan çağrıları otomatik olarak keşfedecektir.
  • Ayrıca gereksiz değişkenleri, sayaçları veya döngüleri de fark edecektir.

Puanlama

Kodlayıcı ve kod çözücü ayrı ayrı puanlanacaktır.

Her biri rastgele oluşturulmuş 100 giriş dosyası kümesine karşı 3 kez çalıştırılır, her biri 3 milyon birim büyüklüğünde bir dosyadır.

Kodlayıcı test senaryoları için veriler yaklaşık olarak şu şekilde oluşturulacaktır:

for (l = 1 => bigNum)
  for (t = 1 => 20)
    random_pick(3,ATGC)
    t == 20 ? newline : space

Kod çözücü test senaryoları için veriler yaklaşık olarak aşağıdaki şekilde oluşturulacaktır:

for (u = 1 => bigNum)
  for (t = 1 => 20)
    random_byte() | 0b11000000
   0x00

Kodlayıcı

  • Gerçek uzunluktaki beklenen minimum uzunluktan eksik olan her bayt, maksimum -1000'e kadar -1 puan kazanacaktır. (Beklenen minimum uzunluk ceil(count(ATGC) / 3).)

Kod çözücü

  • Gerçek uzunluktaki beklenen maksimum uzunluk üzerindeki her bayt, maksimum -1000'e kadar -1 puan kazanacaktır. (Beklenen maksimum uzunluk size(input) * 4 + 1.)

Her ikisi de

  • Üretilebilecek her türlü hata 100 puan alacaktır; her biri için toplam 600 puan, toplam 1200 puan için.
  • Kodlayıcının kendi ortalamasından% 30 daha fazla veya daha az hata ürettiği her test durumu -5 puan cezalandırılacaktır.
  • Kodlayıcının kendi ortalamasından% 15 daha fazla veya daha az hata ürettiği her test senaryosuna 5 puan verilecektir.
  • Üç çalışmanın da aynı çıktıları ürettiği her test senaryosu -10 puan cezalandırılacaktır.

Zor gereksinimler

Bir giriş şu durumlarda diskalifiye edilecektir:

  • Bir üçlüden uzun geçerli herhangi bir giriş için bir hata bile üretemez.
  • Performansı, test eldivenini yaklaşık bir saat içinde tamamlayamayacağı şekildedir.
  • Ortalama olarak her on bin birimde birden fazla hata üretir.
  • Ortalama olarak her milyon birimde birden az hata üretir.

Arayüz

Katılımcılar standart girdi üzerindeki girdiyi kabul etmeli ve standart çıktıya çıktı almalıdır.

Giriş çift fonksiyonlu bir program ise; geçer -eve -dsırasıyla kodlama ve kod çözme için bir program belirlemelidir.

Örnek çağrılar:

$ encoder <infile.txt >outfile.bin
$ decoder <infile.bin >outfile.txt
$ recoder -e <infile.txt >outfile.bin

Kazanan

Kazanan en yüksek puana sahip olan katılımdır; teorik maksimum hata türleri için 1200, hata oluşturma oranlarında kararlılık için 3000 puandır.

Beklenmedik bir beraberlik durumunda; kazanan oy sayısına göre belirlenir.

Ek notlar

Test eldiveni çalıştırmak için her giriş çalışma veya derleme talimatlarını içermelidir.

Tüm girişler tercihen X olmayan bir Linux makinesinde çalıştırılabilir olmalıdır.


4
Etiketi değiştirdi. KotH, gönderilerin birbiriyle etkileşime girdiği zorluklar içindir. Ayrıca korkuyorum ki "gizli" bileşeni objektif olarak uygulamak imkansız.
Martin Ender

2
@ M.buettner'ın gizli görüşün yargılanmasının zor olduğu yorumuna katılıyorum. Öte yandan, bunun meydan okumadaki tek ilginç kısım olduğunu hissediyorum. Hata üretiminin ve oranının tam olarak spesifikasyonlar dahilinde olduğunu ve bu nedenle maksimum puanlara sahip olduğunu garanti edebilirim. Yoksa teknik özelliklerden bir şey mi kaçırıyorum? Ayrıca, ek bir tür hata kabul edilirse, yukarıdaki listeye eklenecektir; ve tüm cevaplar puanlanacaktır. insanlar çalışmaya başladıktan veya iyi bir fikir olmadığını düşündüğüm çözümler gönderdikten sonra bu zorluğu değiştireceksiniz gibi görünüyor.
Howard

@Howard: Kaydetti. Kurallar spesifik yetersizlik kriterleri ile güncellenir; ve mutasyonel yönü wrt. hatalar kaldırıldı.
Williham Totland

1
Cevabımı vereceğim .. ama sanırım iki cümle "Her dönüşüm küçük bir hata oranı getirmeli; on bin kişi başına bir hata sırayla işlenen milyonlarca birime." ve "Aşağıdaki durumlarda bir girdi diskalifiye edilecektir: Ortalama olarak her on bin birimde birden fazla hata üretir." uyumsuz. Aynı durum "Her dönüşüm küçük bir hata oranı getirmelidir; işlenen on bin ila bir milyon birimdeki bir hata sırasıyla." ve "Aşağıdaki durumlarda bir girdi diskalifiye edilecektir: Ortalama olarak her milyon birimde birden az hata üretir."
Mattsteel

1
Bu soruyu konu dışı olarak kapatmak için oy kullanıyorum çünkü el altında kalan zorluklar artık bu sitede konuyla ilgili değil. meta.codegolf.stackexchange.com/a/8326/20469
kedi

Yanıtlar:


3

Perl 5.10

Çözümümü Perl'de sunmaktan mutluluk duyuyorum.

Meydan okumaya başladığımda Perl'in 1 saat sınırının çok altında kalacağından emindim.

Test amacıyla düz bir örnek jeneratör ve kodlanmış bir örnek jeneratör geliştirdim.

Sonra daha fazla çaba harcayan ve daha uzun bir kod üreten kodlayıcıyı geliştirdim. Kodlayıcı aşağıdaki gibi çalışır:

  1. ilk döngü tüm dosyayı okur ve tüm üçlülerin bir dizisine sahip olmak için verileri böler
  2. ikinci döngü diziyi dolaşır ve her öğenin uzunluğunu
  3. üçüncü döngü tekrar çapraz hareket eder ve çıktıyı vermek için her karakteri eşler.

Kodlanmış ikili çıkış, 20 oktetten oluşan yeni satır sonlandırılmış "satırlar" olarak biçimlendirilir; burada her sekizlinin bir üçlüyü iki önek karakteriyle (döngüsel bir satır numarası gibi) kodlar.

örneğin, en kısa üç baytlık giriş:

AAA

üç bayt artı yeni satırın en kısa çıktısını vermelidir.

00ÿ

yani

30 30 FF 0A

ve

AGG CGC AAC GGC TAA ATC GTT TTC ACA CCA CGT TTG AAA CGG GTG ACA CGA GAT TTA GTC
TAT GGT ACT AGG TAC GCC GTG GTG CGT GCG GAG TTA CTA GAT GTG TTA GTA CGC CAT CGT

Aşağıdaki ikili vermelidir.

01ÊûÃëÐÇå×ÌüùÖÀúæÌøáÔç
00ÑéÍÊÓïææùîâÔôáæÔäûñù

Küçük hata oranı nedeniyle gerekir : En küçük giriş için, komut dosyası 1 hata verir.

3 milyon üçüz dosya çalışması için kodlayıcı 11 hata verir.

Komut dosyasının dnacodec3.pl olması koşuluyla, çalışma her zamanki gibi komut isteminde çağrılır:

$> perl dnacodec3.pl -e < plain.txt > coded.txt

Kod çözücü aşağıdaki gibi çalışır:

  1. ilk döngü tüm dosyayı okur ve tüm sekizli diziler için verileri böler. Her yeni hattı takip eder.
  2. ikinci döngü, her sekizliyi inceler, 00 ile başlamayanları korur ve gerisini göz ardı eder. Düz Ascii çıkışı, bir boşlukla ayrılmış yeni satır sonlandırılmış üçüz çizgileri olarak biçimlendirilir. Yeni hat , girdideki ile aynı konumda.

3 milyon üçüz örnek test dosyası (yaklaşık 12 MBayt) hazırladım ve zamanlama için test ettim. Dizüstü bilgisayarımı 2,6 GHz'de Intel Core i5 vPro ile kullanan 3M kodlayıcı çalışması her zaman 20 saniyeden az sürer. Çalışma sırasında 200-220 MByte RAM alır. Ne gereksiz!

Kod çözme işlemi 10 saniyeden az sürer. Şu anda hata getiremiyor ...

Tekrar, kod çözme işlemi için

$> perl dnacodec3.pl -d < coded.txt > plain.txt

İşte kod

#!/usr/bin/perl
use strict ;
use warnings ;
my $switch = shift || die "usage $0 [-e|-d]\n";
my %map = qw( x 10  X 11  c 0b  ? 00
              A 00  T 01  G 10  C 11  
              0 00  1 01  2 10  3 11  
              00 A  01 T  10 G  11 C  ) ;
my $r = 20 ;
my @dummy = unpack ( '(A4)*', '0xxx' x $r ) ;
my $map = oct( $map{ c } . ($map{ C } x 9) ) ;
my $t = time() ;
my @inp = () ;
my @out = () ;
my @buf = () ;
my $n ;

sub arch {
    push @buf, @dummy[ 0 .. $r - $#buf - 2 ] ;
    push @out, "@buf" ;
    @buf = () ;
}

sub encode {
    my $mask = '(A3)*' ;
    while ( my $row = <STDIN> ) {
        chomp $row ;
        $row =~ s/\s+//g ;
        $row =~ s/[^\r\n\tATGC]//g ;
        next unless $row ;
        my @row = unpack( $mask, $row ) ;
        push @inp, @row if $row ;
    }
    $n = scalar @inp ;
    $r = $n if $r > $n ;
    for ( my $i = $n - 1 ; $i >= 0 ; --$i ) {
        my $e = $inp[$n-$i-1] ;
        my $l = length( $e ) ;
        my $d = $e =~ /\?/? 0: $l ;
        push @buf, ( $d -((($i-($n>>1))&$map)?0:1) )
           . $e . 'x'x(3-$l) ;
        arch unless $i % $r ;
    }
    arch if scalar @buf ;
    my $m = scalar @out ;
    for ( my $j = $m - 1 ; $j >= 0; --$j ) {
        my @ary = () ;
        my $e = $out[$m-$j-1] ;
        for my $byte ( split / /, $e ) {
            my @byte = split ( //, $byte ) ;
            my @trad = map { $map{ $_ } } @byte ;
            my $byte = join( '', @trad ) ;
            push @ary, $byte ;
        };
        my $row = sprintf( '%02d', $j % $r) ;
        $row .= pack( '(B8)*', @ary ) ;
        print "$row\n" ;
    }
}

sub decode {
    my $mask = '(B8)*' ;
    while ( my $row = <STDIN> ) {
        chomp $row ;
        next unless $row ;
        my @row = unpack( $mask, $row ) ;
        push @inp, @row[0..$#row], '?' if $row ;
    }
    $n = scalar @inp ;
    my @ary = () ;
    for ( my $i = $n - 1 ; $i >= 0 ; --$i ) {
        my $e = $inp[$n-$i-1] ;
        if ( $e ne '?' ) {
            my $u = oct( '0b'. substr($e,0,2) ) ;
            my $a = '' ;
            for my $j ( 1 .. $u ) {
                $a .= $map{ substr($e,$j+$j,2) } ;
            }
            push @ary, $a if $u ;
        }
        else {
            my $row = "@ary" ;
            $row =~ s/\s{2,}//g ;
            print "$row\n" if $row ;
            @ary =() ;
        }
    }
}

decode if $switch eq '-d' ;
encode if $switch eq '-e' ;

Ve işte örnek jeneratör:

sub test_coder {
    my $n = shift || 1000 ;
    my @b = qw( A C G T ) ;
    for (my $l = 0; $l < $n; $l++) {
        my @ary = () ;
        for (my $t = 0; $t < 20; $t++) {
            push @ary, $b[ int(rand(4)) ] . $b[ int(rand(4)) ] . $b[ int(rand(4)) ] ;
        }
        print "@ary\n" ;
    }
    1;
}

sub test_decoder {
    my $n = shift || 1000;
    for (my $l = 0; $l < $n; $l++) {
        my @ary = () ;
        for (my $t = 0; $t < 20; $t++) {
            push @ary, int(rand(256)) | 0b11000000 ;
        }
        my $row = pack( 'C*', @ary ) ;
        print "$row\000" ;
    }
    1;
}


test_coder( @ARGV ) if $switch eq '-g' ;
test_decoder( @ARGV )  if $switch eq '-h' ;

Hatanın nereye enjekte edildiğini göstermeyi unuttum: ikinci döngüdeki push @buf hile yapar.
Mattsteel

Çok incedir, sana vereceğim. Birden fazla rakip olana kadar tam ölçekli testler yapmayacağım, ama bu iyi şeyler. :)
Williham Totland

Teşekkürler. Bu diğer arkadaşlar için bir öneri olduğunu biliyorum ... (hala kullanılmayan) zaman fonk kullanarak hata pozisyonu rastgele geliştirmek istiyorum: tek veya çift saniyede başlangıç ​​farklı çıktı vermelidir
Mattsteel
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.