Imprima a frase “E ela disse: 'Mas é dele.'” Usando apenas o alfabeto


51

Imprima a frase And she said, 'But that's his.'usando apenas os seguintes caracteres: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ Sem pontuação ou caracteres não alfabéticos. Você pode usar qualquer linguagem de programação que desejar. Espaço em branco é completamente permitido. O programa mais curto vence.


E o espaço em branco na saída? (líder / final?)
attinat 13/06

2
Droga, meu esolang não pode ser concluído porque não há capacidade de produzir saída apenas a-zA-Z. Em teoria, eu poderia usar write e Eval para criar as instruções necessárias, mas nenhuma delas +-*,%'"pode ser construída sem usar (pelo menos) uma das +-*,%'"0-9.
Draco18s 13/06

11
(programmer-of (language 'lisp))não gosta disso.
MatthewRock 13/06

4
Tenho que admitir, eu não achei isso particularmente interessante no começo, mas a combinação de personagens repetidos e únicos realmente tornou algo divertido de otimizar (especialmente em uma linguagem de pilha!). Muito agradável.
brhfl 14/06

11
Você pode esclarecer se é permitido espaço em branco extra na saída ? Como novas linhas extras à direita? Ou apenas espaço em branco na fonte , além de caracteres alfabéticos. Há uma resposta Befunge que imprime com uma nova linha extra.
Peter Cordes

Respostas:


75

De espaço em branco , 417 414 349 265 bytes

265 bytes graças a Kevin Cruijssen

  							
  				   
   		 	
   		
   	 
  		   		 
 	  		
 	  		 
   			 
  		 	
   	 
 	  	 
 	  		 
 	  	
   				
  		  	  
  							
 	  	  
  				 	 
  		 
   		
  		 	
   		 	
 	  	 	
  		
   	 
 	  		
 	  		
  		 
   	   
  		  	 	

  
   		  		 
	   	
  
 


Experimente online!

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.Vejo que você entendeu isso literalmente.
Benjamin Urquhart

3
Você me venceu. No entanto, muitas coisas podem ser jogadas no golfe. :) Você pode remover o final NNNpara sair, pois ele já pára com um erro quando você está adicionando antes do print_char, para que ele nem venha após o Jump_to_Label. Além disso, por que armazenar o arquivo 63no início e recuperá-lo no loop? Você pode simplesmente pressioná-lo antes de adicionar. E, por que o Label-nr TTSSSSTN? Um rótulo pode até estar vazio; portanto, basta NSSNcriar o rótulo e NSNNpular para o rótulo quando você estiver usando apenas um rótulo.
Kevin Cruijssen 13/06

11
318 bytes com as alterações que propus acima. Aqui está o mesmo programa com destaque adicional. E como você deduziu o valor constante 63? Não tenho 100% de certeza de que é a menor constante possível aqui. Se estiver, algo está errado com meu programa de geração constante que escrevi para um desafio anterior. :)
Kevin Cruijssen 13/06

11
Sim, eu estava certa. Constante 102é a mais eficiente: 281 bytes (ou aqui com destaque ). (NOTA: Eu também usei uma cópia para salvar 4 bytes para o espaço entre ehs dnA(copiado do espaço entre eles dias ehs).)
Kevin Cruijssen

3
Ok, agora eu terminei. :) 265 bytes (ou aqui com destaque ). Adicionadas algumas cópias adicionais. ( Aqui, a dica relevante do espaço em branco .)
Kevin Cruijssen

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

Experimente online!

Explicação:

Regexes, print e chop todos se aplicam à variável $_por padrão.

s qqAnd she saidZ ZBut thatZs hisZZGjGGfq

Substitui a cadeia vazia por And she saidZ ZBut thatZs hisZZGjGGf.

s qZqchr oct oct oct ord chopqge

Substitui cada um Zpelo resultado da avaliação chr oct oct oct ord chop. Isso remove o último caractere de $_, pega seu código-chave, interpreta-o como octal três vezes e converte-o novamente em um caractere. Por exemplo, j→ 106 → 70 → 56 → 46 → ..

Devido à maneira como a substituição funciona, as modificações $_que acontecem durante a avaliação da substituição são perdidas, o que $_ocorre agora And she said, 'But that's his.'GjGGf.

y qGjfqqd

Exclui tudo G, je fentra $_.


27
Sem conhecer Perl, parece que você tentou digitar a frase, mas entrou em várias brigas com seu gato no processo
popctrl 14/06

2
Esse pode ser o código mais bonito que eu já vi escrito neste site, e eu digo isso como alguém que conhece Perl.
Silvio Mayolo 14/06

11
Relacionados, mas você pode substituir printcom saya -2 caracteres. O meta consenso atual diz que os sinalizadores da linha de comando, como -M5.010não contam para a contagem de bytes.
Silvio Mayolo 14/06

34

> <> , 916 915 903 bytes

No começo, pensei que uma solução em> <> era impossível, mas depois percebi ... quem precisa de condicionais ou controle lógico? : D

fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffloffffffffffffffffffffffffffffffffffffffffffffflopppgloppppppppppppppppppppppggloffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppggloploppppppppppppppppppppppploffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppplofffffffflopggloppppppppppppppppppgglopppplofffffffloffffffffffffffffffffffffffflofffffffffffffffffffffffffffffffffffffffffffffffffffloglopppppppppppppppppppppppppppplofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppploppgloffffffffffffffffffflopppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflopppppppppppppppppppppppppppgglofffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffflofloffffffffffloppppppppppppppppppppppploppgloio

Experimente Online

Empurro repetidamente os números (o número 15) para a pilha, depois empurro o comprimento da pilha e imprimo o caractere com esse valor ASCII. Se eu precisar diminuir o comprimento da pilha, reduza a pilha três valores por vez usando p, ou um de cada vez usando gse estiver dentro de três do alvo. O programa termina chamando i(entrada), que pressiona a uma -1vez que não há entrada e, em seguida, imprime para causar um erro.

Este é o programa Python 3 que eu usei para criar a solução, depois que pensei em como fazê-lo:

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

Experimente Online


5
Este é o contraponto adequado à solução de espaço em branco! Ter um +1 de mim, eu também aprecio o programa de geração ...
Francesco

A última seção pode ser removida completamente com o uso cuidadoso de p: crie um 59 na pilha enquanto move do espaço para o sin e said, em seguida, coloque-o no código no caminho de dpara ,. (Observe que (15,15) tem 15 por este ponto.)
Nitrodon

Na verdade, você pode abusar le pcolocar vários caracteres úteis no retângulo (10,10) - (15,15) e recuperá-los gonde for mais conveniente.
Nitrodon 14/06

Essa é realmente uma boa ideia. É tão difícil pensar em> <> dessa maneira. É como codificar com BF
mbomb007 14/06

Eu postei minha própria resposta: codegolf.stackexchange.com/a/186916/69059
Nitrodon 14/06

28

8086 Assembly no IBM PC, 1463 845 664 bytes

Esclarecimento: A fonte real da linguagem assembly é a entrada, não o código de máquina gerado.

A dificuldade é que a maioria das instruções x86 (como ADD, SUB, JMP, saltos condicionais, acesso à memória) têm dois argumentos e, portanto, precisam de uma vírgula ou precisam de um endereço de memória. Portanto, não podemos usar adição, subtração, ifs ou loops!

Durante minha primeira tentativa, consegui "construir" números usando uma combinação de incremento, decremento, multiplicação, divisão, truques de bytes e as instruções obscuras do BCD (como AAA, DAS). Depois disso, percebi que essa idéia poderia ser usada para criar código de auto-inspeção e auto-modificação.

  • Tentativa 1. (1463 bytes)

    Use as instruções disponíveis para construir códigos ASCII e o endereço 0xb800 do buffer de tela. O cálculo de cada caractere na sequência foi jogado à mão.

  • Tentativa 2. (não concluída)

    Percebeu que existe um código de operação para cada número inteiro no intervalo 0x40-0x5f. Este intervalo inclui AZ. Assim, por exemplo, INC CX corresponde a 0x41 = 'A'. (Esta tabela opcode é muito útil.)

    Tentei construir 3 seqüências de "dados" e colocá-las em camadas umas sobre as outras. O primeiro como está (maiúsculo), o segundo "deslocado" para a zona 0x60-0x7f (minúsculo) e o último "deslocado" para a zona 0x20-0x3f (pontuação).

    O código auto-modificável produziria um loop ou três para iterar sobre os dados.

  • Tentativa 3. (845 bytes)

    Como a abordagem anterior, mas para reduzir os dados, a string seria codificada apenas uma vez, com "caracteres de controle" misturados para alternar os conjuntos de caracteres.

  • Tentativa 4. (664 bytes)

    Como se livrar dos caracteres de controle que exigem muitas instruções corrigidas para lidar com ramificações? Dado que apenas duas letras maiúsculas são usadas, me perguntei se eu poderia "inverter" a tabela opcode para codificar letras minúsculas usando o intervalo 0x40-0x4f e pontuação usando o intervalo 0x90-0x9f (subtraindo 0xc0). O "A" e o "B" podem ser colocados separadamente.

    No entanto, apenas metade dos opcodes no intervalo 0x90-0x9f é utilizável e não se alinham com os necessários. Então pensei que talvez pudesse embaralhá-los usando um XOR e encontrei um que funcionasse. E aqui está.

Golfe:

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

Monte com

nasm golf.asm -o golf.com

e execute no DOSBOX (execute o CLS primeiro). Se parece com isso:

Saída de amostra

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"

Hum. Estou obtendo arquivos .COM diferentes das duas fontes de montagem, começando no deslocamento 0x3e. Editar - a Nvm encontrou a diferença: a linha 117 na versão comentada é INC AXenquanto a não comentada é INC AL.
gastropner 14/06

11
Eu quero ver um binário totalmente alfabético. :-)
peter ferrie

11
Se você estiver confortável em bloquear o NASM como o montador de sua escolha, poderá criar etiquetas executando label1 dbuma linha própria. Irá gerar um aviso, mas nenhum erro.
gastropner 17/06

11
@gastropner bem, isso tornaria muito fácil. : P Não sabia disso, obrigado! Talvez eu deva renomear meu idioma como "algo que você pode alimentar no DEBUG.COM". Que aliás eu costumava depurar isso. xD
Artelius 17/06

11
@ PeterCordes agora este é auto-modificável!
Artelius

23

Perl 6 , 1299 1272 1220 1215 bytes

Obrigado ao Grimy por -27 bytes.

-52 bytes porque, em primeiro lugar, não precisamos das orelhas de coelho.

Agradecimentos 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

Experimente online!

Produz a string com uma nova linha à direita. Se você não quiser isso, substitua o último saypor a print. Você também pode substituir as novas linhas na fonte por espaços.

Explicação

Esse código imprime a seqüência de caracteres caractere. Cada caractere é formado, alimentando o código de caractere apropriado na chrfunção e minúsculas, lcse necessário.

Atualmente, todos os valores são gerados gerando uma sequência com o número correto de caracteres; em alguns casos, o número de caracteres é o inverso do código de caractere de destino. Teoricamente, seria possível usar funções matemáticas como loge expdiretamente, mas não achei muito fácil usá-las.

Para o uso como números, nós temos e, pie tau; no lado direito de xou xx, eles são implicitamente pavimentados. Todos eles têm 17 caracteres em suas representações de seqüência de caracteres, então usamos epara contagem mínima de caracteres. Também temos i(4 caracteres), False(5 caracteres) e NaN(3 caracteres). Podemos multiplicar comprimentos de string com x; xxmultiplica um mais o comprimento da corda pelo lado direito e adiciona um. chopremove um caractere da string, caso estejamos um longe do alvo.

As instruções de impressão são encadeadas usando and, que tem uma precedência bastante baixa. É quase um milagre que exista; caso contrário, teríamos que usar ponto e vírgula ilegal.

Encontrei as expressões dos personagens à mão. Pode valer a pena procurá-los programaticamente para encontrar expressões mais curtas.



A propósito, @JoKing, você procurou as expressões mais curtas à mão ou usou um programa para ajudar?
bb94 13/06

11
À mão, eu tenho medo. Uma maneira algorítmica provavelmente não seria muito difícil
Jo King


@ Grimy Clever, mas infelizmente só é possível porque o espaço de largura zero que você está usando não é um caractere de espaço em branco
Jo King

17

Largura , 66 64 bytes

QaaGmwmiimaGcwWiimawAGawmfciiiGaFmAmFiimFGcwAmFiGmaiiGcGamafFiGQ

Experimente online!

Imprime para depuração. Para imprimir em stdout, acrescente wwo final do código, que aparece e gera a parte superior da pilha.

Explicação

Em Largura, cada letra se correlaciona com um número, com base em quão "larga" é, de acordo com esta tabela . Isso atribui a cada letra um número de 0 a 9. Em seguida, esses números são usados ​​para realmente executar o código.

Em particular, uma letra que corresponde 7a iniciará uma string literal. Ele lerá conjuntos de duas letras de uma só vez, até ler a letra original novamente. Cada conjunto de duas letras será convertido em seus números de largura, lidos como um número decimal entre 0 e 99, e o caractere igual a eles será seu índice na seguinte string:

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

Por exemplo, o índice de !é 1, assim 01serão os números de largura corretos. Assim, if, iI, jt, etc serão todos correlato a um literal de cadeia de !.

Nesse caso, traduzi os 31 caracteres da saída necessária para letras apropriadas, usando Qcomo aspas. A parte superior da pilha é impressa para depuração quando o programa termina.


Este é o mais curto ainda. Eu acho que você poderia ganhar!
Blue-Maned Hawk

14

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

Quando imprimo meu código no console da página de códigos 437, vejo o seguinte:

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 

Ele contém alguns caracteres de espaço em branco; portanto, aqui está o mesmo código quando substituo todos os caracteres de tabulação por e todos os caracteres de espaço não separável (com o 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

Algumas explicações sobre como funciona:

Instruções úteis são:

  • push imm8, push imm16e push imm32, seguido por popgerar constantes. Isso também pode gerar zero (in ah) ao pressionar um byte ( imm8).
  • and [ecx+32], ah- assumindo ah = 0, isso define o byte como zero. Acontece que o comprimento da string de saída é 32, então o código preenche o buffer do início ao fim.
  • or [ecx+32], edx- assumindo que o byte de saída está definido como zero, isso copia edx(4 bytes) para a saída. Eu uso uma variante com em dxvez de edxperto do final do buffer, porque ele não deve gravar além do buffer de saída. A restrição no código torna impossível escrever bytes únicos dessa maneira!
  • imul edx, [ecx+32], whatever- esta é a principal idéia de embaralhar. Com entropia suficiente [ecx+32]e qualquer número, ele pode gerar qualquer saída. Eu o uso para gerar 2 ou 3 bytes dos valores necessários. Alguma complicação é que, ao gravá-lo na saída, ele deve ser lógico ORcom o que já estiver lá. Às vezes, isso tornava necessário zerar a memória mais uma vez.
  • Uma variante de uma jmpinstrução é usada para retornar. Eu o escolhi porque sua codificação é 0xff, o que corresponde a um espaço ininterrupto na página de códigos 437. Um pouco exagerado nas regras, mas, caso contrário, acho que a tarefa é impossível ...

Código fonte do assembly, junto com um programa C que o executa (usa a sintaxe do 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);
}

Isso não parece ser totalmente jogado para mim. Certamente você salvaria vários bytes usando loops, em vez de repetir uma série de instruções idênticas. Tudo isso dec ecx+ and [ecx+32], ahmaterial pode ser tomada fora.
Cody Gray

Você pode tentar. Isso é o melhor que eu poderia fazer; Eu ficaria feliz em ver uma abordagem diferente. Decidi abandonar a ideia de loops quando vi que eles exigem um deslocamento negativo do salto. Talvez essa restrição possa ser resolvida de maneira criativa - não sei como.
anatolyg 13/06

11
@anatolyg Pode ser a posição do ambiente de teste em relação ao código auto-modificável. Ou suas opiniões sobre a execução de código que você criou na pilha.
gastropner 14/06

O char não 0xffviola "Sem pontuação ou caracteres não 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

Experimente online!

Isso usa 32 cópias dos números inteiros 89 25 20 6. Todos os códigos de caracteres da cadeia de destino podem ser obtidos com operações nesses números inteiros, em ordem de pilha: por exemplo, 'A' (ASCII 65) é 89 - (25 e (20 + 6)). Muitas quatro tuplas de números inteiros têm essa propriedade; este foi escolhido porque é particularmente fácil de gerar.

currentflat string dup rrand

O padrão é 1, então isso cria uma sequência de comprimento 1 (inicializada em \0). dupnão é uma cópia profunda: cria uma segunda referência para a mesma string. rrand empurra a semente aleatória, que assume como padrão 0. Stack is now ["\0", "\0", 0].

count dup count count mul mul xor

count empurra o número de itens na pilha; portanto, calcula 3 ^ (3 * (5 * 6)) = 89.

count count mul count dup mul exch count

4 * 5 = 20, 5 * 5 = 25, 6 = 6. A pilha está agora ["\0", "\0", 0, 89, 25, 20, 6].

count copy count copy count copy count copy count copy

Duplique a pilha inteira, cinco vezes. Assim, terminamos com 32 cópias da nossa pilha inicial de 7 elementos. Precisamos apenas de 31 cópias, pois a sequência de destino tem 31 caracteres, mas a cópia extra não dói.

add and sub put print

Calcule um código dos quatro números inteiros, escreva-o no índice 0 da sequência e imprima a sequência.

quit

Suprime o prompt padrão.


11

Ruby , 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

Experimente online!

Em ordem crescente de jankiness:

Palavras que começam com uma letra maiúscula podem ser impressas definindo uma classe com esse nome e chamando displaydentro do corpo da definição de classe.

Outras palavras podem ser exibidas definindo métodos com esse nome, que retorna um símbolo, e convertendo-o em uma String para remover os dois pontos principais.

Outros caracteres podem ser exibidos chamando putcseu código ASCII. Podemos gerar os números apropriados reutilizando o String deftruque para obter uma string e, em seguida, obtendo a soma de seus bytes usando um módulo determinado por seu tamanho. Infelizmente, não temos como chamar métodos em um objeto além da definição de classe desse objeto, o que dificulta a transmissão de argumentos. Portanto, o hack final é redefinir String#inspect, que é chamado implicitamente ao passar uma String para o pmétodo, para que calcule e produza o caractere apropriado como efeito colateral, antes de gerar um erro para que pnão seja possível concluir a execução e imprimir um nova linha. Então, precisamos resgatar o erro no código principal.

Edit: Jordan fez o byte contar muito menos, ahem, alto com algum controle de fluxo de controle inteligente, e eu cortei mais alguns bytes substituindo raisepor uma chamada de método inexistente de uma letra, que gera um NameError.

Edit 2: Note-se que, com print Stringextraído em um método, é mais barato usá-lo com uma definição de método do que usar o truque de definição de classe, uma vez que é permitido que os métodos sejam case case.


Lindo .... Não entendo como sum sizefica a soma do módulo, mas todo o resto dá uma olhada!
Value Ink

Coloquei isso um pouco preguiçosamente, na verdade, está passando o tamanho da string como o argumento opcional para o método sum.
histocrat 13/06

11

> <> , 233 122 bytes

cdacaabbglccgpcbfbbcaacdebbafbebbcebdbealbcpcdbcccdlcdpacbbalccpaalacpbcfafbaab









       g  sandBe
       o  Aviuth

Experimente online!

Isso começou como um golf da resposta do mbomb , mas eu descobri uma mudança fundamental que economiza um grande número de bytes, por isso estou publicando como minha própria resposta.

A geração de caracteres não alfabéticos para a saída é feita pressionando repetidamente os valores para a pilha e usando lpara empurrar o comprimento da pilha. No entanto, isso não precisa ser gerado imediatamente: usando p, esse caractere pode ser colocado em qualquer célula cujas coordenadas estejam entre 10 e 15 inclusive, para serem recuperadas posteriormente com g. Da mesma forma, os caracteres alfabéticos podem ser colocados no código-fonte inicial e lidos da seguinte forma: como o código de caracteres não alfabéticos mais alto na entrada é 46 ( .), isso significa que a pilha não precisa ser pressionada mais que os 62 necessários para armazenar todos os 31 caracteres da saída.

Além disso, a vé colocado no código da coluna 7. Quando o ponteiro da instrução se aproxima e o atinge v, a sequência goé executada repetidamente para ler as coordenadas pressionadas e gerar os caracteres correspondentes. Eventualmente, a pilha fica vazia e gfinaliza o programa com um erro.

Os primeiros 7 bytes de código são reutilizados conforme as 7 e 7 últimas coordenadas pressionadas. A colocação da vcoluna 9 economizaria teoricamente mais dois bytes, mas teria forçado os caracteres Ainsva um quadrado 2x2 no código, o que é impossível. Uma versão anterior usava a coluna 15, mas exigia uma linha extra no código-fonte e terminava seis bytes a mais.


Após uma reflexão mais aprofundada, acho que posso fazer a coluna 9 funcionar gastando um byte rpara mover o alinhamento para onde eu quiser. No entanto, jogar golfe nesse programa machuca um pouco o meu cérebro.
Nitrodon 16/06

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

Experimente online! As novas linhas são mostradas aqui apenas para maior clareza; cada linha representa um caractere.

Uau, isso foi divertido. Restringir-nos a comandos alfabéticos apresenta alguns desafios interessantes:

  • Sem {e }, não há praticamente nenhuma oportunidade para o fluxo de controle (exceto f, que eu não achei uma oportunidade de usar).
  • Sem \, _, ;, ou $, não temos meios para manipulação de pilha.

Isso significa que o objetivo principal será obter os pontos de código relevantes na pilha e convertê-los em caracteres com c.

O problema é que também não temos os comandos aritméticos mais básicos, bem como literais inteiros. Isso é bom, pois o mnamespace contém inúmeras operações matemáticas avançadas e há muitas variáveis ​​predefinidas para números úteis.

Acabei fazendo uso intenso de raízes quadradas ( mQe mq), da função exponencial mee da conversão de base ( b), que também podem ser usadas para emular a multiplicação ( [X 0] Ybcalcula X * Y). Além disso, às vezes é mais fácil construir o ponto de código em maiúsculas; nesse caso, podemos usar el(converter em minúsculas) no caractere resultante.

Ainda não estou satisfeito com alguns dos mais longos. Ah bem.

Explicação

Esta é uma explicação caractere por caractere da saída. Antes de começar, aqui estão algumas maneiras curtas de criar números:

  • 0, 1, 2, 3 estão contidos em variáveis T, X, Y, Zrespectivamente.
  • Os números 10 a 20 estão contidos nas variáveis Athrough K.
  • 32 pode ser feito usando Sci( Sempurra uma string contendo um espaço, cobtém o primeiro caractere dessa string e iconverte esse caractere em seu ponto de código). Stambém é usado para espaços.
  • 4 é dado por GmQ(raiz quadrada inteira de 16).
  • 5 é dado por AZbYb(converta 10 na base 3, produzindo [1 0 1]e converta a matriz de números resultante na base 2, produzindo 5).
  • 7 é dado por Ymei(calcule exp (2) e converta em número inteiro).

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

11
Você pode fazer conversões básicas com dígitos fora do intervalo usual da base, como HYbYCtYbc, HYbXAtYbce HYbXBtYbc.
Nitrodon 21/06

7

Peixe morto ~ , 943 bytes

iiisdsiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicddddddddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcdddddddddddcdddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsddddddcddddddddddddddddddciiiiiiiicdddddcddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddciiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiicdcddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddddddddddddddddsdddddcddddddddddddcdddddddciiiiiiiiiiiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddddddddsddddddcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcddddddddddddddddddddddsiiiiciciiiiiiiiiicdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddcdddddddc

Experimente online!

Não são permitidos loops :(


7

mal , 198 bytes

aeeeannkhhwzuuuuuueaeuekwuuuuuuuuuunkhwzaeeeeehknwgueeywguuuuuuhhknnwuuuwhgwpwnngheeuwguuuuuwngwzaeeeaaaeeeeeewhhgwnguuuueewnngawpaawuwnngwpawhgwhhgeeuwpawhguuuueewpwhgwhgwawpwnngaaaaaaeeeewguuuueew

Experimente online!

Isso foi bem divertido.



6

MATL , 187 158 bytes

IEWQKEtqhpEqqKQHhthpKWEyQKWEqqYqQQXJwtQQQwKWEJKQthpYqKQHhthptQQQQQwIIhKQhpqKWEIWKQhpqIEWQQJQQtqKWEyIIhIhpYqQXJyKQthpYqwIWKQhpqyqKWEyJtQwhhPIIhKQhpQIWKQhpqvlec

Experimente online!

Versão mais legível: Experimente online! Tentativa manual de construção da string. Provavelmente há muito espaço para jogar golfe, cortando a corda em pedaços convenientes, usando Pe hpara virar e construir uma corda. Espero que alguém aceite o desafio de me superar. O principal desafio é que você não pode usar +ou -, portanto, a aritmética básica geralmente não é possível.

Luzes:

  • KQthpYq: o 25º ( KQthp) primo Yqé 97, correspondendo à letra a. A letra s(115) é gerada de maneira semelhante a partir do 113, o 30º número primo. É então amplamente reutilizado na área de transferência J.
  • hisé encurtado armazenando o hde antes na área de transferência J. Desde que armazenado anteriormente s, construímos hisao contrário, para que ainda possamos recuperar o suso recente ye invertê-lo após o uso P.
  • Um grande número de bytes salvos graças a Luis Mendo (principalmente alterando um monte de hpara vle)

Huh - eu realmente pensei que usar viria mexer com o que heu tinha anteriormente. Acho que eu deveria ter isso em vez de apenas assumir. Além disso, obrigado pelo aviso, a exclusão excessiva de zelo aconteceu. Estou curioso para ver se você pode fazer melhor do que isso ...
Sanchises

Eu gostaria de tentar, mas terá que esperar. Responder a isso parece levar muito tempo!
Luis Mendo

11
@LuisMendo Yup. Levei uma hora para fazer isso, e isso inclui apenas uma otimização muito local. Tenho certeza de que se pode fazer melhor com um pouco mais de visão global das coisas.
Sanchises

Minha tentativa . Eu não olhei para a sua, então espero que as abordagens sejam diferentes
Luis Mendo

@LuisMendo Eu esqueci completamente que isso Usignifica ^2que poderia ter me poupado alguns bytes ...
Sanchises

6

MATL , 118 bytes

KEUQtVQsQKBFZAXHKUqyyhsXJyyhdQtQQQwOJIUEyhdtKEhsHKQYqEEKQyywhdXJKEUQQHKUhstQwOytHKhsKYqyhdbJyqOHKhstQHKUqhsKUqYqqJvlec

Experimente online!

Versão mais legível (cada linha corresponde a um caractere, exceto operações de reorganização da pilha).

Explicação

O programa produz os pontos de código dos caracteres necessários, como números independentes. No final, todos esses números são concatenados em um vetor de coluna, remodelados como um vetor de linha e convertidos em caracteres. O resultado é exibido implicitamente.

Alguns dos truques usados:

  • A maioria dos pontos de código abaixo de 32 é exibida como espaço. Então, 0é usado na maioria dos espaços, porque custa apenas um byte ( O).
  • No entanto, o primeiro espaço 15é usado (gerado como KUq), pois pode ser reutilizado adicionando-o a 100(char d) para fornecer 115( s). Em outra ocasião, 5é usado para o espaço (gerado como KQ), para que possa ser subtraído posteriormente de 44( ,) para fornecer 39( ').
  • A área de transferência Jé usada para armazenar caracteres que serão repetidos: primeiro se depois '. Da mesma forma, a área de transferência Harmazena 100, o que é útil para de para gerar outros caracteres.
  • O uso extensivo é feito de funções Q(adicionar 1), q(subtrair 1), E(multiplicar por 2) e U(quadrado), juntamente com os literais predefinidos nas pranchetas I( 3) e K( 4).
  • A adição e subtração arbitrárias são feitas concatenando em um vetor ( h) e calculando sua soma ( s) ou diferenças consecutivas ( d).
  • 100( d) é gerado como 4em binário interpretado como um número decimal.
  • 110( n) é obtido de 65( A) convertendo para string ( '65': pontos de código [54 53]), adicionando 1aos pontos de código ( [55 54]), somando-os e somando-os 1.
  • A ordem na qual os números são gerados às vezes é alterada por conveniência; e eles são reordenados por funções de reorganização da pilha: swap ( w), subida de bolha b).

11
Muito agradável! Toque inteligente usando em Ovez de KWEespaços. E você confirmou minha suspeita de que provavelmente é melhor sacrificar outra prancheta H.
Sanchises

5

dc , 240 222 209 bytes

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdOOlAxlAxPOBlBxdIlAxoPAdlBxddsrIlAxssPPOPlsIZlCxddspPOZlCxPPOPlrdZlCxPlsPlrPlcPPKPdZlBxdZlAxPOAZlAxdPIZlCxdPrPdPlpPlrdZlCxPPKPOPPlpPlsPOPldPKP

Experimente online!

Meu primeiro pensamento foi o mesmo que @seshoumara, basta colocar coisas suficientes na pilha para gerar todos os valores ASCII dos caracteres. Ocorreu-me que +, uma vez que -, e *são operadores de caracteres únicos, posso apenas recriá-los e ter a capacidade de usar aritmética! Certamente isso seria menor!E, não ficaria surpreso se soubesse jogar mais bytes, mas por enquanto ... essa abordagem complicada conseguiu amarrar a ingênua (ish).

OOOOOziOOOOOOOOOOOOOOOOOOOOOOOOOOOzddddddzkdddzasBdzasAdzscdzdasCzsdé a parte da abordagem semelhante à @ seshoumara, mas só chegamos a 46, o que é .. Fazemos isso porque precisamos ir até 45, -e também precisamos de um período em nossa string, portanto, avançar um pouco mais no período é (eu acho) mais barato. Ao longo do caminho, armazenamos alguns valores: 5, 32, 39 são úteis mais tarde. 5 para itens utilitários, 32 e 39 para seus valores ASCII. Originalmente, eu fazia de 1 a 5, mas isso era caro e conseguia simplesmente evitar o uso de 4; use Z(digite um valor, pressione o número de dígitos que possui) em um número de três, dois ou um dígito para esses valores. Aos 42, 43 e 45, que convertê-los para strings ( *, +e, -respectivamente) e armazená-los como macros ( B, AeCrespectivamente). Isso significa que, sem usar os caracteres*+-, agora podemos usar esses operadores.

A partir daqui, basicamente começamos a gerar os valores ASCII usando o poder da matemática em vez da simples acumulação, armazenando algumas das repetições ao longo do caminho. 100, 105 e 115 surgem o suficiente para que armazená-los (em registros ou outros) fizesse sentido. Originalmente, deixei a pilha cheia de 10s e usei para fazer 100s; acabou economizando bytes para preencher a pilha com 32 segundos e usá-los como espaços posteriormente. Uma versão um pouco mais legível da seção 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 .

Raspou 18 bytes: armazenando o número 5 como o radical de entrada em vez de um registro; o número 32 como precisão em vez de um registro; o número 115 como raiz de saída em vez de um registrador; em seguida, teve que mudar KZpara IZgerar 1s e OZpara KZgerar 2s.

Raspou mais 13 bytes inundando a pilha com 32s; definindo precisão para 39; usando manipulação de pilha para evitar armazenar 116; cortando alguns trabalhos duplos que acidentalmente deixei.


+1 Boa ideia para arecriar esses operadores e depois chamá-los com x. Isso mostra o comportamento dos dados é código do dc. Quando tiver tempo, aplicarei seu truque mais recente de armazenamento de dados em parâmetros, em vez de registradores. Você acha que poderíamos obter uma solução CC ainda mais curta, abusando da maneira como P trabalha para imprimir mais letras de cada vez, se tivermos sorte de inserir o grande número necessário usando apenas hexadecimal?
seshoumara

@seshoumara É possível, embora minhas tentativas de fazer isso com outros desafios sugiram que é improvável simplesmente porque esses valores se tornam grandes rapidamente. Apenas para obter as duas primeiras letras, 'An', precisamos P16750 ou 0x416E. Se por acaso tivéssemos sorte e um dos substrings fosse composto exclusivamente pelos valores AF, isso poderia nos dar um atalho. Isso seria um pouco de sorte! Caso contrário, estaríamos inserindo números grandes de alguma forma, apresentando-os de alguma forma, ou adicionando e multiplicando muito por 256. O que parece ... mais robusto do que um monte de Ps.
brhfl 14/06

5

Japonês , 87 bytes

Bs g caA
HzG
Ts caV
iWisiiihiSisiUitiaihitiSitiuibu iUiSiWcaV idiiiaisiSieihisiSidiniau

Tente

Explicação

A primeira linha gera 'e atribui a variável U.

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

A segunda linha atribui 2à variável V.

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

A terceira linha gera .e atribui a variável W.

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

A última linha, então, constrói a string, um caractere de cada vez, no sentido inverso.

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

Ótima solução. Você pode salvar um byte, substituindo a primeira linha porQc dGaB
Modalidade de Ignorância

4

Vermelho , 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

Se as aspas duplas forem necessárias:

Vermelho , 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

Não funciona no TIO, mas funciona no intérprete vermelho.

Console vermelho

Explicação:

As palavras são triviais - imprimo-as ​​(imprima sem nova linha) como literais com quote. Vermelho tem uma palavra embutida para espaço - sp, assim como commae dot. "e 'mais interessante: Eu prin-los subtraindo um espaço de Be G, respectivamente, a partir de um literal Be G, convertendo-os primeiro a string com molde depois caracteres (para uso subtração sobre eles) wtih to sp( Red tem conversão de protótipo - converter o string para o tipo de sp, que é caractere).


11
A questão foi esclarecida; eles removeram a parte interessante dele.
anatolyg 13/06

@ anatolyg Obrigado, eu ainda preciso disso ', então a solução de 272 bytes é a mesma.
Galen Ivanov

4

Quarto (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

Pena que não consigo redefinir CHAR ou EMIT para palavras de uma letra, pois isso exigiria o uso de :e ;(por exemplo : C CHAR ;) ou '(por exemplo ' CHAR ALIAS C)

De fato, se eu pudesse definir palavras, poderia fazer : P CHAR EMIT ;e depois P ximprimir x. Ah bem.

Não consigo nem criar um buffer, gravar essa sequência de caracteres para lá e usá-la como entrada, já que gravar na memória requer o uso !ouC!


3

AlphaBeta , 180 177 175 163 bytes

cccaaggtFgDILrFigggDLjDLCLigggggDLjhDLhhhDLCLiggggDLjjggDLihhDLhhhhhDLcaaCLdbbCLcbbbCLHgDLiiiiigDLhDLdaaaCLDLjhhDLjgggDLiihDLcbbbCLhDLdaaaCLjhDLgDLiDLcaaaaCLdaaaCL

Experimente online!

WIP


3

Pepe , 266 bytes

Eu mantenho a pilha r vazia e tenho 's' na pilha 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

Isso não está no TIO, mas você pode tentar aqui


3

dc , 240 bytes

A idéia principal é aumentar continuamente a pilha em 1 ( K), salvando ( sX) o tamanho da pilha ( z) em registros personalizados quando corresponder a cada código ASCII exclusivo. Printing ( P) é feito por toda parte.

KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsSKKzsQKKKKKzsqKKKKKzsCKKzsDKKKKKKKKKKKKKKKKKKKzPKzsBKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKzsaKKKzsdKzseKKKzshKzsiKKKKKzPldPlSPKKKKKzsszPlhPlePlSPlsPlaPliPldPlCPlSPlqPlBPKzdstzPdPlSPdPlhPlaPPlqPlsdPlSPlhPliPPlDPlqP

Experimente online!

Fiz alguma otimização, como não salvar uma letra se não for usada depois disso, como duplicar ( d) uma letra, por exemplo, t, na pilha para salvar um byte, já que recall ( lX) tem 2 bytes.


Eu vim com uma solução dc que usa aritmética criando macros para +, - e *. São 262 bytes. Vou continuar tentando otimizá-lo para tentar ser competitivo, mas devo dizer que estou decepcionado por ser muito mais gordo que a solução (relativamente) ingênua.
brhfl 13/06

@brhfl Sim, o DC fica detalhado rapidamente. Mesmo assim, eu gostaria muito de ver sua solução, então publique-a! Enquanto isso, também estou pensando em jogar mais o método atual, usar um programa ou ter outra ideia para o dc.
seshoumara 14/06

Eu consegui amarrar 240! E não ficaria surpreso se conseguisse jogar mais um ou dois bytes, mas ... é uma abordagem muito mais obtusa para pouco / nenhum ganho. Enfim, eu postei lá em algum lugar ...
brhfl 14/06

Cheguei a 222 substituindo alguns dos meus registradores mais comuns com base e precisão de entrada / saída; economiza um byte na loja e um byte em cada carregamento ... Como os números são irrelevantes, isso não afeta nada ... Você também pode usar isso a seu favor!
brhfl 14/06

3

80186+ código da máquina, formato .com do MS-DOS, 822 787 bytes

Apenas tabulações e espaços são usados ​​além das letras. Dado que a maioria dos códigos de operação no intervalo permitido são certos incrementos, decrementos, pushes, pops e ANDs e ORs indiretos do registro, além do IMUL, utilizo o fato de que o registrador de pilha se envolve quando atinge o final do segmento para modificar o código ao contrário! A montagem 80186+ é necessária porque estou pressionando valores imediatos.

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

Origem 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

Isso não é montagem, é código de máquina ...
Artelius 16/06

@ Artelius Fair suficiente. Eu atualizei a descrição.
ErikF 16/06

3

Befunge-98 (FBBI) , 125 124 121 bytes

wab









And she said   But that s his












wakekekaayyeapwayyaayybyapayybyapcyabcyaayycayyba
a



b
wayapapoq

Experimente online! Saídas para um arquivo chamado \n(uma única nova linha). Obrigado a Jo King por seu roteiro.

A saída inclui 10 novas linhas finais.

Para apenas uma nova linha à direita, +1 byte , alterando a seguinte linha:

wakekekaayyeapwayydayybyapayybyapycyabcyaayycayyba

Experimente online!


Explicação:

O ponteiro de instruções se move da seguinte maneira:Caminho IP

O programa coloca os caracteres não alfabéticos em posição, antes de enviar essa linha para um arquivo.

O Befunge-98 inclui instruções a... f, que enviam o valor hexadecimal correspondente para a pilha. Para gerar outros números, ele passa esses valores para y("Get SysInfo") como argumentos para obter:

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

23* stack size

Colocando a maior parte do código em y = 23, ayypode ser usado para acesso repetido ao tamanho da pilha, que é usada para gerar códigos de caracteres.


Não é permitida apenas uma nova linha à direita?
Delioth 13/06

A postagem afirma "Espaço em branco é completamente permitido". Acho legal abusar dessa redação para justificar novas linhas!
anatolyg 13/06

2

Pitão , 210 bytes

pChyCdpCyhyhlGpCyytlGpdpChFhTyylGpCyylGpChyytlGpdpChFhTyylGpCtytytlGpChyylGpCyytlGpCyyhTpdpCtyyTpCyhCdpCtFyyCdhTpCyhFlGCdpdpCyhFlGCdpCyylGpCtytytlGpCyhFlGCdpCtyyTpChFhTyylGpdpCyylGpChyylGpChFhTyylGpCyhyhTpCtyyT

Experimente online!

Encontrei alguns números que poderiam ser expressos usando apenas letras (como T= 10, Z= 0, lG= comprimento (alfabeto) = 26, Cd= código (espaço) = 32) e algumas funções que poderiam ser executadas usando apenas letras (como t= decremento, h= incremento, hF= aplicação repetida de incremento = adição) e, em seguida, executei uma pesquisa de força bruta para encontrar as combinações mais curtas dessas funções e números que resultaram em cada uma das letras de que eu precisava.


2

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

(o binário é alfabético, não a fonte)

De alguma forma, esqueci a regra que permite espaços em branco. Certamente o código pode ser jogado como resultado.

Bytecode:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXsBFVKZPFFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPFPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXkLAFQQZJJJRkDCGPLXDPDJRkDBEPZJJRLZDRDZAAAQPLYDQDYXXDQhishZhDRDhZsDQDhaththRDhuthZBDQDRhidhsaRDhhehZsDRDhndhZADTZPiDEFY

Fonte:

    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 assim:

  • move o ponteiro da pilha para o final do código, via POP AX (não pode POP SP porque não é alfabético);

  • constrói a instrução para despachar uma chamada do DOS (algoritmicamente porque não é alfabética);

  • constrói os caracteres não alfabéticos;

  • coloca a string na pilha;

  • coloca a instrução de despacho na pilha no final exato do código, para que a execução flua diretamente para essa instrução;

  • constrói a instrução para imprimir uma string;

  • exibe a string e eles imediatamente travam. : - / (Uma saída normal exigiria mais código)




0

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

Versão em texto:

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

Versão em texto, com tabulações (código 9) substituídas por 9e espaços (código 32) substituídos 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

O código da máquina aparece em um arquivo com extensão .com. Quando o executo, ele imprime a mensagem necessária e, em seguida, trava (executando dados aleatórios).

Explicação de alto nível sobre o que faz:

  1. Inicializa registradores com valores constantes
  2. Substitui os espaços na mensagem pelos símbolos especiais necessários ( ,'.$)
  3. Corrige o código para gerar a int 21instrução, que imprime a mensagem
  4. Chamadas DOS

Código de montagem (pode ser compilado com 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

Ele usa a popainstrução para exibir todos os registros, porque o regular popnão pode preencher todos os registros necessários (por exemplo, pop dié um código de operação proibido).

Os endereços de bytes a serem corrigidos estão no intervalo 0x100 ... 0x160. Por sorte, eles podem ser representados como uma soma de 3 bytes com valores permitidos:

  • 0x7a in bp
  • 0x7a ou 0x67 em sioudi
  • Valor imediato

A correção de bytes na mensagem funciona de maneira lógica ORem 0x20 (caractere de espaço) e uma pequena constante (4, 7, 12 ou 14). A pequena constante é obtida inicializando cxe dxaté 9 (caractere de tabulação) e fazendo INCou DECconforme necessário.

O patch do código usa a IMULinstrução Encontrei as constantes de 16 bits necessárias para multiplicar usando a pesquisa de força bruta.

Finalmente, o endereço da mensagem (0x13b) é obtido por multiplicação. Para economizar espaço, peguei uma das constantes de uma das instruções, que contém um valor imediato 0x96d. Aqui, a 9peça escolhe uma função de impressão do DOS e a 6dpeça é um parâmetro livre. Acontece que 6dé a única possibilidade que pode dar 0x13b após a multiplicação.

Desmontagem da parte do 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)

Fato engraçado: Normalmente, eu usaria em offset messagevez do codificado 13bh, mas nesse caso, porque no momento da análise de seu endereço é desconhecido, o tasm gera deslocamento imediato de 16 bits, desperdiçando 1 byte de código:

06BA:0131 098A4600          OR      [BP+SI+0046],CX
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.