Wydrukuj frazę „A ona powiedziała:„ Ale to jego ”.” Używając tylko alfabetu


50

Wydrukuj frazę, And she said, 'But that's his.'używając tylko następujących znaków: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ Żadnych znaków interpunkcyjnych ani niealfabetycznych. Możesz używać dowolnego języka programowania. Biała spacja jest całkowicie dozwolona. Najkrótszy program wygrywa.


Co z białymi znakami na wyjściu? (prowadzący / końcowy?)
attinat

2
Cholera, mój esolang nie może ukończyć, ponieważ nie ma możliwości wyprodukowania tylko za pomocą a-zA-Z. Teoretycznie mógłbym użyć wrytuału i Eval do stworzenia niezbędnych instrukcji, ale żadnej z nich nie +-*,%'"da się zbudować bez użycia (przynajmniej) jednej z nich +-*,%'"0-9.
Draco18s

10
(programmer-of (language 'lisp))nie lubi tego.
MatthewRock

4
Muszę przyznać, że początkowo nie wydawało mi się to interesujące, ale kombinacja powtarzających się i unikalnych postaci naprawdę sprawiła, że ​​optymalizacja była przyjemna (szczególnie w języku stosu!). Bardzo dobrze.
brhfl

1
Czy możesz wyjaśnić, czy dozwolone są dodatkowe białe znaki na wydruku ? Jak dodatkowe końcowe linie? Lub tylko białe znaki w źródle oraz znaki alfabetyczne. Istnieje odpowiedź Befunge, która drukuje z dodatkowym znakiem nowej linii.
Peter Cordes

Odpowiedzi:


75

Biała spacja , 417 414 349 265 bajtów

265 bajtów dzięki Kevin Cruijssen

  							
  				   
   		 	
   		
   	 
  		   		 
 	  		
 	  		 
   			 
  		 	
   	 
 	  	 
 	  		 
 	  	
   				
  		  	  
  							
 	  	  
  				 	 
  		 
   		
  		 	
   		 	
 	  	 	
  		
   	 
 	  		
 	  		
  		 
   	   
  		  	 	

  
   		  		 
	   	
  
 


Wypróbuj online!

Wyjaśniono:

[S S T  T   T   T   T   T   T   N
_Push_-63_'][S S T  T   T   T   S S S N
_Push_-53_.][S S S T    T   S T N
_Push_13_s][S S S T T   N
_Push_3_i][S S S T  S N
_Push_2_h][S S T    T   S S S T T   S N
_Push_-70_space][S T    S S T   T   N
_Copy_0-based_3rd_s][S T    S S T   T   S N
_Copy_0-based_6th_'][S S S T    T   T   S N
_Push_14_t][S S T   T   S T N
_Push_-5_a][S S S T S N
_Push_2_h][S T  S S T   S N
_Copy_0-based_2nd_t][S T    S S T   T   S N
_Copy_0-based_6th_space][S T    S S T   N
_Copy_0-based_1st_t][S S S T    T   T   T   N
_Push-15_u][S S T   T   S S T   S S N
_Push_-36_B][S S T  T   T   T   T   T   T   N
_Push_-63_'][S T    S S T   S S N
_Copy_0-based_4th_space][S S T  T   T   T   S T S N
_Push_-58_,][S S T  T   S N
_Push_-2_d][S S S T T   N
_Push_3_i][S S T    T   S T N
_Push_-5_a][S S S T T   S T N
_Push-13_s][S T S S T   S T N
_Copy_0-based_3rd_space][S S T  T   N
_Push_-1_e][S S S T S N
_Push_2_h][S T  S S T   T   N
_Copy_0-based_3rd_s][S T    S S T   T   N
_Copy_0-based_3rd_space][S S T  T   S N
_Push_-2_d][S S S T S S S N
_Push_8_n][S S T    T   S S T   S T N
_Push_-37_A][N
S S N
_Create_Label_LOOP][S S S T T   S S T   T   S N
_Push_102][T    S S S _Add][T   N
S S _Print_as_character][N
S N
N
_Jump_to_Label_LOOP]

100
Whitespace is completely allowed.Widzę, że wziąłeś to dosłownie.
Benjamin Urquhart

3
Pokonałeś mnie do tego. Ale można grać w golfa na kilka sposobów. :) Możesz usunąć NNNznak końca, aby wyjść, ponieważ już kończy się na błędzie, gdy dodajesz przed print_char, więc nie pojawi się nawet po Jump_to_Label. Ponadto, dlaczego przechowywać 63na początku i pobierać go w pętli? Możesz go po prostu wcisnąć przed dodaniem. I dlaczego jest Label-nr TTSSSSTN? Etykieta może być nawet pusta, więc wystarczy NSSNutworzyć etykietę i NSNNprzejść do niej, jeśli używasz tylko jednej etykiety.
Kevin Cruijssen

1
318 bajtów wraz ze zmianami, które zaproponowałem powyżej. Oto ten sam program z dodanym podświetleniem. A jak odliczyłeś stałą wartość 63? Nie jestem w 100% pewien, że jest to najkrótsza możliwa stała tutaj. Jeśli tak, coś jest nie tak z moim programem do ciągłego generowania, który napisałem dla wcześniejszego wyzwania. :)
Kevin Cruijssen

1
Tak, miałem rację. Stała 102jest najbardziej wydajna: 281 bajtów (lub tutaj z podświetleniem ). (UWAGA: Użyłem również jednej kopii, aby zapisać 4 bajty na miejsce pomiędzy ehs dnA(skopiowane z miejsca między dias ehs).
Kevin Cruijssen

3
Ok, teraz skończyłem. :) 265 bajtów (lub tutaj z podświetleniem ). Dodano kilka dodatkowych kopii. ( Tutaj odpowiednia wskazówka dotycząca
białych znaków

62

Perl 5 , 133 102 95 bajtów

s qqAnd she saidZ ZBut thatZs hisZZGjGGfq x
s qZqchr oct oct oct ord chopqge x
y qGjfqqdx
print

Wypróbuj online!

Wyjaśnienie:

Regeksy, drukowanie i krojenie $_są domyślnie stosowane do zmiennej .

s qqAnd she saidZ ZBut thatZs hisZZGjGGfq

Zamienia pusty ciąg na And she saidZ ZBut thatZs hisZZGjGGf.

s qZqchr oct oct oct ord chopqge

Zastępuje każdy Zwynikiem ewaluacji chr oct oct oct ord chop. To usuwa ostatni znak $_, pobiera jego kod, interpretuje go jako ósemkowy trzykrotnie i konwertuje z powrotem na znak. Na przykład j→ 106 → 70 → 56 → 46 → ..

Ze względu na sposób, w jaki działa zamiana, modyfikacje $_tego dokonane podczas oceny zamiany są tracone, podobnie jak $_teraz And she said, 'But that's his.'GjGGf.

y qGjfqqd

Usuwa wszystko G, ji fw $_.


26
Nie znając Perla, wygląda na to, że właśnie próbowałeś wpisać zdanie, ale
wdałeś

2
To może być najpiękniejszy fragment kodu, jaki kiedykolwiek widziałem, napisany na tej stronie i mówię to jako ktoś, kto zna Perla.
Silvio Mayolo

1
Powiązane, ale można zastąpić printz saydo -2 znaków. Obecny meta konsensus mówi, że flagi wiersza poleceń -M5.010nie liczą się do liczby bajtów.
Silvio Mayolo

34

> <> , 916 915 903 bajtów

Na początku myślałem, że rozwiązanie w> <> jest niemożliwe, ale potem zdałem sobie sprawę ... kto potrzebuje warunkowej kontroli logicznej? :RE

fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffloffffffffffffffffffffffffffffffffffffffffffffflopppgloppppppppppppppppppppppggloffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppggloploppppppppppppppppppppppploffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppplofffffffflopggloppppppppppppppppppgglopppplofffffffloffffffffffffffffffffffffffflofffffffffffffffffffffffffffffffffffffffffffffffffffloglopppppppppppppppppppppppppppplofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppploppgloffffffffffffffffffflopppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflofloffffffffffloppppppppppppppppppppppploppgloio

Wypróbuj online

Wielokrotnie wypycham liczby (liczbę 15) na stos, następnie wypycham długość stosu i drukuję znak o tej wartości ASCII. Jeśli muszę zmniejszyć długość stosu, zmniejszam stos o trzy wartości naraz, używając p, lub jedną naraz, gjeśli jestem w granicach trzech wartości docelowych. Program kończy się wywołaniem i(wejście), które wypycha a, -1ponieważ nie ma danych wejściowych, a następnie drukuje je, aby spowodować błąd.

To jest program Python 3, którego użyłem do stworzenia rozwiązania, gdy pomyślałem o tym, jak to zrobić:

s = "And she said, 'But that's his.'"
L = [0]+[ord(c) for c in s]
#print(L)
M = L[1:]+[0]
D = [x[1]-x[0] for x in zip(L,M)]
#print(D)
while D:
	n=D.pop(0)
	if not D:print('io',end='');exit()
	if n>0:print('f'*n,end='lo')
	else:
		while n<-2:print('p',end='');n+=3
		print('g'*-n,end='lo')

Wypróbuj online


5
To jest właściwy kontrapunkt dla rozwiązania białych znaków! Mam ode mnie +1, doceniam również program generujący ...
Francesco

Ostatnia sekcja mogą być usunięte całkowicie z ostrożnego korzystania z p: utworzenie 59 na stosie podczas przemieszczania się z miejsca na sIN said, a następnie umieścić go w kodzie na drodze w dół od dcelu ,. (Zauważ, że (15,15) ma w tym momencie 15).
Nitrodon

W rzeczywistości możesz nadużywać li pumieszczać kilka użytecznych postaci w prostokącie (10,10) - (15,15), a następnie odzyskiwać je gtam, gdzie jest to wygodniejsze.
Nitrodon

To naprawdę dobry pomysł. Tak trudno jest myśleć o> <> w ten sposób. To jak kodowanie za pomocą BF
mbomb007

Zamieściłem własną odpowiedź: codegolf.stackexchange.com/a/186916/69059
Nitrodon

28

8086 Montaż na komputerze IBM, 1463 845 664 bajtów

Wyjaśnienie: Rzeczywistym źródłem języka asemblera jest wpis, a nie wygenerowany kod maszynowy.

Trudność polega na tym, że większość instrukcji x86 (takich jak ADD, SUB, JMP, skoki warunkowe, dostęp do pamięci) mają dwa argumenty i dlatego potrzebują przecinka lub adresu pamięci. Nie możemy więc używać dodawania, odejmowania, ifs ani pętli!

Podczas mojej pierwszej próby byłem w stanie „konstruować” liczby przy użyciu kombinacji inkrementacji, dekrementacji, mnożenia, dzielenia, sztuczek bajtowych i niejasnych instrukcji BCD (takich jak AAA, DAS). Po tym zdałem sobie sprawę, że ten pomysł można wykorzystać do stworzenia kodu do samokontroli i samokontroli.

  • Próba 1. (1463 bajtów)

    Wykorzystano dostępne instrukcje do skonstruowania kodów ASCII i adresu 0xb800 bufora ekranu. Obliczenia każdego znaku w sekwencji zostały ręcznie zagrane w golfa.

  • Próba 2. (niekompletna)

    Uświadomiono sobie, że dla każdej liczby całkowitej z zakresu 0x40-0x5f istnieje kod operacji. Ten zakres obejmuje AZ. Na przykład INC CX odpowiada 0x41 = „A”. (Ta tabela kodów operacyjnych jest bardzo przydatna).

    Próbowałem skonstruować 3 ciągi „danych” i nałożyć je jedna na drugą. Pierwszy „tak jak jest” (wielkie litery), drugi „przesunięty” do strefy 0x60-0x7f (małe litery), a ostatni „przesunięty” do strefy 0x20-0x3f (interpunkcja).

    Kod samomodyfikujący wytworzyłby pętlę lub trzy do iteracji danych.

  • Próba 3. (845 bajtów)

    Podobnie jak w poprzednim podejściu, ale w celu ograniczenia danych, ciąg byłby kodowany tylko raz, z „mieszanymi znakami kontrolnymi”, aby przełączać zestawy znaków.

  • Próba 4. (664 bajty)

    Jak pozbyć się postaci kontrolnych, które wymagają wielu łatanych instrukcji, aby radzić sobie z rozgałęzianiem? Biorąc pod uwagę, że używane są tylko dwie wielkie litery, zastanawiałem się, czy mógłbym „przerzucić” tabelę opcode, aby kodować małe litery przy użyciu zakresu 0x40-0x4f i interpunkcji przy użyciu zakresu 0x90-0x9f (odejmując od 0xc0). „A” i „B” można wstawić osobno.

    Jednak tylko połowa kodów z zakresu 0x90-0x9f jest użyteczna i nie zgadzała się z potrzebnymi. Potem pomyślałem, że może uda mi się je przetasować za pomocą XOR i znalazłem taki, który zadziałał. I oto jest.

Gra w golfa:

REP LODSB
PUSH CX
PUSH CX
POP AX
INC CH
PUSH CX
POP DI
DEC AX
DEC AX
REPNE SCASB
REPNE SCASB
PUSH DI
REPNE SCASB
PUSH DI
REPNE SCASB
PUSH DI
POP SI
POP DI
DEC DI
LODSB
NOT AL
STOSB
POP CX
DEC CH
LODSB
NOT AL
STOSB
LODSB
AAA
STOSB
INC DI
LODSB
NEG AL
STOSB
LODSB
NOT AL
PUSH AX
PUSH AX
INC SP
POP ES
INC SP
POP DI
LODSB
NOT AL
PUSH AX
POP BX
NEG AL
STOSB
INC DI
LODSB
DEC AL
NEG AL
DIV BH
PUSH AX
POP DI
LODSB
STOSB
RET
DEC BL
PUSH CS
STOSB
PUSH DS
INC DI
INC AX
POP SI
PUSH SP
NOP
INC BP
POP AX
PUSH DI
NOP
INC BP
PUSH BX
POP BX
PUSH SP
PUSHF
NOP
CWD
PUSH DX
INC DI
INC SP
NOP
INC SP
POP AX
PUSH BX
INC SP
CWD
INC BP
NOP
POP AX
POP BX
INC BP
SAHF
CWD
SCASB
INC DX

Zbierz z

nasm golf.asm -o golf.com

i uruchom w DOSBOX (najpierw uruchom CLS). Wygląda tak:

Próbka wyjściowa

Skomentowano:

; ASSUME DS = ES = CS
; ASSUME IP = 0x0100
; true for .COM file

; We treat 0xFE as a special marker that we scan for
; This marks our patch zone and the start of our data

; We also use it as a cheap trick to get a constant 0x1f
; into CX

; 0xFE is the first byte of INC or DEC instructions
; that operate on half-word registers (AL, BL, CH etc.)
; WATCH OUT! Adding these breaks the scan


; Can't assume any register contains zero
; so use this trick to zero out CX
REP LODSB

PUSH CX ; needed later

; zero AX
PUSH CX
POP AX

INC CH
PUSH CX
POP DI ; 0x100, where our code starts

DEC AX
DEC AX ; AL = 0xFE, our marker (AH = 0xFF)

REPNE SCASB ; skip the INC CH above
REPNE SCASB ; find the DEC CH located at 0x10E

; we will later need 0xF, the char count minus the 'A'
PUSH DI ; DI = 0x10F

REPNE SCASB ; find the patch position
PUSH DI

REPNE SCASB ; find the next 0xfe; our data section
PUSH DI
POP SI ; load data from here

POP DI ; store data to the patch position
DEC DI

; patch in XOR
; XOR is 0x34, start with 0xCB
; second byte of DEC BL is 0xCB
LODSB
NOT AL
STOSB

POP CX ; get 0x0f in CX for our strlen
DEC CH

; patch in our XOR arg
; it is 0xF1 (take 0x0E and NOT it)
LODSB ; 0x0E (PUSH CS)
NOT AL
STOSB

; ADD is 0x00 (take 0xAA, apply weird AAA behaviour)
; this also zeroes AH
LODSB ; 0xAA (STOSB)
AAA
STOSB

INC DI ; skip next instruction byte

; LOOP is 0xE2
LODSB ; 0x1E PUSH DS
NEG AL
STOSB


; get b800 in ES (address of screen buffer)
; first get 0x47 in AL (INC DI)
LODSB  ; get 0x47 (INC DI)
NOT AL ; NOT 0x47 = 0xb8
; AX = 0x00b8 (bytes backwards)

PUSH AX
PUSH AX
; stack contains 0xb8 0x00 0xb8 0x00
; stack off-by-1 trick
INC SP
; now POP gives you 0xb800
POP ES
INC SP ;and clean up after ourselves

; store 0 in DI ***** PUSHED AT START OF PROGRAM ***
POP DI


LODSB ; get our magic 0xC0 (0x40 INC AX)
NOT AL
PUSH AX
POP BX

NEG AL ; NOT and +1 to get 0x41 ("A")


; charloop:
STOSB
INC DI
LODSB
DEC AL ; XOR
NEG AL ; modify this into an ADD AL, BL
DIV BH ; modify this to LOOP back to charloop

; doesn't print the last character
; but the last character turns into the address where 'B'
; is supposed to go

PUSH AX
POP DI
LODSB ; "B"
STOSB

; graceful exit this time ;)
RET


; *** DATA SECTION ***

         ; PURPOSE

DEC BL   ; 0xFE marks data section, 0xCB for XOR
PUSH CS  ; for XOR arg
STOSB    ; for ADD
PUSH DS  ; for LOOP
INC DI   ; 0x47 -> for 0xb800

INC AX   ; for magic number but also "A"


POP     SI ;n
PUSH    SP ;d
NOP        ;
INC     BP ;s
POP     AX ;h 
PUSH    DI ;e
NOP        ;
INC     BP ;s
PUSH    BX ;a
POP     BX ;i
PUSH    SP ;d
PUSHF      ;,
NOP        ;
CWD        ;'
PUSH    DX ;B
INC     DI ;u
INC     SP ;t
NOP        ;
INC     SP ;t
POP     AX ;h
PUSH    BX ;a
INC     SP ;t
CWD        ;'
INC     BP ;s
NOP        ;
POP     AX ;h
POP     BX ;i
INC     BP ;s
SAHF       ;.
CWD        ;'

SCASB     ; treated as char but turns into screen address!
INC DX    ; "B"

Hm Otrzymuję różne pliki .COM z dwóch źródeł zestawu, zaczynając od przesunięcia 0x3e. Edycja - Nvm znalazł różnicę: linia 117 w komentowanej wersji jest, INC AXgdy nie ma komentarza INC AL.
gastropner

1
Zamiast tego chcę zobaczyć w pełni alfabetyczny plik binarny. :-)
Peter Ferrie

1
Jeśli nie masz ochoty blokować NASM jako wybranego asemblera, możesz tworzyć etykiety, wykonując label1 dbwłasną linię. Daje ostrzeżenie, ale nie ma błędu.
gastropner

1
@Gastropner dobrze, to tylko uczyniłoby to zbyt łatwym. : P Nie wiedziałem o tym, dzięki! Może powinienem zmienić nazwę mojego języka na „coś, co możesz dodać do DEBUG.COM”. Które zresztą użyłem do debugowania tego. xD
Artelius

1
@PeterCordes teraz ten sam się modyfikuje!
Artelius

23

Perl 6 , 1299 1272 1220 1215 bajtów

Dzięki Grimy za -27 bajtów.

-52 bajty, ponieważ w pierwszej kolejności nie potrzebowaliśmy królików.

Dzięki Jo King za -5 bajtów.

print chr flip chars i x chars i xx pi
and print lc chr chars NaN x chars cis pi
and print lc chr chars e x e x e
and print chr chars i x e x e x e
and print lc chr flip chars exp i
and print lc chr chars NaN x tau x e x e
and print chr chars chop NaN x e lcm chars e
and print chr chars i x e x e x e
and print lc chr flip chars exp i
and print lc chr flip chars i x chars i xx pi
and print chr chars False x pi x ceiling tau
and print lc chr chars e x e x e
and print chr chars i xx chars NaN x pi
and print chr chars i x e x e x e
and print chr chars chop False x e x e x e
and print chr chars chop NaN xx chars e
and print lc chr chars e x chars False
and print lc chr chars chop e x chars False
and print chr chars i x e x e x e
and print lc chr chars chop e x chars False
and print lc chr chars NaN x tau x e x e
and print lc chr flip chars i x chars i xx pi
and print lc chr chars chop e x chars False
and print chr chars chop False x e x e x e
and print lc chr flip chars exp i
and print chr chars i x e x e x e
and print lc chr chars NaN x tau x e x e
and print chr chars False x pi x ceiling tau
and print lc chr flip chars exp i
and print chr chars NaN xx tau x e
and say chr chars chop False x e x e x e

Wypróbuj online!

Zwraca ciąg z końcowym znakiem nowej linii. Jeśli nie chcesz tego, zamień ostatni sayna print. Można również zastąpić znaki nowej linii w źródle spacjami.

Wyjaśnienie

Ten kod drukuje ciąg znaków po znaku. Każdy znak jest tworzony przez wprowadzenie odpowiedniego kodu znakowego do chrfunkcji i obniżenie go, lcjeśli to konieczne.

Obecnie wszystkie wartości są generowane przez generowanie ciągu zawierającego poprawną liczbę znaków; w niektórych przypadkach liczba znaków jest odwrotnością kodu znaku docelowego. Teoretycznie powinno być możliwe korzystanie z funkcji matematycznych, takich jak logi expbezpośrednio, ale nie uważałem, że korzystanie z nich jest bardzo łatwe.

Do stosowania jako liczby, mamy e, pii tau; po prawej stronie xlub xxsą ukryte. Wszystkie mają 17 znaków w swoich reprezentacjach łańcuchowych, więc używamy edo minimalnej liczby znaków. Mamy również i(4 znaki), False(5 znaków) i NaN(3 znaki). Możemy pomnożyć długości łańcuchów przez x; xxmnoży jeden plus długość sznurka przez prawą stronę i dodaje jeden. chopusuwa jeden znak z łańcucha na wypadek, gdybyśmy byli jeden od celu.

Instrukcje drukowania są łączone w łańcuchy za pomocą and, co ma dość niski priorytet. To prawie cud, że istnieje; w przeciwnym razie musielibyśmy użyć nielegalnych średników.

Znaki dla postaci znalazłem ręcznie. Warto szukać ich programowo, aby znaleźć krótsze wyrażenia.



Nawiasem mówiąc, @JoKing, czy szukałeś krótszych wyrażeń ręcznie, czy korzystałeś z programu, aby pomóc?
bb94

1
Obawiam się ręcznie. Algorytmiczny sposób prawdopodobnie nie byłby zbyt trudny
Jo King


@Grimy Clever, ale niestety możliwe tylko dlatego, że przestrzeń zerowej szerokości, której używasz, nie jest znakiem spacji
Jo King

17

Szerokość , 66 64 bajtów

QaaGmwmiimaGcwWiimawAGawmfciiiGaFmAmFiimFGcwAmFiGmaiiGcGamafFiGQ

Wypróbuj online!

Drukuje do debugowania. Aby wydrukować na standardowe wyjście, dołącz wwna końcu kodu, który wyskakuje i wysyła górę stosu.

Wyjaśnienie

W opcji Szerokość każda litera koreluje z liczbą na podstawie jej „szerokości”, zgodnie z tą tabelą . Przypisuje to każdej literze cyfrę od 0 do 9. Następnie liczby te są używane do wykonania kodu.

W szczególności litera niż dopasowania 7rozpocznie literał ciągu. Odczyta zestawy dwóch liter naraz, dopóki nie odczyta oryginalnej litery. Każdy zestaw dwóch liter zostanie przekonwertowany na ich liczby szerokości, odczytane jako liczba dziesiętna od 0 do 99, a znak, który będą równe, będzie ich indeksem w następującym ciągu:

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n\t

Na przykład indeks !wynosi 1, więc 01będą odpowiednie liczby szerokości. Zatem if, iI, jt, etc wszystko będzie korelować na ciąg dosłownym !.

W tym przypadku przetłumaczyłem 31 znaków wymaganego wyniku na odpowiednie litery, używając Qjako cudzysłowu. Górna część stosu jest drukowana w celu debugowania po zakończeniu programu.


To jest najkrótszy jak dotąd. Myślę, że możesz wygrać!
Blue-Maned Hawk

14

kod maszynowy x86 (32-bit), 256 bajtów

Kiedy drukuję kod na konsoli 437 strony kodowej, widzę następujące informacje:

j XI a I a I a jbZ      Q fiQ Gf a f    Q I a I a I a I a h hisZ        Q I a I a I a I a hBP  Z        Q iQ
y       Q  a I a I a I a h thaZ Q I a I a I a Ih ButZ   Q  a I a I a I a fhu fZf        Q iQ g  S       Q  a I a I a I a hsaidZ Q I a I a I a I a hshe Z        Q I a I a I a I a hAnd Z        Q TZBX b 

Zawiera niektóre znaki spacji, więc tutaj jest ten sam kod, gdy zastępuję wszystkie znaki tabulacji wszystkimi znakami spacji (z kodem 255) *:

j XI a I a I a jbZ→Q fiQ Gf a f→Q I a I a I a I a h hisZ→Q I a I a I a I a hBP  Z→Q iQ →→y →Q  a I a I a I a h thaZ→Q I a I a I a Ih ButZ→Q  a I a I a I a fhu fZf→Q iQ g→S →Q  a I a I a I a hsaidZ→Q I a I a I a I a hshe Z→Q I a I a I a I a hAnd Z→Q TZBX*b*

Hexdump:

6a 20 58 49 20 61 20 49 20 61 20 49 20 61 20 6a
62 5a 09 51 20 66 69 51 20 47 66 20 61 20 66 09
51 20 49 20 61 20 49 20 61 20 49 20 61 20 49 20
61 20 68 20 68 69 73 5a 09 51 20 49 20 61 20 49
20 61 20 49 20 61 20 49 20 61 20 68 42 50 20 20
5a 09 51 20 69 51 20 09 09 79 20 09 51 20 20 61
20 49 20 61 20 49 20 61 20 49 20 61 20 68 20 74
68 61 5a 09 51 20 49 20 61 20 49 20 61 20 49 20
61 20 49 68 20 42 75 74 5a 09 51 20 20 61 20 49
20 61 20 49 20 61 20 49 20 61 20 66 68 75 20 66
5a 66 09 51 20 69 51 20 67 09 53 20 09 51 20 20
61 20 49 20 61 20 49 20 61 20 49 20 61 20 68 73
61 69 64 5a 09 51 20 49 20 61 20 49 20 61 20 49
20 61 20 49 20 61 20 68 73 68 65 20 5a 09 51 20
49 20 61 20 49 20 61 20 49 20 61 20 49 20 61 20
68 41 6e 64 20 5a 09 51 20 54 5a 42 58 ff 62 ff

Kilka wyjaśnień, jak to działa:

Przydatne instrukcje to:

  • push imm8, push imm16a push imm32następnie popgeneruj stałe. Może to również generować zero (in ah) podczas wypychania bajtu ( imm8).
  • and [ecx+32], ah- zakładając, że ah = 0, ustawia to bajt na zero. Tak się składa, że ​​długość ciągu wyjściowego wynosi 32, więc kod wypełnia bufor od końca do początku.
  • or [ecx+32], edx- zakładając, że bajt wyjściowy jest ustawiony na zero, kopie te edx(4 bajty) są wysyłane. Używam wariantu z dxzamiast edxkońca bufora, ponieważ nie powinien on pisać poza buforem wyjściowym. Ograniczenia w kodzie uniemożliwiają pisanie w ten sposób pojedynczych bajtów!
  • imul edx, [ecx+32], whatever- to główny pomysł na szyfrowanie. Przy wystarczającej liczbie entropii [ecx+32]i dowolnej liczbie może wygenerować dowolny wynik. Używam go do generowania 2 lub 3 bajtów potrzebnych wartości. Pewna komplikacja polega na tym, że zapisując ją na wyjściu, musi logicznie logować się ORz tym, co już tam jest. Czasami konieczne było ponowne wyzerowanie pamięci.
  • Do jmpinstrukcji używany jest wariant instrukcji. Wybrałem go, ponieważ jest to kodowanie 0xff, które odpowiada niezłomnej spacji na stronie kodowej 437. Trochę rozciąga się na regułach, ale poza tym uważam, że zadanie jest niemożliwe ...

Kod źródłowy asemblera wraz z programem C, który go uruchamia (używa składni Visual Studio):

#include <stdio.h>

__declspec(naked) void __fastcall doit(char* buf)
{
    __asm {
        push ' '
        pop eax

        dec ecx
        and [ecx+32], ah    // terminating 0 byte

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah

        push 98
        pop edx
        or [ecx+32], edx
        imul dx, [ecx+32], 26183
        and [ecx+32], ah
        or [ecx+32], dx    // two bytes: [.']

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 'sih '
        pop edx
        or [ecx+32], edx    // 4 bytes: [ his]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 538988610
        pop edx
        or [ecx+32], edx
        imul edx, [ecx+32], 544803081
        or [ecx+32], edx // 1 junk byte and 3 good bytes: (t's)

        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 'aht '
        pop edx
        or [ecx+32], edx    // 4 bytes: [ tha]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        push 'tuB '
        pop edx
        or [ecx+32], edx    // 1 junk byte and 3 good bytes: [But]

        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push word ptr 8309
        pop dx
        or [ecx+32], dx
        imul edx, [ecx+32], 542312807
        or [ecx+32], edx    // 1 junk byte and 3 good bytes: [, ']

        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push 'dias'
        pop edx
        or [ecx+32], edx    // 4 bytes: [said]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push ' ehs'
        pop edx
        or [ecx+32], edx    // 4 bytes: [she ]

        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        dec ecx
        and [ecx+32], ah
        push ' dnA'
        pop edx
        or [ecx+32], edx    // 4 bytes: [And ]

        push esp
        pop edx
        inc edx

        pop eax
        jmp dword ptr[edx-1]
    }
}

int main()
{
    char buf[100];
    doit(buf);
    puts(buf);
}

Nie wydaje mi się to w pełni golfem. Z pewnością zaoszczędziłbyś kilka bajtów, używając pętli, zamiast powtarzać serię identycznych instrukcji. Wszystkie te dec ecx+ and [ecx+32], ahrzeczy można rozdzielić.
Cody Gray

Możesz spróbować. To najlepsze, co mogłem zrobić; Byłbym szczęśliwy widząc inne podejście. Zdecydowałem się porzucić ideę pętli, gdy zobaczyłem, że wymagają one ujemnego przesunięcia skoku. Może to ograniczenie można rozwiązać w sposób kreatywny - nie wiem jak.
anatolyg

1
@anatolyg Może to sprowadzać się do postawy środowiska testowego wobec kodu samodmodyfikującego się. Lub jego opinie na temat wykonywania kodu zbudowanego na stosie.
gastropner

Czy znak nie 0xffnarusza „Żadnych znaków interpunkcyjnych ani znaków innych niż alfabetyczne”?
val


13

PostScript, 889 874 837 835 bajtów

currentflat string dup rrand
count dup count count mul mul xor count count mul count dup mul exch count
count copy count copy count copy count copy count copy
add and sub put print
and sub add put print
sub sub add put print
mul or xor put print
idiv xor add put print
or xor add put print
mod idiv add put print
mul or xor put print
idiv xor add put print
sub and add put print
or and add put print
sub sub add put print
pop add sub put print
mul or xor dup copy put print
mod mul sub put print
add or xor put print
idiv add add put print
add or add put print
put print
add or add put print
or xor add put print
sub and add put print
add or add put print
mod mul sub put print
idiv xor add put print
mul or xor put print
or xor add put print
or and add put print
idiv xor add put print
xor add sub put print
mod mul sub put print
quit

Wypróbuj online!

Używa 32 kopii liczb całkowitych 89 25 20 6. Wszystkie kody znaków ciągu docelowego można uzyskać za pomocą operacji na tych liczbach całkowitych, w kolejności stosu: na przykład „A” (ASCII 65) wynosi 89 - (25 i (20 + 6)). Wiele 4-krotnych liczb całkowitych ma tę właściwość; ten został wybrany, ponieważ są szczególnie łatwe do wygenerowania.

currentflat string dup rrand

Flat ma domyślną wartość 1, więc tworzy ciąg o długości 1 (inicjowany na \0). dupnie jest głęboką kopią: tworzy drugie odwołanie do tego samego ciągu. rrand wypycha losowe ziarno, które domyślnie ma wartość 0. Stos jest teraz ["\0", "\0", 0].

count dup count count mul mul xor

count wypycha liczbę elementów na stosie, więc oblicza 3 ^ (3 * (5 * 6)) = 89.

count count mul count dup mul exch count

4 * 5 = 20, 5 * 5 = 25, 6 = 6. Stos jest teraz ["\0", "\0", 0, 89, 25, 20, 6].

count copy count copy count copy count copy count copy

Duplikuj cały stos pięć razy. W ten sposób otrzymujemy 32 kopie naszego początkowego 7-elementowego stosu. Potrzebujemy tylko 31 kopii, ponieważ ciąg docelowy ma 31 znaków, ale dodatkowa kopia nie zaszkodzi.

add and sub put print

Oblicz kod znaków z czterech pierwszych liczb całkowitych, zapisz go pod indeksem 0 ciągu, a następnie wydrukuj ten ciąg.

quit

Pomija domyślny monit.


11

Rubinowy , 420 354 338 bajtów

def P a
print String a
end
def Q a
p String a
end
class String
def inspect
putc sum size
q
end
end
def w
Q def hacked
end
rescue
end
P def And
end
w
P def she
end
w
P def said
end
Q def gadget
end rescue
w
def a
Q def afraid
end
rescue
end
a
P def But
end
w
P def that
end
a
putc String def s
end
w
P def his
end
Q def fierce
end rescue
a

Wypróbuj online!

W porządku rosnącym wesołości:

Słowa zaczynające się od dużej litery można wydrukować, definiując klasę o tej nazwie i wywołując displayw treści definicji klasy.

Inne słowa można wyświetlić, definiując metody o tej nazwie, które zwracają symbol, a następnie rzutując je na ciąg znaków, aby usunąć wiodący dwukropek.

Inne znaki można wyświetlić, wywołując putcich kod ASCII. Możemy wygenerować odpowiednie liczby, ponownie wykorzystując String deflewę, aby uzyskać ciąg, a następnie pobierając sumę jego bajtów przy użyciu modułu określonego przez jego rozmiar. Niestety nie mamy możliwości wywoływania metod na obiekcie innym niż z definicji klasy tego obiektu, co utrudnia przekazywanie argumentów. Tak więc ostatnim hackiem jest przedefiniowanie String#inspect, które jest wywoływane niejawnie podczas przekazywania ciągu do pmetody, aby obliczał i wyświetlał odpowiedni znak jako efekt uboczny, zanim zgłosi błąd, aby pnie mógł dokończyć wykonywania i wydrukować Nowa linia. Następnie musimy uratować błąd w głównym kodzie.

Edycja: Jordan sprawił, że liczba bajtów była o wiele mniejsza, hmm, wysoka z pewnym sprytnym sterowaniem golfem, a ja wyciąłem jeszcze kilka bajtów, zastępując raisejedno-nieistniejące wywołanie metody, które wywołuje błąd NameError.

Edycja 2: Zauważyłem, że po print Stringwyodrębnieniu do metody taniej jest po prostu użyć tego z definicją metody, niż użyć sztuczki definicji klasy, ponieważ metody mogą być tytułami.


Piękne .... Nie rozumiem, skąd sum sizesuma modulo ma swój rozmiar, ale wszystko inne się sprawdza!
Wartość tuszu

Mówię to nieco leniwie, faktycznie przekazuje rozmiar łańcucha jako opcjonalny argument metody sumowania.
histocrat

11

> <> , 233 122 bajtów

cdacaabbglccgpcbfbbcaacdebbafbebbcebdbealbcpcdbcccdlcdpacbbalccpaalacpbcfafbaab









       g  sandBe
       o  Aviuth

Wypróbuj online!

Zaczęło się od golfa odpowiedzi mbomb , ale odkryłem fundamentalną zmianę, która oszczędza ogromną liczbę bajtów, więc zamieszczam ją jako własną odpowiedź.

Generowanie znaków niealfabetycznych na wyjściu odbywa się poprzez wielokrotne wypychanie wartości na stos, a następnie za pomocą lwypychania długości stosu. Nie musi to jednak być generowane natychmiast: za pomocą ptej postaci można umieścić ją w dowolnej komórce, której współrzędne wynoszą od 10 do 15 włącznie, do późniejszego odzyskania g. Podobnie, znaki alfabetyczne mogą być umieszczane w początkowym kodzie źródłowym i czytane w ten sposób: ponieważ najwyższy niealfabetyczny kod znaków na wejściu to 46 ( .), oznacza to, że stos nie musi być przesuwany wyżej niż 62 potrzebny do przechowywania wszystkie 31 znaków wyniku.

Dodatkowo, vw kodzie w kolumnie 7. umieszczany jest a . Gdy wskaźnik instrukcji zawija się i uderza v, sekwencja gojest wykonywana wielokrotnie w celu odczytania z popchniętych współrzędnych i wyprowadzenia odpowiednich znaków. W końcu stos staje się pusty i gkończy działanie programu z błędem.

Pierwsze 7 bajtów kodu jest ponownie wykorzystywane, gdy zarówno pierwsza 7, jak i ostatnia 7 współrzędnych są wypychane. Umieszczenie vw kolumnie 9 teoretycznie zaoszczędziłoby jeszcze dwa bajty, ale zmusiłoby znaki Ainsvdo kwadratu 2x2 w kodzie, co jest niemożliwe. Wcześniejsza wersja używała kolumny 15, ale wymagała dodatkowej linii w kodzie źródłowym i kończyła się o sześć bajtów dłużej.


Po dalszych przemyśleniach myślę, że mogę sprawić, by kolumna 9 działała, poświęcając bajt na rprzesunięcie linii trasowania, gdziekolwiek chcę. Jednak gra w golfa trochę boli mój mózg.
Nitrodon

8

CJam , 262 bajty

  KAbScibCmhc  CZbsic          GmQYbsic
S CmfYmeibc    ImqmeKmhcel     AZbAbc
S CmfYmeibc    KAbScibCmhcel   ImqmeKmhAmhcel  GmQYbsic    KAZbYbbBbc
S CGmQbDbc     EYbTYtZbc       FYbGmQbcel      EYbGmQbcel
S EYbGmQbcel   ImqmeKmhcel     KAbScibCmhcel   EYbGmQbcel  CGmQbDbc    CmfYmeibc
S ImqmeKmhcel  ImqmeKmhAmhcel  CmfYmeibc       PYmhmeKmhc  CGmQbDbc

Wypróbuj online! Nowe linie są tutaj pokazane tylko dla jasności; każda linia reprezentuje znak.

Uff, było fajnie. Ograniczanie się do poleceń alfabetycznych stanowi interesujące wyzwanie:

  • Bez {i }praktycznie nie ma możliwości sterowania przepływem (poza tym f, że nie znalazłem okazji do użycia).
  • Bez \, _, ;, lub $, nie mamy środki do manipulacji stosu.

Oznacza to, że głównym celem będzie uzyskanie odpowiednich punktów kodu na stosie, a następnie przekształcenie ich w znaki za pomocą c.

Problem polega na tym, że brakuje nam również podstawowych komend arytmetycznych, a także literałów całkowitych. Jest to w porządku, ponieważ mprzestrzeń nazw zawiera wiele zaawansowanych operacji matematycznych i istnieje wiele zmiennych predefiniowanych do przydatnych liczb.

Skończyło się na tym, że intensywnie korzystałem z pierwiastków kwadratowych ( mQi mq), funkcji wykładniczej mei konwersji podstawy ( b), których można również użyć do emulacji mnożenia ( [X 0] Yboblicza X * Y). Ponadto czasami łatwiej jest zbudować wieloznacznik, w którym to przypadku możemy użyć el(przekonwertować na małe litery) wynikowego znaku.

Nadal nie jestem zadowolony z niektórych dłuższych. No cóż.

Wyjaśnienie

To jest wyjaśnienie wyniku po znaku. Zanim zacznę, oto kilka krótkich sposobów tworzenia liczb:

  • 0, 1, 2, 3, są zawarte w zmiennych T, X, Y, Zodpowiednio.
  • Liczby od 10 do 20 są zawarte w zmiennych Ado K.
  • 32 można wykonać za pomocą Sci( Swypycha ciąg zawierający spację, cpobiera pierwszy znak tego ciągu i ikonwertuje ten znak do punktu kodowego). Sjest również używany do spacji.
  • 4 podano jako GmQ(pierwiastek kwadratowy z liczby całkowitej 16).
  • 5 jest podane przez AZbYb(konwersja 10 na bazę 3, dając [1 0 1], i konwertuj wynikową tablicę liczb na bazę 2, dając 5).
  • 7 jest podane przez Ymei(oblicza exp (2) i konwertuje na liczbę całkowitą).

A

K           - push 20                        | 20
 Ab         - convert to base 10             | [2 0]
   Scib     - convert from base 32           | 64
       Cmh  - hypot(TOS, 12)                 | 65.115
          c - round down and convert to char | 'A

n

C      - push 12            | 12
 Zb    - convert to base 3  | [1 1 0]
   s   - convert to string  | "110"
    i  - convert to integer | 110
     c - convert to char    | 'n

d

GmQ      - push 4             | 4
   Yb    - convert to base 2  | [1 0 0]
     s   - convert to string  | "100"
      i  - convert to integer | 100
       c - convert to char    | 'd

s

C         - push 12         | 12
 mf       - factors         | [2 2 3]
   Ymeib  - base 7          | 115
        c - convert to char | 's

h

I           - push 18                        | 18
 mq         - sqrt                           | 4.242
   me       - exp                            | 69.591
     Kmh    - hypot(TOS, 20)                 | 72.408
        c   - round down and convert to char | 'H
         el - lowercase                      | 'h

e

A      - push 10              | 10
 Zb    - convert to base 3    | [1 0 1]
   Ab  - convert from base 10 | 101
     c - convert to char      | 'c

a

KAbScibCmhc   - push 'A (see above) | 'A
           el - lowercase           | 'a

i

I              - push 18         | 18
 mq            - square root     | 4.242
   me          - exp             | 69.591
     Kmh       - hypot(TOS, 20)  | 72.408
        Amh    - hypot(TOS, 10)  | 73.095
           c   - convert to char | 'I
            el - lowercase       | 'i

,

K          - push 20              | 20
 AZbYbb    - convert to base 5    | [4 0]
       Bb  - convert from base 11 | 44
         c - convert to char      | ',

'

C        - push 12              | 12
 GmQb    - convert to base 4    | [3 0]
     Db  - convert from base 13 | 39
       c - convert to char      | ''

B

E         - push 14               | 14
 Yb       - convert to base 2     | [1 1 1 0]
   TYt    - replace elem 0 with 2 | [2 1 1 0]
      Zb  - convert from base 3   | 66
        c - convert to char       | 'B

u

F          - push 15             | 15
 Yb        - convert to base 2   | [1 1 1 1]
   GmQb    - convert from base 4 | 85
       c   - convert to char     | 'U
        el - lowercase           | 'u

t

E          - push 14             | 14
 Yb        - convert to base 2   | [1 1 1 0]
   GmQb    - convert from base 4 | 85
       c   - convert to char     | 'T
        el - lowercase           | 't

.

P          - push pi                        | 3.141
 Ymh       - hypot(TOS, 2)                  | 3.724
    me     - exp                            | 41.437
      Kmh  - hypot(TOS, 20)                 | 46.011
         c - round down and convert to char | '.

1
Można zrobić konwersje zasad z cyfr poza zwykłym zakresie do zasady, takiej jak HYbYCtYbc, HYbXAtYbci HYbXBtYbc.
Nitrodon

7

Deadfish ~ , 943 bajtów

iiisdsiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicddddddddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcdddddddddddcdddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcddddddddddddddddddciiiiiiiicdddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddciiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicdcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsdddddcddddddddddddcdddddddciiiiiiiiiiiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddddddddsddddddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddsiiiiciciiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddc

Wypróbuj online!

Pętle nie są dozwolone :(


7

zło , 198 bajtów

aeeeannkhhwzuuuuuueaeuekwuuuuuuuuuunkhwzaeeeeehknwgueeywguuuuuuhhknnwuuuwhgwpwnngheeuwguuuuuwngwzaeeeaaaeeeeeewhhgwnguuuueewnngawpaawuwnngwpawhgwhhgeeuwpawhguuuueewpwhgwhgwawpwnngaaaaaaeeeewguuuueew

Wypróbuj online!

To było całkiem fajne.



6

MATL , 187 158 bajtów

IEWQKEtqhpEqqKQHhthpKWEyQKWEqqYqQQXJwtQQQwKWEJKQthpYqKQHhthptQQQQQwIIhKQhpqKWEIWKQhpqIEWQQJQQtqKWEyIIhIhpYqQXJyKQthpYqwIWKQhpqyqKWEyJtQwhhPIIhKQhpQIWKQhpqvlec

Wypróbuj online!

Bardziej czytelna wersja: Wypróbuj online! Ręczna próba zbudowania łańcucha. Prawdopodobnie jest dużo miejsca do gry w golfa, dzieląc sznurek na wygodne kawałki, używając Pi hobracając i budując sznurek. Mam nadzieję, że ktoś podejmie wyzwanie, by mnie obezwładnić. Głównym wyzwaniem jest to, że nie można użyć +lub -, tak podstawowa arytmetyka często nie jest możliwe.

Najważniejsze:

  • KQthpYq: 25-ta liczba KQthppierwsza Yqwynosi 97, co odpowiada literze a. Litera s(115) jest generowana podobnie z 113, 30-tej liczby pierwszej. Następnie jest szeroko ponownie wykorzystywany w schowku J.
  • hisjest skracany przez przechowywanie hpoprzedniego w schowku J. Ponieważ to poprzednio przechowywane s, budujemy hisw odwrotnej kolejności, abyśmy mogli nadal pobierać ostatnio sużywane yi odwracać je po użyciu P.
  • Duża liczba bajtów zaoszczędzonych dzięki Luisowi Mendo (głównie przez zmianę kilku hna vle)

Huh - naprawdę myślałem, że używanie vmoże zepsuć to, hco miałem wcześniej. Chyba powinienem to mieć, zamiast zakładać. Ponadto, dzięki za heads-up, nastąpiło nadgorliwe usunięcie. Jestem ciekawy, czy dasz radę lepiej ...
Sanchises

Chciałbym spróbować, ale będzie musiał poczekać. Odpowiedź na to pytanie zajmuje dużo czasu!
Luis Mendo

1
@LuisMendo Yup. Zajęło mi to około godziny, a to obejmuje tylko bardzo lokalną optymalizację. Jestem pewien, że można zrobić lepiej z odrobiną globalnego spojrzenia na rzeczy.
Sanchises

Moja próba . Nie patrzyłem na twoje, więc mam nadzieję, że podejścia są inne
Luis Mendo

@LuisMendo Całkowicie zapomniałem, co Uoznacza ^2, że mogłem zaoszczędzić sporo bajtów ...
Sanchises

6

MATL , 118 bajtów

KEUQtVQsQKBFZAXHKUqyyhsXJyyhdQtQQQwOJIUEyhdtKEhsHKQYqEEKQyywhdXJKEUQQHKUhstQwOytHKhsKYqyhdbJyqOHKhstQHKUqhsKUqYqqJvlec

Wypróbuj online!

Bardziej czytelna wersja (każda linia odpowiada jednemu znakowi, z wyjątkiem operacji przestawiania stosu).

Wyjaśnienie

Program generuje punkty kodowe wymaganych znaków, jako niezależne liczby. Na koniec wszystkie te liczby są łączone w wektor kolumny, przekształcane jako wektor wiersza i konwertowane na znaki. Wynik jest domyślnie wyświetlany.

Niektóre z zastosowanych sztuczek:

  • Większość punktów kodowych poniżej 32 jest wyświetlanych jako spacja. Tak 0jest używany dla większości spacji, ponieważ kosztuje tylko bajt ( O).
  • Jednak dla pierwszej spacji 15jest używana (generowana jako KUq), ponieważ można ją ponownie wykorzystać, dodając ją do 100(char d), aby dać 115( s). Przy innej okazji 5używa się miejsca (generowanego jako KQ), więc można go później odjąć od 44( ,), aby dać 39( ').
  • Schowek Jsłuży do przechowywania znaków, które będą powtarzane: najpierw s, a potem '. Podobnie, schowki Hprzechowują informacje 100przydatne di do generowania innych znaków.
  • W dużym stopniu wykorzystuje się funkcje Q(dodawanie 1), q(odejmowanie 1), E(mnożenie przez 2) i U(kwadrat), a także predefiniowane literały w schowkach I( 3) i K( 4).
  • Arbitralne dodawanie i odejmowanie odbywa się przez połączenie w wektor ( h) i obliczenie jego sumy ( s) lub kolejnych różnic ( d).
  • 100( d) jest generowany jak 4w formacie binarnym interpretowanym jako liczba dziesiętna.
  • 110( n) jest uzyskiwane z 65( A) przez konwersję na string ( '65': punkty kodowe [54 53]), dodawanie 1do punktów kodowych ( [55 54]), sumowanie ich razem i dodawanie 1.
  • Kolejność generowania liczb jest czasami zmieniana dla wygody; a następnie są one porządkowane za pomocą funkcji przestawiania stosu: swap ( w), bubble up b).

1
Bardzo dobrze! Sprytny dotyk za pomocą Ozamiast KWEspacji. I potwierdziłeś moje podejrzenie, że prawdopodobnie lepiej poświęcić inny schowek H.
Sanchises

5

dc , 240 222 209 bajtów

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdOOlAxlAxPOBlBxdIlAxoPAdlBxddsrIlAxssPPOPlsIZlCxddspPOZlCxPPOPlrdZlCxPlsPlrPlcPPKPdZlBxdZlAxPOAZlAxdPIZlCxdPrPdPlpPlrdZlCxPPKPOPPlpPlsPOPldPKP

Wypróbuj online!

Moja pierwsza myśl była taka sama jak @seshoumara, po prostu wepchnąłem wystarczającą ilość rzeczy na stos, aby wygenerować wszystkie wartości ASCII znaków. Wtedy dotarło do mnie, że skoro +, -i *są operatorzy pojedynczej postaci, mogę tylko odtwarzać je i mieć możliwość korzystania z arytmetyki! Z pewnością byłoby to mniejsze! I nie zdziwiłbym się, gdybym mógł zagrać w więcej bajtów, ale na razie ... to zawiłe podejście udało się powiązać z naiwnym (ish).

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdjest częścią podejścia podobnego do @ seshoumara, ale idziemy tylko do 46, czyli .. Robimy to, ponieważ musimy zwiększyć do 45, -a także potrzebujemy kropki w naszym ciągu, więc pójście o jeden krok dalej w tym okresie jest (myślę) najtańsze. Po drodze przechowujemy pewne wartości: 5, 32, 39, wszystkie przydają się później. 5 dla przedmiotów użytkowych, 32 i 39 dla ich wartości ASCII. Początkowo robiłem 1-5, ale to było drogie i mogłem po prostu uniknąć używania 4; użyj Z( wpisz wartość, wciśnij liczbę cyfr, które ma) na trzy-, dwu- lub jednocyfrową liczbę dla tych wartości. Na 42, 43, i 45, możemy przekonwertować je na ciągi znaków ( *, +, i -, odpowiednio) i zapisać je jako makra ( B, A, iCodpowiednio, kolejno). Oznacza to, że bez używania znaków *+-możemy teraz używać tych operatorów.

Odtąd zaczynamy generować wartości ASCII przy użyciu mocy matematyki zamiast zwykłej akumulacji, przechowując niektóre powtórzenia po drodze. 100, 105 i 115 pojawiają się na tyle, że przechowywanie ich (w rejestrach lub w inny sposób) ma sens. Pierwotnie zostawiłem stos wypełniony 10s i użyłem ich do stworzenia 100; skończyło się to na zapisaniu bajtów, aby wypełnić stos 32s i użyć ich jako spacji później. Nieco bardziej czytelna wersja sekcji ASCII: OOlAxlAxP OBlBxdIlAxoP AdlBxddsrIlAxssP P OP lsIZlCxddspP OZlCxP P OP lrdZlCxP lsP lrP lcP P KP dZlBxdZlAxP OAZlAxdP IZlCxdP rPdP lpP lrdZlCxP P KP OP P lpP lsP OP ldP KP.

Ogolono 18 bajtów poprzez: zapisanie liczby 5 jako podstawki wejściowej zamiast rejestru; liczba 32 jako precyzja zamiast rejestru; liczba 115 jako podstawa wyjściowa zamiast rejestru; Następnie było zmienić KZaby IZwygenerować 1s i OZaby KZwygenerować 2s.

Ogolono jeszcze 13 bajtów, zalewając stos 32s; ustawienie precyzji na 39; stosowanie manipulacji stosami, aby uniknąć przechowywania 116; wycinając podwójną pracę, którą przypadkowo zostawiłem.


+1 Fajny pomysł, aby aodtworzyć tych operatorów, a następnie zadzwonić do nich x. To pokazuje zachowanie danych w kodzie dc. Kiedy będę miał czas, zastosuję twoją najnowszą sztuczkę przechowywania danych w parametrach zamiast w rejestrach. Czy myślisz, że moglibyśmy uzyskać jeszcze krótsze rozwiązanie DC, nadużywając sposobu, w jaki P działa, aby drukować więcej liter na raz, jeśli mamy szczęście, że wprowadzamy potrzebną ogromną liczbę za pomocą tylko heksa?
seshoumara

@seshoumara Jest to możliwe, chociaż moje próby zrobienia tego z innymi wyzwaniami sugerują, że jest mało prawdopodobne, ponieważ te wartości szybko stają się duże. Aby otrzymać dwie pierwsze litery „An”, musimy mieć P16750 lub 0x416E. Gdybyśmy po prostu mieli szczęście, a jeden z podłańcuchów składał się wyłącznie z wartości AF, to może nas to skrócić. To by było trochę szczęścia! W przeciwnym razie albo wprowadzilibyśmy duże liczby, wymyślając je, albo dodając i mnożąc przez 256. Co wydaje się ... bardziej skomplikowane niż kilka Ps.
brhfl

5

Japt , 87 bajtów

Bs g caA
HzG
Ts caV
iWisiiihiSisiUitiaihitiSitiuibu iUiSiWcaV idiiiaisiSieihisiSidiniau

Spróbuj

Wyjaśnienie

Pierwszy wiersz generuje 'i przypisuje go do zmiennej U.

Bs g caA
B                            :11
 s                           :To string
   g                         :First character
     c                       :Character code
      a                      :  Absolute difference with
       A                     :  10

Drugi wiersz przypisuje 2do zmiennej V.

HzG
H                            :32
 z                           :Floor divided by
  G                          :16

Trzeci wiersz generuje .i przypisuje go do zmiennej W.

Ts caV
Ts                           :Convert 0 to a string
   caV                       :Absolute difference of its charcode with V (2)

Ostatni wiersz buduje ciąg po jednym znaku na odwrót.

iW...ibu ...iWcaV ...iau
iW                           :Start by prepending W (.) to U (')
  ...                        :Each i prepends the literal character that follows it to the string, with S being space and U being "'"
     ibu                     :As B is the constant for 11 and it can't be quoted, here i prepends "b" to the string and u uppercases it
         ...                 :As above, each i is prepending the character/constant that follows it to the string
            iWcaV            :Gets the absolute difference of the charcode of W (.) and V (2) to get the "," and prepends that
                  ...        :Some more literals
                     iau     :And, finally, the same trick is used for the "A" as was for the "B", as A is the constant for 10

Niezłe rozwiązanie. Możesz zapisać bajt, zastępując pierwszą linięQc dGaB
Embodiment of Ignorance

4

Czerwony , 272 bajty

prin quote And prin sp prin quote she prin sp prin quote said prin comma prin sp prin subtract to sp mold quote G sp prin quote But prin sp prin quote that prin subtract to sp mold quote G sp prin quote s prin sp prin quote his prin dot prin subtract to sp mold quote G sp

Jeśli konieczne są podwójne cudzysłowy:

Czerwony , 344 bajty

prin subtract to sp mold quote B sp prin quote And prin sp prin quote she prin sp prin quote said prin comma prin sp prin subtract to sp mold quote G sp prin quote But prin sp prin quote that prin subtract to sp mold quote G sp prin quote s prin sp prin quote his prin dot prin subtract to sp mold quote G sp prin subtract to sp mold quote B sp

Nie działa w TIO, ale działa w czerwonym tłumaczu.

Czerwona konsola

Wyjaśnienie:

Słowa są trywialne - opisuję je (drukuj bez nowej linii) jako literały z quote. Czerwony ma wbudowane słowo oznaczające przestrzeń - sporaz, commai dot. "i 'bardziej interesujące: drukuję je, odejmując odpowiednio spację Bi G, zaczynając od literału, Bi Gprzekształcając je najpierw na ciąg znaków, molda następnie na znak (w celu użycia odejmowania na nich) za pomocą to sp( czerwony ma konwersję według prototypu - przekonwertować ciąg do typu sp, który jest znakiem).


1
Pytanie zostało wyjaśnione; usunęli z niego interesującą część.
anatolyg

@anatolyg Dzięki, wciąż go potrzebuję ', więc rozwiązanie 272 bajtów jest takie samo.
Galen Iwanow

4

Dalej (gforth), 351

CHAR A DUP EMIT
CHAR n EMIT
CHAR d EMIT
SPACE
CHAR s DUP EMIT
CHAR h EMIT
CHAR e EMIT
SPACE
EMIT
CHAR a EMIT
CHAR i EMIT
CHAR d EMIT
DUP CHAR m XOR EMIT
SPACE
CHAR f XOR DUP EMIT
CHAR B EMIT
CHAR u EMIT
CHAR t DUP EMIT
SPACE
DUP EMIT
CHAR h EMIT
CHAR a EMIT
EMIT
DUP EMIT
CHAR s EMIT
SPACE
CHAR h EMIT
CHAR i DUP EMIT
CHAR s EMIT
CHAR G XOR EMIT
EMIT

Szkoda, że ​​nie mogę przedefiniować CHAR lub EMIT na słowa jednoliterowe, ponieważ wymagałoby to użycia zarówno :i ;(np. : C CHAR ;) Lub '(np. ' CHAR ALIAS C)

W rzeczywistości, gdybym mógł zdefiniować słowa, mógłbym zrobić, : P CHAR EMIT ;a następnie zrobić, P xaby wydrukować x. No cóż.

Nie mogę nawet utworzyć bufora, zapisać tam sekwencji znaków, a następnie użyć jej jako danych wejściowych, ponieważ zapisywanie w pamięci wymaga użycia !lubC!


3

AlphaBeta , 180 177 175 163 bajtów

cccaaggtFgDILrFigggDLjDLCLigggggDLjhDLhhhDLCLiggggDLjjggDLihhDLhhhhhDLcaaCLdbbCLcbbbCLHgDLiiiiigDLhDLdaaaCLDLjhhDLjgggDLiihDLcbbbCLhDLdaaaCLjhDLgDLiDLcaaaaCLdaaaCL

Wypróbuj online!

WIP


3

Pepe , 266 bajtów

Trzymam stos r pusty i mam „s” na stosie R.

reeEeeeeeE reeEEeEEEe reeEEeeEee reEe REeEEEeeEE Reee reeEEeEeee reeEEeeEeE reEe Reee reeEEeeeeE reeEEeEeeE reeEEeeEee reeeEeEEee reEe reeeEeeeEe reeEeeeeEe reeEEEeEeE reeEEEeEee reEe reeEEEeEee reeEEeEeee reeEEeeeeE reeEEEeEee reeeEeeEEE Reee reEe reeEEeEeee reeEEeEeeE Reee reeeEeEEEe reeeEeeeEe

To nie jest w TIO, ale możesz spróbować tutaj


3

dc , 240 bajtów

Główną ideą jest ciągłe powiększanie stosu o 1 ( K), oszczędzając ( sX) rozmiar stosu ( z) w niestandardowych rejestrach, gdy pasuje do każdego unikalnego kodu ASCII. Drukowanie ( P) odbywa się przez cały czas.

KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsSKKzsQKKKKKzsqKKKKKzsCKKzsDKKKKKKKKKKKKKKKKKKKzPKzsBKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsaKKKzsdKzseKKKzshKzsiKKKKKzPldPlSPKKKKKzsszPlhPlePlSPlsPlaPliPldPlCPlSPlqPlBPKzdstzPdPlSPdPlhPlaPPlqPlsdPlSPlhPliPPlDPlqP

Wypróbuj online!

Zrobiłem pewną optymalizację, jak na przykład nie zapisywanie litery, jeśli nie jest ona później używana, na przykład powielanie ( d) litery, np. T, na stosie w celu zapisania bajtu, ponieważ recall ( lX) ma 2 bajty.


Wymyśliłem rozwiązanie dc, które wykorzystuje arytmetykę, tworząc makra dla +, - i *. Ma 262 bajtów. Będę nadal próbował go zoptymalizować, aby uzyskać konkurencyjność, ale muszę powiedzieć, że jestem rozczarowany, że jest o wiele grubszy niż (stosunkowo) naiwne rozwiązanie.
brhfl

@brhfl Tak, dc robi się dość gadatliwy. Mimo to bardzo chciałbym zobaczyć twoje rozwiązanie, więc opublikuj je! W międzyczasie myślę też o graniu w golfa obecną metodą, użyciu programu lub wymyśleniu innego pomysłu na dc.
seshoumara

Udało mi się zawiązać 240! I nie zdziwiłbym się, gdybym mógł zagrać w golfa z jeszcze jednym lub dwoma bajtami, ale ... jest to znacznie bardziej tępe podejście przy małym / zerowym zysku. W każdym razie opublikowałem go gdzieś tam ...
brhfl

Doszedłem do 222, zastępując niektóre z moich najczęściej używanych rejestrów z podstawką i precyzją wejścia / wyjścia; oszczędza jeden bajt w sklepie i jeden bajt przy każdym ładowaniu ... Ponieważ liczby są nieistotne, nie ma to wpływu na nic ... Możesz to również wykorzystać na swoją korzyść!
brhfl

3

Kod maszynowy 80186+, format MS-DOS .COM, 822 787 bajtów

Oprócz liter używane są tylko tabulatory i spacje. Biorąc pod uwagę, że większość kodów operacyjnych w dozwolonym zakresie to pewne przyrosty, zmniejszenia, wypychania, wyskakiwania i operatory pośredniczące w rejestrach i operatory OR, oprócz IMUL, korzystam z faktu, że rejestr stosu zawija się, gdy osiąga koniec segmentu, aby zmodyfikować kod w odwrotnej kolejności! Wymagany jest montaż 80186+, ponieważ przekazuję natychmiastowe wartości.

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXjhX   GXkOXYIQSX GXjdX    GXkOXwIIIIIIIIIQhhihs kOXeQh ihutSXH    GXHHHHHH GXSX GYkOXDAAAQSX GXjGX    GXkOXtQhidhsahe hshhd hAnSX GXjTX   GXkOXdIIIQkOXgAQSX GXHHHHHHHHHHHHHHHHHHHHH  GXSX GYkOXbAAAAAAAAAAAAAAQhhlh  Xhh qM

Źródło z adnotacjami (format TASM):

IDEAL
P186

MODEL   TINY
CODESEG
ORG 100H

MAIN:   
REPT 582
    POP AX  ; Set up stack to end of string
ENDM

    PUSH 68H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],59H ; 68H*59H=2428H
    DEC CX ; -1=2427H
    PUSH CX

    PUSH BX
    POP AX
    AND [BX+58H],AL
    PUSH 64H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],77H ; 64H*77H=2E7CH
REPT 9
    DEC CX ; -9=2E73H
ENDM
    PUSH CX

    PUSH 6968H
    PUSH 2073H

    IMUL CX,[BX+58H],65H ; 64H*65H=2774H
    PUSH CX

    PUSH 6920H
    PUSH 7475H

    PUSH BX
    POP AX
    DEC AX
    OR [BX+58H],AX ; FFFFH
REPT 6
    DEC AX
ENDM
    AND [BX+58H],AL ; FFF9H
    PUSH BX
    POP AX
    AND [BX+59H],AL ; 00F9H
    IMUL CX,[BX+58H],44H ; 0F9H*44H=4224H
REPT 3
    INC CX ; +3=4227H
ENDM
    PUSH CX

    PUSH BX
    POP AX
    AND [BX+58H],AL
    PUSH 47H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],74H ; 47H*74H=202CH
    PUSH CX

    PUSH 6469H
    PUSH 6173H
    PUSH 2065H
    PUSH 6873H
    PUSH 2064H
    PUSH 6E41H

;; CODE STARTS:
;; PUSH 0909H
;; POP AX
;; PUSH 046CH
;; POP DX
;; INT 21H
;; INT 20H

    PUSH BX
    POP AX
    AND [BX+58H],AL
    PUSH 54H
    POP AX
    OR [BX+58H],AX
    IMUL CX,[BX+58H],64H ; 54H*64H=20D0H
REPT 3
    DEC CX ; -3=20CDH
ENDM
    PUSH CX

    IMUL CX,[BX+58H],67H ; 54H*67H=21CCH
    INC CX ; 21CDH
    PUSH CX

    PUSH BX
    POP AX
    AND [BX+58H],AL
REPT 21
    DEC AX
ENDM
    OR [BX+58H],AX ; 0FFEBH
    PUSH BX
    POP AX
    AND [BX+59H],AL ; 0EBH
    IMUL CX,[BX+58H],62H ; 0EBH*62H=59F6H
REPT 14
    INC CX ; +14=5A04H
ENDM
    PUSH CX

    PUSH 6C68H
    PUSH 5809H
    PUSH 0968H

    JNO $+4FH

END MAIN
ENDS

To nie jest montaż, to kod maszynowy ...
Artelius

@Artelius Fair wystarczy. Zaktualizowałem opis.
ErikF

3

Befunge-98 (FBBI) , 125 124 121 bajtów

wab









And she said   But that s his












wakekekaayyeapwayyaayybyapayybyapcyabcyaayycayyba
a



b
wayapapoq

Wypróbuj online! Dane wyjściowe do pliku o nazwie \n(pojedynczy nowy wiersz). Podziękowania dla Jo Kinga za scenariusz.

Dane wyjściowe obejmują 10 nowych linii.

Dla tylko jednej nowej linii, +1 bajt , zmieniając następujący wiersz:

wakekekaayyeapwayydayybyapayybyapycyabcyaayycayyba

Wypróbuj online!


Wyjaśnienie:

Wskaźnik instrukcji porusza się w następujący sposób:Ścieżka IP

Program umieszcza znaki niealfabetyczne na swoim miejscu przed wypisaniem tego wiersza do pliku.

Befunge-98 zawiera instrukcje a... f, które wypychają odpowiadającą im wartość szesnastkową na stos. Aby wygenerować inne liczby, przekazuje te wartości do y(„Get SysInfo”) jako argumentów w celu uzyskania:

10  y-position
11  x-position
12  y-velocity (= 0)
13  x-velocity (= 1)

23* stack size

Umieszczając większość kodu na y = 23, ayymożna go użyć do wielokrotnego dostępu do wielkości stosu, który jest następnie wykorzystywany do generowania kodów znaków.


Czy nie jest dozwolony tylko jeden znak nowej linii?
Delioth

W poście stwierdza się, że „Biała spacja jest całkowicie dozwolona”. Myślę, że fajnie jest nadużywać tego sformułowania, aby usprawiedliwić końcowe znaki nowej linii!
anatolyg

2

Pyth , 210 bajtów

pChyCdpCyhyhlGpCyytlGpdpChFhTyylGpCyylGpChyytlGpdpChFhTyylGpCtytytlGpChyylGpCyytlGpCyyhTpdpCtyyTpCyhCdpCtFyyCdhTpCyhFlGCdpdpCyhFlGCdpCyylGpCtytytlGpCyhFlGCdpCtyyTpChFhTyylGpdpCyylGpChyylGpChFhTyylGpCyhyhTpCtyyT

Wypróbuj online!

Znalazłem kilka liczb, które można wyrazić przy użyciu samych liter (np. T= 10, Z= 0, lG= długość (alfabet) = 26, Cd= kod znaków (spacja) = 32) i kilka funkcji, które można wykonać przy użyciu samych liter (jak t= zmniejszanie, h= zwiększanie, hF= wielokrotne stosowanie przyrostu = dodawanie), a następnie po prostu uruchomiłem wyszukiwanie z użyciem siły, aby znaleźć najkrótsze kombinacje tych funkcji i liczb, które skutkowały każdą z potrzebnych liter.


2

16-bitowy kod zestawu x86, 665 bajtów

(plik binarny jest alfabetyczny, a nie źródło)

Jakoś zapomniałem o regule zezwalającej na białe znaki. Z pewnością kod może zostać w ten sposób zagrany w golfa.

Kod bajtowy:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXsBFVKZPFFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXkLAFQQZJJJRkDCGPLXDPDJRkDBEPZJJRLZDRDZAAAQPLYDQDYXXDQhishZhDRDhZsDQDhaththRDhuthZBDQDRhidhsaRDhhehZsDRDhndhZADTZPiDEFY

Źródło:

    db    63 dup (58h) ;pop ax
    jnb   label1
    dw    5646h      ;magic #1
    dw    5a4bh      ;magic #2
    dw    4650h      ;magic #3
    dw    (42h-6)/2 dup ("PF")

label1:
    db    416 dup (58h) ;more pop ax
    imul  cx,[si+41h],46h ;cl=24h (string sentinel)
    push  cx         ;push string sentinel
    push  cx
    pop   dx         ;dl=24h
    dec   dx
    dec   dx
    dec   dx         ;dl=21h
    push  dx         ;save for later
    imul  ax,[si+43h],47h ;al=0CDh
    push  ax         ;push xxCDh
    dec   sp         ;insert xx
    pop   ax         ;ah=0CDh
    inc   sp         ;discard xx
    push  ax         ;push 0CDxx
    inc   sp         ;discard xx
    dec   dx         ;cl=20h (space)
    push  dx
    imul  ax,[si+42h],45h ;al=2Eh (dot)
    push  ax
    pop   dx         ;dl=2Eh
    dec   dx
    dec   dx         ;dl=2Ch (comma)
    push  dx         ;push xx2Ch
    dec   sp         ;insert xx
    pop   dx         ;dl=2Ch
    inc   sp         ;discard xx
    push  dx         ;push 2Cxxh
    inc   sp         ;discard xx
    pop   dx         ;dx=202Ch
    inc   cx
    inc   cx
    inc   cx         ;cl=27h (quote)
    push  cx         ;push xx27h
    push  ax         ;push xx2Eh
    dec   sp         ;insert xx
    pop   cx         ;ch=2Eh
    inc   sp         ;discard xx
    push  cx         ;push 2Exxh
    inc   sp         ;discard xx
    pop   cx         ;cx=272Eh
    pop   ax         ;discard xxxx
    pop   ax         ;ax=0CD21h
    inc   sp         ;discard xx
    push  cx         ;push ".'"
    push  7369h      ;push "is"
    push  685ah      ;push "h"+xx
    inc   sp         ;discard xx
    push  dx         ;" "+xx
    inc   sp         ;discard xx
    push  735ah      ;push "s"+xx
    inc   sp         ;discard xx
    push  cx         ;push "'"+xx
    inc   sp         ;discard xx
    push  7461h      ;push "at"
    push  6874h      ;push "th"
    push  dx         ;push " "+xx
    inc   sp         ;discard xx
    push  7475h      ;push "ut"
    push  425ah      ;push "B"+xx
    inc   sp         ;discard xx
    push  cx         ;push "'"+xx
    inc   sp         ;discard xx
    push  dx         ;push ", "+xx
    push  6469h      ;push "id"
    push  6173h      ;push "sa"
    push  dx         ;push " "+xx
    inc   sp         ;discard xx
    push  6568h      ;push "he"
    push  735ah      ;push "s"+xx
    inc   sp         ;discard xx
    push  dx         ;push " "+xx
    inc   sp         ;discard xx
    push  646eh      ;push "nd"
    push  415ah      ;push "A"+xx
    inc   sp         ;discard xx
    push  sp
    pop   dx         ;dx=sp
    push  ax
    imul  ax,[si+45h],5946h ;ah=09h

Działa w ten sposób:

  • przesuwa wskaźnik stosu na koniec kodu za pośrednictwem POP AX (nie może POP SP, ponieważ nie jest alfabetyczny);

  • konstruuje instrukcję do wywołania wywołania DOS (algorytmicznie, ponieważ nie jest to alfabetycznie);

  • konstruuje znaki niealfabetyczne;

  • umieszcza ciąg na stosie;

  • umieszcza instrukcję wysyłki na stosie na dokładnym końcu kodu, aby wykonanie przepływało bezpośrednio do tej instrukcji;

  • konstruuje instrukcję drukowania łańcucha;

  • wyświetla ciąg i natychmiast ulega awarii. : - / (Pełne wyjście wymagałoby więcej kodu)




0

Kod maszynowy 80186 + DOS, 91 bajtów

Wersja tekstowa:

hm  j   j   PPjzjzjgaAAA    JSJJ    RU  Sq  ReAA    JdJJJ   RfiJElK JEiS GtI And she said   But that s his   

Wersja tekstowa, z tabulatorami (kod 9) zastąpionymi przez 9i spacje (kod 32) zastąpione przez *:

hm9j9j9PPjzjzjgaAAA9JSJJ9RU9Sq9ReAA9JdJJJ9RfiJElK9JEiS*GtI*And*she*said***But*that*s*his***

Hexdump:

68 6D 09 6A 09 6A 09 50 50 6A 7A 6A 7A 6A 67 61
41 41 41 09 4A 53 4A 4A 09 52 55 09 53 71 09 52
65 41 41 09 4A 64 4A 4A 4A 09 52 66 69 4A 45 6C
4B 09 4A 45 69 53 20 47 74 49 20 41 6E 64 20 73
68 65 20 73 61 69 64 20 20 20 42 75 74 20 74 68
61 74 20 73 20 68 69 73 20 20 20

Kod maszynowy pojawia się w pliku z rozszerzeniem .com. Po uruchomieniu drukuje wymagany komunikat, a następnie zawiesza się (wykonując losowe dane).

Ogólne wyjaśnienie tego, co robi:

  1. Inicjuje rejestry o stałych wartościach
  2. Zastępuje spacje w komunikacie wymaganymi symbolami specjalnymi ( ,'.$)
  3. Łata kod generuje int 21instrukcję, która drukuje komunikat
  4. Dzwoni do DOS

Kod zestawu (można skompilować tasm):

my_bp equ 7ah
my_si equ 7ah
my_di equ 67h
my_msg equ 13bh
    .model tiny
    .code
    .startup
    .186
    org 100h
    push 96dh   ; ax (ah = 0; al = don't care, but see below)
    push 9      ; cx
    push 9      ; dx
    push ax     ; bx = don't care
    push ax     ; don't care
    push my_bp
    push my_si
    push my_di
    popa
    inc cx
    inc cx
    inc cx
    or [bp+si+my_msg-my_bp-my_si+12], cx ; ,
    dec dx
    dec dx
    or [bp+si+my_msg-my_bp-my_si+14], dx ; '
    or [bp+di+my_msg-my_bp-my_di+23], dx ; '
    or [bp+si+my_msg-my_bp-my_si+30], dx ; '
    inc cx
    inc cx
    or [bp+si+my_msg-my_bp-my_si+29], cx ; .
    dec dx
    dec dx
    dec dx
    or [bp+si+my_msg-my_bp-my_si+31], dx ; $

    ; 0x2049 * 0x4b6c = 0x98301cc
    ; So this sets cx to 1cc (a temporary constant used to patch code)
    imul cx, [bp+si+my_msg-my_bp-my_si-2], 4b6ch
    ; 0x1cc | 0x2049 = 0x21cd (the instruction which calls DOS int 21)
    ; Here ah = 9 ("print" mode)
    or [bp+si+my_msg-my_bp-my_si-2], cx

    ; At address 101, there is the constant 96d, which was loaded into ax
    ; 0x96d * 0x7447 = 0x448013b
    ; So the following sets dx to 13b (adddress of the message)
    imul dx, [bp+di+101h-my_bp-my_di], 7447h

int21:
    dw 2049h

    db 'And she said   But that s his   '
    end

Używa popainstrukcji do wyskakiwania wszystkich rejestrów, ponieważ regularne popnie może wypełnić wszystkich potrzebnych rejestrów (np. pop diJest zabronionym kodem operacyjnym).

Adresy bajtów do załatania są w zakresie 0x100 ... 0x160. Na szczęście można je przedstawić jako sumę 3 bajtów z dozwolonymi wartościami:

  • 0x7a w bp
  • 0x7a lub 0x67 w silubdi
  • Natychmiastowa wartość

Łata bajtów w komunikacie działa logicznie ORna 0x20 (znak spacji) i małej stałej (4, 7, 12 lub 14). Mała stała jest uzyskiwana przez inicjalizację cxi dxdo 9 (znak tabulacji) i wykonywanie INClub DECw razie potrzeby.

Patchowanie kodu korzysta z IMULinstrukcji. Znalazłem potrzebne 16-bitowe stałe do pomnożenia za pomocą wyszukiwania brute-force.

Wreszcie adres wiadomości (0x13b) jest uzyskiwany przez pomnożenie. Aby zaoszczędzić miejsce, wziąłem jedną ze stałych z jednej z instrukcji, która zawiera bezpośrednią wartość 0x96d. Tutaj 9część wybiera funkcję drukowania DOS, a 6dczęść jest parametrem wolnym. Okazuje się, że 6djest to jedyna możliwość, która może dać 0x13b po pomnożeniu.

Demontaż części kodowej:

06BA:0100 686D09            PUSH    096D
06BA:0103 6A09              PUSH    +09
06BA:0105 6A09              PUSH    +09
06BA:0107 50                PUSH    AX
06BA:0108 50                PUSH    AX
06BA:0109 6A7A              PUSH    +7A
06BA:010B 6A7A              PUSH    +7A
06BA:010D 6A67              PUSH    +67
06BA:010F 61                POPA
06BA:0110 41                INC     CX
06BA:0111 41                INC     CX
06BA:0112 41                INC     CX
06BA:0113 094A53            OR      [BP+SI+53],CX
06BA:0116 4A                DEC     DX
06BA:0117 4A                DEC     DX
06BA:0118 095255            OR      [BP+SI+55],DX
06BA:011B 095371            OR      [BP+DI+71],DX
06BA:011E 095265            OR      [BP+SI+65],DX
06BA:0121 41                INC     CX
06BA:0122 41                INC     CX
06BA:0123 094A64            OR      [BP+SI+64],CX
06BA:0126 4A                DEC     DX
06BA:0127 4A                DEC     DX
06BA:0128 4A                DEC     DX
06BA:0129 095266            OR      [BP+SI+66],DX
06BA:012C 694A456C4B        IMUL    CX,[BP+SI+45],4B6C
06BA:0131 094A45            OR      [BP+SI+45],CX
06BA:0134 6953204774        IMUL    DX,[BP+DI+20],7447
06BA:0139 CD21              INT     21 (after the code patches itself)

Ciekawostka: normalnie używałbym offset messagezamiast zakodowanego na 13bhstałe, ale w tym przypadku, ponieważ w czasie analizy jego adres jest nieznany, tasm generuje natychmiastowe 16-bitowe przesunięcie, marnując 1 bajt kodu:

06BA:0131 098A4600          OR      [BP+SI+0046],CX
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.