메타 퀸 할 수 있습니까?


25

다른 quine 퍼즐과 유사하게 (보다 구체적으로는 this ) 퍼즐 자체를 만드는 프로그램을 작성하십시오.

여기에 새로운 트위스트입니다 : 생성 된 코드는해야 하지 소스와 동일합니다. 오히려 첫 번째 프로그램을 생성하는 다른 프로그램을 출력해야합니다.

위의 문제는 두 언어 사이를 뛰어 넘어 달성했습니다. 나는 이것이 하나의 언어 로 이루어질 것이라고 생각 하지만 소스의 두 가지 (또는 그 이상) 버전은 크게 달라야합니다 (아래 규칙 참조). 이 제약 조건으로 인해 단일 문자 답변 이 허용되지 않으므로 최종 제출에 조금 더 많은 생각이 필요합니다.


규칙

  1. 코드는 하나의 언어로만 제작해야합니다. (각 언어마다 하나씩 여러 번 제출할 수 있습니다.)
  2. 다른 코드 버전은 구문 상 고유해야합니다. 다시 말해, 코드 의 추상 구문 트리 를 작성하려면 하나 이상의 노드가 있어야합니다.
    • 공급 AST하는 것은 필요하지 않을 것이다, 그러나 당신은 당신의 프로그램 각각에 대해 하나를 제공하는 경향 느낀다면, 그것은 것입니다 판단에 도움이됩니다.
  3. 구문 상 고유하게 유지되는 한 원하는만큼 반복을 생성 할 수 있습니다. (점수가 더 도움이 될 것입니다. 아래를 참조하십시오.)

점수

최종 점수는 모든 프로그램의 평균 길이를 프로그램 수로 나눈 값입니다.

예 1 :

A (B 소스) = 50 자
B (A 소스) = 75 자
최종 점수 = 31.25

예 2 :

A (B 소스) = 50 자
B (C ​​소스) = 75 자
C (A 소스) = 100 자
최종 점수 = 25


18
나는 메타 퀘인 한 번.
mellamokb

1
@mellamokb har har ;-)
Gaffi

이것은 실제로 단지의보다 일반적인 버전 quine 도전, 너무 여기에 이길이 주어진 답.
반 시계 회전을 중지

@leftaroundabout, 구문 차이에 대한 요구 사항은 '회전 퀴인'을 무효화하므로 더 일반적이지 않습니다.
boothby

2
내가 좋아하지 않은 메타 퀘인은 절대로 사용하지 마십시오.
Stack Tracer

답변:


35

파이썬, 0 ((68 + 3 n ) / (16 n ) 제한)

상수가 다른 두 개의 추상 구문 트리가 다른 경우

r='r=%r;n=(0x%XL+1)%%0x10...0L;print r%%(r,n)';n=(0xF...FL+1)%0x10...0L;print r%(r,n)

(16 개)가 n은 0의 점근 점수를주는 68 + 3N 최대 길이의 프로그램.

가변 구조의 프로그램을 원한다면 n 비트 에 이진 가산기를 구현할 수 있습니다 . 여기에는 길이 O ( n 2 ) 의 2n 프로그램이 있습니다. 캐리 비트가 떨어지면 사이클이 진행됩니다.

s="""
print 's='+'"'+'"'+'"'+s+'"'+'"'+'"'
n=lambda m:reduce(lambda (s,c),y:(s+(c^y,),c&y),m,((),1))[0]
print s[:112]
t=n(t)
print "t=(%s,)+(0,)*%s"%(t[0],len(t)-1)
for i in range(len(t)-1):
    print i*' '+'for i in range(2):'
    print ' '+i*' '+['pass','t=n(t)'][t[i+1]]
print s[113:-1]
"""

print 's='+'"'+'"'+'"'+s+'"'+'"'+'"'
n=lambda m:reduce(lambda (s,c),y:(s+(c^y,),c&y),m,((),1))[0]
print s[:112]
t=(0,)+(0,)*10
for i in range(2):
 t=n(t)
 for i in range(2):
  t=n(t)
  for i in range(2):
   t=n(t)
   for i in range(2):
    t=n(t)
    for i in range(2):
     pass
     for i in range(2):
      t=n(t)
      for i in range(2):
       pass
       for i in range(2):
        pass
        for i in range(2):
         pass
         for i in range(2):
          t=n(t)
t=n(t)
print "t=(%s,)+(0,)*%s"%(t[0],len(t)-1)
for i in range(len(t)-1):
    print i*' '+'for i in range(2):'
    print ' '+i*' '+['pass','t=n(t)'][t[i+1]]
print s[113:-1]

혼란 스러울 수 있습니까? 출력이 소스와 동일한 것 같습니다 (이 도전의 목적이 아님)?
Gaffi

중첩 된 블록을보십시오. 모든 2 ^ n 조합에서 앞뒤로 pass변경됩니다 t=n(t).
boothby

나는 지금 그것을 참조하십시오. 당신은 모든 반복과 저를 혼동했습니다!
Gaffi

22
어떤 이유로, 나는 작은 점수를 가진 매우 긴 골프 솔루션을 좋아합니다.
boothby

와우, 당신은 그것을 완전히 소유했습니다! 아주 좋아요
Claudiu

4

펄, 110.25 점

나는 인정해야한다, 나는 quines에별로 좋지 않다. 개선의 여지가 있다고 100 % 확신합니다. 솔루션은 아래의 요소 솔루션과 동일한 원칙을 기반으로합니다.

첫 번째 프로그램은 264 자입니다.

$s='$a=chr(39);print"\$s=$a$s$a;";$s=reverse$s;for(1..87){chop$s}$s=reverse$s;print$s;$f++;if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}';$a=chr(39);print"\$s=$a$s$a;";$s=reverse$s;for(1..87){chop$s}$s=reverse$s;print$s;$f++;if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}

두 번째 프로그램은 177 자입니다.

$s='$a=chr(39);print"\$s=$a$s$a;";$s=reverse$s;for(1..87){chop$s}$s=reverse$s;print$s;$f++;if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}';if($f==0){$a=chr(39);print"\$s=$a$s$a;$s"}

이 항목 (및 요소 항목)의 AST 작업 중입니다.


요소 , 47.25 점

첫 번째 프로그램은 105 자입니다.

\ \3\:\$\'\[\\\\\`\(\`\]\#\2\1\'\[\(\#\]\`\ \3\:\$\'\[\\\\\`\(\`\]\#\` 3:$'[\\`(`]#21'[(#]` 3:$'[\\`(`]#`

두 번째 프로그램은 84 자입니다.

\ \3\:\$\'\[\\\\\`\(\`\]\#\2\1\'\[\(\#\]\`\ \3\:\$\'\[\\\\\`\(\`\]\#\` 3:$'[\\`(`]#`

개선의 여지가 많다고 확신합니다.

첫 번째 프로그램에는 하나의 문자열 (많은 중복성에도 불구하고 모든 문자가 이스케이프 됨)과 실행 가능한 부분 A 및 B가 있습니다. 부분 A는 여러 가지 작업을 수행합니다. 문자열을 인쇄하고 모든 문자에서 이스케이프하고 마지막 절반을 인쇄합니다 문자열 (부분 B의 소스)의 다음 부분 B가 문자열을 수행하지 못하게합니다.

두 번째 프로그램은 동일한 문자열 다음에 파트 B가옵니다. 파트 B는 간단한 quine에 기반합니다. 이스케이프 된 버전이 앞에 오는 문자열을 인쇄합니다. 이것은 문자열과 파트 A와 B를 모두 인쇄한다는 것을 의미합니다.


의심의 여지없이 이것이 프로그래밍 언어로서 Element의 유효성을 입증한다고 생각합니다. 사용하기가 너무 쉬워서 경험이 없어서 Element에 대한 하나의 완전한 통역사 만 작성할 수 있었으며이 지구상의 다른 사람보다 7,000,000,000 명의 사람들 에게이 질문에 대답 할 수있었습니다. Element의 "한 문자, 하나의 함수, 항상"패러다임은 모든 코드가 완전히 명확하다는 것을 의미합니다. 이 언어는 다재다능합니다.를 제외하고 []{}모든 명령을 구문 오류없이 전체 프로그램의 어느 곳에 나 배치 할 수 있습니다. 이거 완벽 해.
PhiNotPi

4
약간 편향되어 있습니까? ;-)
Gaffi

3

VBA : (251 + 216) / 2 / 2 = 116.75

251

Sub a()
r=vbCrLf:c="If b.Lines(4, 4) = c Then"&r &"b.InsertLines 8, d"&r &"b.DeleteLines 4, 4"&r &"End If":d="b.InsertLines 6, c"&r &"b.DeleteLines 4, 2"
Set b=Modules("Q")
If b.Lines(4, 4) = c Then
b.InsertLines 8, d
b.DeleteLines 4, 4
End If
End Sub

216

Sub a()
r=vbCrLf:c="If b.Lines(4, 4) = c Then"&r &"b.InsertLines 8, d"&r &"b.DeleteLines 4, 4"&r &"End If":d="b.InsertLines 6, c"&r &"b.DeleteLines 4, 2"
Set b=Modules("Q")
b.InsertLines 6,c
b.DeleteLines 4,2
End Sub

이 개체를 사용하기 위해 MSAccess 에서 실행됩니다 Module. 이 모듈은 "Q"골프 용 으로 명명 되었습니다. 구문의 차이점 If ... Then은 짧은 버전에서 누락 된 것입니다.


당신은 가능성이 가장 높은 변화와 함께 멀리 얻을 수 vbCrLFvbCr
테일러 스콧

3

C ++, 0.734194 점

다음 소스 코드는 순서 999의 메타 퀴인을 콘솔에 인쇄합니다 (아래 설명).

#define X 1*(1+1)
#include<iostream>
#include<vector>
#define Q(S)auto q=#S;S
Q( \
  main() \
  { \
      using namespace std; \
      cout<<"#define X 1"; \
      int x=X==2?1000:X-1; \
      vector<int> factors; \
      for ( int p = 2; p <= x; ++p) \
      { \
        while ( x % p == 0 ) \
        { \
          factors.push_back( p ); \
          x /= p; \
        } \
      } \
      for ( int factor : factors ) \
      { \
        cout<<"*(1"; \
        for ( int i=1;i<factor;++i) \
          cout<<"+1"; \
        cout<<")"; \
      } \
      cout<<"\n#include<iostream>\n#include<vector>\n#define Q(S)auto q=#S;S\nQ("<<q<<")"; \
  })

변경되는 유일한 줄은 첫 번째 줄입니다. 값은 X1000, 999, 998, ..., 3, 2가되고 다시 시작됩니다. 그러나 매번 다른 구문 트리를 얻기 위해 X모든 소수는 1s 의 합으로 작성된 소수 분해로 표시됩니다 . 정수의 소인수 분해는 모든 값마다 다르기 때문에 AST는 다릅니다.

첫 번째 줄이 변경되고 그 안에있는 백 슬래시, 줄 바꿈 및 들여 쓰기 Q(...)가 제거 된다는 점을 제외하고 프로그램 자체가 인쇄 됩니다.

다음 프로그램은 내 답변의 점수를 계산합니다.

#include <iostream>

const int n = 1000;

int getProgramLength( int n )
{
  int sum = 442;
  for ( int p = 2; p*p <= n; ++p )
  {
    while ( n % p == 0 )
    {
      sum += 2 * ( 1 + p );
      n /= p;
    }
  }
  if ( n > 1 )
    sum += 2 * ( 1 + n );
  return sum;
}

int main()
{
  int sum = 0;
  for ( int i = 2; i <= n; ++i )
    sum += getProgramLength( i );
  std::cout << (double)sum/(n-1)/(n-1) << '\n';
}

콘솔에 0.734194를 인쇄했습니다. 분명히 1000은 더 큰 정수로 대체 될 수 있으며 점수는 한계로 0에 접근합니다. 수학적 증거는 리만 (Riemann)의 제타 (Zeta) 기능이 다소 복잡하다는 것을 의미합니다. 나는 그것을 독자에게 연습으로 남겨 둡니다. ;)


2

자바 스크립트, 84.5 64 61

두 프로그램 모두 길이 169 (128) (122).

(function c(){alert(/*
2/*/1/**/);return ('('+c+')()').replace(/\/([/\*])/,function(m,a){return a=='*'?'/\/':'/\*'});
})()

골프를 치기 전에 시청의 즐거움을 위해

(function c() {
    var r = /\/([/\*])/;
    var f = function(m, a) { return a === '*' ? '/\/' : '/\*' };
    var p = '(' + c + ')();';
    p = p.replace(r, f);
    /* This is just a comment!
    console.log('Quine, part two!'); /*/
    console.log('Quine, part one!'); /**/
    return p;
})();

새로운 프로그램을 반환하고 현재 부분을 출력합니다! 정규식 함수없이 짧게 만들 수는 있지만 ...하고 싶지 않습니다.


아니요, 그것들은 구문 상 구별됩니다. 줄 바꿈을 추가하면 즉.
Ry-

2

J-(24 + 30) / 2 / 2 = 13.5 점

J의 문자열은 백 슬래시 이스케이프되지 않고 따옴표 이스케이프 처리 된 a la Pascal : 'I can''t breathe!'입니다.

30$(,5#{.)'''30$(,5#{.)'         NB. program 1, 24 char
'30$(,5#{.)''''''30$(,5#{.)'''   NB. program 2, 30 char

프로그램 1에는 AST가 noun verb hook noun있고 프로그램 2에는 AST가 noun있습니다. 프로그램 2는 프로그램 1의 인용 버전으로, 실행시 프로그램 1 만 반환하므로이 방법을 쉽게 세 개의 사본으로 확장 할 수 없습니다.

프로그램 1은 소스의 코드 부분의 사본을 앞에 인용 부호를 붙여서 그 인용 부호 중 다섯 개를 끝에 추가하여 작동합니다 ( (,5#{.)). 그런 다음이 16 자 문자열에서 주기적으로 30자를 가져 오므로 결과적으로 정확하게 프로그램 2가 제공됩니다.

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