Сделать переплетение

17

Ваша задача - создать программу, которая при запуске возвращает себя в качестве вывода (это называется quine). Тем не менее, эта квинна должна, когда она копируется nраз, возвращает квин, но с каждым из ее символов, продублированных по местам n, где nположительное целое число.

Если ваша оригинальная программа Derp:

Derp -> Derp (must return itself as output to be a quine)

DerpDerp -> DDeerrpp
(the "Derp" is copied twice, so each character in the output has to be copied twice)

DerpDerpDerp -> DDDeeerrrppp
etc. etc.

Имейте в виду, что вам разрешено иметь пробелы в вашей «базовой» программе, но они учитываются при «переплетении». Скажи, что твоя программа

Derp 
{newline}

(Новая строка означает завершающий символ новой строки, после которого есть дополнительный пробел Derp). Когда дублируется, чтобы стать

Derp 
Derp 
{newline}

Вы должны вывести

DDeerrpp  
{newline}
{newline}

Имейте в виду, что 2после DDeerrpp.

Правила и характеристики:

  • Ваша программа должна содержать как минимум два разных символа (это означает, что ваш код должен быть длиной не менее 2 байтов).
  • Применяются стандартные правила Квина .

Это , поэтому выигрывает самый короткий код в байтах!

clismique
источник
1
«Применяются стандартные правила» - значит ли это, что вы не читаете исходный код?
FlipTack
@FlipTack Это означает, что - прочитайте ссылку для получения дополнительной информации.
clismique

Ответы:

12

Деление , 6 байт

'!+OR"

Попробуйте онлайн! Попробуйте две копии! Попробуй три!

объяснение

Это просто стандартная квинция деления . Это работает для этой задачи, потому что у Fission есть явные точки входа в программу. В частности, дублируя программу, мы добавляем еще один, Rкоторый добавляет еще один атом (указатель инструкции). Поскольку исходный код является тороидальным, эффективный исполняемый код не изменяется в противном случае - для каждого атома код по-прежнему выглядит одинаково локально. Однако атомы выполняются в шаге блокировки, так что вещи, которые они печатают, чередуются, и мы получаем дополнительную копию каждого символа в выводе.

Для полноты картины я просто вкратце повторю, как работает сама программа. Независимо от того, повторяем ли мы программу или нет (например '!+OR"'!+OR"'!+OR"), каждый атом видит следующий код:

R"'!+OR"'!+O

"Режим печати переключает строки, так что программа начинается печать '!+ORнепосредственно на STDOUT, что все , кроме Куайной цитаты. Затем '!устанавливает массу атома в код символа !, +увеличивает его, что дает ", и Oпечатает его, одновременно уничтожая атом. Затем программа завершается, потому что не осталось ни одного атома.

Мартин Эндер
источник
11

Python 2,7 377 310 304 194 191 байт!

Это мой первый гольф, поэтому я не ожидал, что он будет слишком хорошим. Но я думал, что концепция в предложенном мной решении была несколько забавной, поэтому я все равно публикую ее.

def f():
 import threading as T,inspect as i;global t,a,i
 try:t.cancel()
 except:a=0
 a+=1;t=T.Timer(1,d);t.start()
def d():print''.join(c*a for c in i.getsource(f)+i.getsource(d)+"f()")
f()

В самом деле, это Quine; Вы можете попробовать это здесь . Он злоупотребляет модулем проверки довольно сложно.

Если мы попробуем запустить его с тем же исходным кодом x2, мы также получим правильный вывод; Вы можете попробовать это здесь . х3, х4 и т.д. все работают как положено.

Разгромленный с объяснением:

def f():                                   # Defines a central function f
    import threading as T,inspect as i     # Imports threading and inspect
    global t,a,i                           # Global vars
    try:
        t.cancel()                         # Tries to cancel Timer from previous code
    except:
        a = 0                              # Reached when code is 1st copy; initializes a.
    a += 1                                 # a++; this is the number of copies thus far.
    t = T.Timer(1,d)               # Creates, then starts a timer to call function
    t.start()                              # d in 1 second.

def d():                                   # Prints out the source code; the quine part.
    print''.join(c*a for c in i.getsource(f)+i.getsource(d)+"f()")

f()                                        # Calls f()!
Calconym
источник
Разве это не обман, поскольку он читает исходный код своих собственных функций, используя inspect? (см. соответствующий мета-пост ). На PPCG у нас есть конкретные определения того, что делает квину действительной, и «чтение источника» обычно рассматривается как мошенничество.
FlipTack
@FlipTack Я не уверен, что проверка функции - это то же самое, что чтение исходного кода. Квины в JavaScript и в стековых языках делают это постоянно.
Деннис
Ok :). Я добавил подсветку синтаксиса для вашего поста. Хорошая идея с использованием потоков!
FlipTack
import threading,inspect as iможет бытьimport threading as T,inspect as i
nedla2004
@FlipTack Ой, спасибо.
Calconym
3

CJam , 19 байтов

{]W=s"_~"+T):Te*}_~

Попробуйте онлайн!

Как это устроено

{               }_~  Define an anonymous code block (function).
                 _~  Push a copy, and execute the copy.
 ]W=                 Wrap the entire stack in an array and select its last element.
                     This discards whatever was on the stack before the original
                     code block, which is needed for subsequent iterations.
    s"_~"+           Cast the code block to string, push "_~", and concatenate.
                     This pushes the stringified source code on the stack.
          T):T       Push T (initially 0), increment it, and save the result in T.
              e*     Repeat each character in the stringified source code T times.
Деннис
источник
Что ... как ... так быстро ... пожалуйста, объясните код, чтобы вы могли научить меня способам CJam.
clismique
@ Qwerp-Derp Я добавил объяснение.
Деннис
3

RProgN , 66 байт

Значительный пробел будет смертью меня

[ "[ %q ] F 0 1 + `0 = `. { 0 m } R " ] F 0 1 + `0 = `. { 0 m } R 

Разъяснения

[ "[ %q ] F 0 1 + `0 = `. { 0 m } R " ] F 0 1 + `0 = `. { 0 m } R   #
[                                                                   # Pop whatever is already on the stack, if anything.
  "[ %q ] F 0 1 + `0 = `. { 0 m } R "                               # This string contains basically the entire function.
                                      ] F                           # ] F duplicates the string, and then F formats it, which in this case puts the first string into the second at %q, surrounded by qoutes.
                                          0 1 + `0 =                # I needed an Incrementer, so I chose 0. 0, is conveniently, pre initilized at 0. And because RProgN is horrifying, you can remap the number functions as they're just more variables. So this increments 0 every time the group is called.
                                                     `. { 0 m } R   # Replace each character with itself repeated '0' times. Because '0' is an incrementer, each time the script is called, the amount of times the characters are repeated increase.

Боже мой, я монстр ...

Попробуйте онлайн!

Ataco
источник
Кроме того, хотя ~["[%q]F01+`0=`.{0m}R"]F01+`0=`.{0m}Rв целом работает нормально, это недопустимое решение, поскольку нет способа реплицировать маркер ZSS.
ATaco
2

Perl 5, 107 байт

$_=q[$_=q[S];s/S/$_/;$a++;END{s/./$&x$a/eg;print if$a;$a=0}];s/S/$_/;$a++;END{s/./$&x$a/eg;print if$a;$a=0}

Ungolfed:

$_ = '...INSERT_SOURCE_HERE...';      # Standard quine
s/INSERT_SOURCE_HERE/$_;
$a++;                                 # Count the number of repetitions
END {
    s/./$&x$a/eg;                     # Interweave
    print if $a;                      # Print...
    $a=0;                             # ...but only once
}

Попробуйте онлайн!

Джои Марианер
источник
2

Питон 3 , 122 121 112 байтов

s='try:from atexit import*;n+=1\nexcept:n=1;register(lambda:[print(end=c*n)for c in"s=%r;exec(s);"%s])';exec(s);

Попробуй онлайн: одна копия | две копии | три копии | четыре копии, с автоматической проверкой

Как это устроено

При этом используется стандартная строка Python: сохраняйте код, который вы хотите выполнить, в переменной (в виде строки); включить некоторую логику в эту строку, чтобы напечатать себя, все до него и все после него; затем выполните эту строку.

Код, который выполняется через строку s следующий.

try:from atexit import*;n+=1
except:n=1;register(lambda:[print(end=c*n)for c in"s=%r;exec(s);"%s])

Первая строка безоговорочно импортирует модуль atexit , что позволит нам зарегистрировать обработчик выхода. Попытка импортировать один и тот же модуль несколько раз никак не повлияет на сценарий. Затем он пытается увеличить переменную n , чтобы отслеживать, сколько копий исходного кода было выполнено.

Вторая строка выполняется только в том случае, если первая содержит ошибку. Это будет иметь место в первой итерации, так как n все еще не определено. В этом случае мы инициализируем n как 1 и регистрируем лямбду, которая выполняет действительную магию.

Зарегистрированный обработчик выхода

lambda:[print(end=c*n)for c in"s=%r;exec(s);"%s]

будет вызван прямо перед завершением программы. Лямбда сама создает строку "s=%r;exec(s);"%s- %rсоздает строковое представление правильного аргумента ( ов ), который включает все между одинарными кавычками и самими кавычками, - затем перебирает свои символы. Для каждого символа c мы просто печатаем n копий c . Переходя в c*nкачестве имени аргумента endв printозначает , что нет перевода строки не будет прилагаемым.

Деннис
источник