Вихід з рядкового коду


18

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

Символи між 0x20та 0x7eвключно.

Ще кілька правил:

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

Виграє найкоротша така програма в байтах.

Для певного рудиментарного тестування цей сценарій рубіну може бути використаний. (Перший аргумент - це спосіб виклику сценарію, другий - програма, а третій - рядок введення.)

Гіпотетичний приклад

Скажіть, програма є FOO. Коли задано рядок "ABC", він виводить BARA. Ця програма закінчується кодом 65та виходами BARB. Це, в свою чергу, виходить з кодом 66і вихід BARC. Ця програма закінчується кодом 67та виходами BAR!. Це нічого не виводить і завершує роботу з кодом 0.


Чи буде це вважати вихідними кодами у Forth? Змініть параметр, щоб побачити інші помилки ОС. 0є Успіх. tio.run/nexus/…
mbomb007

@ mbomb007 Я не знаю багато про Forth. Це як умовно використовувати "код помилки" у Forth?
Conor O'Brien

Це залежить, якщо ваша мета - мати коди помилок на рівні ОС. Якщо тільки число має значення, ви можете просто зробити щось на кшталт, 33 throwщоб кинути довільне число. Ви використовуєте мінуси для рівня ОС, а зміщення становить -512. Шукаю багато, але я шукаю тут: скаргу.tuwien.ac.at
forth/

Відповіді:


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

Я просто кажу, що я повинен був подумати про це.
Leaky Nun

@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, щоб скасувати автоматично вставлені закривальні роздільники. Просто використовуйте клавішу ENTER для перевірки. Не забувайте пробіл після оператор набору.)

Ця функція негайно висуває на стек самомодифікуючу програму під формою списку. (Але функція вище не змінюється). Оскільки L в RPL спочатку означає LISP, натискання клавіші EVAL дійсно оцінить цю програму. Він повертає код виходу на рівні другого стеку і залишає себе, модифікований (так, тут це сумнівно), для останнього EVAL. Тому натискайте кнопку EVAL кілька разів, поки програма нарешті не зупиниться, щоб опуститися на рівень першого стека. Кінцевий код виходу 0 таким чином з'являється на першому рівні з попередніми кодами виходу вище. Якщо ви забули -52 SF, ви можете переміщатися в стеку після кожного EVAL, натискаючи клавішу ▴ (залиште цей режим навігації за допомогою клавіші ON). Вищенаведена функція приймає рядки з 0x0 символами всередині, щоб створити такі рядки 0 CHRта+ваші друзі. Модифікація self полягає у видаленні використаного char із вбудованого рядка ( SUB 2 SWAP PUTгілки). Отже, випала програма стає коротшою після кожного EVAL. 4 DROPNГілка забезпечує вихід нічого інструкцію від OP поважається, опустившись серед іншого самої програми. Звичайно, все це сприймає вашу нотатку -55 SFадептом. Користувачам -55 SFзабороняється. Назавжди.

Я припускаю, що рішення RPL / 2 існує і може містити реальний код виходу unix, але afaik RPL / 2 має обмежений самоаналіз і не може оцінити списки.


Я не думаю, що використання самовиправляючого коду вважається дійсним квіном згідно нашого консенсусу, оскільки він має доступ до власного вихідного коду. Я запитаю ОП у коментарі. Дивіться відповідні мета-повідомлення: Що вважається належною квінкою? ; Чи вважається використання SMBF як обману? <- це те, що застосовується
mbomb007

1
Тільки створена програма самомодифікується, а не функція, яка відповідає на виклик. Але я згоден, це сумнівно! Додано кілька змін, щоб виділити це.
Перламутр

1

sed , 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. Приємне рішення! :)
Conor O'Brien

@ 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.