Imprima la frase “Y ella dijo: 'Pero ese es el suyo'” usando solo el alfabeto


51

Imprima la frase And she said, 'But that's his.'usando solo los siguientes caracteres: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ Sin signos de puntuación o caracteres no alfabéticos. Puede usar el lenguaje de programación que desee. El espacio en blanco está completamente permitido. El programa más corto gana.


¿Qué pasa con los espacios en blanco en la salida? (¿al
inicio

2
Maldición, mi esolang no se puede completar porque no hay capacidad para producir resultados solo con a-zA-Z. En teoría, podría usar write y Eval para crear las instrucciones necesarias, pero ninguna de ellas +-*,%'"se puede construir sin usar (al menos) una de ellas +-*,%'"0-9.
Draco18s

11
(programmer-of (language 'lisp))no le gusta esto
MatthewRock

44
Debo admitir que no pensé que esto fuera particularmente interesante al principio, pero la combinación de caracteres repetidos y únicos realmente hizo que fuera algo divertido de optimizar (¡especialmente en un lenguaje de pila!). Muy agradable.
brhfl

1
¿Puedes aclarar si se permite un espacio en blanco adicional en la salida ? ¿Te gustan las nuevas líneas finales? O solo espacios en blanco en la fuente , más caracteres alfabéticos. Hay una respuesta Befunge que imprime con una nueva línea adicional.
Peter Cordes

Respuestas:


75

De espacio en blanco , 417 414 349 265 bytes

265 bytes gracias a Kevin Cruijssen

  							
  				   
   		 	
   		
   	 
  		   		 
 	  		
 	  		 
   			 
  		 	
   	 
 	  	 
 	  		 
 	  	
   				
  		  	  
  							
 	  	  
  				 	 
  		 
   		
  		 	
   		 	
 	  	 	
  		
   	 
 	  		
 	  		
  		 
   	   
  		  	 	

  
   		  		 
	   	
  
 


Pruébalo en línea!

Explicado:

[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]

101
Whitespace is completely allowed.Veo que has tomado esto literalmente.
Benjamin Urquhart

3
Me superaste ... Sin embargo, se pueden jugar muchas cosas. :) Puede eliminar el final NNNpara salir, ya que ya se detiene con un error cuando está agregando antes de print_char, por lo que ni siquiera vendrá después de Jump_to_Label. Además, ¿por qué almacenar el 63al principio y recuperarlo en el bucle? Simplemente puede presionarlo antes de agregarlo. Y, ¿por qué es el Label-nr TTSSSSTN? Una etiqueta incluso puede estar vacía, por lo que solo NSSNpara crear la etiqueta y NSNNsaltar a la etiqueta es suficiente cuando solo está usando una etiqueta.
Kevin Cruijssen

1
318 bytes con los cambios que propuse anteriormente. Aquí está el mismo programa con resaltado agregado. ¿Y cómo dedujiste el valor constante 63? No estoy 100% seguro de que sea la constante más corta posible aquí. Si es así, algo está mal con mi programa de generación constante que escribí para un desafío anterior. :)
Kevin Cruijssen

1
Sí, tenía razón. La constante 102es la más eficiente: 281 bytes (o aquí con resaltado ). (NOTA: También he usado una copia para guardar 4 bytes para el espacio intermedio ehs dnA(copiado del espacio intermedio dias ehs).
Kevin Cruijssen

3
Ok, ya he terminado. :) 265 bytes (o aquí con resaltado ). Se agregaron algunas copias adicionales. ( Aquí el consejo de
espacio

63

Perl 5 , 133 102 95 bytes

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

Pruébalo en línea!

Explicación:

Regexes, print y chop se aplican a la variable $_por defecto.

s qqAnd she saidZ ZBut thatZs hisZZGjGGfq

Reemplaza la cadena vacía con And she saidZ ZBut thatZs hisZZGjGGf.

s qZqchr oct oct oct ord chopqge

Reemplaza cada uno Zcon el resultado de la evaluación chr oct oct oct ord chop. Esto elimina el último carácter de $_, toma su código clave, lo interpreta como octal tres veces y lo convierte de nuevo en un carácter. Por ejemplo, j→ 106 → 70 → 56 → 46 → ..

Debido a la forma en que funciona el reemplazo, las modificaciones $_que ocurren mientras se evalúa el reemplazo se pierden, por $_lo que ahora es así And she said, 'But that's his.'GjGGf.

y qGjfqqd

Elimina todo G, jy fen $_.


27
Sin conocer a Perl, parece que solo intentaste escribir la oración, pero te metiste en múltiples peleas con tu gato en el proceso
popctrl

2
Este puede ser el código más hermoso que he visto escrito en este sitio web, y lo digo como alguien que conoce a Perl.
Silvio Mayolo

1
Relacionados, pero se puede sustituir printcon sayde -2 caracteres. El meta consenso actual dice que las banderas de línea de comando como -M5.010no cuentan para el conteo de bytes.
Silvio Mayolo

34

> <> , 916 915 903 bytes

Al principio pensé que una solución en> <> era imposible, pero luego me di cuenta ... ¿quién necesita condicionales o control lógico? :RE

fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffloffffffffffffffffffffffffffffffffffffffffffffflopppgloppppppppppppppppppppppggloffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppggloploppppppppppppppppppppppploffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppplofffffffflopggloppppppppppppppppppgglopppplofffffffloffffffffffffffffffffffffffflofffffffffffffffffffffffffffffffffffffffffffffffffffloglopppppppppppppppppppppppppppplofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppploppgloffffffffffffffffffflopppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflofloffffffffffloppppppppppppppppppppppploppgloio

Pruébalo en línea

Empujo repetidamente los números (el número 15) a la pila, luego empujo la longitud de la pila e imprimo el carácter con ese valor ASCII. Si necesito reducir la longitud de la pila, reduzco la pila tres valores a la vez usando p, o uno a la vez usando gsi estoy dentro de tres del objetivo. El programa termina llamando i(input), que empuja a -1ya que no hay entrada, luego lo imprime para causar un error.

Este es el programa Python 3 que usé para crear la solución una vez que pensé en cómo hacerlo:

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

Pruébalo en línea


55
¡Este es el contrapunto adecuado para la solución de espacios en blanco! Tengo un +1 de mi parte, también aprecio el programa generador ...
Francesco

La última sección se puede quitar por completo con el uso cuidadoso de p: crear un 59 en la pila mientras se mueve desde el espacio a la sen said, luego se coloca en el código en el camino hacia abajo desde da ,. (Tenga en cuenta que (15,15) tiene 15 en este punto.)
Nitrodon

En realidad, puede abusar ly pponer varios caracteres útiles en el rectángulo (10,10) - (15,15), luego recuperarlos gdonde sea más conveniente.
Nitrodon

Esa es una muy buena idea. Es muy difícil pensar en> <> de esta manera. Es como codificar con BF
mbomb007


28

8086 Asamblea en PC IBM, 1463 845 664 bytes

Aclaración: La fuente real del lenguaje ensamblador es la entrada, no el código de máquina generado.

La dificultad es que la mayoría de las instrucciones x86 (como ADD, SUB, JMP, saltos condicionales, acceso a memoria) tienen dos argumentos y, por lo tanto, necesitan una coma o una dirección de memoria. Por lo tanto, no podemos usar sumas, restas, ifs o bucles.

Durante mi primer intento pude "construir" números usando una combinación de incremento, decremento, multiplicación, división, trucos de bytes y las oscuras instrucciones BCD (como AAA, DAS). Después de eso, me di cuenta de que esta idea podría usarse para crear código de autoinspección y auto modificación.

  • Intento 1. (1463 bytes)

    Usó las instrucciones disponibles para construir códigos ASCII y la dirección 0xb800 del búfer de pantalla. El cálculo de cada personaje en la secuencia fue golfizado a mano.

  • Intento 2. (no completo)

    Se dio cuenta de que hay un código de operación para cada número entero en el rango 0x40-0x5f. Esta gama incluye AZ. Entonces, por ejemplo, INC CX corresponde a 0x41 = 'A'. (Esta tabla de códigos de operación es muy útil).

    Intenté construir 3 cadenas de "datos" y colocarlas una encima de la otra. El primer as-is (mayúscula), el segundo "desplazado" a la zona 0x60-0x7f (minúscula) y el último "desplazado" a la zona 0x20-0x3f (puntuación).

    El código auto modificable produciría un bucle o tres para iterar sobre los datos.

  • Intento 3. (845 bytes)

    Al igual que el enfoque anterior, pero para reducir los datos, la cadena solo se codificaría una vez, con "caracteres de control" mezclados para cambiar los conjuntos de caracteres.

  • Intento 4. (664 bytes)

    ¿Cómo deshacerse de los caracteres de control que requieren muchas instrucciones parcheadas para lidiar con la ramificación? Dado que solo se usan dos letras mayúsculas, me preguntaba si podría "voltear" la tabla de códigos de operación para codificar letras minúsculas usando el rango 0x40-0x4f y la puntuación usando el rango 0x90-0x9f (restando de 0xc0). La "A" y la "B" se pueden poner por separado.

    Sin embargo, solo la mitad de los códigos de operación en el rango 0x90-0x9f son utilizables y no se alinearon con los necesarios. Entonces pensé que tal vez podría barajarlos usando un XOR, y encontré uno que funcionó. Y aquí está.

Golfizado:

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

Montar con

nasm golf.asm -o golf.com

y ejecutar en DOSBOX (ejecutar CLS primero). Se ve como esto:

Salida de muestra

Comentado:

; 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. Estoy obteniendo diferentes archivos .COM de las dos fuentes de ensamblaje, comenzando en el desplazamiento 0x3e. Editar - Nvm encontró la diferencia: la línea 117 en la versión comentada es INC AXmientras que la no comentada es INC AL.
Gastropner

1
Quiero ver un binario completamente alfabético en su lugar. :-)
Peter Ferrie

1
Si se siente cómodo bloqueando NASM como el ensamblador elegido, puede crear etiquetas haciendo label1 dbuna línea propia. Producirá una advertencia, pero no un error.
Gastropner

1
@gastropner bueno, eso simplemente lo haría demasiado fácil. : P No sabía sobre eso, gracias! Tal vez debería cambiar el nombre de mi idioma como "algo que puede alimentar a DEBUG.COM" Que por cierto solía depurar esto. xD
Artelius

1
@PeterCordes ahora este se auto modifica!
Artelius

23

Perl 6 , 1299 1272 1220 1215 bytes

Gracias a Grimy por -27 bytes.

-52 bytes porque no necesitábamos las orejas de conejo en primer lugar.

Gracias a Jo King por -5 bytes.

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

Pruébalo en línea!

Emite la cadena con una nueva línea final. Si no quiere eso, reemplace el último saycon a print. También puede reemplazar las nuevas líneas en la fuente con espacios.

Explicación

Este código imprime la cadena carácter por carácter. Cada carácter se forma al alimentar el código de carácter apropiado en la chrfunción y ponerlo en minúscula lcsi es necesario.

Actualmente, todos los valores se generan al generar una cadena con el número correcto de caracteres; En algunos casos, el número de caracteres es el reverso del código de caracteres de destino. Teóricamente debería ser posible usar funciones matemáticas como logy expdirectamente, pero no me resultó muy fácil usarlas.

Para usar como números, tenemos e, piy tau; en el lado derecho de xo xx, están implícitamente en el suelo. Todos tienen 17 caracteres en sus representaciones de cadena, por lo que los usamos epara un recuento mínimo de caracteres. También tenemos i(4 caracteres), False(5 caracteres) y NaN(3 caracteres). Podemos multiplicar longitudes de cuerda con x; xxmultiplica uno más el largo de la cuerda por el lado derecho y agrega uno. chopelimina un personaje de la cadena en caso de que estemos lejos del objetivo.

Las declaraciones de impresión se encadenan juntas usando and, que tiene una precedencia bastante baja. Es casi un milagro que exista; de lo contrario, tendríamos que usar puntos y comas ilegales.

Encontré las expresiones de los personajes a mano. Puede valer la pena buscarlos mediante programación para encontrar expresiones más cortas.



Por cierto, @JoKing, ¿buscó las expresiones más cortas a mano o utilizó un programa para ayudar?
bb94

1
A mano tengo miedo. Una forma algorítmica probablemente no sería demasiado difícil
Jo King


@Grimy Clever, pero desafortunadamente solo es posible porque el espacio de ancho cero que estás usando no es un personaje de espacio en blanco
Jo King

17

Ancho , 66 64 bytes

QaaGmwmiimaGcwWiimawAGawmfciiiGaFmAmFiimFGcwAmFiGmaiiGcGamafFiGQ

Pruébalo en línea!

Impresiones para depurar. Para imprimir en stdout, agregue wwal final del código, que aparece y genera la parte superior de la pila.

Explicación

En Ancho, cada letra se correlaciona con un número, según su "ancho", según esta tabla . Esto asigna a cada letra un número del 0 al 9. Luego, esos números se utilizan para ejecutar el código.

En particular, una letra que coincide 7iniciará un literal de cadena. Leerá conjuntos de dos letras a la vez, hasta que vuelva a leer la letra original. Cada conjunto de dos letras se convertirá a sus números de ancho, se leerá como un número decimal entre 0 y 99, y el carácter que igualarán será su índice en la siguiente cadena:

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

Por ejemplo, el índice de !es 1, por 01lo que serán los números de ancho correctos. Por lo tanto, if, iI, jt, etc hará todo correlato a un literal de cadena de !.

En este caso, traduje los 31 caracteres de la salida requerida a las letras apropiadas, utilizando Qcomo comillas. La parte superior de la pila se imprime para depurar cuando finaliza el programa.


Este es el más corto hasta ahora. ¡Creo que podrías ganar!
Blue-Maned Hawk

14

Código de máquina x86 (32 bits), 256 bytes

Cuando imprimo mi código en mi consola de página de códigos 437, veo lo siguiente:

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 

Contiene algunos caracteres de espacio en blanco, por lo que aquí está el mismo código cuando reemplazo todos los caracteres de tabulación por y todos los caracteres de espacio sin separación (con el código 255) por *:

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

Algunas explicaciones sobre cómo funciona:

Las instrucciones útiles son:

  • push imm8, push imm16y push imm32, seguido de popgenerar constantes. Esto también puede generar cero (in ah) al presionar un byte ( imm8).
  • and [ecx+32], ah- suponiendo ah = 0, esto establece el byte a cero. Sucede que la longitud de la cadena de salida es 32, por lo que el código llena el búfer de principio a fin.
  • or [ecx+32], edx- suponiendo que el byte de salida se establece en cero, esto copia edx(4 bytes) a la salida. Utilizo una variante en dxlugar de edxcerca del final del búfer, porque no debería escribir más allá del búfer de salida. ¡La restricción en el código hace que sea imposible escribir bytes individuales de esta manera!
  • imul edx, [ecx+32], whatever- Esta es la idea principal de codificación. Con suficiente entropía [ecx+32]y cualquier número, puede generar cualquier salida. Lo uso para generar 2 o 3 bytes de valores necesarios. Alguna complicación es que, al escribirlo en la salida, debe hacer lógica ORcon lo que ya está allí. Esto a veces hizo necesario volver a poner a cero la memoria.
  • Una variante de una jmpinstrucción se utiliza para regresar. Lo elegí porque su codificación es 0xff, que corresponde a un espacio que no se rompe en la página de códigos 437. Un poco exagerado en las reglas, pero de lo contrario creo que la tarea es imposible ...

Código fuente del ensamblado, junto con un programa en C que lo ejecuta (usa la sintaxis de 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);
}

Esto no parece estar totalmente golfizado para mí. Seguramente ahorraría varios bytes utilizando bucles, en lugar de repetir una serie de instrucciones idénticas. Todo eso dec ecx+ and [ecx+32], ahcosas se pueden factorizar.
Cody Gray

Eres bienvenido a intentarlo. Esto es lo mejor que pude hacer; Estaría feliz de ver un enfoque diferente. Decidí abandonar la idea de los bucles cuando vi que requieren un desplazamiento de salto negativo. Tal vez esta restricción pueda resolverse de manera creativa, no sé cómo.
anatolyg

1
@anatolyg Podría reducirse a cuál es la posición de su entorno de prueba sobre el código auto modificable. O sus opiniones sobre la ejecución de código que ha creado en la pila.
Gastropner

¿Char no 0xffviola "Sin signos de puntuación o caracteres no alfabéticos"?
val


13

PostScript, 889 874 837 835 bytes

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

Pruébalo en línea!

Esto usa 32 copias de los enteros 89 25 20 6. Todos los códigos de barras de la cadena de destino se pueden obtener con operaciones en esos enteros, en orden de pila: por ejemplo, 'A' (ASCII 65) es 89 - (25 y (20 + 6)). Muchas 4 tuplas de enteros tienen esta propiedad; este fue elegido porque son particularmente fáciles de generar.

currentflat string dup rrand

El valor predeterminado plano es 1, por lo que esto crea una cadena de longitud 1 (inicializada en \0). dupno es una copia profunda: crea una segunda referencia a la misma cadena. rrand empuja la semilla aleatoria, que por defecto es 0. La pila es ahora ["\0", "\0", 0].

count dup count count mul mul xor

count empuja el número de elementos en la pila, por lo que calcula 3 ^ (3 * (5 * 6)) = 89.

count count mul count dup mul exch count

4 * 5 = 20, 5 * 5 = 25, 6 = 6. La pila es ahora ["\0", "\0", 0, 89, 25, 20, 6].

count copy count copy count copy count copy count copy

Duplicar toda la pila, cinco veces. Así terminamos con 32 copias de nuestra pila inicial de 7 elementos. Solo necesitamos 31 copias, ya que la cadena de destino tiene 31 caracteres de largo, pero la copia adicional no duele.

add and sub put print

Calcule un código de char de los cuatro enteros superiores, escríbalo en el índice 0 de la cadena, luego imprima la cadena.

quit

Suprime la solicitud predeterminada.


11

Rubí , 420 354 338 bytes

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

Pruébalo en línea!

En orden ascendente de disgusto:

Las palabras que comienzan con una letra mayúscula pueden imprimirse definiendo una clase con ese nombre y llamando displaydentro del cuerpo de definición de clase.

Se pueden mostrar otras palabras definiendo métodos con ese nombre, que devuelve un Símbolo, y luego convirtiéndolo en una Cadena para eliminar los dos puntos iniciales.

Se pueden mostrar otros caracteres llamando putca su código ASCII. Podemos generar los números apropiados reutilizando el String deftruco para obtener una cadena, luego tomando la suma de sus bytes usando un módulo determinado por su tamaño. Desafortunadamente, no tenemos ninguna forma de invocar métodos en un objeto que no sea dentro de la definición de clase de ese objeto, lo que hace que sea difícil pasar argumentos. Entonces, el truco final es redefinir String#inspect, que se llama implícitamente al pasar una Cadena al pmétodo, para que calcule y muestre el carácter apropiado como efecto secundario, antes de generar un error para que pno pueda terminar de ejecutarse e imprimir un nueva línea. Entonces necesitamos rescatar el error en el código principal.

Editar: Jordan hizo que el byte contara mucho menos, ejem, alto con un poco de flujo de control de golf inteligente, y he cortado algunos bytes más al reemplazarlo raisecon una llamada de método inexistente de una letra, lo que genera un NameError.

Edición 2: Noté que con print Stringextraído en un método, es más barato usarlo solo con una definición de método que usar el truco de definición de clase, ya que los métodos pueden estar en mayúsculas.


Hermoso ... No entiendo cómo sum sizela suma del módulo tiene su tamaño, ¡pero todo lo demás funciona!
Value Ink

Lo pongo un poco vago, en realidad está pasando el tamaño de la cadena como argumento opcional para el método de suma.
Histocrat

11

> <> , 233 122 bytes

cdacaabbglccgpcbfbbcaacdebbafbebbcebdbealbcpcdbcccdlcdpacbbalccpaalacpbcfafbaab









       g  sandBe
       o  Aviuth

Pruébalo en línea!

Esto comenzó como un golf de la respuesta de mbomb , pero descubrí un cambio fundamental que ahorra una gran cantidad de bytes, así que lo publico como mi propia respuesta.

La generación de caracteres no alfabéticos para la salida se realiza presionando repetidamente valores en la pila, luego se usa lpara empujar la longitud de la pila. Sin embargo, esto no necesita ser emitido de inmediato: usando p, este carácter puede colocarse en cualquier celda cuyas coordenadas estén entre 10 y 15 inclusive, para ser recuperado más tarde con g. Del mismo modo, los caracteres alfabéticos se pueden colocar en el código fuente inicial y leer de esta manera: dado que el código de caracteres no alfabéticos más alto en la entrada es 46 ( .), esto significa que la pila no necesita ser empujada más arriba de los 62 necesarios para almacenar los 31 caracteres de la salida.

Además, vse coloca a en el código de la columna 7. Cuando el puntero de instrucción se ajusta y golpea v, la secuencia gose ejecuta repetidamente para leer desde las coordenadas empujadas y generar los caracteres correspondientes. Finalmente, la pila se vacía y gfinaliza el programa con un error.

Los primeros 7 bytes de código se reutilizan como las primeras 7 y las últimas 7 coordenadas empujadas. Colocar el ven la columna 9 teóricamente habría guardado dos bytes más, pero habría forzado a los caracteres Ainsva un cuadrado de 2x2 en el código, lo cual es imposible. Una versión anterior usaba la columna 15, pero eso requería una línea adicional en el código fuente y terminaba seis bytes más.


Después de pensarlo más, creo que puedo hacer que la columna 9 funcione gastando un byte rpara mover la alineación donde quiera. Sin embargo, jugar golf a este programa me duele un poco el cerebro.
Nitrodon

8

CJam , 262 bytes

  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

Pruébalo en línea! Las líneas nuevas solo se muestran aquí para mayor claridad; Cada línea representa un personaje.

Menos mal, esto fue divertido. Restringirnos a los comandos alfabéticos plantea algunos desafíos interesantes:

  • Sin {y }, prácticamente no hay oportunidad para controlar el flujo (excepto f, que no encontré una oportunidad para usar).
  • Sin \, _, ;, o $, no tenemos medios para la manipulación de pila.

Esto significa que el objetivo principal será obtener los puntos de código relevantes en la pila y luego convertirlos en caracteres con c.

El problema es que también nos faltan los comandos aritméticos más básicos, así como los literales enteros. Sin embargo, esto está bien, ya que el mespacio de nombres contiene numerosas operaciones matemáticas avanzadas, y hay muchas variables predefinidas para números útiles.

Terminé haciendo un uso intensivo de las raíces cuadradas ( mQy mq), la función exponencial mey la conversión de base ( b), que también se pueden usar para emular la multiplicación ( [X 0] Ybcalcula X * Y). Además, a veces es más fácil construir el punto de código en mayúsculas, en cuyo caso podemos usar el(convertir a minúsculas) en el carácter resultante.

Todavía no estoy satisfecho con algunos de los más largos. Oh bien.

Explicación

Esta es una explicación carácter por carácter de la salida. Antes de comenzar, aquí hay algunas formas cortas de hacer números:

  • 0, 1, 2, 3 están contenidos en las variables T, X, Y, Zrespectivamente.
  • Los números del 10 al 20 están contenidos en variables a Através K.
  • 32 se puede hacer usando Sci( Sempuja una cadena que contiene un espacio, cobtiene el primer carácter de esta cadena y iconvierte ese carácter en su punto de código). STambién se utiliza para espacios.
  • 4 viene dado por GmQ(raíz cuadrada entera de 16).
  • 5 viene dado por AZbYb(convertir 10 a base 3, rindiendo [1 0 1], y convertir la matriz de números resultante a base 2, rindiendo 5).
  • 7 viene dado por Ymei(compute exp (2) y convertir a entero).

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
Puede realizar conversiones de base con dígitos fuera del rango habitual para la base, como HYbYCtYbc, HYbXAtYbcy HYbXBtYbc.
Nitrodon

7

Deadfish ~ , 943 bytes

iiisdsiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicddddddddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcdddddddddddcdddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcddddddddddddddddddciiiiiiiicdddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddciiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicdcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsdddddcddddddddddddcdddddddciiiiiiiiiiiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddddddddsddddddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddsiiiiciciiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddc

Pruébalo en línea!

No se permiten bucles :(


7

malvado , 198 bytes

aeeeannkhhwzuuuuuueaeuekwuuuuuuuuuunkhwzaeeeeehknwgueeywguuuuuuhhknnwuuuwhgwpwnngheeuwguuuuuwngwzaeeeaaaeeeeeewhhgwnguuuueewnngawpaawuwnngwpawhgwhhgeeuwpawhguuuueewpwhgwhgwawpwnngaaaaaaeeeewguuuueew

Pruébalo en línea!

Esto fue muy divertido.



6

MATL , 187158 bytes

IEWQKEtqhpEqqKQHhthpKWEyQKWEqqYqQQXJwtQQQwKWEJKQthpYqKQHhthptQQQQQwIIhKQhpqKWEIWKQhpqIEWQQJQQtqKWEyIIhIhpYqQXJyKQthpYqwIWKQhpqyqKWEyJtQwhhPIIhKQhpQIWKQhpqvlec

Pruébalo en línea!

Versión más legible: ¡ Pruébelo en línea! Intento manual de construir la cuerda. Probablemente haya mucho espacio para jugar al golf cortando la cuerda en trozos convenientes, usando Py hpara voltear y construir una cuerda. Espero que alguien acepte el desafío de superarme. El principal desafío es que no puede usar +o -, por lo que la aritmética básica a menudo no es posible.

Reflejos:

  • KQthpYq: el número 25 ( KQthp) primo Yqes 97, correspondiente a la letra a. La letra s(115) se genera de manera similar a partir del 113, el 30º número primo. Luego se reutiliza ampliamente en el portapapeles J.
  • hisse acorta almacenando el hde antes en el portapapeles J. Desde que se almacenó anteriormente s, construimos hisen reversa para que podamos recuperar el suso reciente yy voltearlo después de usarlo P.
  • Una gran cantidad de bytes guardados gracias a Luis Mendo (principalmente cambiando un montón de ha vle)

Huh, realmente pensé que usarlo vmetería el hque tenía antes. Supongo que debería haberlo hecho en lugar de asumirlo. Además, gracias por el aviso, se produjo una eliminación excesivamente celosa. Tengo curiosidad por ver si puedes hacerlo mejor que esto ...
Sanchises

Me gustaría intentarlo, pero tendrá que esperar. ¡Contestar esto parece tomar mucho tiempo!
Luis Mendo

1
@LuisMendo Sí. Me llevó aproximadamente una hora hacer esto, y esto solo incluye una optimización muy local. Estoy seguro de que uno puede mejorar con un poco más de una visión global de las cosas.
Sanchises

Mi intento . No miré el tuyo, por lo que espero que los enfoques sean diferentes
Luis Mendo

@LuisMendo Olvidé por completo que eso Usignifica ^2que eso podría haberme ahorrado bastantes bytes ...
Sanchises

6

MATL , 118 bytes

KEUQtVQsQKBFZAXHKUqyyhsXJyyhdQtQQQwOJIUEyhdtKEhsHKQYqEEKQyywhdXJKEUQQHKUhstQwOytHKhsKYqyhdbJyqOHKhstQHKUqhsKUqYqqJvlec

Pruébalo en línea!

Versión más legible (cada línea corresponde a un carácter, excepto las operaciones de reorganización de la pila).

Explicación

El programa produce los puntos de código de los caracteres requeridos, como números independientes. Al final, todos esos números se concatenan en un vector de columna, se reforman como un vector de fila y se convierten en caracteres. El resultado se muestra implícitamente.

Algunos de los trucos utilizados:

  • La mayoría de los puntos de código por debajo de 32 se muestran como espacio. Entonces 0se usa para la mayoría de los espacios, porque solo cuesta un byte ( O).
  • Para el primer espacio, sin embargo, 15se usa (generado como KUq), porque luego se puede reutilizar agregándolo a 100(char d) para dar 115( s). En otra ocasión 5se usa para el espacio (generado como KQ), por lo que luego se puede restar de 44( ,) para dar 39( ').
  • El portapapeles Jse usa para almacenar caracteres que se repetirán: primero s, luego '. Del mismo modo, el portapapeles Halmacena 100, lo cual es útil para dy para generar otros caracteres.
  • Se hace un uso extensivo de las funciones Q(sumar 1), q(restar 1), E(multiplicar por 2) y U(cuadrado), junto con los literales predefinidos en los portapapeles I( 3) y K( 4).
  • La suma y resta arbitrarias se realizan concatenando en un vector ( h) y calculando su suma ( s) o diferencias consecutivas ( d).
  • 100( d) se genera como 4en binario interpretado como un número decimal.
  • 110( n) se obtiene de 65( A) mediante la conversión a cadena ( '65': puntos de código [54 53]), sumando 1a los puntos de código ( [55 54]), sumándolos y sumando 1.
  • El orden en que se generan los números a veces se modifica por conveniencia; y luego se reordenan por las funciones de reorganización de la pila: swap ( w), bubble up b).

1
¡Muy agradable! Toque inteligente usando en Olugar de KWEpara espacios. Y confirmó mi sospecha de que probablemente sea mejor sacrificar otro portapapeles H.
Sanchises

5

dc , 240 222 209 bytes

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdOOlAxlAxPOBlBxdIlAxoPAdlBxddsrIlAxssPPOPlsIZlCxddspPOZlCxPPOPlrdZlCxPlsPlrPlcPPKPdZlBxdZlAxPOAZlAxdPIZlCxdPrPdPlpPlrdZlCxPPKPOPPlpPlsPOPldPKP

Pruébalo en línea!

Mi primer pensamiento fue el mismo que @seshoumara, solo empuje suficientes cosas en la pila para generar todos los valores ASCII de los personajes. Entonces se me ocurrió que desde entonces +, -y que *somos operadores de un solo carácter, ¡puedo recrearlos y tener la capacidad de usar la aritmética! ¡Seguramente eso sería más pequeño! Y, no me sorprendería si pudiera jugar golf más bytes, pero por ahora ... este enfoque complicado ha logrado vincular al ingenuo (ish).

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdes la parte del enfoque que es similar a la de @ seshoumara, pero solo subimos a 46, que es .. Hacemos esto porque necesitamos subir a 45, -y también necesitamos un período en nuestra cadena, por lo que solo ir uno más para el período es (creo) más barato. En el camino, almacenamos algunos valores: 5, 32, 39, todos serán útiles más tarde. 5 para cosas utilitarias, 32 y 39 para sus valores ASCII. Originalmente hice 1-5, pero eso era costoso, y pude simplemente evitar usar 4; use Z(resalte un valor, presione el número de dígitos que tiene) en un número de tres, dos o un dígito para esos valores. A los 42, 43 y 45, convertimos estos para cuerdas ( *, +, y -respectivamente) y guardarlas como macros ( B, AyCrespectivamente). Esto significa que sin usar los caracteres *+-, ahora podemos usar esos operadores.

A partir de aquí, básicamente comenzamos a generar los valores ASCII utilizando el poder de las matemáticas en lugar de la simple acumulación, almacenando algunas de las repeticiones en el camino. 100, 105 y 115 aparecen lo suficiente como para almacenarlos (en registros o de otro modo) tiene sentido. Originalmente, dejé la pila llena de 10 y los usé para hacer 100; terminó guardando bytes para llenar la pila con 32s y usarlos como espacios más adelante. Una versión ligeramente más legible de la sección 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.

Afeitó 18 bytes: almacenando el número 5 como la raíz de entrada en lugar de un registro; el número 32 como precisión en lugar de un registro; el número 115 como raíz de salida en lugar de un registro; a continuación, tuvo que cambiar KZa IZgenerar 1s y OZpara KZgenerar 2s.

Afeitó 13 bytes más inundando la pila con 32s; ajuste de precisión a 39; usando la manipulación de la pila para evitar almacenar 116; cortando algo de trabajo doble que accidentalmente dejé.


+1 Buena idea para usar apara recrear esos operadores, luego llamarlos con x. Esto muestra el comportamiento de datos es código de DC. Cuando tenga tiempo, aplicaré tu último truco para almacenar datos en parámetros, en lugar de registros. ¿Crees que podríamos obtener una solución de CC aún más corta al abusar de la forma en que P funciona para imprimir más letras a la vez si tenemos la suerte de ingresar el gran número necesario usando solo hexadecimal?
seshoumara

@seshoumara Es posible, aunque mis intentos de hacerlo con otros desafíos sugieren que es poco probable simplemente porque esos valores se vuelven grandes rápidamente. Solo para obtener las dos primeras letras, 'An', necesitamos P16750 o 0x416E. Si acabamos de tener suerte y una de las subcadenas estaba compuesta exclusivamente por valores AF, entonces eso podría darnos un atajo. ¡Sin embargo, eso sería un poco de suerte! De lo contrario, estaríamos ingresando números grandes de alguna manera, ideándolos de alguna manera, o agregando y multiplicando por 256. Lo que parece ... más grueso que un montón de Ps.
brhfl

5

Japt , 87 bytes

Bs g caA
HzG
Ts caV
iWisiiihiSisiUitiaihitiSitiuibu iUiSiWcaV idiiiaisiSieihisiSidiniau

Intentalo

Explicación

La primera línea genera 'y lo asigna a variable U.

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

La segunda línea se asigna 2a la variable V.

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

La tercera línea genera .y lo asigna a variable W.

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

La última línea, entonces, construye la cadena un carácter a la vez en reversa.

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

Buena solución Puede guardar un byte reemplazando la primera línea conQc dGaB
Encarnación de la ignorancia

4

Rojo , 272 bytes

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

Si las comillas dobles son necesarias:

Rojo , 344 bytes

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

No funciona en TIO pero funciona en el intérprete Red.

Consola roja

Explicación:

Las palabras son triviales: las imprimo (imprimo sin nueva línea) como literales con quote. Rojo tiene una palabra incorporada para espacio sp, así como commay dot. "y 'más interesante: los imprimo restando un espacio de By Grespectivamente, comenzando desde un literal By G, convirtiéndolos primero en una cadena con moldy luego en un carácter (para usar la resta en ellos) con to sp( Rojo tiene conversión por prototipo - convierta el cadena al tipo de sp, que es el carácter).


1
La pregunta fue aclarada; le quitaron la parte interesante.
anatolyg

@anatolyg Gracias, todavía lo necesito ', así que la solución de 272 bytes es la misma.
Galen Ivanov

4

Adelante (adelante), 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

Lástima que no puedo redefinir CHAR o EMIT a palabras de una letra, ya que eso requeriría usar :y ;(eg : C CHAR ;) o '(eg ' CHAR ALIAS C)

De hecho, si pudiera definir palabras, podría hacer : P CHAR EMIT ;y luego P ximprimir x. Oh bien.

Ni siquiera puedo crear un búfer, escribir esa secuencia de caracteres allí y luego usarla como entrada, ya que escribir en la memoria requiere usar !oC!


3

Alphabeta , 180 177 175 163 bytes

cccaaggtFgDILrFigggDLjDLCLigggggDLjhDLhhhDLCLiggggDLjjggDLihhDLhhhhhDLcaaCLdbbCLcbbbCLHgDLiiiiigDLhDLdaaaCLDLjhhDLjgggDLiihDLcbbbCLhDLdaaaCLjhDLgDLiDLcaaaaCLdaaaCL

Pruébalo en línea!

WIP


3

Pepe , 266 bytes

Mantengo la pila r vacía y tengo 's' en la pila 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

Esto no está en TIO, pero puedes probarlo aquí


3

dc , 240 bytes

La idea principal es aumentar continuamente la pila en 1 ( K), guardando ( sX) el tamaño de la pila ( z) en registros personalizados cuando coincide con cada código ASCII único. La impresión ( P) se realiza en todo momento.

KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsSKKzsQKKKKKzsqKKKKKzsCKKzsDKKKKKKKKKKKKKKKKKKKzPKzsBKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsaKKKzsdKzseKKKzshKzsiKKKKKzPldPlSPKKKKKzsszPlhPlePlSPlsPlaPliPldPlCPlSPlqPlBPKzdstzPdPlSPdPlhPlaPPlqPlsdPlSPlhPliPPlDPlqP

Pruébalo en línea!

Hice alguna optimización, como no guardar una letra si no se usa después de eso, como duplicar ( d) una letra, por ejemplo t, en la pila para guardar un byte, ya que recordar ( lX) es de 2 bytes.


Se me ocurrió una solución de CC que usa aritmética creando macros para +, - y *. Son 262 bytes. Seguiré intentando optimizarlo para intentar ser competitivo, pero debo decir que estoy decepcionado porque es mucho más gordo que la solución (relativamente) ingenua.
brhfl

@brhfl Sí, DC se vuelve bastante rápido. Aun así, me gustaría mucho ver tu solución, ¡así que publícala! Mientras tanto, también estoy pensando en jugar más al golf con el método actual, usar un programa o tener otra idea para DC.
seshoumara

¡Logré atar 240! Y no me sorprendería si pudiera jugar golf uno o dos bytes más, pero ... es un enfoque mucho más obtuso para poca / ninguna ganancia. De todos modos, lo
publiqué

Llegué a 222 reemplazando algunos de mis registros más comunes con radix de entrada / salida y precisión; ahorra un byte en la tienda y un byte en cada carga ... Dado que los números son irrelevantes, no afecta nada ... ¡También podría usar esto para su ventaja!
brhfl

3

80186+ código de máquina, formato .COM de MS-DOS, 822 787 bytes

Solo se usan pestañas y espacios además de las letras. Dado que la mayoría de los códigos de operación en el rango permitido son ciertos incrementos, decrementos, empujes, estallidos y AND y OR indirectos de registro, además de IMUL, aprovecho el hecho de que el registro de pila se envuelve cuando llega al final del segmento para modificar el código a la inversa! Se requiere el ensamblaje 80186+ porque estoy presionando valores inmediatos.

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

Fuente anotada (formato 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

Esto no es ensamblaje, este es el código de máquina ...
Artelius

@Artelius lo suficientemente justo. He actualizado la descripción.
ErikF

3

Befunge-98 (FBBI) , 125 124 121 bytes

wab









And she said   But that s his












wakekekaayyeapwayyaayybyapayybyapcyabcyaayycayyba
a



b
wayapapoq

Pruébalo en línea! Salidas a un archivo llamado \n(una nueva línea nueva). Gracias a Jo King por su guión.

La salida incluye 10 nuevas líneas finales.

Para una nueva línea final, +1 byte cambiando la siguiente línea:

wakekekaayyeapwayydayybyapayybyapycyabcyaayycayyba

Pruébalo en línea!


Explicación:

El puntero de instrucciones se mueve de la siguiente manera:Ruta IP

El programa coloca los caracteres no alfabéticos en posición, antes de enviar esa línea a un archivo.

Befunge-98 incluye instrucciones a... f, que empujan su valor hexadecimal correspondiente a la pila. Para generar otros números, pasa esos valores a y("Get SysInfo") como argumentos para obtener:

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

23* stack size

Al colocar la mayor parte del código en y = 23, ayypuede usarse para acceso repetido al tamaño de la pila, que luego se usa para generar códigos de caracteres.


¿No se permite solo una nueva línea final?
Delioth

La publicación dice "El espacio en blanco está completamente permitido". ¡Creo que es genial abusar de esta redacción para justificar las nuevas líneas finales!
anatolyg

2

Pyth , 210 bytes

pChyCdpCyhyhlGpCyytlGpdpChFhTyylGpCyylGpChyytlGpdpChFhTyylGpCtytytlGpChyylGpCyytlGpCyyhTpdpCtyyTpCyhCdpCtFyyCdhTpCyhFlGCdpdpCyhFlGCdpCyylGpCtytytlGpCyhFlGCdpCtyyTpChFhTyylGpdpCyylGpChyylGpChFhTyylGpCyhyhTpCtyyT

Pruébalo en línea!

Encontré algunos números que podrían expresarse usando solo letras (como T= 10, Z= 0, lG= longitud (alfabeto) = 26, Cd= charcode (espacio) = 32), y algunas funciones que podrían realizarse usando solo letras (como t= decremento, h= incremento, hF= aplicación repetida de incremento = suma), y luego ejecuté una búsqueda de fuerza bruta para encontrar las combinaciones más cortas de esas funciones y números que dieron como resultado cada una de las letras que necesitaba.


2

Código de ensamblado x86 de 16 bits, 665 bytes

(el binario es alfabético, no la fuente)

De alguna manera olvidé la regla que permite el espacio en blanco. Seguramente el código se puede jugar como resultado.

Bytecode:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXsBFVKZPFFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXkLAFQQZJJJRkDCGPLXDPDJRkDBEPZJJRLZDRDZAAAQPLYDQDYXXDQhishZhDRDhZsDQDhaththRDhuthZBDQDRhidhsaRDhhehZsDRDhndhZADTZPiDEFY

Fuente:

    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

Funciona de esta manera:

  • mueve el puntero de la pila al final del código, a través de POP AX (no puede POP SP porque no es alfabético);

  • construye la instrucción para despachar una llamada DOS (algorítmicamente porque no es alfabética);

  • construye los caracteres no alfabéticos;

  • coloca la cuerda en la pila;

  • coloca la instrucción de envío en la pila en el extremo exacto del código, de modo que la ejecución fluya directamente a esa instrucción;

  • construye la instrucción para imprimir una cadena;

  • muestra la cadena y se bloquea rápidamente. : - / (Una salida elegante requeriría más código)




0

80186 código máquina + DOS, 91 bytes

Versión de texto:

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

Versión de texto, con pestañas (código 9) reemplazadas por 9y espacios (código 32) reemplazados por *:

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

El código de la máquina aparece en un archivo con extensión .com. Cuando lo ejecuto, imprime el mensaje requerido y luego se cuelga (ejecutando datos aleatorios).

Explicación de alto nivel sobre lo que hace:

  1. Inicializa registros con valores constantes.
  2. Reemplaza espacios en el mensaje por los símbolos especiales requeridos ( ,'.$)
  3. Parchea el código para generar la int 21instrucción, que imprime el mensaje
  4. Llamadas DOS

Código de ensamblaje (se puede compilar con 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

Utiliza la popainstrucción para abrir todos los registros, porque regular popno puede completar todos los registros necesarios (por ejemplo, pop dies un código de operación prohibido).

Las direcciones de bytes a parche están en el rango 0x100 ... 0x160. Por suerte, se pueden representar como una suma de 3 bytes con valores permitidos:

  • 0x7a en bp
  • 0x7a o 0x67 en siodi
  • Valor inmediato

El parcheo de bytes en el mensaje funciona haciendo lógica ORen 0x20 (carácter de espacio) y una pequeña constante (4, 7, 12 o 14). La constante pequeña se obtiene inicializando cxy dxhasta 9 (carácter de tabulación) y haciendo INCo DECsegún sea necesario.

El parcheo de código utiliza las IMULinstrucciones. Encontré las constantes de 16 bits necesarias para multiplicar usando la búsqueda de fuerza bruta.

Finalmente, la dirección del mensaje (0x13b) se obtiene por multiplicación. Para ahorrar espacio, tomé una de las constantes de una de las instrucciones, que contiene un valor inmediato 0x96d. Aquí la 9parte elige una función de impresión de DOS, y la 6dparte es un parámetro libre. Resulta que esa 6des la única posibilidad que puede dar 0x13b después de la multiplicación.

Desmontaje de la parte del código:

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)

Dato curioso: Normalmente, usaría en offset messagelugar del codificado 13bh, pero en este caso, porque al momento de analizar su dirección es desconocida, tasm genera un desplazamiento inmediato de 16 bits, desperdiciando 1 byte de código:

06BA:0131 098A4600          OR      [BP+SI+0046],CX
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.