OOP : 겹치는 지향 프로그래밍


32

코드 골프에 적합한 것으로 알려진 덜 알려진 프로그래밍 패러다임 중 하나는 OPP (Overlapping Oriented Programming) *입니다. 부분적으로 동일한 코드를 작성할 때 단순히 동일한 부분을 겹치고 두 개의 원래 코드 행이 시작되는 방식을 기억하여 많은 바이트를 절약 할 수 있습니다. 당신의 작업은 두 작성하는 것입니다 중복의 프로그램 또는 기능 compressdecompress다음과 같은 사양을 :

* 아마도 프로덕션 코드에는 사용하지 마십시오.

compress

compress편리한 형식으로 두 개의 문자열을 사용하고 가능한 한 겹칩니다. 즉, s입력 문자열이 모두의 하위 문자열이되도록 최소 길이 의 문자열 이 반환 s됩니다. 또한 두 문자열의 시작 및 끝 인덱스를 식별하는 일부 출력이 반환됩니다.

예 : (정확한 IO 형식은 사용자에게 달려 있습니다)

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

decompress의 역함수를 계산합니다 compress. 즉, 문자열과 두 개의 시작 및 끝 색인 (에서 반환되는 형식으로)이 주어지고 두 compress개의 원래 문자열을 반환합니다. 유효한 입력 만 처리하면됩니다. 다음 평등은 모든 문자열을 유지해야한다 s1, s2:

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

예 : ( 예와 반대 compress)

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"

채점

점수는을 호출하여 반환 된 문자열의 크기입니다 compress("<code of compress>", "<code of decompress>"). 이것이 이기 때문에 점수가 낮을수록 좋습니다.

예:

함수 의 코드 compress는 is c=abcd이고 코드는 decompress입니다 d=efghi. 그런 다음 compress("c=abcd", "d=efghi")수익률 "c=abcd=efghi"(및 지수, 그러나 점수에는 영향을 미치지 않음)이 표시되므로 점수는 length "c=abcd=efghi" = 12입니다.

추가 규칙

  • 이 도전의 정신에서, 당신 compress과 적어도 하나의 성격에 decompress 겹쳐 야합니다 . 주석을 추가하여 간단하게이 작업을 수행 할 수 있지만 그렇게하면 점수가 높아지고 본질적으로 겹치는 코드를 사용하는 솔루션이 더 짧을 수 있습니다.
  • compressdecompress인쇄 가능한 ASCII 문자가 포함 된 문자열뿐 아니라 사용자가 정의하는 데 사용되는 모든 문자를 처리 할 수 있어야합니다 compressdecompress.
  • 인덱스는 0 또는 1 인덱스 일 수 있습니다.
  • 귀하의 프로그램이나 기능은 실제로 이름이 필요가 없습니다 compressdecompress.

다른 명령 줄 인수를 사용하여 코드를 압축 및 압축 해제 할 수 있습니까?
MildlyMilquetoast

확실한. 두 개의 프로그램을 제공해야하며 사이트 정책에 따라 계산되는 한 명령 줄 인수가 허용되므로 각 프로그램마다 다른 명령 줄 인수를 지정할 수 있습니다.
Laikoni

답변:


25

GNU 프롤로그, 105 점

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).

(때문에 GNU 프롤로그가 필요 prefix하고 suffix이식 할 수 없습니다.)

프롤로그는이 도전에 대한 한 가지 흥미로운 주요 이점이 있습니다. 여러 호출 패턴을 처리하는 함수를 작성할 수 있습니다 (즉, 해당 출력을 얻기 위해 함수에 입력을 제공 할 수있을뿐만 아니라 해당 입력을 얻기 위해 함수에 출력을 제공 할 수 있음). 따라서 압축과 압축 해제를 모두 처리 할 수있는 함수 o를 정의하여 두 가지 방식으로 작동 하는 함수 를 정의하는 105 바이트 제출이 가능합니다 . (우연히, 나는 압축을 풀기 위해 압축을 풀고 압축기를 무료로 사용했습니다.) 일반적으로, 우리는 Prolog에서이 작업에 대해 매우 짧은 프로그램을 기대할 수 있습니다. 문자열 처리시 (기본형 누락과 해당 이름이 너무 긴 기본형 측면에서)

첫 번째 인수 o는 문자열의 튜플입니다 (예 :) "abcd"-"deab". 두 번째 인수는 다음과 같은 형식입니다 "deabcd"-4/6-4/4. 이것은 상당히 표준적인 중첩 튜플이며 문자열이 "deabcd"이고 첫 번째 문자열의 길이는 4이고 6 번째 문자에서 끝나고 두 번째 문자열은 길이 4이며 네 번째 문자에서 끝납니다. (GNU Prolog의 문자열은 문자 코드 목록 일 뿐이며, 구현시 기본적으로 후자의 해석을 선호하기 때문에 디버깅을 성가 시게합니다.)o하나의 인수는 다른 인수를 출력합니다 (따라서 첫 번째 인수를 제공하면 압축기로 작동하고 두 번째 인수를 제공하면 압축 해제기로 작동). 두 인수를 모두 제공하면 압축 된 표현이 주어진 문자열과 일치하는지 확인합니다. 인수를 0으로 지정하면 다음과 같은 출력이 생성됩니다.

| ?- 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 ? ;

위의 I / O 형식 설명은 프로그램에 대한 설명 일뿐입니다. 프로그램에는 그다지 많지 않습니다. 미묘한 점은 평가 순서 힌트와 관련이 있습니다. 우리는 프로그램이 종료 보장 된 검색 전략을 사용할뿐만 아니라 가능한 가장 짧은 출력 문자열을 생성하도록 보장해야합니다.

압축 할 때, 우리는 length(C,_)( " C길이가있다")로 시작하는데, 이것은 많은 Prolog 및 Brachylog 답변에서 사용한 트릭입니다. 이것이 프롤로그가 처음 보는 것이라면 C다른 것보다 길이를 줄 이도록 우선 순위를 정하게됩니다. 이를 통해 최소 길이를 확보 할 수 C있습니다. 에서 제약 조건의 순서 s는 신중하게 선택되어 검색은 가능한 각 후보 길이에 대해 유한 한 시간이 소요됩니다 C. A에 의해 제한된다 C(우리가 모르는 C,하지만 우리는 우리가 그것의 길이가 목표 값을 알고) M에 의해 A, U에 의해 A, 그리고 L에 의해 U검색어 중 어느 것도 제한 시간이 걸릴 수 있도록.

압축 해제시 C사용자가 직접 제공 합니다. 이렇게하면 동일한 제약 조건 시퀀스로 인해 프로그램이 유한 시간 내에 실행됩니다. (프롤로그의 평가 순서를 알고있는 사람들의 정의가 있음을주의 할 것이다 s배치, 압축을 할 때 매우 비효율적입니다 length(A,M)length(U,L)첫 번째 빠른 것이지만, 이동 length(A,M)압축으로 인해 어느 때 시작하는 무한 루프가 발생할 수 AM시간에 무엇에 의해 결합되어 .)


13

Brachylog , 50 46 바이트

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

온라인으로 사용해보십시오!

압축 해제 :

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

온라인으로 사용해보십시오!

@ ais523 덕분에 5 바이트 절약

설명

선언적 언어의 장점은 압축과 압축 해제에 동일한 코드를 재사용 할 수 있다는 것입니다. 따라서 압축 코드는 압축 해제 코드와 정확히 동일 하며 처음에 추가 코드가 있습니다.~

이는 ~Brachylog에게 인수 순서를 반대로하도록 지시합니다 (즉, 입력을 출력으로, 출력을 입력으로 사용). compress에는이 없기 ~때문에 실제로 표준 순서로 술어를 실행합니다. 압축 해제에는 하나만 있기 때문에 입력을 출력으로, 출력을 입력으로 실행합니다.

그렇게하면 ~압축과 압축 해제 모두에 같은 코드 (extra와 같은 모듈 )를 사용할 수 있습니다 . 압축은 두 문자열을 입력으로 출력하고 변수를 출력으로 제공하고 압축 해제는 인덱스와 압축 문자열을 출력으로, 변수를 입력으로 제공합니다 .

분명히 이것은 또한 우리가 압축 코드에 대해 약간 명시 적이 어서 해석기가 "뒤로"실행할 수 있음을 의미합니다. 이것이 압축기 자체가 약간 긴 이유입니다.

압축 코드 (및 압축 해제)는 다음과 같습니다.

{……………………………………………………………………}   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

젤리 , 58 50 바이트

ais523 덕분에 -1 바이트 ( 2 바이트 문자열에 사용)

이것은 꽤 골프 타는 것일 수 있습니다 ...

압축 은 두 개의 문자열 인수를 사용하여 목록을 반환합니다.
[[[startA, lengthA], [startB, lengthB]], compressedString]

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

압축 해제 는 하나의 인수 (예 : 목록)를 사용하여 두 개의 * 문자열을 리턴합니다.

,
⁾ṫḣżFv
Ḣç€Ṫ

겹친 코드 :

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

하나의 색인.

* 이것은 젤리의 암시 적 인쇄 형식으로 인해 명확하지 않을 수 있으므로 위에 연결된 TryItOnline의 코드 Y에는 인쇄 된 출력에서 ​​두 개 사이에 줄 바꿈을 삽입 할 여분의 바이트 ( 끝)가 있습니다.

압축과 압축 해제를 결정하기 위해 첫 번째 (또는 유일한) 인수의 깊이를 사용하는 단일 프로그램으로 시작했지만 압축 해제 코드 (첫 번째 줄)에 사용되지 않는 링크가 있고 단일 겹치는 바이트는 7 바이트 더 짧습니다. .

방법?

ç;ç@ÑẠ$Ð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 문자열에 Jelly의 구문을 사용하여 1 바이트 씩 골프를 칠 수 있습니다.

이것은 답변 자체와 완전히 관련이없는 질문이지만 직접 코드에 대한 설명을 작성합니까, 아니면 코드에서 생성하는 도구가 있습니까?
tfrascaroli 2012 년

@tfrascaroli 손으로 작성
Jonathan Allan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.