Умножение путем само-модификации


33

... по крайней мере, для некоторого определения "само-модификации".

Задание

В этих проблемах, ваша задача состоит в том, чтобы написать три строки A, Bи Cкоторые удовлетворяют следующие свойства.

  • Строка Bимеет длину не менее 1.

  • Для каждого n ≥ 0, строка является допустимой программой (имеется в виду полностью исполняемая программа или определение функции) на выбранном вами языке программирования. Индекс указывает повторение, поэтому это означает , что строки , , , и т.д. Каждая программа занимает одну строку в качестве входных данных, и возвращает одну строку в качестве вывода.ABnCACABCABBCABBBC

  • Для любого m, n ≥ 0, если программа запускается с вводом , она возвращается . Для входных данных, не имеющих этой формы, программа может делать все что угодно, включая сбой.ABmCABnCABm*n+1C

Некоторые примеры в формате program(input) -> output:

AC(AC) -> ABC
ABC(AC) -> ABC
ABBBBBC(AC) -> ABC
AC(ABC) -> ABC
AC(ABBBBC) -> ABC
ABC(ABC) -> ABBC
ABBC(ABC) -> ABBBC
ABBBBC(ABBBC) -> ABBBBBBBBBBBBBC
ABBBC(ABBBBBBC) -> ABBBBBBBBBBBBBBBBBBBC

Правила и оценки

Ваша оценка - это общая длина AиC , чем ниже, тем лучше. Обратите внимание, что хотя Bсчет не учитывается, он должен быть получен Aи Cкак в первом примере.

Стандартные лазейки запрещены. Программам не разрешен прямой или косвенный доступ к их собственному исходному коду (кроме случаев, когда они передаются в качестве входных данных). Вы должны определить строки A, Bи Cв своем ответе каким-то образом, и рекомендуется объяснить свое решение.

Ответы:


16

CJam, 9 8 байтов

A: 1
B: 0
C:  r,(#0q

Попробуйте онлайн в интерпретаторе CJam .

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

(ABcode) e# Push the integer 10 ** len(Bcode).
<SP>     e# Noop. Separates (AB) and C for input reading.
r        e# Read the first whitespace-separated token from STDIN (ABinput).
,(       e# Push the string length minus 1: len(Binput)
#        e# Power operator: 10 ** len(Bcode) len(Binput) # ->
         e#   (10 ** len(Bcode)) ** len(Binput) = 10 ** (len(Bcode) * len(Binput))
0        e# Push an additional 0 to complete len(Bcode) * len(Binput) + 1 zeroes.
q        e# Read the remaining input (C).

12

CJam, 15 13 11 байт

A: rl"
B: <SP>
C: <LF>",(*SNq

Попробуйте онлайн в интерпретаторе CJam .

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

e# A

r     e# Read a whitespace-separated token from STDIN.
      e# This reads the input up to the first space, but does not consume it.
l     e# Read the rest of the first line from STDIN.
      e# This reads up to the first linefeed and consumes it.

"     e# Initiate a string.

e# B

<SP>  e# Fill the string with as many spaces as there are copies of B.

e# C

<LF>" e# Terminate the string with a linefeed.
      e# This serves as a delimiter for the `l' command.
,(    e# Compute the length of the string minus 1 (to account for the LF).
*     e# Repeat the string read by `l' that many times.
SN    e# Push a space and a linefeed.
q     e# Read the remaining input (i.e., the second line) from STDIN.

В конце, стек содержит токен, прочитанный r, пространство, произведенное *, пространство и перевод строки и нажатую SNстроку q. CJam печатает все это автоматически.


Ха, приятно использовать цитаты там: D
Оптимизатор

9

Пиф, 10

A: w*\0hl*w[<newline>
B: 0
C: <empty>

Мы разбили источник на две строки. Первая строка A, вторая строка Bs. Поскольку A находится на первой строке, первая wпросто печатает A - легко, готово.

В Pyth ведущие нули - это отдельные токены, так оно и есть на [00)самом деле [0, 0]. Обратите внимание, что первая строка заканчивается l[, а вторая строка состоит из 0000.... Так что на l[самом деле подсчитывает количество Bs в этой программе. Вторая wчитается во второй строке ввода - это число Bs ввода. Отсюда простое умножение, приращение и вывод множества нулей.


9

Сетчатка , 25 19 байт

A: ]\]<LF>
B: ]]
C: <LF>m`^]*$<LF>]$0]

<LF> stands for newline

Пример ABCкода:

]\]
]]
m`^]*$
]$0]

Код имеет два шага замены:

  • изменить вход AB^mC в AB^(m*n)Cизменив каждый Bна B^n:

    • ]\]соответствует каждому Bвходу и ничему другому благодаря экранированию в строках шаблона
    • ]]...]] является B^n
  • менять B^(m*n) к B^(m*n+1)по

    • m`^]*$занимая линию только ]с
    • ]$0]добавив к нему дополнительную пару ]]таким образом, чтобы эта строка не соответствовала первому регулярному выражению

Я добавил 3 байта в счет для -s многострочного флага, который необходим, чтобы весь код Retina мог быть в одном файле.

2 байта сохранены благодаря @ MartinBüttner.


8

Python 3, 51 байт

A: lambda s:s[:28]+"x"*(1+len("
B: x
C: ")*(len(s)-51))+s[-23:]

Пример использования:

>>> f=lambda s:s[:28]+"x"*(1+len("xx")*(len(s)-51))+s[-23:]
>>> f('lambda s:s[:28]+"x"*(1+len("xxx")*(len(s)-51))+s[-23:]')
'lambda s:s[:28]+"x"*(1+len("xxxxxxx")*(len(s)-51))+s[-23:]'

Функция вычисляет n*m+1с , (1+len("xxx")*(len(s)-51))где есть m x«ы в строке ( xxxчасть является B^m). Умножение строки "x"на это число дает, B^(n*m+1)и функция берет Aи Cвыводит данные и объединяет их все для получения AB^(n*m+1)C.

Тот же подход в J:

J 35 байт

A: (19{.]),('x'#~1+(#'
B: x
C: ')*35-~#),_16{.]

5

CJam, 22

A:<empty>
B:{])`\,q,K/(*))*"_~"}
C:{])`\,q,K/(*))*"_~"}_~

Пример выполнения:

ABBC(ABC) -> ABBBC

что переводится как

{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

с вводом как

{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

который дает следующий вывод:

{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

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

Давайте посмотрим на какие программы ACи ABCкак они выглядят:

AC :{])`\,q,K/(*))*"_~"}_~
ABC:{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

Мы замечаем, что C=B_~

Давайте посмотрим на то, что Bделает:

{])`\,q,K/(*))*"_~"}

{                  }    e# This is a code block. Alone, this does nothing except
                        e# pushing this block to stack as is
 ]                      e# Wrap everything on stack in an array
  )`                    e# Take out the last part and convert it to its string representation
    \,                  e# Take length of remaining array
      q,K/              e# Read the input, take its length and int divide by K (i.e. 20)
          (*            e# Decrement and multiply by the array length on stack
            ))          e# Add two to the product
              *         e# Repeat the string representation on stack that many times
               "_~"     e# Put this string on stack

Теперь давайте посмотрим, что ACбудет делать бег без какого-либо ввода:

{])`\,q,K/(*))*"_~"}_~                      e# Copy the block and run it
{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}~   e# Block is copied, run it
{      ...         } ])                     e# Wrapped array has the block in it.
                       `\,                  e# Stringify it and take length of remaining = 0
                          q,K/              e# No input so 0
                              (*))          e# 0 * -1 = 0. 0 + 2 = 2
                                  *         e# Repeat the stringified block 2 times:
                                            e# "{])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}"
                                   "_~"     e# Put this string. Program ends, so print stack:
                                            e# {])`\,q,K/(*))*"_~"}{])`\,q,K/(*))*"_~"}_~

Вау, выход есть ABC.

Мы в основном считаем, сколько Bсуществует в коде. Тогда сколько их на входе (используя длину). Умножьте их, увеличьте в два раза (так как Cтакже есть B) и добавьте, _~чтобы получитьC

Попробуйте онлайн здесь


3

Haskell , 50 байтов

fэто функция, принимающая и возвращающая String.

Строка B - это просто один пробел, а C начинается с одного.

A:_:b="
B: 
C: ";f s|a:c<-words s=unwords$a:(drop 50s>>b):c

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

  • _:b=" "присваивает всем кроме первого пробела в строковом литерале значение b, равное m программы B копий программы.
  • sявляется входной строкой. a:c<-words sразбивает его на разделенные пробелами слова, так что aстановится A и cстановится списком слов, составляющих C. Копии B игнорируются, так как wordsсжимает несколько пробелов (чего избегает остальная часть программы).
  • drop 50sявляется строкой длиной, равной числу n из B копий на входе. drop 50s>>bобъединяет столько копий b, давая мн пробел.
  • unwords$a:(drop 50s>>b):cобъединяет все строки обратно вместе с пробелами. Поскольку (drop 50s>>b)в список добавлено дополнительное «слово» , есть также дополнительное место для соединения, автоматически добавляющее +1 к умножению.

2

Матлаб, 85

Впервые я выполнил такую ​​абстрактную задачу, поэтому для меня это было больше проблемой кодирования, чем проблемой код-гольфа!

Три строки без кавычек:

A:    "X=strsplit(input('','s'));m=0 "
B:    "+1 "
C:    ";[X{1},32,repmat(['+1',32],1,m*(length(X)-2)+1),X{end}]"

Как это работает: я разбил входной аргумент на пробел, так что nего можно определить по количеству строковых частей. Б работает как своего рода счетчик, чтобы получить m. Для восстановления ответа я использую A и C из разбиения, повторяю B m * n + 1 раз, и я вставляю пробелы, используя их значение ASCII, чтобы не возникало нежелательных разбиений в C.

РЕДАКТИРОВАТЬ: упс, случайно посчитал A + B


1

C (gcc) , 81 байт

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

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

A: m;f(char*s){m=strrchr(s+66,32)-s-65;printf("%.66s%*s",s,m*strlen("
B: <SPACE>
C: ")+16,s+m+66);}

По идентификации я просто имел в виду , что это должно быть ясно из вашего ответа , который фрагменты кода A , B и C . Это не требование к программе.
Згарб

1

TI-Basic (серия 83), 65 байт

Сегмент A (33 байта):

Input Str1:sub(Str1,1,27:For(I,0,(length(Str1)-55)(length("

Сегмент Б:

X

Сегмент C (32 байта):

Y")-1:Ans+"X":End:Ans+sub(Str1,length(Str1)-27,28

Я действительно взволнован тем, что нашел этот похожий на квинну вызов! Большинство квин не работают в TI-Basic без хотя бы небольшого обмана, потому что нет способа избежать "символа. (В обоих смыслах слова «escape».) Но здесь мы получаем входную строку с помощью Inputкоманды, и ввод "там отлично.

Здесь все еще есть некоторая глупость TI-Basic: пустая строка недопустима, поэтому наивное решение вставки строки "XXX...XX"в цикл не будет работать, когда n = 0. Вместо этого мы вручную вычисляем значение mn + 1 и вставляем строку "X"много раз.

Постоянные магические 27и 28в программе, немного не от подсчета байт 33 и 32, потому что Str1, sub(и length(два байта маркеры , которые только способствуют 1 к длине струны.

Если мы вместо новой строки используем строки :, похоже, что можно сохранить несколько байтов, не добавляя конечные кавычки, но на самом деле это не работает. Прежде всего, вам нужен шестнадцатеричный редактор, прежде чем вы сможете добавить символ новой строки в строку: вы не можете просто набрать его, потому что если вы нажмете клавишу ВВОД во время Inputкоманды, она отправит ввод. Когда я попробовал подход с использованием шестнадцатеричного редактора, я получил странную ошибку переполнения буфера, которая изменила содержимое моей программы, так что не пытайтесь сделать это дома с помощью вашего дорогого калькулятора.


0

Java 11, 135 65 + 26 = 91 байт

A

s->{var p=s.split("\\(\"|\"\\.");return p[0]+"(\"B"+p[1].repeat("

В

B

С

".length())+'"'+'.'+p[2];}

Попробуйте онлайн здесь (у TIO пока нет Java 11, так что вместо этого используется вспомогательный метод String::repeat()).

Ungolfed:

s -> { // lambda taking and returning a String
    var p = s.split("\\(\"|\"\\."); // split input into parts A, B^n, C (where n may be 0) at the "(\"" and "\"."
    return p[0] + "(\"B" + // put it back together: A plus the part the split shaved off, plus an extra B ...
    p[1].repeat("BBB".length()) + // ... plus B^(n*m)
    '"' + '.' + p[2]; // plus C, with the part the split shaved off reattached
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.