Árvorezinha 2.0
Ora viva amigos!
Há uns tempos no trabalho um colega meu começou a fazer pouco das minhas árvorezinhas, a dizer que só eram meia árvore, e que eu devia era de fazer uma árvore completa. Eu fiquei SENTIDO com tal AFRONTA, e fiquei a MATUTAR sobre isso, até que decidi por mãos à obra, e criar a Árvorezinha 2.0.
Primeiro decidi faze-la em C porque é a linguagem STANDARD!
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int altura; int i,x; int lul; if (argc < 2) { return(0); } altura = atoi(argv[1]); /* Ciclo da altura da Arvore */ for(i = 1; i <= altura; i++) { /* Numero de Espaços Começa em 0 porque existem linhas com 0 espaços Algoritmo: altura - linha */ for(x = 0 ; x < (altura-i); x++) { putchar(' '); } /* Numero de Asteriscos Começa em 1 porque não existem linhas sem * Algoritmo: (2 * linha) - 1 */ for (x = 1; x <= (2*i)-1; x++) { putchar('*'); } putchar('\n'); } /* Largura ultima linha */ lul = (altura * 2) - 1; /* Ciclo da altura do tronco Algoritmo: altura / 2 */ for(i = 1; i <= (altura/2); i++) { /* Por causa do ASCII nao permitir meio char tive de fazer duas implementacoes diferentes, uma para quando o valor da altura do tronco e' par, e outra para quando e' impar. */ if (altura % 2) { /* Impar */ /* Numero de Espaços Algoritmo: (lul / 4) - 1 */ for(x = 0; x <= (lul/4)-1; x++) { putchar(' '); } /* Numero de # (tronco) Algoritmo: lul / 2 */ for(x = 0; x <= (lul/2); x++) { putchar('#'); } putchar('\n'); } else { /* Par */ /* Numero de Espaços Algoritmo: lul / 4 */ for(x = 0; x <= (lul/4); x++) { putchar(' '); } /* Numero de # (tronco) Algoritmo: (lul / 2) - 1 */ for(x = 0; x <= (lul/2)-1; x++) { putchar('#'); } putchar('\n'); } } }A pedido de muitas famílias, foi me imposta a tarefa de fazer um RFC da nova árvorezinha, mas não tenho muito jeito para escrever algoritmos em pseudo-código. Então tal obra heróica fica para o caro leitor, façam me um baseado no código em C e enviem-me!
Segundo as próprias leis já pré-estabelecidas da Árvorezinha, tem de existir uma implementação em Assembly! Então não podia cá faltar a minha versão em x86 Assembly.
; ; Arvorezinha 2.0 ; x86 Assembly ; Copyright (C) 2010 Pedro de Oliveira ; //blol.org ; ; this assembly can never fail ; BITS 32 GLOBAL main ; Vou usar duas funcoes da libc para o codigo nao crescer gigantescamente ; com rotinas que nao interessam nada para aqui. EXTERN atoi EXTERN printf ; Definicao das Variaveis SECTION .data argc dd 0 argv dd 0 erro db "ERRO! Executar: %s <altura da arvore>",10,0 card db '#' newl db 0xa aste db '*' espa db ' ' altura dd 0 i dd 1 x dd 0 lul dd 0 ; He cometh! SECTION .text main: pop eax ; Ignorar... pop eax ; Saca o argc da Stack mov dword [argc], eax ; Guarda o valor na variavel argc pop ebx ; Saca a posicao de memoria do ; argv[0] da Stack mov eax, dword [ebx] ; Mete a posicao em EAX mov [argv], eax ; Guarda-a em argv add ebx,0x4 ; Salta 4 bytes para a frente ; para o argv[1] ficar em EBX mov eax, [argc] ; Mete o argc em EAX cmp eax, 0x2 ; Verifica se e' diferente de 2 jne jafoste ; Se for sai com erro push dword [ebx] ; Mete o valor de argv[1] na Stack call atoi ; Corre o atoi com esse valor mov [altura], eax ; O resultado fica em EAX, guarda ; na variavel altura ciclo_linhas: ; INICIO - CICLO DAS LINHAS DA ARVORE mov eax, [i] ; i em EAX mov ebx, [altura] ; altura em EBX cmp ebx, eax ; Compara jb prepara_tronco ; i > altura ? proximo passo mov dword [x], 0 ; Mete x a 0 ciclo_espacos: ; INICIO - CICLO DE ESPAÇOS ANTES DOS ASTERISCOS mov eax, [x] ; x em EAX ; pretende-se (altura - i) em EBX mov ebx, [altura] ; altura em EBX mov ecx, [i] ; i em ECX sub ebx, ecx ; EBX - ECX cmp ebx, eax ; Compara jbe prepara_asteriscos ; x >= (altura - i) ? proximo passo push espa ; Espaço call print ; write() call incrementa_x jmp ciclo_espacos ; Volta para o inicio do ciclo ; FIM - CICLO DE ESPAÇOS ANTES DOS ASTERISCOS prepara_asteriscos: mov dword [x], 1 ; Mete x a 1 ciclo_asteriscos: ; INICIO - CICLO DE ASTERISCOS (ARVORE) mov ebx, [x] ; x em EBX ; pretende-se (2 * i) - 1 em EAX mov eax, 2 ; 2 em EAX mov ecx, [i] ; i em ECX mul ecx ; Multiplica EAX por ECX dec eax ; Subtrai 1 a EAX cmp eax, ebx ; Compara jb fim_ciclo_linhas ; x > (2*i)-1 ? proximo passo push aste ; Asterisco call print ; write() call incrementa_x jmp ciclo_asteriscos ; Volta para o inicio do ciclo ; FIM - CICLO DE ASTERISCOS (ARVORE) fim_ciclo_linhas: push newl ; Newline call print ; write() call incrementa_i jmp ciclo_linhas ; Volta para o inicio ; FIM - CICLO DAS LINHAS DA ARVORE prepara_tronco: ; pretende-se (altura * 2) - 1 em EAX mov eax, [altura] ; altura em EAX mov ecx, 2 ; 2 em ECX mul ecx ; Multiplica EAX por ECX dec eax ; Subtrai 1 a EAX mov dword [lul], eax ; Guarda a largura da ultima linha ; em lul mov dword [i], 1 ; Mete o i a 1 ciclo_linhas_tronco: ; BEGIN - CICLO DAS LINHAS DO TRONCO mov ecx, [i] ; i em ECX ; pretende-se (altura / 2) mov eax, [altura] ; altura em EAX shr eax, 1 ; divide por 2 cmp ecx, eax ; Compara ECX com EAX jg sair ; i > (altura / 2) ? Adeus! mov eax, [altura] ; altura em EAX test eax, 1 je pc_tronco_par_espacos ; e' par? ; --------------------------- IMPAR ------------------------------- pc_tronco_impar_espacos: mov dword [x], 0 ; Mete-se x a 0 c_tronco_impar_espacos: ; INICIO - CICLO DOS ESPAÇOS ANTES DO TRONCO (IMPAR) mov ecx, [x] ; x em EAX ; pretende-se (lul / 4) - 1 em EAX mov eax, [lul] ; lul em EAX shr eax, 2 ; Divide por 4 dec eax ; Subtrai 1 cmp eax, ecx ; Compara jb pc_tronco_impar_cardinal; x > (lul/4)-1 ? Next! push espa ; Espaço call print ; write() call incrementa_x jmp c_tronco_impar_espacos ; Volta para o inicio ; FIM - CICLO DOS ESPAÇOS ANTES DO TRONCO (IMPAR) pc_tronco_impar_cardinal: mov dword [x], 0 ; Mete x a 0 c_tronco_impar_cardinal: ; INICIO - CICLO DOS CARDINAIS DO TRONCO (IMPAR) mov ecx, [x] ; x em ECX ; pretende-se (lul / 2) em EAX mov eax, [lul] ; lul em EAX shr eax, 1 ; Divide por 2 cmp eax, ecx ; Compara jb fim_ciclo_linhas_tronco ; x > (lul/2) ? Next! push card ; Cardinal call print ; write() call incrementa_x jmp c_tronco_impar_cardinal ; Volta para o inico ; FIM - CICLO DOS CARDINAIS DO TRONCO (IMPAR) ; --------------------- FIM IMPAR -------------------------------- ; ----------------------------- PAR ------------------------------ pc_tronco_par_espacos: mov dword [x], 0 ; Mete x a 0 c_tronco_par_espacos: ; INICIO - CICLO DOS ESPAÇOS ANTES DO TRONCO (PAR) mov ecx, [x] ; x em ECX ; pretende-se (lul / 4) em EAX mov eax, [lul] ; lul em EAX shr eax, 2 ; divide por 4 cmp eax, ecx ; Compara jb pc_tronco_par_cardinal ; x > (lul / 4) ? Next! push espa ; Espaço call print ; write() call incrementa_x jmp c_tronco_par_espacos ; Volto para o inico do ciclo ; FIM - CICLO DOS ESPAÇOS ANTES DO TRONCO (PAR) pc_tronco_par_cardinal: mov dword [x], 0 ; Mete x a 0 c_tronco_par_cardinal: ; INICIO - CICLO DOS CARDINAIS DO TRONCO (PAR) mov ecx, [x] ; x em ECX ; pretende-se (lul / 2) - 1 em EAX mov eax, [lul] ; lul em EAX shr eax, 1 ; Divide por 2 dec eax ; Subtrai 1 cmp eax, ecx ; Compara jb fim_ciclo_linhas_tronco ; x > (lul / 2) - 1 ? uhuhuh push card ; Cardinal call print ; write() call incrementa_x jmp c_tronco_par_cardinal ; Volta para o inicio do ciclo ; FIM - CICLO DOS CARDINAIS DO TRONCO (PAR) ; ----------------------- FIM PAR ---------------------------------- fim_ciclo_linhas_tronco: push newl call print call incrementa_i jmp ciclo_linhas_tronco ; Volta para o inico do ciclo ; FIM - CICLO DAS LINHAS DO TRONCO jafoste: mov eax, [argv] ; Mete o apontador de argv em EAX push dword eax ; Mete o endereço de argv na Stack push dword erro ; Mete o endereço da String na Stack call printf ; Escreve no ecra! sair: mov ebx,0x0 ; valor de saida mov eax,0x1 ; sys_exit int 0x80 print: mov ecx,[esp+4] ; Mete o argumento em ECX mov edx,1 ; Length mov ebx,1 ; stdout mov eax,4 ; sys_write int 0x80 ret incrementa_x: mov eax, [x] inc eax mov dword [x], eax ret incrementa_i: mov eax, [i] inc eax mov dword [i], eax retE aqui vai a prova dos nove:
falso@lemonparty:~/src/zbr$ make rm -f arvore2 arvore.o nasm -f elf arvore.asm -o arvore.o gcc -g -o arvore2 arvore.o falso@lemonparty:~/src/zbr$ ./arvore2 4 * *** ***** ******* ### ### falso@lemonparty:~/src/zbr$ ./arvore2 5 * *** ***** ******* ********* ##### ##### falso@lemonparty:~/src/zbr$Espero lançar futuramente um género de Unit Tests, para testar as varias implementações da Arvorezinha 2.0 que possam surgir, para ver se cumprem o standard ou não.
Espero que tenham gostado do post, até à proxima, fiquem bem e joguem muito! Chuuuuuuack!
Mesmo a tempo do natal fALSO. Não te escapa nada. Ta lindo.
Parece-me bem, mas já não tenho muita paciência para fazer mais arvorezinhas.
Para compilar em linux 64bits:
nasm -f elf arvorezinha2.asm -o arvorezinha2.o
gcc -m32 -o arvorezinha2 arvorezinha2.o
[...] última submissão, tem havido vasto progresso no estado da arte da Arvorezinha. Foi lançado um novo standard, e tem havido um renovado interesse em criar arvorezinhas cada vez mais obscuras e [...]