Выход из строки кода


18

Вы должны написать программу или функцию , которая, когда дана непустая строка S из N символов ASCII для печати , выводит программу , которая будет завершаться с кодом выхода C , где C является ASCII элемент кода в положении 0 в S . Эта программа , которую вы напишете дополнительно выводить программу P , таким образом , что при запуске, он выходит с выходом кодом C ' , где C' является ASCII элемент кода в положении 1 в S . Программа P выведет другую программу P ′ . Этот процесс повторяется до тех пор, пока в S не останется символов, После того, как это сделано, вы должны ничего не выводить, за которым следует необязательный перевод строки; и должен выйти с кодом выхода 0.

Знаки между 0x20и 0x7eвключительно.

Еще несколько правил:

  • Самомодифицирующиеся программы недопустимы: вы должны вывести источник в STDOUT (или сначала вернуть значение)
  • Вы не можете читать свой собственный исходный код.

Победит самая короткая такая программа в байтах.

Для некоторого элементарного тестирования может использоваться этот скрипт ruby . (Первый аргумент - это способ вызова сценария, второй - программа, а третий - входная строка.)

Гипотетический пример

Скажи, что программа есть FOO. Когда дана строка «ABC», она выводит BARA. Эта программа выходит с кодом 65и выходами BARB. Это в свою очередь выходит с кодом 66и выходами BARC. Эта программа выходит с кодом 67и выходами BAR!. Это ничего не выводит и выходит с кодом 0.


Будет ли это считаться кодом выхода в Forth? Измените параметр, чтобы увидеть другие ошибки ОС. 0это успех tio.run/nexus/…
mbomb007

@ mbomb007 Я мало что знаю о Форт. Это то, как можно было бы условно использовать «код ошибки» в Forth?
Конор О'Брайен

Это зависит от того, хотите ли вы иметь коды ошибок на уровне ОС. Если имеет значение только число, вы можете просто сделать что-то вроде 33 throwброска произвольного числа. Вы используете негативы для уровня ОС, а смещение -512. ИДК тоже много, но я смотрю здесь: complang.tuwien.ac.at/forth/gforth/Docs-html/…
mbomb007

Ответы:


6

Python 2, 126 101 94 байта

В процессе этого я обнаружил, что код Python может не содержать буквенных байтов NUL.

lambda i,s='''i=%r;s=%r
try:print s%%(i[1:],s,i[0])
except:0
exit(ord(%r))''':s%(i[1:],s,i[0])

Попробуйте онлайн (показывает код выхода в информации отладки)


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

Для ввода Helloвышеуказанных выходов:

i='ello';s='i=%r;s=%r\ntry:print s%%(i[1:],s,i[0])\nexcept:print s%%(0,s,"\\0")*(i>0)\nexit(ord(%r))'
try:print s%(i[1:],s,i[0])
except:0
exit(ord('H'))

какие отпечатки

...

какие отпечатки

i='o';s='i=%r;s=%r\ntry:print s%%(i[1:],s,i[0])\nexcept:print s%%(0,s,"\\0")*(i>0)\nexit(ord(%r))'
try:print s%(i[1:],s,i[0])
except:0
exit(ord('l'))

какие отпечатки

i='';s='i=%r;s=%r\ntry:print s%%(i[1:],s,i[0])\nexcept:print s%%(0,s,"\\0")*(i>0)\nexit(ord(%r))'
try:print s%(i[1:],s,i[0])
except:0
exit(ord('o'))

который ничего не печатает (пустая программа)

который ничего не печатает и выходит с кодом 0.


4

Python 3, 77 байт

p='exit(0)'
for c in input()[::-1]:p='print(%r);exit(ord(%r))'%(p,c)
print(p)

Этот код принимает входные данные из STDIN и выводит первую программу в STDOUT.

Если входные данные ABCDE, результаты

 0 print('print(\'print(\\\'print("print(\\\\\\\'exit(0)\\\\\\\');exit(ord(\\\\\\\'E\\\\\\\'))");exit(ord(\\\\\\\'D\\\\\\\'))\\\');exit(ord(\\\'C\\\'))\');exit(ord(\'B\'))');exit(ord('A'))
65 print('print(\'print("print(\\\'exit(0)\\\');exit(ord(\\\'E\\\'))");exit(ord(\\\'D\\\'))\');exit(ord(\'C\'))');exit(ord('B'))
66 print('print("print(\'exit(0)\');exit(ord(\'E\'))");exit(ord(\'D\'))');exit(ord('C'))
67 print("print('exit(0)');exit(ord('E'))");exit(ord('D'))
68 print('exit(0)');exit(ord('E'))
69 exit(0)
 0 

где каждая строка содержит код завершения и выходные данные ранее выполненной программы (первая строка - первая программа).


Твой ответ похож на мой ... только то, что ты сделал это в противоположном направлении ... Я за это отвечаю.
Утренняя монахиня


@ LeakyNun да, но я не использовал твой ответ в качестве отправной точки, если ты это имеешь в виду
vaultah

Я просто говорю, что должен был подумать об этом.
Утренняя монахиня

@vaultah Ты собираешься играть в гольф до 67 байт, или я должен опубликовать это как отдельный ответ?
mbomb007

3

Python 3 , 115 108 100 байт

i=input()
r="%s"
k=""
for c in i:r%="print(%s\"%%s%s\");exit(%i)"%(k,k,ord(c));k+=k+"\\"
print(r%"")

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


Для ввода Helloпрограмма печатает:

print("print(\"print(\\\"print(\\\\\\\"print(\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\");exit(111)\\\\\\\");exit(108)\\\");exit(108)\");exit(101)");exit(72)

Программа выше печатает:

print("print(\"print(\\\"print(\\\\\\\"\\\\\\\");exit(111)\\\");exit(108)\");exit(108)");exit(101)

и выходит с кодом 72.

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


Программа выше печатает

print("print(\"print(\\\"\\\");exit(111)\");exit(108)");exit(108)

и выходит с кодом 101.

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


Программа выше печатает:

print("print(\"\");exit(111)");exit(108)

и выходит с кодом 108.

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


Программа выше печатает:

print("");exit(111)

и выходит с кодом 108.

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


Программа выше ничего не печатает и выходит с кодом 111.

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


Пустая программа ничего не печатает и завершает работу с кодом 0.

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


2
Ссылка TIO для пустой программы? Это посвящение для вас!
Нейл

2

C 156 байт

char*s="char*s=%c%s%c;n=%d;char*t=%c%s%c;main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}";main(i,t)char**t;{printf(s,34,s,34,0,34,t[1],34);}

Попробуйте онлайн! (Откройте вкладку отладки, чтобы увидеть код выхода.)

Принимает ввод в качестве аргумента командной строки.

Для входа "ABC", это выводит программу

char*s="char*s=%c%s%c;n=%d;char*t=%c%s%c;main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}";n=0;char*t="ABC";main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}

который возвращает 65 и выводит

char*s="char*s=%c%s%c;n=%d;char*t=%c%s%c;main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}";n=1;char*t="ABC";main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}

который возвращает 66 и выводит

char*s="char*s=%c%s%c;n=%d;char*t=%c%s%c;main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}";n=2;char*t="ABC";main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}

который возвращает 67 и выводит

char*s="char*s=%c%s%c;n=%d;char*t=%c%s%c;main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}";n=3;char*t="ABC";main(){n<strlen(t)&&printf(s,34,s,34,n+1,34,t,34);return t[n];}

который ничего не выводит и возвращает 0.


@ mbomb007 Спасибо, теперь это исправлено (и в процессе стало короче).
Steadybox

2
Должен любить это, когда это произойдет.
mbomb007


1

RPL, 73 байта

С кодовой страницей hp8.

Включите ваш HP48 или аналогичный, или включите droid48 . Не забудьте -52 SFдля лучшей визуализации стека. Я предполагаю, что вы уже поместили строку, например "ABC", в стек. Затем введите следующую функцию:

→ x«{LAST}x{DUP NUM 3ROLLD 2OVER SIZE DUP{SUB 2SWAP PUT}{4DROPN}IFTE}+ +»

(Для удобства я предлагаю дважды нажать клавишу «α», прежде чем что-либо вводить, поэтому блокируем режим альфа-ввода. В последнем случае просто используйте клавишу DEL, чтобы отменить автоматически вставленные закрывающие разделители. Просто используйте клавишу ВВОД для подтверждения. Не забывайте пробел после удар ножом.)

Эта функция немедленно помещает в стек самоизменяющуюся программу в виде списка. (Но функция выше не меняет себя). Поскольку L в RPL первоначально обозначает LISP, нажатие клавиши EVAL действительно оценит эту программу. Он возвращает код завершения на уровне стека два и оставляет себя модифицированным (да, здесь это сомнительно) для последнего EVAL. Поэтому нажимайте кнопку EVAL до тех пор, пока программа, наконец, не остановится, чтобы опуститься на первый уровень стека. Окончательный код выхода 0, таким образом, появляется на первом уровне, а предыдущие коды выхода указаны выше. Если вы забыли , ваши друзья. Самомодификация заключается в удалении использованного символа из встроенной строки ( ветви). Следовательно, отброшенная программа короче после каждого EVAL. Ветвь не обеспечивает выход ничего-52 SF , вы можете перемещаться в стеке после каждого EVAL, нажимая клавишу ((выйдите из этого режима навигации с помощью клавиши ON). Вышеуказанная функция принимает строки с 0x0-символами внутри, чтобы создавать такие строки 0 CHRи+SUB 2 SWAP PUT4 DROPNИнструкция от ОП соблюдается, отбрасывая среди прочего саму программу. Конечно, все это предполагает ваше замечание -55 SFадепта. Пользователи-55 SF должны быть забанены. Навсегда.

Я предполагаю, что решение RPL / 2 существует и может содержать настоящий код выхода Unix, но на самом деле RPL / 2 имеет ограниченный самоанализ и не может оценивать списки.


Я не думаю, что использование самоизменяющегося кода считается действительным квинэном в соответствии с нашим консенсусом, поскольку он имеет доступ к своему собственному исходному коду. Я спрошу ОП в комментарии. Смотрите соответствующие мета-посты: что считается правильным quine? ; Использование SMBF считается обманом? <- это тот, который применяется
mbomb007

1
Только сгенерированная программа является самоизменяющейся, а не функция, которая отвечает на вызов. Но я согласен, это сомнительно! Добавлены некоторые правки, чтобы выделить это.
Перламутр

1

Сед , 467 461 байт

Коды символов жесткие:

s:^:Y:
:b
s:ZY[ (2<FPZdnx]:0_Y:
s:ZY[ )3=GQ[eoy]:1_Y:
s:ZY[ *4>HR\fpz]:2_Y:
s:ZY[]!+5?ISgq{]:3_Y:
s:ZY[",6@JT^hr|]:4_Y:
s:ZY[-#7AKU_is}]:5_Y:
s:ZY[$.8BLV`jt~]:6_Y:
s:ZY[%/9CMWaku]:7_Y:
s:ZY[&0:DNXblv]:8_Y:
s:ZY['1;EOYcmw]:9_Y:
s:Y[ -']:3Z&:
s:Y[(-1]:4Z&:
s:Y[2-9:;]:5Z&:
s:Y[<=>?@A-E]:6Z&:
s:Y[F-O]:7Z&:
s:Y[P-Y]:8Z&:
s:Y[]Z\-`abc]:9Z&:
s:Y[d-m]:10Z&:
s:Y[n-w]:11Z&:
s:Y[xyz{-~]:12Z&:
tb
s/([^_]+)_Y$/ q\1/
:
s/[/\]/\\&/g
s/([^_]+)_ (.*)/ s\/^\/\2\/;q\1/
/^\S/b

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

В противном случае логика довольно проста: (1) экранировать специальные символы (их два), (2) перенести в дополнительный s/^/…/;q\1слой, (3) повторить.

Вот вывод для hello:

 s/^/s\/^\/s\\\/^\\\/s\\\\\\\/^\\\\\\\/q111\\\\\\\/;q108\\\/;q108\/;q101/;q104

И маленький скрипт, который я использовал:

#!/bin/bash
set -uo pipefail
IFS=$'\n'

P=$(echo $1 | sed -rf q.sed)
echo $P

echo $1 | od -An -tuC

for char in $(echo $1 | sed 's:.:&\n:g'); do
    P=$(echo | sed $P)
    printf ' %3d' $?
done

Вам не нужно беспокоиться о новых строках, поскольку в сообщении говорится, что вам будут вводить символы только в диапазоне от 0x20 до 0x7E. Отличное решение! :)
Конор О'Брайен

@ ConorO'Brien О, верно. Благодарность!
eush77

1

PowerShell, 172 156 байт.

param($i)
$s=@'
if($i='{0}'){{
$s=@'
{1}'@
$s-f($i-replace'^.'-replace"'","''"),"$s`n"
$host.setshouldexit($i[0])
}}
exit
'@
$s-f$i.replace("'","''"),"$s`n"

h3l}'{l0Ввода приведет к следующему выводу

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

if($i='h3l}''{l0'){
$s=@'
if($i='{0}'){{
$s=@'
{1}'@
$s-f($i-replace'^.'-replace"'","''"),"$s`n"
$host.setshouldexit($i[0])
}}
exit
'@
$s-f($i-replace'^.'-replace"'","''"),"$s`n"
$host.setshouldexit($i[0])
}
exit

Который в свою очередь выведет

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

if($i='3l}''{l0'){
$s=@'
if($i='{0}'){{
$s=@'
{1}'@
$s-f($i-replace'^.'-replace"'","''"),"$s`n"
$host.setshouldexit($i[0])
}}
exit
'@
$s-f($i-replace'^.'-replace"'","''"),"$s`n"
$host.setshouldexit($i[0])
}
exit

Последний запуск ничего не даст и код выхода будет 0.

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

if($i=''){
$s=@'
if($i='{0}'){{
$s=@'
{1}'@
$s-f($i-replace'^.'-replace"'","''"),"$s`n"
$host.setshouldexit($i[0])
}}
exit
'@
$s-f($i-replace'^.'-replace"'","''"),"$s`n"
$host.setshouldexit($i[0])
}
exit
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.