Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Submissão do problema 02 ^-^ #42

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions submissions/anachan01h/problema-2/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*~
bin/
3 changes: 3 additions & 0 deletions submissions/anachan01h/problema-2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*~
bin/
test/
6 changes: 6 additions & 0 deletions submissions/anachan01h/problema-2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM emilienmottet/nasm:latest

COPY . /problema-2
WORKDIR /problema-2
RUN make all
ENTRYPOINT ["./bin/main"]
14 changes: 14 additions & 0 deletions submissions/anachan01h/problema-2/Makefile
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions submissions/anachan01h/problema-2/README.md
Original file line number Diff line number Diff line change
@@ -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/`.
77 changes: 77 additions & 0 deletions submissions/anachan01h/problema-2/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* =============================================================================
* ### main.c
* Interface básica para testar minha solução do Problema 2.
* By: anachan01h
* ========================================================================== */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

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);
}
127 changes: 127 additions & 0 deletions submissions/anachan01h/problema-2/src/mcds.asm
Original file line number Diff line number Diff line change
@@ -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