diff --git a/submissions/anachan01h/problema-2/.dockerignore b/submissions/anachan01h/problema-2/.dockerignore new file mode 100644 index 0000000..385b6ee --- /dev/null +++ b/submissions/anachan01h/problema-2/.dockerignore @@ -0,0 +1,2 @@ +*~ +bin/ diff --git a/submissions/anachan01h/problema-2/.gitignore b/submissions/anachan01h/problema-2/.gitignore new file mode 100644 index 0000000..4d46798 --- /dev/null +++ b/submissions/anachan01h/problema-2/.gitignore @@ -0,0 +1,3 @@ +*~ +bin/ +test/ diff --git a/submissions/anachan01h/problema-2/Dockerfile b/submissions/anachan01h/problema-2/Dockerfile new file mode 100644 index 0000000..b8dcc3f --- /dev/null +++ b/submissions/anachan01h/problema-2/Dockerfile @@ -0,0 +1,6 @@ +FROM emilienmottet/nasm:latest + +COPY . /problema-2 +WORKDIR /problema-2 +RUN make all +ENTRYPOINT ["./bin/main"] diff --git a/submissions/anachan01h/problema-2/Makefile b/submissions/anachan01h/problema-2/Makefile new file mode 100644 index 0000000..cd5981c --- /dev/null +++ b/submissions/anachan01h/problema-2/Makefile @@ -0,0 +1,14 @@ +bin/main: src/main.c bin/mcds.o + gcc -o bin/main src/main.c bin/mcds.o + +bin/mcds.o: src/mcds.asm bin/ + nasm -f elf64 -o bin/mcds.o src/mcds.asm + +bin/: + mkdir bin + +all: clean bin/main + +.PHONY: clean +clean: + rm -rf bin \ No newline at end of file diff --git a/submissions/anachan01h/problema-2/README.md b/submissions/anachan01h/problema-2/README.md new file mode 100644 index 0000000..46c4946 --- /dev/null +++ b/submissions/anachan01h/problema-2/README.md @@ -0,0 +1,35 @@ +# Solução do Problema 2 + +Minha solução do problema 2 em Assembly. + +## Pré-requisitos + +- Um computador com Linux e arquitetura x64 +- NASM +- GCC +- GNU Make + +## Como executar + +Primeiro, execute o comando: +``` +make +``` + +O executável será compilado na basta `bin`. Para executar com um arquivo `exemplo.txt`, basta executar o comando: +``` +./bin/main exemplo.txt +``` + +## Como executar pelo Docker + +Primeiro, criamos a imagem no Docker: +``` +docker build -t problema-2 . +``` + +Para executar com um arquivo `exemplo.txt`, basta executar o comando: +``` +docker run --cpus=2 --memory=2g problema-2 exemplo.txt +``` +**Observação:** Para testar um arquivo `exemplo.txt`, ele precisa estar na pasta `problema-2/` quando a imagem no Docker for criada. Recomendo colocar os arquivos de texto para teste numa pasta `test/`. diff --git a/submissions/anachan01h/problema-2/src/main.c b/submissions/anachan01h/problema-2/src/main.c new file mode 100644 index 0000000..e4cdd73 --- /dev/null +++ b/submissions/anachan01h/problema-2/src/main.c @@ -0,0 +1,77 @@ +/* ============================================================================= + * ### main.c + * Interface básica para testar minha solução do Problema 2. + * By: anachan01h + * ========================================================================== */ + +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + extern uint64_t mcds(uint64_t n, uint8_t *graph, uint8_t *covered, uint8_t *cds); + extern char *slice(char *buf); + uint64_t n; + uint8_t *graph, *covered, *cds; + FILE *fptr; + char buf[256]; + int i; + uint64_t v, u; + + // Verifica se o programa recebeu apenas um argumento + if(argc != 2) { + printf("Erro: número de argumentos inválido!\n"); + return -1; + } + + // Abre o arquivo + fptr = fopen(argv[1], "r"); + if(fptr == NULL) { + printf("Erro: não foi possível abrir o arquivo \"%s\".\n", argv[1]); + return -1; + } + + // Lê a primeira linha do arquivo, obtendo o valor de n + fgets(buf, 256, fptr); + slice(buf); + n = atoi(buf); + + // Cria a matriz de adjacências do grafo, armazenada em graph + graph = calloc(n * n, 1); + for(i = 0; fgets(buf, 256, fptr); i++) { + u = atoi(slice(buf)) - 1; + v = atoi(buf) - 1; + graph[v * n + u] = 1; + graph[u * n + v] = 1; + } + + // Cria os arrays covered e cds, utilizados no algoritmo + covered = calloc(n, 1); + cds = calloc(n, 1); + + // Aplica o algoritmo, e exibe o resultado + printf("%" PRIu64 "\n", n - mcds(n, graph, covered, cds)); + + // Libera a memória alocada dinamicamente + free(cds); + free(covered); + free(graph); + + // Fecha o arquivo + fclose(fptr); + + return 0; +} + +// Pega uma linha do arquivo e separa os números, substituindo o espaço ou tab pelo caractere nulo +char *slice(char *buf) { + int i; + for(i = 0; i < 256; i++) { + if(buf[i] == ' ' || buf[i] == '\t') { + buf[i] = 0; + break; + } + } + return(buf + i + 1); +} diff --git a/submissions/anachan01h/problema-2/src/mcds.asm b/submissions/anachan01h/problema-2/src/mcds.asm new file mode 100644 index 0000000..96da6b1 --- /dev/null +++ b/submissions/anachan01h/problema-2/src/mcds.asm @@ -0,0 +1,127 @@ +; ============================================================================== +; ### mcds.asm +; Minha implementação da solução aproximada do problema Minimum Connected +; Dominating Set +; By: anachan01h +; ============================================================================== + +section .text +global mcds + +; mcds(u64 n, bool *graph, bool *covered, bool *cds) -> u64 +mcds: + mov r8, rdx + ; rdi: n + ; rsi: *graph + ; r8: *covered + ; rcx: *cds + + sub rsp, 16 + ; rsp: vertex + ; rsp + 8: neighbors + mov qword [rsp], 0 + mov qword [rsp + 8], 0 + + ; Find a vertex with maximum neighbors + xor r9, r9 ; r9: v <- 0 +mcds_loop01: + xor r11, r11 ; r11: u <- 0 + xor r10, r10 ; r10: m <- 0 +mcds_loop02: + mov rax, r9 ; rax <- v + mul rdi ; rax <- v * n + add rax, r11 ; rax <- v * n + u + cmp byte [rsi + rax], 1 ; (v, u) not in graph? + jne mcds_loop02_next + inc r10 ; m++ +mcds_loop02_next: + inc r11 ; u++ + cmp r11, rdi ; u < n? + jb mcds_loop02 + cmp [rsp + 8], r10 ; neighbors >= m? + jae mcds_loop01_next + mov [rsp], r9 ; vertex <- v + mov [rsp + 8], r10 ; neighbors <- m +mcds_loop01_next: + inc r9 ; v++ + cmp r9, rdi ; v < n? + jb mcds_loop01 + + mov r9, [rsp] ; r9 <- vertex + or byte [r8 + r9], 0x01 ; vertex in covered +mcds_loop1: + mov qword [rsp], 0 ; vertex <- 0 + mov qword [rsp + 8], 0 ; vizinhos <- 0 + xor r9, r9 ; r9: v <- 0 +mcds_select: + cmp byte [r8 + r9], 1 ; v not in covered? + jne mcds_select_next + cmp byte [rcx + r9], 1 ; v in cds? + je mcds_select_next + xor r11, r11 ; r11: u <- 0 + xor r10, r10 ; r10: m <- 0 +mcds_vizinhos: + cmp byte [r8 + r11], 1 ; u in covered? + je mcds_vizinhos_next + mov rax, r9 ; rax <- v + mul rdi ; rax <- v * n + add rax, r11 ; rax <- v * n + u + cmp byte [rsi + rax], 1 ; (v, u) not in graph? + jne mcds_vizinhos_next + inc r10 ; m++ +mcds_vizinhos_next: + inc r11 ; u++ + cmp r11, rdi ; u < n? + jb mcds_vizinhos + cmp [rsp + 8], r10 ; neighbors >= m? + jae mcds_select_next + mov [rsp], r9 ; vertex <- v + mov [rsp + 8], r10 ; neighbors <- m +mcds_select_next: + inc r9 ; v++ + cmp r9, rdi ; v < n? + jb mcds_select + + mov r9, [rsp] ; r9 <- vertex + or byte [rcx + r9], 0x01 ; vertex in cds + xor r11, r11 ; r11: u <- 0 +mcds_loop2: + cmp byte [r8 + r11], 1 ; u in covered? + je mcds_loop2_next + mov rax, r9 ; rax <- vertex + mul rdi ; rax <- vertex * n + add rax, r11 ; rax <- vertex * n + u + cmp byte [rsi + rax], 1 ; (vertex, u) not in graph? + jne mcds_loop2_next + or byte [r8 + r11], 0x01 ; u in covered +mcds_loop2_next: + inc r11 ; u++ + cmp r11, rdi ; u < n? + jb mcds_loop2 + + xor r11, r11 ; r11: u <- 0 +mcds_loop3: + cmp byte [r8 + r11], 1 ; u not in covered? + jne mcds_loop1 + inc r11 ; u++ + cmp r11, rdi ; u < n? + jb mcds_loop3 + + xor r11, r11 ; r11: u <- 0 + xor rax, rax ; rax: m <- 0 +mcds_loop4: + cmp byte [rcx + r11], 1 ; u not in cds + jne mcds_loop4_next + inc rax ; m++ +mcds_loop4_next: + inc r11 ; u++ + cmp r11, rdi ; u < n? + jb mcds_loop4 + + add rsp, 16 + ret + +_exit: + mov rax, 0x3C + mov rdi, [r8 + 1] + syscall