OOP: Örtüşen Odaklı Programlama


32

Kod golf oynamak için uygun görünen daha az bilinen programlama paradigmalarından biri, Overlapping Oriented Programming (OOP) * dır . Kısmen özdeş kod yazarken, birçok öznitelik, özdeş bölümlerin üst üste binmesi ve iki orijinal kod satırının başladığı bir şekilde hatırlanmasıyla kaydedilebilir. Göreviniz örtüşen iki program veya işlev yazmak compressve decompressaşağıdaki özelliklere sahip olmaktır :

* Muhtemelen üretim kodunda kullanmayınız.

compress

compressHerhangi bir uygun formatta iki dizge alır ve mümkün olduğunca üst üste bindirir. Bu, sher iki giriş dizesinin de alt dizileri olacağı şekilde en az uzunlukta bir dize döndürülür s. Ayrıca, her iki dizenin başlangıç ​​ve bitiş dizinlerini tanımlayan bazı çıktılar döndürülür.

Örnekler: (Kesin GÇ formatı size bağlıdır)

compress("abcd", "deab") -> "deabcd" ((2,5),(0,3))
compress("abcd", "bc")   -> "abcd" ((0,3),(1,2))
compress("abc", "def")   -> "abcdef" ((0,2),(3,5)) or "defabc" ((3,5),(0,2))

decompress

decompresscompressBir dize ve iki başlangıç ​​ve bitiş indeksi verilen ters fonksiyonunu hesaplar (sizin tarafınızdan döndürüldüğü biçimde compress), iki orijinal diziyi döndürür. Sadece geçerli girişleri kullanmanız yeterli. Aşağıdaki eşitlik bütün dizeleri tutmak gerekir s1, s2:

(s1, s2) == decompress (compress (s1, s2))

Örnekler: ( compressörneklerin tersi )

decompress "deabcd" ((2,5),(0,3)) -> "abcd" "deab" 
decompress "abcd" ((0,3),(1,2))   -> "abcd" "bc"

decompress "abcdef" ((0,2),(3,5)) -> "abc" "def"   
 or (whichever version your "compress" generates)
decompress "defabc" ((3,5),(0,2)) -> "abc" "def"

puanlama

Puanınız, çağrılarak döndürülen dizenin boyutudur compress("<code of compress>", "<code of decompress>"). Bu için düşük puan daha iyidir.

Örnek:

Fonksiyonun kodunu varsayalım compressolduğunu c=abcdve kod decompressDİR d=efghi. Sonra compress("c=abcd", "d=efghi")verim "c=abcd=efghi"(ve endeksler, ancak bunlar skorlamayı etkilemez) yani skor length "c=abcd=efghi" = 12.

Ek Kurallar

  • Bu zorluğun ruhuna göre, sizin compressve en az bir karakterle decompress çakışmanız gerekir . Bunu bir yorum ekleyerek başarabilirsiniz, ancak bunu yapmanın puanınızı artıracağını ve kendiliğinden çakışan kodu kullanan daha kısa çözümler olabileceğini unutmayın.
  • compressve decompressherhangi bir yazdırılabilir ASCII karakterleri içeren dizeleri yanı sıra tanımlamak için kullanılan tüm karakterleri işlemek mümkün olmalıdır compressve decompress.
  • Endeksler sıfır veya bir indeksli olabilir.
  • Programların veya işlevlerin aslında adlandırılmaları gerekmiyor compress vedecompress .

Sıkıştırmak ve kodu açmak için çalıştırmak için farklı komut satırı değişkenleri kullanabilir misiniz?
MildlyMilquetoast

Emin. İki program vermelisiniz ve site ilkesi sayıldığı sürece komut satırı argümanlarına izin verir, böylece programlarınızın her biri için farklı komut satırı argümanları verebilirsiniz.
Laikoni

Yanıtlar:


25

GNU Prolog, 105 puan

s(U,L/M,C):-prefix(A,C),length(A,M),suffix(U,A),length(U,L).
o(A-B,C-X-Y):-length(C,_),s(A,X,C),s(B,Y,C).

(Bunun nedeni, GNU Prolog gerektirir prefixve suffixtaşınabilir değildir.)

Prolog bu zorluk için ilginç, büyük bir avantaja sahip; Birden fazla çağrı düzenini işlemek için bir fonksiyon yazabilirsiniz (yani sadece fonksiyona karşılık gelen bir çıktı almak için bir giriş veremezsiniz, fonksiyona ilgili girişi almak için bir çıktı verebilirsiniz). Bu nedenle, hem sıkıştırma hem de açma işlemlerini gerçekleştirebilecek bir işlev tanımlayabiliriz, obu da her iki yönde de çalışan bir işlevi tanımlayan 105 baytlık bir gönderime yol açar . (Bu arada, çoğunlukla bir dekompresör olarak yazdım - daha basit olduğu gibi - ve kompresörü "ücretsiz" olarak aldım.) Genel olarak, Prolog'da bu görev için çok kısa bir program bekleyebiliriz, bu kadar kötü olmasa da sicim kullanımında (hem eksik ilkeller hem de söz konusu ilkeller açısından çok uzun isimlere sahip).

İlk argüman obir dizi ip, örn "abcd"-"deab". İkinci argüman "deabcd"-4/6-4/4; bu oldukça standart bir iç içe demetdir ve dize "deabcd" dir, ilk dizginin uzunluğu 4 4'tür ve altıncı karakterde biter, ikinci dizginin uzunluğu 4'tür ve dördüncü karakterde biter. (GNU Prolog'daki bir dizginin sadece uygulama hatalarının varsayılan olarak tercih edilmesini tercih etmesi nedeniyle hata ayıklamayı sinirlendiren bir karakter kodları listesi olduğunu unutmayın.) VerirsenizoBir argüman, diğerini sizin için çıkartacaktır (böylece birinci argümanı verirseniz kompresör, ikinciyi verirseniz bir dekompresör olarak çalışır). Her ikisine de bağımsız değişkenler verirseniz, sıkıştırılmış gösterimin verilen dizelerle eşleştiğini doğrular. Eğer sıfır argüman verirseniz, şöyle bir çıktı üretecektir:

| ?- o(X,Y).
X = []-[]
Y = []-0/0-0/0 ? ;

X = []-[]
Y = [_]-0/0-0/0 ? ;

X = []-[A]
Y = [A]-0/0-1/1 ? ;

many lines later

X = [A]-[B,A,C]
Y = [B,A,C]-1/2-3/3 ? ;

G / Ç formatının yukarıdaki açıklaması, neredeyse tamamen programın bir açıklamasıdır; Programda pek bir şey yok. Sadece incelik değerlendirme sırası ipuçları ile yapmaktır; Programın yalnızca sonlandırılması garanti edilen bir arama stratejisi değil, aynı zamanda mümkün olan en kısa çıktı dizesini de üretmesini sağlamamız gerekir.

Sıkıştırırken, birçok Prolog ve Brachylog cevabında kullandığım bir numara olan length(C,_)(" Cbir uzunluk") ile başlıyoruz; Prolog'un gördüğü ilk şey buysa, Cbaşka herhangi bir şeyin uzunluğunu azaltmaya öncelik vermesini sağlar . Bu, minimum bir uzunluğa sahip olmamızı sağlar C. Kısıtlamaların sıralanması s, araştırmanın olası her aday uzunluğu için sınırlı bir zaman alacağı şekilde dikkatlice seçilir C; Atarafından kısıtlanır C(biz bilmiyoruz C, ama biz uzunluğu için sahip hedef değerini biliyorum), Mtarafından A, Utarafından A, ve Ltarafından Uaramaların hiçbiri sınırsız zaman alabilir bu yüzden.

Açarken, Cdoğrudan kullanıcı tarafından verilir . Bu da, aynı kısıtlama sırasına bağlı olarak programın sınırlı bir sürede çalışmasını sağlar. (Prolog değerlendirmesinin düzenin farkında olan insanlar tanımı olduğuna dikkat edecektir syerleştirerek; açılırken çok verimsiz length(A,M)ve length(U,L)ilk hızlı olacaktır, ama hareketli length(A,M)sıkıştırarak çünkü ne zaman bir başlangıç sonsuz döngüye neden olabilecek Ane de Mzaman herhangi bir şey ile bağlıdır .)


13

Brachylog , 50 46 bayt

{Ċ∧Lċ₂l∧Lgj:?z{tT∧?h~cṪhlI∧ṪbhTl:I+-₁:I↔}ᵐ:L}

Çevrimiçi deneyin!

Basıncı azaltmak:

~{Ċ∧Lċ₂l∧Lgj:?z{tT∧?h~cṪhlI∧ṪbhTl:I+-₁:I↔}ᵐ:L}

Çevrimiçi deneyin!

@ Ais523 sayesinde 5 bayt kaydedildi

açıklama

Bildirim dillerinin iyi yanı, aynı kodu hem sıkıştırma hem de açma için yeniden kullanabilmemizdir. Bu haliyle, sıkıştırma için olan kod , başlangıçtaki ilave bir değer ile, dekompresyondakiyle tamamen aynıdır .~

Bu ~, Brachylog'a argüman sırasını tersine çevirmesini söyler (yani, Girdiyi çıktı ve Çıktıyı girdi olarak kullanın). Sıkıştırma olmadığından ~, yordayışı standart düzende çalıştırır. Dekompresyonda sadece bir tane olduğundan, çıkış olarak Giriş ve Çıkış olarak Giriş ile çalışır.

Bu şekilde, ~hem sıkıştırmak hem de açmak için aynı kodu (ekstra olan modulo ) kullanabiliriz: sıkıştırma, iki dizeyi girdi olarak ve çıktıyı da değişken olarak sağlarken, sıkıştırmayı açma dizinleri ve sıkıştırılmış dizeyi çıktı olarak ve girdi olarak bir değişken sağlar .

Açıkçası bu aynı zamanda sıkıştırma kodumuz hakkında biraz açık olmamız gerektiği anlamına gelir, böylece tercüman onu "geriye doğru" çalıştırabilir. Bu nedenle kompresörün kendisi biraz uzundur.

İşte Sıkıştırma kodunun bir dökümüdür (ve böylece sıkıştırmanın açılması da):

{……………………………………………………………………}   Call that predicate the normal way (with swapped arguments
                                 for decompress)
   Ċ                           Input has two elements
   ∧Lċ₂l                       L is a string of any length (measuring its length forces it to
                                 take a specific length from 0 to +inf)
   ∧Lgj                        The list [L,L]
       :?z                     The list [[L, First elem of Input],[L,second elem of input]]
          {………………………………}ᵐ:L    Final output is the [M,L] where M is the result of mapping
                                 the predicate below on both elements of the zip
           tT                  The second element of the input is T
           ∧?h~cṪ              Anticoncatenate the first element of the input into [A,B,C]
           hlI                 I = length(A)
           ∧ṪbhTl:I+-₁         J = length(T) + I - 1
           :I↔                 Output = [I,J]

4

Jöle , 58 50 bayt

Ais523 sayesinde -1 bayt (kullanım iki baytlık bir dize için )

Bu oldukça iyi golf oynayabilir ...

Sıkıştırma iki dize argümanı alır ve bir liste döndürür:
[[[startA, lengthA], [startB, lengthB]], compressedString]

w³;w⁴$
0;J⁸ḣ;€
ç;ç@ÑẠ$ÐfLÐṂṪµ³,⁴L€ż@Ñ,

Dekompresyon bir argüman alır (böyle bir liste) ve iki * karakter döndürür:

,
⁾ṫḣżFv
Ḣç€Ṫ

Örtüşen kod:

w³;w⁴$
0;J⁸ḣ;€
ç;ç@ÑẠ$ÐfLÐṂṪµ³,⁴L€ż@Ñ,
⁾ṫḣżFv
Ḣç€Ṫ

Tek endekslendi.

* Jelly’in örtük baskı biçimlendirmesi nedeniyle bu açık olmayabilir, bu nedenle yukarıda belirtilen TryItOnline’da bulunan kodun ekstra bir baytı vardır (a Y , yazdırılan çıktıdaki ikisi arasına bir satır besleme eklemek sonunda a) sahiptir.

Sıkıştırma ve dekompresyon arasında karar vermek için ilk (veya yalnızca) argümanın derinliğini kullanan, ancak dekompresyon kodunda kullanılmayan bir bağlantıya sahip olan (ilk satır) ve tek bir üst üste gelen bayt yedi bayt daha kısa olan tek bir programla başladım. .

Nasıl?

ç;ç@ÑẠ$ÐfLÐṂṪµ³,⁴L€ż@Ñ, - Compression: stringA, stringB
ç                       - call the last link (2) as a dyad
  ç@                    - call the last link (2) as a dyad with reversed arguments
 ;                      - concatenate (gives all overlapping strings)
       Ðf               - filter keep:
      $                 -     last two links as a monad
    Ñ                   -         call the next link (1) as a monad
     Ạ                  -         All? (no zeros exist in that result)
          ÐṂ            - filter keep with minimal:
         L              -     length
            Ṫ           - tail (for when more than one exists)
             µ          - monadic chain separation (we now have the compressed string)
              ³,⁴       - [stringA, stringB]
                 L€     - length of €ach
                   ż@   - zip with reversed arguments with
                     Ñ  - next link (1) as a monad with the compressed string
                      , - paired with the compressed string

J0;⁸ḣ;€ - Link 2, possible overlaps: stringL, stringR
J       - range(length(stringL)) - [1,2,...,length(stringL)]
 0;     - zero concatenate       - [0,1,2,...,length(stringL)]
   ⁸    - stringL
    ḣ   - head (vectorises)      - [empty string, first char, first two, ..., stringL]
     ;€ - concatenate €ach with stringR

w³;w⁴$ - Link 1, substring indexes: stringX
w³     - first index of first program argument in stringX or 0 if not found
  ;    - concatenated with
     $ - last two links as a monad
   w⁴  -     first index of second program argument in stringX or 0 if not found
Ḣñ€Ṫ - Decompression: [[[startA, lengthA], [startB, lengthB]], compressedString], ?
Ḣ    - head - [[startA, lengthA], [startB, lengthB]]
   Ṫ - tail - compressedString
 ç€  - call the last link (2) as a dyad for €ach of the left list
     -- extra Y atom at TIO joins the resulting list of two strings with a line feed.

⁾ṫḣżFv - Link 2, extract a substring: [start, length], string
⁾ṫḣ    - string "ṫḣ"
   ż   - zip with [start, length] to yield [['ṫ', start],['ḣ', length]]
    F  - flatten, making a list of characters
     v - evaluate as Jelly code with the string as an argument
       - this evaluates as string.tail(start).head(length) yielding the substring

, - Link 1: only here to make an overlap with the compression program.

“ṫḣ”2 karakterli dizgiler için Jelly's sözdizimini kullanarak 1 byte ile golf oynayabilir.

Bu, tamamen cevap ile ilgisiz bir sorudur, ancak kodun açıklamasını elle mi yazıyorsunuz yoksa koddan üreten bir araç var mı?
tfrascaroli

@tfrascaroli Elle yazıyorum
Jonathan Allan
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.