|
| 1 | +// compilar no unix/linux |
| 2 | +// > gcc -Ofast primospi.c -o primospi -lm |
| 3 | +// |
| 4 | +// compilado no MINGW64 (Windows) |
| 5 | +// $ gcc -Ofast primospi.c -o primospi -lm |
| 6 | +// |
| 7 | +#include <stdio.h> |
| 8 | +#include <stdlib.h> |
| 9 | +#include <string.h> |
| 10 | + |
| 11 | +#define ORGANIZE 1000 // a cada ORGANIZE em primos eu vejo a maior sequencia e apago a array de primos |
| 12 | + |
| 13 | +typedef struct pilist_st |
| 14 | +{ |
| 15 | + char *start; |
| 16 | + char *end; |
| 17 | +} pilist_t; // lista de números primos extraídos de PI |
| 18 | + |
| 19 | +//// Variáveis globais |
| 20 | +pilist_t maior; // maior início e final |
| 21 | +int *primos_list = NULL; // lista de números primos de 2 até 9973 |
| 22 | +char *buffer = NULL; // arquivo do número PI |
| 23 | +size_t buffer_size = 0; // tamanho do arquivo do número PI |
| 24 | +pilist_t *lista = NULL; // lista de primos de PI |
| 25 | +size_t lista_size = 0; // tamanho da lista |
| 26 | +//// Fim das variáveis globais |
| 27 | + |
| 28 | +void free_all() // limpeza de toda a memória alocada |
| 29 | +{ |
| 30 | + if (lista) |
| 31 | + free(lista); |
| 32 | + if (primos_list) |
| 33 | + free(primos_list); |
| 34 | + if (buffer) |
| 35 | + free(buffer); |
| 36 | +} |
| 37 | + |
| 38 | +void primos_init() // construtor dos primos de 1 a 9973 (solução do desafio 2) |
| 39 | +{ |
| 40 | + int primos_size = 4, j = 0; |
| 41 | + primos_list = (int *)malloc(sizeof(int) * 1230); |
| 42 | + if (!primos_list) |
| 43 | + { |
| 44 | + printf("Memória insuficiente para alocar a lista de números primos\n"); |
| 45 | + exit(1); |
| 46 | + } |
| 47 | + primos_list[0] = 2; |
| 48 | + primos_list[1] = 3; |
| 49 | + primos_list[2] = 5; |
| 50 | + primos_list[3] = 7; |
| 51 | + for (int i = 11; i < 9974; i += 2) |
| 52 | + { |
| 53 | + if ((i % 5) == 0 || (i % 3) == 0) |
| 54 | + continue; |
| 55 | + for (j = 3; j < primos_size; j++) |
| 56 | + { |
| 57 | + if ((i % primos_list[j]) == 0) |
| 58 | + break; |
| 59 | + |
| 60 | + if ((i / primos_list[j]) < primos_list[j]) |
| 61 | + { |
| 62 | + j = primos_size; |
| 63 | + break; |
| 64 | + } |
| 65 | + } |
| 66 | + if (j == primos_size) |
| 67 | + { |
| 68 | + primos_size++; |
| 69 | + primos_list[primos_size - 1] = i; |
| 70 | + } |
| 71 | + } |
| 72 | + primos_list[primos_size] = 0; |
| 73 | +} |
| 74 | + |
| 75 | +int primos_isprimo(int i) // retorna se um número está na lista de primos ou não |
| 76 | +{ |
| 77 | + int *p = primos_list; |
| 78 | + if (i < 2) |
| 79 | + return 0; |
| 80 | + while (*p && *p < i) |
| 81 | + p++; |
| 82 | + if (*p > i || *p == 0) |
| 83 | + return 0; |
| 84 | + return 1; |
| 85 | +} |
| 86 | + |
| 87 | +char *processar_maiorprimo_r(char *in_end, int k) // processo recursivo para achar a maior sequencia de primos possível |
| 88 | +{ |
| 89 | + char *max = in_end, *resp = NULL; |
| 90 | + |
| 91 | + for (; k < lista_size - 1; k++) |
| 92 | + { |
| 93 | + if ((in_end + 1) < lista[k].start) // como está em ordem de início, se o início ficou mais alto que o final procurado, não existe mais sequencia |
| 94 | + break; |
| 95 | + if ((in_end + 1) == lista[k].start) // se o início é igual ao final, aumenta a sequencia para verificar |
| 96 | + { |
| 97 | + resp = processar_maiorprimo_r(lista[k].end, k + 1); |
| 98 | + if (max < resp) |
| 99 | + max = resp; |
| 100 | + } |
| 101 | + } |
| 102 | + return max; |
| 103 | +} |
| 104 | + |
| 105 | +void processar_maiorprimo() // analise das recursões |
| 106 | +{ |
| 107 | + char *resp = NULL; |
| 108 | + |
| 109 | + for (int k = 0; k < lista_size - 1; k++) |
| 110 | + { |
| 111 | + resp = processar_maiorprimo_r(lista[k].end, k + 1); |
| 112 | + if ((maior.end - maior.start) < (resp - lista[k].start)) |
| 113 | + { |
| 114 | + maior.start = lista[k].start; |
| 115 | + maior.end = resp; |
| 116 | + } |
| 117 | + } |
| 118 | + |
| 119 | + // uso a primeira posição para anotar o resultado até agora e saber se ele tem continuidade |
| 120 | + // no próximo processamento |
| 121 | + lista[0].start = maior.start; |
| 122 | + lista[0].end = maior.end; |
| 123 | + lista_size = 1; |
| 124 | +} |
| 125 | +void processar_quicksort(int l, int r) //sort da array de primos pelo menor endereço de "start" |
| 126 | +{ |
| 127 | + pilist_t *v = &lista[r]; |
| 128 | + pilist_t tmp; |
| 129 | + int i = l - 1, j = r; |
| 130 | + if (r <= l) |
| 131 | + return; |
| 132 | + while (1) |
| 133 | + { |
| 134 | + while (lista[++i].start < v->start) |
| 135 | + ; |
| 136 | + while (v->start < lista[--j].start) |
| 137 | + { |
| 138 | + if (j == l) |
| 139 | + break; |
| 140 | + } |
| 141 | + if (i >= j) |
| 142 | + break; |
| 143 | + memcpy(&tmp, &lista[i], sizeof(pilist_t)); |
| 144 | + memcpy(&lista[i], &lista[j], sizeof(pilist_t)); |
| 145 | + memcpy(&lista[j], &tmp, sizeof(pilist_t)); |
| 146 | + } |
| 147 | + memcpy(&tmp, &lista[i], sizeof(pilist_t)); |
| 148 | + memcpy(&lista[i], &lista[r], sizeof(pilist_t)); |
| 149 | + memcpy(&lista[r], &tmp, sizeof(pilist_t)); |
| 150 | + |
| 151 | + processar_quicksort(l, i - 1); |
| 152 | + processar_quicksort(i + 1, r); |
| 153 | +} |
| 154 | + |
| 155 | +void processar() // ler o arquivo de PI, separar os primos e chamar as funcoes que calculam as sequencias |
| 156 | +{ |
| 157 | + char s1[2] = {0, 0}, s2[3] = {0, 0, 0}, s3[4] = {0, 0, 0, 0}, s4[5] = {0, 0, 0, 0, 0}; |
| 158 | + char *p = buffer; |
| 159 | + |
| 160 | + lista = (pilist_t *)malloc(sizeof(pilist_t) * (ORGANIZE + 4)); |
| 161 | + if (!lista) |
| 162 | + { |
| 163 | + printf("Memória insuficiente para alocar a lista de números primos de PI\n"); |
| 164 | + free_all(); |
| 165 | + exit(1); |
| 166 | + } |
| 167 | + |
| 168 | + while (*p != '.') |
| 169 | + p++; |
| 170 | + p++; |
| 171 | + |
| 172 | + fprintf(stdout, "%03d%%", 0); |
| 173 | + while (*p) |
| 174 | + { |
| 175 | + s1[0] = *p; |
| 176 | + s2[0] = s2[1], s2[1] = *p; |
| 177 | + s3[0] = s3[1], s3[1] = s3[2], s3[2] = *p; |
| 178 | + s4[0] = s4[1], s4[1] = s4[2], s4[2] = s4[3], s4[3] = *p; |
| 179 | + |
| 180 | + if (primos_isprimo(atoi(s1))) // somente 1 char |
| 181 | + { |
| 182 | + lista[lista_size].end = p; |
| 183 | + lista[lista_size].start = p; |
| 184 | + lista_size++; |
| 185 | + } |
| 186 | + if (s2[0] && primos_isprimo(atoi(s2))) // somente 2 chars |
| 187 | + { |
| 188 | + lista[lista_size].end = p; |
| 189 | + lista[lista_size].start = p - 1; |
| 190 | + lista_size++; |
| 191 | + } |
| 192 | + if (s3[0] && primos_isprimo(atoi(s3))) // somente 3 chars |
| 193 | + { |
| 194 | + lista[lista_size].end = p; |
| 195 | + lista[lista_size].start = p - 2; |
| 196 | + lista_size++; |
| 197 | + } |
| 198 | + if (s4[0] && primos_isprimo(atoi(s4))) // somente 4 chars |
| 199 | + { |
| 200 | + lista[lista_size].end = p; |
| 201 | + lista[lista_size].start = p - 3; |
| 202 | + lista_size++; |
| 203 | + } |
| 204 | + if (ORGANIZE < lista_size) // a cada ORGANIZE primos na lista ele faz o processamento e apaga a lista |
| 205 | + { |
| 206 | + fprintf(stdout, "\b\b\b\b%03ld%%", ((p - buffer) / 10000)); // esperar sem saber o progresso cansa |
| 207 | + fflush(stdout); |
| 208 | + processar_quicksort(0, lista_size - 1); // sort da array |
| 209 | + processar_maiorprimo(); // processa a array |
| 210 | + } |
| 211 | + |
| 212 | + p++; |
| 213 | + } |
| 214 | + fprintf(stdout, "\b\b\b\b100%%"); |
| 215 | + processar_quicksort(0, lista_size - 1); |
| 216 | + processar_maiorprimo(); // caso ainda tenha algum número incluído na lista, processa antes de retornar |
| 217 | +} |
| 218 | + |
| 219 | +int main() |
| 220 | +{ |
| 221 | + FILE *fs = NULL; |
| 222 | + |
| 223 | + fs = fopen("pi-1M.txt", "r"); // abrir o arquivo e alocar na memória para processar |
| 224 | + if (!fs) |
| 225 | + { |
| 226 | + printf("Erro ao ler o arquivo\n"); |
| 227 | + exit(1); |
| 228 | + } |
| 229 | + fseek(fs, 0, SEEK_END); |
| 230 | + buffer_size = ftell(fs); |
| 231 | + fseek(fs, 0, SEEK_SET); |
| 232 | + buffer = (char *)malloc(sizeof(char) * (buffer_size + 1)); |
| 233 | + if (!buffer) |
| 234 | + { |
| 235 | + printf("Memória insuficiente para abrir o arquivo\n"); |
| 236 | + fclose(fs); |
| 237 | + free_all(); |
| 238 | + exit(1); |
| 239 | + } |
| 240 | + buffer_size = fread(buffer, 1, buffer_size, fs); |
| 241 | + if (buffer_size == 0) |
| 242 | + { |
| 243 | + printf("Erro ao ler o arquivo\n"); |
| 244 | + fclose(fs); |
| 245 | + free_all(); |
| 246 | + exit(1); |
| 247 | + } |
| 248 | + fclose(fs); |
| 249 | + |
| 250 | + primos_init(); |
| 251 | + processar(); |
| 252 | + |
| 253 | + *++maior.end = 0; // para mostrar entre maior inicio e maior fim eu sinalizo que a string acabou em maior.end+1 |
| 254 | + printf("\b\b\b\b%s\n", maior.start); |
| 255 | + |
| 256 | + free_all(); |
| 257 | + |
| 258 | + return 0; |
| 259 | +} |
0 commit comments