Wyjście łańcucha znaków wyjściowych

18

Musisz napisać program lub funkcję, która, gdy dali niepusty ciąg S z N znaków ASCII druku , wyprowadza program, który zakończy się z kodem wyjścia C , gdzie C jest na kod ASCII w pozycji 0 w S . Ten program piszesz dodatkowo wyjście program P , tak, że po uruchomieniu, to wychodzi z kodem wyjścia C " , gdzie C ' jest na kod ASCII w pozycji 1 w S . Program P wygeneruje inny program P ′ . Ten proces powtarza się, dopóki w S nie pozostaną żadne znaki. Po wykonaniu tej czynności nie musisz nic generować, a następnie opcjonalny nowy wiersz; i powinien wyjść z kodem wyjścia 0.

Znaki pomiędzy 0x20i 0x7ewłącznie.

Kilka innych zasad:

  • Programy samomodyfikujące są niedozwolone: ​​musisz wyprowadzić źródło do STDOUT (lub początkowo zwrócić wartość)
  • Nie możesz odczytać własnego kodu źródłowego.

Zwycięży najkrótszy taki program w bajtach.

Do niektórych podstawowych testów można użyć tego skryptu ruby . (Pierwszy argument to sposób wywoływania skryptu, drugi to program, a trzeci to ciąg wejściowy.)

Przykład hipotetyczny

Powiedz, że program jest FOO. Gdy podano ciąg „ABC”, wyświetla wynik BARA. Ten program kończy działanie z kodem 65i wyjściami BARB. To z kolei kończy się wraz z kodem 66i wyjściami BARC. Ten program kończy działanie z kodem 67i wyjściami BAR!. To nic nie wyprowadza i kończy działanie wraz z kodem 0.

Conor O'Brien
źródło
Czy zrobienie tego będzie liczyło się jako kody wyjścia w Forth? Zmień parametr, aby wyświetlić inne błędy systemu operacyjnego. 0to sukces. tio.run/nexus/…
mbomb007
@ mbomb007 Nie wiem wiele o Forth. Czy w taki sposób można konwencjonalnie użyć „kodu błędu” w Forth?
Conor O'Brien,
To zależy, czy Twoim celem jest posiadanie kodów błędów na poziomie systemu operacyjnego. Jeśli liczy się tylko liczba, możesz po prostu zrobić 33 throwdowolną liczbę. Używasz negatywów dla poziomu systemu operacyjnego, a przesunięcie wynosi -512. Też bardzo nie lubię, ale szukam tutaj: Complang.tuwien.ac.at/forth/gforth/Docs-html/...
mbomb007

Odpowiedzi:

6

Python 2, 126 101 94 bajtów

W trakcie tworzenia okazało się, że kod Pythona nie może zawierać literalnych bajtów 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])

Wypróbuj online (pokazuje kod zakończenia w informacjach debugowania)


Zauważ, że każdy z niepustych programów poniżej ma końcowy kanał.

Dla danych wejściowych Hellopowyższe dane wyjściowe:

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'))

który drukuje

...

który drukuje

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'))

który drukuje

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'))

który nic nie drukuje (pusty program)

który nic nie drukuje i wychodzi z kodem 0.

mbomb007
źródło
4

Python 3, 77 bajtów

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

Ten kod pobiera dane wejściowe ze STDIN i wysyła pierwszy program do STDOUT.

Jeśli dane wejściowe to ABCDE, wyniki są

 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 

gdzie każdy wiersz zawiera kod wyjścia i dane wyjściowe wcześniej wykonanego programu (pierwszy wiersz to pierwszy program).

sklepienie
źródło
Twoja odpowiedź jest jak moja ... po prostu to, że zrobiłeś to w odwrotnym kierunku ... Ja sobie to robię.
Leaky Nun
67 bajtów
mbomb007
@LeakyNun tak, ale nie użyłem twojej odpowiedzi jako punktu wyjścia, jeśli o to ci chodzi
vaultah
Mówię tylko, że powinienem o tym pomyśleć.
Leaky Nun
@vaultah Masz zamiar zagrać w golfa do 67 bajtów, czy powinienem opublikować go jako osobną odpowiedź?
mbomb007
3

Python 3 , 115 108 100 bajtów

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

Wypróbuj online!


Dla danych wejściowych Helloprogram drukuje:

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

Powyższy program drukuje:

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

i wychodzi z kodem 72.

Wypróbuj online!


Program powyżej zostanie wydrukowany

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

i wychodzi z kodem 101.

Wypróbuj online!


Powyższy program drukuje:

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

i wychodzi z kodem 108.

Wypróbuj online!


Powyższy program drukuje:

print("");exit(111)

i wychodzi z kodem 108.

Wypróbuj online!


Powyższy program nic nie drukuje i wychodzi z kodem 111.

Wypróbuj online!


Pusty program nic nie drukuje i wychodzi z kodem 0.

Wypróbuj online!

Leaky Nun
źródło
2
Łącze TIO dla pustego programu? To dedykacja dla Ciebie!
Neil
2

C, 156 bajtów

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);}

Wypróbuj online! (Otwórz kartę debugowania, aby zobaczyć kod wyjścia.)

Pobiera dane wejściowe jako argument wiersza poleceń.

W przypadku wejścia „ABC” program jest wyprowadzany

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];}

co zwraca 65 i wyprowadza

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];}

co zwraca 66 i wyprowadza

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];}

co zwraca 67 i wyprowadza

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];}

który nic nie zwraca i zwraca 0.

Steadybox
źródło
@ mbomb007 Dzięki, teraz jest naprawione (i trwało krócej).
Steadybox
2
Uwielbiam to, kiedy tak się dzieje.
mbomb007
2

Python 2, 67 bajtów

Na podstawie tej odpowiedzi , ale zmodyfikowany do używania Python 2, z trywialnym programem, 0aby nic nie drukować i wyjść.

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

Wypróbuj online

mbomb007
źródło
1

RPL, 73 bajty

Ze stroną kodową hp8.

Włącz HP48 lub podobny albo uruchom droid48 . Nie zapomnij -52 SFo lepszej wizualizacji stosu. Zakładam, że nacisnąłeś już sznurek, np. "ABC"Na stosie. Następnie wprowadź następującą funkcję:

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

(Dla wygody sugeruję dwukrotne naciśnięcie klawisza α przed wpisaniem czegokolwiek, stąd blokowanie trybu wprowadzania alfa. Później wystarczy użyć klawisza DEL, aby anulować automatycznie wstawiane ograniczniki zamykania. Po prostu użyj klawisza ENTER, aby zatwierdzić. Nie zapomnij spacji po znaku operator noża.)

Ta funkcja natychmiast wypycha na stos program do samodzielnej modyfikacji pod postacią listy. (Ale powyższa funkcja się nie modyfikuje). Ponieważ L w RPL oryginalnie oznacza LISP, naciśnięcie klawisza EVAL rzeczywiście oceni ten program. Zwraca kod wyjścia na drugim poziomie stosu i pozostawia się zmodyfikowany (tak, tutaj jest wątpliwe) dla drugiego EVAL. Naciskaj kilkakrotnie EVAL, aż program w końcu zatrzyma się na pierwszym poziomie stosu. Końcowy kod wyjścia 0 pojawia się zatem na poziomie pierwszym, z wcześniejszymi kodami wyjścia powyżej. Jeśli zapomniałeś -52 SF, możesz nawigować w stosie po każdym EVAL, naciskając klawisz ▴ (wyjdź z tego trybu nawigacji za pomocą klawisza ON). Powyższa funkcja akceptuje łańcuchy zawierające znaki 0x0 wewnątrz, aby utworzyć takie łańcuchy 0 CHRi+są twoimi przyjaciółmi. Samodzielna modyfikacja polega na usunięciu użytego znaku z osadzonego łańcucha ( SUB 2 SWAP PUTgałęzi). Dlatego porzucony program jest krótszy po każdym EVAL. 4 DROPNOddziału zapewnia, że wyjście nic zostaną zablokowani. Na zawsze.instrukcja z PO jest przestrzegana, porzucając między innymi sam program. Oczywiście wszystko to zakłada, że ​​twoja notatka jest -55 SFbiegła. Użytkownicy-55 SF

Zakładam, że istnieje rozwiązanie RPL / 2, które może zawierać prawdziwy kod wyjścia unix, ale afaik RPL / 2 ma ograniczoną introspekcję i nie może oceniać list.

Masa perłowa
źródło
Nie sądzę, aby korzystanie z kodu samomodyfikującego liczyło się jako prawidłowy quine zgodnie z naszym konsensusem, ponieważ ma on dostęp do własnego kodu źródłowego. Zapytam OP w komentarzu. Zobacz powiązane posty z meta: Co liczy się jako właściwy quine? ; Czy używanie SMBF liczy się jako oszustwo? <- to ten, który dotyczy
mbomb007
1
Tylko wygenerowany program sam się modyfikuje, a nie funkcja, która odpowiada na wyzwanie. Ale zgadzam się, to jest wątpliwe! Dodano kilka zmian, aby to podkreślić.
Nacre
1

sed , 467 461 bajtów

Kody znaków są trudne:

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

Wypróbuj online!

W przeciwnym razie logika jest raczej prosta: (1) unikaj znaków specjalnych (są dwa), (2) owiń dodatkową s/^/…/;q\1warstwę, (3) powtórz.

Oto wynik dla hello :

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

I mały skrypt, którego użyłem:

#!/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
eush77
źródło
Nie musisz się martwić o nowe wiersze, ponieważ post mówi, że otrzymasz znaki tylko między 0x20 a 0x7E. Fajne rozwiązanie! :)
Conor O'Brien
@ ConorO'Brien Och, racja. Dzięki!
eush77
1

PowerShell, 172 156 bajtów.

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"

The h3l}'{l0 wejściowe będą skutkować następnym wyjściem

Wypróbuj online!

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

Który z kolei przyniesie wynik

Wypróbuj online!

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

Ostatnie uruchomienie nic nie wyświetli, a kod wyjścia będzie wynosił 0.

Wypróbuj online!

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
Andrei Odegov
źródło