Чи можете ви Meta Quine?


25

Подібно до інших головоломок-квочок (точніше, цієї ), написати програму, яка виробляє джерело для себе.

Ось новий поворот: Вироблений код НЕ повинен бути ідентичним джерелу. Швидше, вона повинна вивести іншу програму, яка створить першу.

Завдання, пов'язане з вищезгаданим, досягнуто цього, перестрибуючи між двома мовами. Я думаю, що це буде зроблено лише однією мовою , але дві (або більше) версії джерела повинні бути суттєво різними (див. Правила нижче). З цим обмеженням відповіді однозначних персонажів будуть заборонені, що вимагає трохи більше думок, щоб вони були остаточними.


ПРАВИЛА

  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

Це насправді лише більш загальна версія цього виступу, і відповіді, надані там, також виграють.
перестали повертати проти годинника,

@leftaroundabout, вимога до синтаксичних різниць визнає недійсним "обертову квітку", тому це не є більш загальним.
виставка

2
Ніколи мета quine мені не сподобався.
Stack Tracer

Відповіді:


35

Python, 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 програм довжиною не більше 68 + 3n, даючи асимптотичний бал 0.

Якщо ви хочете, щоб програми зі змінною структурою, ми можемо реалізувати двійкове додавання на n бітах. Тут є 2 n програми довжиною O ( n 2 ). Відбувається в циклі через падіння долота для перенесення.

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]

Чи можу я розгубитися? Схоже, вихід є ідентичним джерелу (не мета цієї задачі)?
Гаффі

Подивіться у вкладений блок. passзміниться на t=n(t)та назад у всіх 2 ^ n поєднаннях.
кабінка

Я зараз це бачу. Ви переплутали мене з усім повторенням!
Гаффі

22
мені чомусь подобаються дуже довгі рішення для гольфу з крихітними балами.
виставка

Вау, ви цілком володіли цим! Дуже хороша.
Клавдіу

4

Perl, оцінка 110,25

Треба визнати, я не дуже добре лаяю. Я на 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 для цього запису (і елемента Element).


Елемент , оцінка 47,25

Перша програма - 105 символів.

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

Друга програма - 84 символи.

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

Я впевнений, що є багато можливостей для вдосконалення.

У першій програмі є один рядок (в якому кожен символ втікається, незважаючи на велику надмірність), за яким виконуються виконувані частини A і B. Частина A робить кілька речей: друкує рядок і виходить з кожного символу, друкує останню половину рядка (який є джерелом для частини B), а потім заважає частині B, що йде за ним, нічого не робити.

Друга програма - це той самий рядок, за яким слідує частина B. Частина B заснована на простому квінті; він друкує рядок, якому передує уникнута версія. Це означає, що вона друкує рядок, і обидві частини A і B.


Я думаю, що це остаточно, поза всяким сумнівом, доводить правомірність Element як мови програмування. Це настільки просто у використанні, що мені, настільки недосвідченому, що мені вдалося написати лише одного повного перекладача для Element, вдалося відповісти на це питання перед будь-якою іншою людиною на всій цій планеті у 7000 000 000 людей. Парадигма "один символ, одна функція, весь час" Елемента означає, що весь код абсолютно однозначний. Мова універсальна: за винятком []{}будь-якої команди можна розмістити в будь-якій точці всієї програми, не викликаючи синтаксичної помилки. Це ідеально.
PhiNotPi

4
Трохи упереджене, чи не так? ;-)
Гаффі

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відсутньої у коротшій версії.


ви, швидше за все, зможете піти, переходячи vbCrLFнаvbCr
Тейлор Скотт

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<<")"; \
  })

Єдиний рядок, який змінюється, - це перший рядок. Значення Xбуде 1000, 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 як до межі. Математичне підтвердження передбачає, що функція Зета Рімана є дещо викривленою. Я залишаю це як вправу для читача. ;)


2

JavaScript, 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;
})();

Повертає нову програму та виводить поточну частину! Я, мабуть, міг би скоротити його без функції регулярного вираження, але ... я цього не хочу.


Ні, вони синтаксично відрізняються. Після додавання нових рядків, тобто.
Ри-

2

J - (24 + 30) / 2/2 = 13,5 балів

Зауважте, що рядки в J - це не зворотна косою рисою, а ухилена цитатою à 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 під час запуску, тому цей метод не можна легко поширити на три копії: P

Програма 1 діє, беручи копію кодової частини джерела з цитатою, доданою в передній частині, і додаючи до кінця п'ять цитат ( (,5#{.)). Потім він циклічно займає 30 символів з цієї 16-символьної рядки, що дає саме програму 2.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.