Програма, що перетворює себе на кодування рядка (quine-variant)


16

Напишіть програму, яка друкує наступну лінію з 80 символів:

Ця програма з codegolf.stackexchange.com пересмучує себе для кодування рядка.

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

Регекс у стилі Perl ^[A-Za-z0-9. ]{80}$буде відповідати будь-якій лінії введення. Ви не можете робити жодних додаткових припущень.

Оцінка подання - це кількість кодових балів у вихідному коді менше 94 . Нижній краще.

Код не повинен робити нічого, що було б неприйнятним у квіне ( наприклад, читання файлів). Зокрема, будь-яке подання з негативною оцінкою повинно якось обдурити, як 93! менше 64 80 .

Додано 2014-04-21: Весь вихідний код вашої програми повинен бути добре сформований у кодуванні символів, під яким ви рахуєте кодові очки. Наприклад, ви не можете використовувати 80 послідовних байт у діапазоні байтів UTF-8 (80..BF) і рахувати кожен як єдиний ЗНАЧЕННЯ ЗАМІНИ U + FFFD (або ще гірше, як зовсім не точку коду).

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


Перечитавши своє запитання, я не впевнений, чи відповідає моя відповідь саме тим, що ви мали на увазі. Чи все в порядку передачі нового рядка в програму чи потрібно запустити інтерактивний запит?
Денніс

@Dennis: Тому ваша відповідь не прийнятна. Швидше, він читає вхід перед друком "Ця програма від [...]".
Будь ласка, продовжте

Це я мав на увазі, я просто не висловив це добре. Інтерпретатор GolfScript зчитує все, що йому передано, перш ніж почати виконувати сценарій. Єдиний спосіб уникнути цього - запустити підказку, що робить трубопровід неможливим.
Денніс

Привіт, я пробую це в JavaScript. Здається, неможливо скласти квінти, не читаючи текст між тегами <script>? Яка мета permuting вихідного коду? Ви кажете "можливо перепорядкований"; це означає перестановку лише за потреби?
bacchusbeale

Відповіді:


5

GolfScript, 231 162 131

'1àâ4ÿaVo5GùpZBtiXOürsóNîMmWåKHc09JdñúêyzíECäYïhDU ãáIFõ6é8òRìjTv23ønuðLwxfSkôbëAelqý.çèPQ
öûg7'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~

Як це працює

Почнемо з вибору 94 різних символів, які отримають перестановку для кодування рядка. Будь-які 94 символи спрацюють, але для цілей гольфу ми вибираємо наступне:

\n .0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
àáâãäåçèéêëìíîïðñòóôõöøùúûüýÿ

Назвемо масив цих символів "&".

Рядок введення завжди буде містити 81 символ (включаючи НЧ). Усі ці символи присутні в перших 65 символах "&". Це єдина причина вибору символів у верхньому 128 байті.

Ми замінюємо кожен символ рядка його індексом на "&", тому LF стає 0, пробіл стає 1 і т.д.

Ми вважаємо 81 отримане число цифрами одного базового числа 65. Назвемо це число «N».

Тепер ми перераховуємо всі можливі перестановки "&" і отримуємо перестановку, що відповідає номеру зверху. Це досягається таким чином:

  1. Встановити c = 1і A = [].
  2. Додати N % cдо A.
  3. Встановити N = N / cі c = c + 1.
  4. Якщо c < 95повернутися до 2.
  5. Встановити i = 0і s = "".
  6. Отримайте charter &[A[i]], додайте його до “s” та вийміть його з “&”.
  7. Встановити i = i + 1.
  8. Якщо i < 94повернутися до 6.

Припустимо, у нас є кодові блоки "E" і "D", які кодують і декодують рядок, як пояснено вище.

Тепер нам потрібна обгортка для тих кодових блоків, які відповідають вимогам питання:

'encoded string'{\.$[{}/]:&; D puts '"#{`head -1`}"'~ E "'".@+\+\'.~'}.~

Це робить наступне:

  • {…}.~визначає блок, дублює його і виконує другу копію. Перший примірник залишиться на стеці.

  • \.$ поміняє кодований рядок на блок і створює копію кодованого рядка з відсортованими символами.

  • [{}/]:&; перетворює рядок зверху в масив, зберігає його у "&" та відкидає.

  • D puts розшифровує закодований рядок і друкує результат.

  • '"#{`head -1`}"'~читає один рядок введення, виконуючи head -1в оболонці.

  • E "'".@+\+ кодує рядок і попередньо додає одну пропозицію.

  • \'.~'поміняє кодований рядок і блок і додає рядок '.~'.

  • Після виконання блоку GolfScript друкує вміст стеку (закодований рядок, блок, '.~') і виходить.

"E" можна визначити так:

{&?}%        # Replace each character by its index in “&”.
);           # Remove the last integer from the array, since it corresponds to the LF.
65base       # Convert the array to an integer “N” by considering it a base 65 number.
[            #
  94,        # For each integer “c” in 0 … 93:
  {          #
    )        # Increment “c”.
    1$1$%    # Push “N % c”.
    @@/      # Rotate “N % c” below “N” and “c” and divide the first by the latter.
  }/;        # Discard “N”.
]            # Collect the results of “N % c” in an array “A”.
-1%          # Reverse “A”.
&\           # Push “&” and swap it with “A”.
[            #
  {          # For each “j” in “A”:
    1$=.[]+  # Push “&[j] [&[j]]”.
    @^       # Rotate “&” on top of “[&[j]]” and take their symmetric difference.
  }/         #
]            # Collect the charcters into an array.

"D" можна визначити так:

0&           # Push 0 (initial value of the accumulator “A”) and “&”.
@            # Rotate the encoded string on top of “&”.
{            # For each character “c” of the encoded string:
    @2$,*    # Rotate “A” on top of the stack and multiply it by the length of “&”.
    2$2$?+   # Get the index of “c” in “&” and add it to “A”.
    @@^      # Rotate “A” below “&” and “c” and take their symmetric difference.
}/;          # Discard “&”.
65base       # Convert “A” into the array of its digits in base 65.
{&=}%        # Replace each digit by the corresponding character in “&”.
''+          # Convert the resulting array into a string.

Заключний гольф:

  • Замініть \.$[{}/]:&;0&@на, 0@.$[{}/]:&\щоб зберегти два символи.

  • Визначте функцію {;65base}:bзбереження одного символу.

  • Видаліть усе пробіли, за винятком проміжних LF та LF у рядку.

Приклад

$ # Create GolfScript file using base64 to avoid encoding issues.
$ base64 > permute.gs -d <<< JzHg4jT/YVZvNUf5cFpCdGlYT/xyc/NO7k1tV+VLSGMwOUpk8frqeXrtRUPkWe9oRFUg4+FJRvU26TjyUuxqVHYyM/hudfBMd3hmU2v0YutBZWxx/S7n6FBRCvb7ZzcnezBALiRbe30vXTomXHtAMiQsKjIkMiQ/K0BAXn0vezs2NWJhc2V9OmJ+eyY9fSUnJytwdXRzJyIje2BoZWFkIC0xYH0iJ357Jj99JSliWzk0LHspMSQxJCVAQC99LztdLTElJlxbezEkPS5AXn0vXSInIi5AK1wrXCcufid9Ln4K
$
$ # Set locale to en_US (or any other where one character is one byte).
$ LANG=en_US
$
$ # Go back and forth between two different strings.
$ # Second and sixth line are user input, not output from the script.
$
$ golfscript permute.gs | tee >(tail -n+2 > tmp.gs) && golfscript tmp.gs && rm tmp.gs
This program from codegolf.stackexchange.com permutes itself to encode a string.
Permuting source code code points to encode a string is a certain quine variant.
'18äJoS3sgV9qdçëxm0ÿKMNe5íPî.Htn2ciâIuøbRZéð4AwB7áìUüöôWõèûfñåLàóDrhQlO6
pTaýzòkùYCyFêïãG júEvX'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~
Permuting source code code points to encode a string is a certain quine variant.
This program from codegolf.stackexchange.com permutes itself to encode a string.
'1àâ4ÿaVo5GùpZBtiXOürsóNîMmWåKHc09JdñúêyzíECäYïhDU ãáIFõ6é8òRìjTv23ønuðLwxfSkôbëAelqý.çèPQ
öûg7'{0@.$[{}/]:&\{@2$,*2$2$?+@@^}/{;65base}:b~{&=}%''+puts'"#{`head -1`}"'~{&?}%)b[94,{)1$1$%@@/}/;]-1%&\[{1$=.@^}/]"'".@+\+\'.~'}.~
$
$ # Sort all characters from the original source code and hash them.
$ fold -1 permute.gs | sort | md5sum
b5d978c81df5354fcda8662cf89a9784  -
$
$ # Sort all characters from the second output (modified source code) and hash them.
$ golfscript permute.gs | tail -n+2 | fold -1 | sort | md5sum
Permuting source code code points to encode a string is a certain quine variant.
b5d978c81df5354fcda8662cf89a9784  -
$
$ # The hashes match, so the characters of the modified source code are a permutation
$ # of the character of the original one.

224 мінус 94 - 130.
mbomb007

Не могли б ви детальніше?
Денніс

1

Перл, 1428 1099

Він містить 1193 символи ASCII (включаючи 960 перестановлених двійкових цифр). 1193 - 94 = 1099

$s='010011100001100010101100111111101001101011101000100000101011011010100110111111011111101011101000100110111111011100101000011101011110100000101000100101011111111110101100101101011010011100100100011110110001011100100001011010100111100000011110111110011100101000100110111111101001011110101011100110101110101101011110101100111111100010101101101100011110100101011111111111101101101000111111011110100111011100101000011101011110111111011010111111101100101101101011100010100111100000111110';$_=q{$i=join'',A..Z,a..z,0..9,'. ';print map({substr$i,oct'0b'.$_,1}$s=~/.{6}/g),$/;chop($s=<>);$s=join'',map{sprintf"%06b",index$i,$_}$s=~/./g;$t=join'',map{$_ x(480-(()=$s=~/$_/g))}0,1;print"\$s='$s';\$_=q{$_};eval#$t"};eval#000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

Моя перша конструкція

Перш ніж я взяв пропозицію від Денніса перейти на бінарний, у моїй програмі перестановлено восьмеричні цифри.

Моя перша конструкція кодує кожну рядок у 160 восьмеричних цифрах, по 2 цифри на символ. Це кодування має 100 8 = 64 різних символів. Восьма система має 8 різних цифр. Програма повинна мати 160 копій кожної цифри, тому вона перестановлює 8 × 160 = 1280 цифр.

Я зберігаю 160 цифр, $sа інші 1120 цифр $t. Я починаю з програми, яка не є квинтом, а лише друкує завдання до $sта $tдля наступного запуску. Це воно:

$s = '2341425477515350405332467737535046773450353640504537765455323444366134413247403676345046775136534656553654774255543645377755507736473450353677327754555342474076';
$t = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777';

# $i = character map of 64 characters, such that:
#  substr($i, $_, 1) is the character at index $_
#  index($i, $_) is the index of character $_
$i = join '', 'A'..'Z', 'a'..'z', '0'..'9', '. ';

# Decode $s from octal, print.
#  1. ($s =~ /../g) splits $s into a list of pairs of octal digits.
#  2. map() takes each $_ from this list.
#  3. oct() converts $_ from an octal string to a number.
#  4. substr() on $i converts number to character.
#  5. print() outputs the characters from map() and a final "\n".
print map({ substr $i, oct, 1 } $s =~ /../g), "\n";

# Read new $s, encode to octal.
#  1. ($s = <>) reads a line.
#  2. chop($s) removes the last character of $s, the "\n".
#  3. ($s =~ /./g) splits $s into characters.
#  4. map() encodes each character $_ as a pair of octal digits.
#  5. join() concatenates the pairs from map().
chop($s = <>);
$s = join '', map { sprintf "%02o", index $i, $_ } $s =~ /./g;

# Make new $t.
#  1. map() takes each $_ from 0 to 7.
#  2. $_ x (160 - (() = $s =~ /$_/g)) makes a string where $_ repeats
#     160 times, minus the number of times that $_ appears in $s.
#  3. join() concatentates the strings from map().
$t = join '', map { $_ x (160 - (() = $s =~ /$_/g)) } 0..7;

# Print the new assignments for $s and $t.  This is not yet a quine,
# because it does not print the rest of the program.
print "\$s = '$s';\n\$t = '$t';\n";

(() = $s =~ /$_/g))- призначення порожнього списку змінних. Цей трюк я беру з підручника з контексту на PerlMonks . Це змушує перелічити контекст оператора матчу =~. У скалярному контексті збіг був би істинним чи хибним, і мені знадобиться цикл, який би хотів $i++ while ($s =~ /$_/g)рахувати збіги. У контексті списку $s =~ /$_/g- це список відповідностей. Я ставлю цей список у скалярний контекст віднімання, тому Perl рахує елементи списку.

Щоб зробити квінку, я беру форму $_=q{print"\$_=q{$_};eval"};evalз лайків Perl за кодом Rosetta . Це одна Призначає рядок q{...}з , $_а потім дзвонить eval, так що я можу мати свій код в рядку , а також запустити його. Моя програма стає лайкою, коли я переношу свої треті до останніх рядків у $_=q{та };evalі змінюю останній printна print "\$s = '$s';\n\$t = '$t';\n\$_=q{$_};eval".

Нарешті, я програю програму, змінюючи перше завдання на $tкоментар та видаляючи зайві символи.

Він містить 1522 символи ASCII (включаючи 1280 перестановлених восьмеричних цифр).
1522 - 94 = 1428

$s='2341425477515350405332467737535046773450353640504537765455323444366134413247403676345046775136534656553654774255543645377755507736473450353677327754555342474076';#0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777
$_=q{$i=join'','A'..'Z','a'..'z','0'..'9','. ';print map({substr$i,oct,1}$s=~/../g),"\n";chop($s=<>);$s=join'',map{sprintf"%02o",index$i,$_}$s=~/./g;$t=join'',map{$_ x(160-(()=$s=~/$_/g))}0..7;print"\$s='$s';#$t\n\$_=q{$_};eval"};eval

Перехід на бінарний

У коментарях Денніс зауважив, що 960 перестановлених двійкових цифр буде менше 1280 восьмеричних цифр. Тому я зрозумів кількість перестановлених цифр для кожної бази від 2 до 16.

Maxima 5.29.1 http://maxima.sourceforge.net
using Lisp ECL 13.5.1
...
(%i36) n : floor(x);
(%o36)                             floor(x)
...
(%i41) plot2d(n * ceiling(log(64) / log(n)) * 80, [x, 2, 16],
              [xlabel, "base"], [ylabel, "number of permuted digits"]);
(%o41) 

графік з базою на осі x, число перестановлених цифр на осі y

Хоча база 8 є локальним мінімумом, бази 2 і 3 і 4 прив'язують до кращої бази, на 960 перестановлених цифр. Для кодового гольфу найкраще базувати 2, оскільки Perl має перетворення для бази 2.

Заміна 1280 восьмеричних цифр на 960 двійкових цифр економить 320 символів.

Перехід коду з восьмеричного на двійковий коштує 8 символів:

  • Перехід octдо oct'0b'.$_витрат 7.
  • Перехід /../gдо /.{6}/gвитрат 2.
  • Зміна "%02o" на "% 06b" `коштує 0.
  • Перехід 160до 480витрат 0.
  • Змінити, 0..7щоб 0,1зберегти 1.

Я дізнався деякі поради щодо гольфу Perl . Вони зберігають 14 символів:

  • Змінити 'A'..'Z','a'..'z','0'..'9'на A..Z,a..z,0..9, використовуючи голосні слова та голого числа, зберігається 12 символів.
  • Змінити, "\n"щоб $/зберегти 2 символи.

Я зберігаю 3 символи, переміщуючи #$tкоментар до кінця файлу. Це видаляє новий рядок, який закінчує коментар, і літерал \nу квині.

Ці зміни врятують загалом 329 символів і зменшили мою оцінку з 1428 до 1099.


1
Використання двійкових замість восьмеричних цифр вимагатиме "лише" 960 перестановних символів.
Денніс

@Dennis Дякую за пораду! Я перейшов на бінарний (збереження 312 символів). Перебуваючи тут, я переграв ще 17 персонажів.
Керніг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.