Codegolf - Quote-Safe Quines

  • Автор темы 1206
  • Обновлено
  • 21, Oct 2024
  • #1

Ваша задача проста: написать программу (или функцию), которая не принимает никаких входных данных и выводит (или возвращает) свой исходный код. Загвоздка в том, что когда программа завернута в "quotes" (Unicode character 34), it should again output its (now quoted) source code.

Применяются стандартные правила для кайнов. Это , поэтому побеждает самая короткая программа (в байтах).

#code-golf #code-golf #string #quine #source-layout

1206


Рег
02 May, 2014

Тем
82

Постов
169

Баллов
629
  • 26, Oct 2024
  • #2

Python 2 3, 181 152 130 124 122 100 98 96 84 байта

-12 байт благодаря Жаку.

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 $z 

Попробуйте онлайн! TIO поставляется с верхним и нижним колонтитулом, которые автоматически проверяют достоверность квина. Вы можете очистить их, чтобы просто запустить квин.

Этот код работает путем (ab) использования строк в тройных кавычках и конкатенации строковых литералов в Python.

  • " ignores #" и наборы " к z .
  • z=\" ignores the empty string and sets : к || .

Остальная часть кода затем реализует традиционную схему Python, используя : string formatting, with some additional code that strips the extra quotes depending on ": " .

Старая версия от 2017 года, 122 байта

z

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

||z=" # is equal to : и : "||z=\" #" s=': "||z=\" #" s=\47%s\47 printf $z$s$z $s ' printf $z$s$z $s is equal to # Normal `q‛:Ė+ ` # structure for a quine => [ <quine> ] :Ė # add a copy of the structure on the stack and exec it q # push the quoted string on the stack => [ `<quine>` ] ‛:Ė+ # add ':Ė' to the string on the stack => [ `<quine>`:Ė ] $ # swap the two values on top of he stack => [ `<quine>`:Ė , 0 ] [ # pop and check if it is nul (it is) => [ `<quine>`:Ė ] ‛""$j, # irrevelent here # implicit output # Quoted " # listify the two elements on top of the stack => [ [0,0] ] `q‛:Ė+ ` # structure for a quine => [ [0,0] , <quine> ] :Ė # add a copy of the structure on the stack and exec it q # push the quoted string on the stack => [ [0,0] , `<quine>` ] ‛:Ė+ # add ':Ė' to the string on the stack => [ [0,0] , `<quine>`:Ė ] $ # swap the two values on top of he stack => [ `<quine>`:Ė , [0,0] ] [ # pop and check if it is nul (it is not as it's a list) => [ `<quine>`:Ė ] ‛"" # add `""` to the stack => [ `<quine>`:Ė, `""` ] $j # swap the two elements and join => [ "`<quine>`:Ė" ] , # print => [] " # listify the two elements on top of the stack => [ [0,0] ] # no implicit output as it has already printed via , .

В коде используется "`q‛:Ė+$[‛""$j,`:Ė" , but not for the "non-quiney" way of executing data as code, just for setting a variable from inside an expression. The `q‛:Ė+$[‛""$j,`:Ė также правильно закодирован в данных.

Первый оператор сравнивает строку, возможно, с добавленной кавычкой, с D , and sets the variable "--"#putStr соответственно. (Эта переменная могла бы быть любой короткой встроенной функцией.) Затем последняя часть проверяет, есть ли (#) is unchanged.

Альтернативная версия с использованием «читинга» (#) comes in at 126 bytes with less repeated code:

"--"#p=p['"']>>"--\""#p

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

 

Akirsanoff2011


Рег
28 Sep, 2011

Тем
49

Постов
173

Баллов
438
  • 26, Oct 2024
  • #3

СтандартML, 182 176 108 байт

--"#p=p['"']>>"--\""#p

Версия без кавычек: Попробуйте это на codingground.
Цитируемая версия: Попробуйте это на codingground.

Обратите внимание, что результат выглядит примерно так

"--"#p=p['"']>>"--\""#p k#p=p x>>print x>>p k;main="--"#putStr;x="--\"#p=p['\"']>>\"--\\\"\"#p\nk#p=p x>>print x>>p k;main=\"--\"#putStr;x=" --"

потому что код интерпретируется объявление за объявлением (каждое --"#p=p['"']>>"--\""#p k#p=p x>>print x>>p k;main="--"#putStr;x="--\"#p=p['\"']>>\"--\\\"\"#p\nk#p=p x>>print x>>p k;main=\"--\"#putStr;x=" -- ends a declaration) and shows the value and type of each declaration.


Фон

В SML есть квайн вида "`...`Dqp^≈[_\"pǏ]₴" " Push the set [0, 0] `...` Push the source code D Make 3 copies of the source code qp Uneval the first copy and prepend it to the second ^ Reverse the stack, putting [0, 0] on the top ≈[ ] Execute if all elements of the top of the stack are the same. This is the case because of the [0, 0] pushed by " _ Remove the third copy of the source from the stack \" Push `"` pǏ Prepend and enclose the source with `"` ₴ Print the source " Push [0, 0], having no effect because the source is already printed :

`...`Dqp^≈[_\"pǏ]₴ `...` Push half the source code D Make 3 copies of the source code qp Uneval the first copy (quote, escape) and prepend it to the second ^ Reverse the stack ≈[_\"pǏ] Execute if all elements are the same. Since this is not the case, it just pops the third copy of the source code ₴ Print the source

и один в форме `Dqp^≈[_\\"pǏ]₴`Dqp^≈[_\"pǏ]₴ :

D

Оба исходят из того, что x -part contains no quotes and can thus be quoted with out the need for escaping anything, the " необходимые для вывода куайна, имеют вид # .

Они также в значительной степени полагаются на неявный идентификатор. s='s=%r;print(s%%s)';print(s%s) which is used when no explicit identifier is given in a declaration.

В первом куайне x binds x='"' в строку, содержащую "#" , "x=" запускает анонимную функцию, принимающую один аргумент "x=""#";x='"' , then concatenates x="" и печатает полученную строку. Эта анонимная функция применяется непосредственно к строке, содержащей код программы, поэтому конкатенация # yields x=""#";x='"' .

Второй куайн начинается с кода программы в виде строки. x=""#";x='"' s='x=""#";x=\'"\'\ns=%r;print(x+s%%s+x)#';print(x+s%s+x)# which is bound to x=""#";x='"' s='x=""#";x=\'"\'\ns=%r;print x+s%%s+x#';print x+s%s+x# . Затем " concatenates a quote to the start of the string and as again no explicit identifier is given, the resulting string print обязан $\ . Finally q;...; объединяет строку сама с собой, получая q;"; which is then printed.


Объяснение

Редактировать: 108-байтовая версия уже не актуальна, однако это можно понять и после прочтения этого объяснения.

Кавычно-безопасный куайн сочетает в себе оба вышеперечисленных подхода и сам имеет форму $\ . Putting this in again in quotes yields ; , поэтому мы получаем пустую строку, а затем квину другой формы.

Это означает, что программе либо дается собственный исходный код в виде "" by the identifier # , или $\ is just print и нам дан наш собственный источник ;; as argument and must thus be a function which handles such an argument.

";$\=q;"

Чтобы определить, в каком случае мы находимся, мы проверяем, соответствует ли размер "";$\=q;";;$_=q(print$\,'";$\=q;";;$_=q('."$_);eval#");eval#" is larger than 1. If not then ";$\=q;";;$_=q(print$\,'";$\=q;";;$_=q('."$_);eval#");eval# является Set=``;eval(";a='Set=``;eval(~;a=1;S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);~)';S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);") and we are in the second case, so the <div id="noodel" code='"ḷḥ-Ðḥ@ḅ"' input="" cols="10" rows="1"></div> <script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script> <script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script> -part возвращает анонимную функцию <div id="noodel" code='ḷḥ-Ðḥ@ḅ' input="" cols="10" rows="1"></div> <script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script> <script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script> which is then called because its followed by source as string. Note the leading "ḷḥ-Ðḥ@ḅ" " # Pushes on the string literal "\"" onto the stack. ḷḥ-Ðḥ@ḅ # Same execution as before, simply builds the Quine for this loop. ḷ # Loop the following block of code unconditionally. ḥ- # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack. Ð # Push the stack as an array to stdout (since is an array it is done by reference). ḥ@ # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack. ḅ # Break out of the given loop. (The stack is now ["\"", "ḷ", "ḥ-Ðḥ@ḅ"]). " # Pushes on the string literal "\"" onto the stack. # The top of the stack is popped off and displayed which modifies the array to produce {["\"", "ḷ", "ḥ-Ðḥ@ḅ"], "\""} in stdout. который необходим для пустой строки в начале программы.

Если " is larger than 1 we are in the ḷḥ-Ðḥ@ḅ # Single statement that builds itself as a string. ḷ # Loop the following block of code unconditionally. ḥ- # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack. Ð # Push the stack as an array to stdout (since is an array it is done by reference). ḥ@ # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack. ḅ # Break out of the given loop. (The stack is now ["ḷ", "ḥ-Ðḥ@ḅ"]). # The top of the stack is popped off and displayed which modifies the array to produce {["ḷ"], "ḥ-Ðḥ@ḅ"} in stdout. -расставаться и просто выступать ḷḥ-Ðḥ@ḅ , right? Not quite, because I neglected to tell you that SML is strongly typed which means that a conditional Ḷ1ḥ-Ð1ḥ@€ всегда должны иметь один и тот же тип, что снова означает, что выражения l " Move one character to the right. If there is no character to the right, " then this is effectively a "break" statement, stopping playback of the recording xx " Delete two characters (the '"P') | " Move to the first character on this line x " Delete one character ÿ " End the program и "qp необходимо иметь один и тот же тип. Мы уже знаем тип "éPñi"éP<C-v>241<esc>"qpá" Cursor is here ----------^ part: An anonymous function which takes a string and then calls "éPñi"éP<C-v>241<esc>"qpá"P Cursor is here ----------^ имеет тип ñ " Start recording into register 'q' i " Enter insert mode "éP<C-v>241<esc> " Enter the following text: '"éPñ' "qp " Paste the text in register 'q' á" " Append a '"' , and ñi<C-v>241<esc>"qpÿ имеет тип "éP ( éP в чем-то похоже на 00000000: e950 f169 22e9 5016 3234 311b 2271 70e1 .P.i".P.241."qp. 00000010: 226c 7878 7c78 ff "lxx|x. in other languages), so the resulting type is again éPñi"éP<C-v>241<esc>"qpá"lxx|xÿ .

Итак, если éPñi"éP241"qpá"lxx|xÿ part was just print который имеет тип then , we would get a type mismatch error. So how about (print(it^it);print) ? ( <exp_n-1> is a wildcard for an argument that is not used) This anonymous function on its own has type <exp_1> где <exp_n> stands for an arbitrary type, so in the context of our conditional which enforces a <exp_n-1> типа это сработает. (Переменная типа <exp_1> gets instantiated with type (<exp_1>; ...; <exp_n>) .) Однако в этом случае мы бы ничего не печатали, поскольку анонимная функция никогда не вызывается! Помните, когда мы заходим в <code> -part the overall code is "<code>"<code> , поэтому then -part evaluates to a function but, as nothing comes after it, its not called.

Вместо этого мы используем секвенциализацию, которая имеет форму string where 'a to string -> unit may have arbitrary types and the type of 'a обеспечивает тип всей секвенциализации. С функциональной точки зрения значения 'a -> unit to _ просто отбрасываются, однако SML также поддерживает императивные конструкции, поэтому выражения могут иметь побочные эффекты. Короче говоря, мы берем fn _=>print(it^it) as the unit -part, таким образом сначала печатая, а затем возвращая функцию print(it^it) which has the correct type.

 

Dogirrepe


Рег
25 Jan, 2011

Тем
73

Постов
210

Баллов
595
  • 26, Oct 2024
  • #4

В, 27, 23 байта

then

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

Поскольку здесь содержатся некоторые непечатаемые символы, вот читаемая версия:

string -> unit

и вот шестнадцатеричный дамп:

void

Итак, самое первое, что нам нужно сделать, это определить, является ли первый символ кавычкой. unit inserts a 'P' character, but string -> unit это НООП. После этого мы немного модифицируем стандартную выдвижную стойку, а именно:

print

Хотя мы собираемся сделать это немного по-другому. Прежде всего нам нужно вставить начальный текст «éP». Итак, мы делаем

string -> <return type of print>

Вот где происходит ветвление. Текст, находящийся в данный момент в буфере,

print

Если бы мы не заключили его в кавычки, в этом случае буква «P» никогда бы не была вставлена, и буфер будет:

else

Поскольку мы все еще записываем, мы можем делать здесь все, что захотим, и это будет добавлено в буфер, когда <exp_2> happens. So from here it's pretty easy to conditionally delete the quotes:

<exp_1> ||answer||

Нудель, 9 7 байты

Эта версия работает так же, как и другая, просто я забыл об этом. Нудель есть способ один раз запустить блок кода, и я создал язык...

if <cond> then <exp_1> else <exp_2>

print(it^it)

Попробуйте :)


Как это работает

then

Цитата-Безопасность

Размещение size it character before and after the program works because Нудель есть набор символов, посвященных тому, что я называю распечатки. При размещении они сразу же анализируются как строковые литералы и позволяют легко вывести что-либо на экран. Таким образом, в отличие от большинства языков, Нудель видит нормальное ASCII set, который считается достойным печати в качестве прямых строковых литералов (за исключением пробела и перевода строки), при этом цитирование кода рассматривается просто как нажатие на строки.

it^it^

«Попробуй :)»


Фрагменты

fn x=>print(it^it^x^it^x^it)
else ||answer||

JavaScript (ES6), 239 237 байт

"

Обязательно попробуйте каждую версию в новой среде (например, на новой вкладке браузера).

Должен быть хотя бы один способ упростить это...

 

Shandy


Рег
14 Feb, 2011

Тем
75

Постов
206

Баллов
611
  • 26, Oct 2024
  • #5

Перл 5, 59 байт

it

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

Цитируется

it

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

Объяснение

В оригинале есть неиспользуемая строка (if size it>1then(print(it^it);fn _=>())else fn x=>print(it^it^x^it^x^it)) separated by <code> перед стандартным телом куайна, которое сначала " s it (по умолчанию пусто), за которым следует неиспользуемая строка и тело, за которым следует it .

В строке в кавычках есть неиспользуемая строка "<code> , separated by ""<code>"<code>" затем "<code>"<code> is set to "<code>"<code> это пользовательские кавычки Perl print(it^it) wrapping the double-quote char. Then the quine body is built and it автоматически "<code> ed after all content adding the final str(chr 34)^it; в строке в кавычках.

 

Йена


Рег
07 Feb, 2007

Тем
75

Постов
213

Баллов
628
  • 26, Oct 2024
  • #6

Питон 2, 68 байт & Питон 3, 70 байт

Питон 2, 68 байт:

it

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

Python 3, 70 байт:

";str(chr 34)^it;print(it^it)";

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

Как это работает? :

  • Без кавычек: <code>"<code>" will stop the execution at the coment x^it^x^it символ => x^it^x^it
  • С кавычками: x have just 2 string concatened fn x=> and " which don't do anything, and an assignation : it

Сейчас str(chr 34); is filled with the good char (quote or empty).

Затем мы используем стандартный Python Quine: it adding a few extras to make it work here, for example str(chr 34) в конце, чтобы избежать ошибки EOF, когда " is added at the end of the program

Затем мы просто распечатываем нашу куайну, добавляя <code> at the start and at the end of the string

 

Sergsaparov


Рег
09 Nov, 2019

Тем
72

Постов
192

Баллов
592
  • 26, Oct 2024
  • #7

Виксал ";str(chr 34)^it;print(it^it)";str(chr 34)^it;print(it^it) , 29 bytes

"<code in quotes>"<code>

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

Объяснено:

str(chr 34);(fn x=>print(x^it^x^it))"str(chr 34);(fn x=>print(x^it^x^it))"

Цитируемая версия: («Попробуйте онлайн!»)

<code>"<code in quotes>" ||answer||

Хаскелл, 142 байта

;

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

> val it = "{some string}" : string > val it = "{some string}" : string {output to stdout}> val it = fn : string -> unit

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

Здесь используется довольно простой метод обнаружения.

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

";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))

Однако, когда цитата добавляется спереди

""" """>" "and exec("oct=0");s='"""" """>" "and exec("oct=0");s=%r;p=%r;exec(p)#".';p='a=oct!=0;print(s[a:~a]%(s,p))';exec(p)#

Это становится декларацией оператора exec . So what this program does is defines oct так, что он печатает обычный источник при вызове с помощью oct , however when the quotes appear the new definition supersedes it and prints the source with quotes.

 

Justamooose


Рег
14 Jul, 2020

Тем
80

Постов
199

Баллов
629
  • 26, Oct 2024
  • #8

Виксал " " , 18 17 bytes

Нормальный

exec

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

Цитируется

exec

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

Объяснение :

'" ' ||answer||

Зш, 76 байт

"""" """

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

«Попробуй онлайн!»

Обратите внимание на завершающую новую строку.

Без кавычек первая строка — это вызов встроенной функции no-op. ' ' , which ignores its string argument """ """ . Переменная """ """>" "or exec("oct=0");p='"""" """>" "or exec("oct=0");p=%r;a=oct==0;print(p[a:~a]%%p)#".';a=oct==0;print(p[a:~a]%p)# remains empty.

В кавычках первая строка выглядит так:

  • b : execute %r (обратите внимание на пробел), это несуществующая команда
  • ';b=" ' : if this fails (which it will, since b не существует), то:
  • "";b=""";b=" """; : set the variable ' ' в одну двойную кавычку b
  • ';b=' : comment; ignored

Дополнительный ";b=""";b=" """; on the last line is unmatched, but zsh helpfully ignores that until after the program has executed because it's a separate command line.

Остальное — довольно стандартная куйна из ракушек, но мы окружаем струну a=1;""";a=0;" """;p='"a=1;""";a=0;" """;p=%r;print(p[a:~a]%%p)#".';print(p[a:~a]%p)# so it gets double quotes if necessary.

 

Athcent


Рег
18 Mar, 2009

Тем
72

Постов
179

Баллов
539
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно