diff --git a/.gitignore b/.gitignore index 0b30b8aa6846e4bbaf1cf6aef5e398df0d28946f..ce9f7b9cf56f2efb8f93836630bad4882a7dd875 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ tests/*.txt tests/*.png massif.out* *.out +!tests/tabuleiros.out diff --git a/Makefile b/Makefile index 7c05fe51a1b74208aa4d919384a1669fa8f09a20..1f81904340439593bd6b5c0d5c215cac003583e9 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -std=c99 -O2 -W -Wall -g +CFLAGS = -std=c99 -O2 -W -Wall -g .PHONY: all clean diff --git a/customTests/14x14-1.txt b/customTests/14x14-1.txt index 0aac78f0a329f41b712d3a88cd63a79246e00439..cfc40f26f8a283bacd024324e90b206314c980a1 100644 --- a/customTests/14x14-1.txt +++ b/customTests/14x14-1.txt @@ -1,15 +1,15 @@ 14 14 9 - 0 0 1 2 2 3 4 4 1 1 5 3 5 3 - 3 4 0 0 1 2 2 4 1 1 5 4 2 1 - 0 0 0 2 4 0 2 3 5 0 1 5 1 5 - 1 3 3 3 4 4 0 0 4 0 0 0 5 2 - 3 0 4 0 2 4 2 4 3 3 4 4 2 2 - 3 5 2 2 5 1 5 2 5 3 0 1 2 0 - 1 4 3 3 5 1 4 1 2 2 0 2 5 1 - 5 2 1 0 4 0 2 5 1 2 2 5 3 4 - 1 3 2 1 3 0 5 0 0 2 3 4 5 0 - 0 4 2 0 1 4 4 4 0 1 3 1 1 2 - 0 0 3 2 5 5 4 3 3 5 3 4 5 0 - 0 1 1 5 4 0 1 5 4 4 3 0 1 3 - 4 3 5 5 4 2 2 5 2 1 5 1 5 5 - 3 1 2 2 2 1 1 1 5 1 1 3 2 1 +1 1 2 3 3 4 5 5 2 2 6 4 6 4 +4 5 1 1 2 3 3 5 2 2 6 5 3 2 +1 1 1 3 5 1 3 4 6 1 2 6 2 6 +2 4 4 4 5 5 1 1 5 1 1 1 6 3 +4 1 5 1 3 5 3 5 4 4 5 5 3 3 +4 6 3 3 6 2 6 3 6 4 1 2 3 1 +2 5 4 4 6 2 5 2 3 3 1 3 6 2 +6 3 2 1 5 1 3 6 2 3 3 6 4 5 +2 4 3 2 4 1 6 1 1 3 4 5 6 1 +1 5 3 1 2 5 5 5 1 2 4 2 2 3 +1 1 4 3 6 6 5 4 4 6 4 5 6 1 +1 2 2 6 5 1 2 6 5 5 4 1 2 4 +5 4 6 6 5 3 3 6 3 2 6 2 6 6 +4 2 3 3 3 2 2 2 6 2 2 4 3 2 diff --git a/libs/grafo.c b/libs/grafo.c index 79bbc3a08078a4341690d250feec26c06e46c275..dd81194df53b12dd4d18ddefab71e0e5460d6013 100644 --- a/libs/grafo.c +++ b/libs/grafo.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include "grafo.h" #include "lista.h" +#include "filha.h" #include "vertice.h" #include "tabuleiro.h" #include <stdio.h> @@ -42,6 +43,9 @@ Floodfill(celula, vertice) */ void tabuleiroParaGrafo(Tblr t, Grafo g) { + g->x = t->x; + g->y = t->y; + g->cores = t->cores; //Para cada celula do tabuleiro for(int i=0; i < t->x; ++i) { for(int j=0; j < t->y; ++j) { @@ -127,8 +131,8 @@ void floodFill(Tblr t, Vertice v, int i, int j){ return; } -#include "filha.h" -void calculaAltura(Grafo g, Lista raiz) { +int calculaAltura(Grafo g, Lista raiz) { + int alturaMax = 0; for(No n = primeiroNoLista(g->vertices); n; n = getSucessorNo(n)) { Vertice v = (Vertice) getConteudo(n); v->altura = -1; @@ -151,10 +155,16 @@ void calculaAltura(Grafo g, Lista raiz) { Vertice filho = (Vertice) getConteudo(m); if(filho->altura == -1) { filho->altura = v->altura+1; + if(filho->altura > alturaMax) { + alturaMax = filho->altura; + } insereFilha(filho, fila); } } + free(n); } + destroiFilha(fila, NULL); + return alturaMax; } void destroiGrafo(Grafo g) { @@ -174,10 +184,10 @@ void grafoParaDot(Grafo g, Lista grupo, FILE* fp) { // Imprime o grafo for(No n = primeiroNoLista(g->vertices); n; n = getSucessorNo(n)) { Vertice pai = (Vertice) getConteudo(n); - fprintf(fp, "\t\"%p\" [label=\"cor=%d\npeso=%d\naltura=%d\"];\n", pai, pai->cor, pai->peso, pai->altura); + fprintf(fp, "\t\"%p\" [label=\"cor=%d\npeso=%d\nbonus=%d\naltura=%d\"];\n", pai, pai->cor, pai->peso, pai->bonus, pai->altura); for(No m = primeiroNoLista(pai->filhos); m; m = getSucessorNo(m)) { Vertice filho = (Vertice) getConteudo(m); - fprintf(fp, "\t\"%p\" [label=\"cor=%d\npeso=%d\naltura=%d\"];\n", filho, filho->cor, filho->peso, filho->altura); + fprintf(fp, "\t\"%p\" [label=\"cor=%d\npeso=%d\nbonus=%d\naltura=%d\"];\n", filho, filho->cor, filho->peso, filho->bonus, filho->altura); fprintf(fp, "\t\"%p\" -- \"%p\";\n", pai, filho); } } diff --git a/libs/grafo.h b/libs/grafo.h index 847f6f714f2b7230809ee8f1d7917671df975efd..189edbf4a01c8e2f636141a76793729d08a10dfd 100644 --- a/libs/grafo.h +++ b/libs/grafo.h @@ -4,6 +4,7 @@ #include <stdio.h> struct Grafo { + int x, y, cores; Lista vertices; }; @@ -19,7 +20,7 @@ void tabuleiroParaGrafo(Tblr t, Grafo g); void floodFill(Tblr t, Vertice v, int i, int j); -void calculaAltura(Grafo g, Lista raiz); +int calculaAltura(Grafo g, Lista raiz); void destroiGrafo(Grafo g); diff --git a/libs/jogador.c b/libs/jogador.c index 310b94ec628a36e711591cda8dec763f58945a9d..eb15333aa9f2e432a748509e12662811f6c2d13b 100644 --- a/libs/jogador.c +++ b/libs/jogador.c @@ -4,12 +4,13 @@ #include "jogador.h" #include "lista.h" #include "grafo.h" +#include <math.h> Lista Joga(Grafo g, Lista grupo){ Lista jogadas = constroiLista(); //TODO: A Logica toda do jogo vai ficar aqui int counter = 1; - do { + while(tamanhoLista(grupo) < tamanhoLista(g->vertices)) { // Pega os filhos do grupo Lista filhos = filhosGrupo(grupo); // Monta a árvore de busca: @@ -17,7 +18,17 @@ Lista Joga(Grafo g, Lista grupo){ // - FILHOS: Cores alcancáveis a partir da raiz // - NETOS: Cores alcançáveis a partir dos filhos que NÃO são alcançáveis a partir da raiz // Só é necessário para calcular o bônus de cada filho - Lista coresFilhos = agrupaCores(filhos); + int altura = calculaAltura(g, grupo); + // printf("\tJOGADA %d\n", counter); + Lista coresFilhos = agrupaCores(filhos, g, altura, tamanhoLista(g->vertices) - tamanhoLista(grupo)); + // printf("\tAltura da árvore: %d\n", altura); + // printf("\tNúmero de grupos: %d\n", tamanhoLista(g->vertices)); + // printf("\tNúmero de grupos não consumidos: %d\n", tamanhoLista(g->vertices) - tamanhoLista(grupo)); + // printf("\tTamanho coresFilhos %d\n", tamanhoLista(coresFilhos)); + // for(No n = primeiroNoLista(coresFilhos); n; n = getSucessorNo(n)) { + // Vertice v = (Vertice) getConteudo(n); + // printf("\t\tVértice - cor: %d, peso: %d, bonus: %d\n", v->cor, v->peso, v->bonus); + // } // Seleciona o melhor filho baseado em peso(filho) + bônus(filho) // (filho com a maior soma de filho e peso) // O bônus é calculado da seguinte forma: // - Soma o valor de cada neto (que não é alcançável pela raiz) @@ -31,12 +42,13 @@ Lista Joga(Grafo g, Lista grupo){ // TODO: tratar empates! if((v->bonus) > (maior->bonus)) { maior = v; - } else if(v->bonus == maior->bonus) { + } else if((v->bonus) == (maior->bonus)) { if(v->peso > maior->peso) { maior = v; } } } + // printf("\t\tCOR ESCOLHIDA: %d\n", maior->cor); insereLista(maior->cor, jogadas); // "Pinta o tablueiro" for(No n = primeiroNoLista(filhos); n; n = getSucessorNo(n)) { @@ -50,7 +62,7 @@ Lista Joga(Grafo g, Lista grupo){ // Limpa as coisas destroiLista(filhos, NULL); destroiLista(coresFilhos, destroiVertice); - + calculaAltura(g, grupo); // PARA DEBUG!! Imprime as últimas 10 jogadas em um arquivo char str[32]; @@ -61,7 +73,7 @@ Lista Joga(Grafo g, Lista grupo){ } fclose(debug); ++counter; - } while(tamanhoLista(grupo) < tamanhoLista(g->vertices)); + } return jogadas; } @@ -80,8 +92,17 @@ Lista filhosGrupo(Lista grupoPai) { return filhos; } -Lista agrupaCores(Lista filhos) { +// TODO: primeiro agrupa, DEPOIS calcula os bônus!!! +// Para calcular o bônus, agrupa os filhos de um grupo e aà calcula o bônus +// Ou seja, 2 ou mais vértices da MESMA COR que tenham o mesmo filho (repetição) +// só contarão UMA VEZ o bônus+peso daquele filho +Lista agrupaCores(Lista filhos, Grafo g, int altura, int naoConsumidos) { Lista agrupa = constroiLista(); + double max = 2*(g->x) + (sqrt(2*g->cores))*(g->x) + g->cores; + double min = (sqrt(g->cores - 1)*g->x/2) - (g->cores/2); + int profundidade = sqrt(max) * (sqrt(altura) / sqrt(min)) * (altura/sqrt(naoConsumidos)); + // printf("\t\tProfundidade: %d\n", profundidade); + // printf("\t\tRazão: %f\n", (altura/sqrt(naoConsumidos))); for(No n = primeiroNoLista(filhos); n; n = getSucessorNo(n)) { Vertice v = (Vertice) getConteudo(n); // Verifica se a cor já está na lista @@ -91,7 +112,7 @@ Lista agrupaCores(Lista filhos) { // Se está, soma o peso do vértice if(w->cor == v->cor) { w->peso += v->peso; - w->bonus += calculaBonus(v, filhos); + w->bonus += calculaBonus(v, filhos, profundidade); estaNaLista = true; } } @@ -100,22 +121,52 @@ Lista agrupaCores(Lista filhos) { Vertice w = criaVertice(); w->cor = v->cor; w->peso = v->peso; - w->bonus = calculaBonus(v, filhos); + w->bonus = calculaBonus(v, filhos, profundidade); insereLista(w, agrupa); } } + // Depois de agrupar, verifica se alguma cor vai chegar ao fim nesta jogada + for(No n = primeiroNoLista(agrupa); n; n = getSucessorNo(n)) { + Vertice v = (Vertice) getConteudo(n); + int somaCor = 0; + for(No m = primeiroNoLista(g->vertices); m; m = getSucessorNo(m)) { + Vertice w = (Vertice) getConteudo(m); + if(!w->grupo && w->cor == v->cor) { + somaCor += w->peso; + } + } + // Se a soma de todos os vértices que não pertencem ao grupo for igual + // ao peso do vértice agrupado, esta é a última jogada com aquela cor + if(v->peso == somaCor) { + v->bonus += 100; // Mais bonus para que essa cor seja a escolhida + } + } + return agrupa; } -int calculaBonus(Vertice v, Lista filhos) { +int calculaBonus(Vertice v, Lista filhos, int profundidade) { int bonus = 0; for(No n = primeiroNoLista(v->filhos); n; n = getSucessorNo(n)) { - Vertice filho = getConteudo(n); - // Se o filho não está na lsita filhos e não está no grupo de vértices já consumidos + Vertice filho = (Vertice) getConteudo(n); + // Se o filho não está na lista filhos e não está no grupo de vértices já consumidos if(!filho->grupo && !pertenceLista(filho, filhos)) { - bonus += filho->peso; + bonus += filho->peso + calculaBonusRec(filho, v, profundidade); + } + } + return v->bonus = bonus; +} + +int calculaBonusRec(Vertice v, Vertice pai, int profundidade) { + if(profundidade <= 0) return 0; + int bonus = 0; + for(No n = primeiroNoLista(v->filhos); n; n = getSucessorNo(n)) { + Vertice filho = (Vertice) getConteudo(n); + + if(!filho->grupo && !pertenceLista(filho, pai->filhos) && (filho->altura > v->altura)) { + bonus += filho->peso + calculaBonusRec(filho, v, profundidade-1); } } - return bonus; + return v->bonus = bonus; } diff --git a/libs/jogador.h b/libs/jogador.h index aba24f9d772994cd3c93ee51efde2dbfa1750d30..b3d0b3961b60c18878d16a33b156651cfa847bda 100644 --- a/libs/jogador.h +++ b/libs/jogador.h @@ -13,7 +13,7 @@ Lista Joga(Grafo g, Lista grupo); Lista filhosGrupo(Lista grupoPai); // Retorna uma lista de vértices com as cores e pesos agrupadas a partir de l -Lista agrupaCores(Lista filhos); +Lista agrupaCores(Lista filhos, Grafo g, int altura, int naoConsumidos); -int calculaBonus(Vertice v, Lista filhos); +int calculaBonus(Vertice v, Lista filhos, int profundidade); #endif diff --git a/tests/floodit_h1 b/tests/floodit_h1 new file mode 100755 index 0000000000000000000000000000000000000000..1bf1bb07d92475f1b8cdb825d5eca2382ee1a529 Binary files /dev/null and b/tests/floodit_h1 differ diff --git a/tests/floodit_h2 b/tests/floodit_h2 new file mode 100755 index 0000000000000000000000000000000000000000..8b18fcdbf8d7c9d330d4a627f4f2558d52eca984 Binary files /dev/null and b/tests/floodit_h2 differ diff --git a/tests/runTests.sh b/tests/runTests.sh index 46c5f05ff73d5f267ef650decc47f7329d70fe97..5dbf1752f271ba51e538e213ab0613d992ce5f04 100755 --- a/tests/runTests.sh +++ b/tests/runTests.sh @@ -1,13 +1,13 @@ #!/bin/bash # tempo máximo para executar, em milisegundos -tempo_max=10000 #10s +tempo_max=120000 #120s # tamanhos do tabuleiro -tams=(4 8 16 32 64 128) +tams=(2 3 4 8 16 32) # lista de cores -cores=(2 4 8 16) +cores=(4 8 10 16) #-- Cores do terminal RED='\033[0;31m' @@ -31,19 +31,33 @@ do echo "Número de cores: ${cor}" T_soma_cor=0 T_max_cor=0 - for j in $(seq 1 $i) + N_TESTES=500 + for j in $(seq 1 ${N_TESTES}) do - echo -ne "Tabuleiro com ${i} linhas e ${cor} cores: ${i}x${j} (T max: $(($T_max_cor/1000000000))." - printf "%03d" $(($T_max_cor/1000000)) + echo -ne "Tabuleiro ${i}x${i} com ${cor} cores: (${j}/${N_TESTES}) (T max: $(($T_max_cor/1000000000))." + printf "%03d" $(($T_max_cor/1000000%1000)) echo -ne ")"\\r semente=$RANDOM # echo "Usando semente: ${semente}" - ./test $i $j $cor $semente + ./test $i $i $cor $semente T_inicial=$(date +%s%N) - ../main < "/tmp/${semente}.in" > /dev/null + ../main < "/tmp/${semente}.in" > /tmp/resp.out T_gasto=$(($(date +%s%N) - $T_inicial)) T_soma_cor=$(($T_gasto + $T_soma_cor)) T_soma_total=$(($T_gasto + $T_soma_total)) + ./floodit_h1 < "/tmp/${semente}.in" > /tmp/h1.out + ./floodit_h2 < "/tmp/${semente}.in" > /tmp/h2.out + RESP=$(cat /tmp/resp.out | head -n1) + H1=$(cat /tmp/h1.out | head -n1) + H2=$(cat /tmp/h2.out | head -n1) + if [ $RESP -gt $H1 ]; then + echo -ne "${RED}HeurÃstica h1 fez tabuleiro ${i} ${i} ${cor} ${semente} em ${H1} e nós em ${RESP}${NC}\n" + echo "${i} ${i} ${cor} ${semente} (h1: ${H1})" >> tabuleiros.txt + fi + if [ $RESP -gt $H2 ]; then + echo -ne "${RED}HeurÃstica h2 fez tabuleiro ${i} ${i} ${cor} ${semente} em ${H2} e nós em ${RESP}${NC}\n" + echo "${i} ${i} ${cor} ${semente} (h2: ${H2})" >> tabuleiros.txt + fi # tempo em segundos S=$(($T_gasto/1000000000)) # tempo em milisegundos @@ -52,36 +66,39 @@ do if [ $T_max_cor -lt $T_gasto ]; then T_max_cor=$T_gasto fi - if (($M>$tempo_max)); then - echo -e "\n${RED}Tabuleiro ${i} ${j} ${cor} ${semente} levou mais de ${tempo_max} milisegundos: ${S}.${M}s${NC}" - echo "${i} ${j} ${cor} ${semente}" >> tabuleiros.txt - fi + # if (($M>$tempo_max)); then + # echo -e "\n${RED}Tabuleiro ${i} ${i} ${cor} ${semente} levou mais de ${tempo_max} milisegundos: ${S}.${M}s${NC}" + # echo "${i} ${i} ${cor} ${semente}" >> tabuleiros.txt + # fi rm "/tmp/${semente}.in" + rm "/tmp/resp.out" + rm "/tmp/h1.out" + rm "/tmp/h2.out" done - T_medio_cor=$(($T_soma_cor/$i)) + T_medio_cor=$(($T_soma_cor/${N_TESTES})) S_medio_cor=$(($T_medio_cor/1000000000)) M_medio_cor=$(($T_medio_cor/1000000)) echo -ne "\n${CYAN}Tempo médio com ${cor} cores: ${S_medio_cor}." - printf "%03d" ${M_medio_cor} + printf "%03d" $((${M_medio_cor}%1000)) echo -e "s (${T_medio_cor})${NC}\n" echo -e "${i}\t${cor}\t${M_medio_cor}" >> tempos.txt echo -e "${i}\t${cor}\t$(($T_max_cor/1000000))" >> piores.txt done - T_medio_total=$(( $T_soma_total/($i * ${#cores[*]}) )) + T_medio_total=$(( $T_soma_total/(${N_TESTES} * ${#cores[*]}) )) S_medio_total=$(($T_medio_total/1000000000)) M_medio_total=$(($T_medio_total/1000000)) echo -ne "${BLUE}Tempo médio com tamanho ${i}: ${S_medio_total}." - printf "%03d" ${M_medio_total} + printf "%03d" $((${M_medio_total}%1000)) echo -e "s (${T_medio_total})${NC}\n" echo -e "${i}\t${M_medio_total}" >> medias.txt done fs=$(cat tabuleiros.txt | wc -l) if [ ${fs} -gt "1" ]; then - echo -e "${RED}${fs} tabuleiro(s) passou(passaram) do tempo limite de ${tempo_max} milisegundos:${NC}" + echo -e "${RED}${fs} tabuleiro(s) perdeu(perderam) para outras heurÃsticas${NC}" cat tabuleiros.txt exit 1 else - echo -e "${GREEN}Nenhum tabuleiro passou do tempo limite de ${tempo_max} milisegundos${NC}" + echo -e "${GREEN}Nenhum tabuleiro perdeu para as outras heurÃsticas${NC}" exit 0 fi diff --git a/tests/tabuleiros.out b/tests/tabuleiros.out new file mode 100644 index 0000000000000000000000000000000000000000..8bc4f3389d9229ee6e187d2cd439f6cc4188d8a3 --- /dev/null +++ b/tests/tabuleiros.out @@ -0,0 +1,322 @@ +3 3 8 26909 (h1: 5) +3 3 8 26909 (h2: 5) +4 4 10 14295 (h2: 8) +4 4 10 15795 (h1: 10) +4 4 10 15795 (h2: 10) +4 4 10 20490 (h1: 10) +4 4 10 20490 (h2: 10) +4 4 10 29581 (h1: 9) +4 4 10 4049 (h1: 8) +4 4 10 4049 (h2: 8) +4 4 16 1235 (h1: 10) +4 4 4 13848 (h2: 6) +4 4 4 17004 (h1: 6) +4 4 4 23024 (h1: 6) +4 4 4 25453 (h2: 5) +4 4 4 2597 (h1: 6) +4 4 4 27649 (h1: 7) +4 4 4 27649 (h2: 7) +4 4 4 6629 (h1: 6) +4 4 4 6629 (h1: 6) +4 4 8 20898 (h1: 8) +4 4 8 22414 (h2: 8) +4 4 8 27865 (h1: 8) +4 4 8 6846 (h1: 8) +4 4 8 6846 (h2: 8) +4 4 8 934 (h1: 8) +4 4 8 934 (h2: 8) +4 4 8 9699 (h1: 9) +4 4 8 9699 (h2: 9) +8 8 10 19467 (h1: 21) +8 8 10 28993 (h2: 19) +8 8 10 7105 (h2: 20) +8 8 4 11513 (h2: 7) +8 8 4 12332 (h2: 9) +8 8 4 12593 (h2: 9) +8 8 4 13507 (h1: 9) +8 8 4 13507 (h2: 9) +8 8 4 15307 (h2: 8) +8 8 4 15554 (h2: 11) +8 8 4 15903 (h2: 8) +8 8 4 17156 (h1: 9) +8 8 4 17203 (h2: 8) +8 8 4 17614 (h1: 10) +8 8 4 17614 (h2: 10) +8 8 4 19677 (h1: 7) +8 8 4 20183 (h2: 10) +8 8 4 21208 (h2: 8) +8 8 4 21352 (h1: 10) +8 8 4 21352 (h2: 10) +8 8 4 21946 (h1: 11) +8 8 4 21946 (h2: 11) +8 8 4 22652 (h1: 10) +8 8 4 22791 (h2: 9) +8 8 4 22893 (h2: 9) +8 8 4 25309 (h2: 7) +8 8 4 26112 (h2: 10) +8 8 4 30518 (h2: 8) +8 8 4 3970 (h1: 12) +8 8 4 496 (h2: 9) +8 8 4 5020 (h1: 8) +8 8 4 5427 (h1: 9) +8 8 4 5427 (h2: 9) +8 8 4 74 (h2: 9) +8 8 4 8073 (h1: 10) +8 8 4 853 (h1: 8) +8 8 4 9982 (h2: 9) +8 8 8 1111 (h2: 19) +8 8 8 11191 (h2: 17) +8 8 8 15190 (h1: 15) +8 8 8 15820 (h2: 17) +8 8 8 20926 (h2: 13) +8 8 8 5956 (h2: 15) +8 8 8 8458 (h2: 17) +16 16 4 12080 (h2: 15) +16 16 4 17382 (h2: 18) +16 16 4 19519 (h2: 18) +16 16 4 20629 (h2: 14) +16 16 4 22277 (h2: 17) +16 16 4 23645 (h2: 16) +16 16 4 24852 (h2: 16) +16 16 4 28245 (h2: 17) +16 16 4 3916 (h2: 18) +16 16 4 5514 (h2: 16) +16 16 8 1142 (h2: 29) +16 16 8 18339 (h2: 34) +16 16 8 7218 (h2: 35) +32 32 4 6052 (h2: 30) +3 3 4 20010 (h1: 4) +3 3 4 20010 (h2: 4) +3 3 4 5987 (h1: 5) +3 3 4 5987 (h2: 5) +3 3 8 20411 (h1: 4) +4 4 10 13182 (h1: 8) +4 4 10 15113 (h1: 8) +4 4 10 15113 (h2: 8) +4 4 10 17622 (h1: 9) +4 4 10 17622 (h2: 9) +4 4 10 26074 (h1: 9) +4 4 10 26074 (h2: 9) +4 4 10 29580 (h1: 10) +4 4 10 29580 (h2: 10) +4 4 10 30396 (h1: 9) +4 4 10 30396 (h2: 9) +4 4 10 4203 (h1: 10) +4 4 10 4203 (h2: 10) +4 4 16 4021 (h1: 10) +4 4 16 4021 (h2: 10) +4 4 4 12924 (h1: 5) +4 4 4 19886 (h2: 5) +4 4 4 25409 (h1: 5) +4 4 4 25409 (h2: 5) +4 4 4 25453 (h2: 5) +4 4 4 27649 (h1: 7) +4 4 4 27649 (h2: 7) +4 4 4 4016 (h1: 6) +4 4 4 4016 (h2: 6) +4 4 4 8294 (h2: 5) +4 4 4 8672 (h1: 5) +4 4 4 8672 (h2: 5) +4 4 8 22013 (h1: 9) +4 4 8 7793 (h1: 8) +4 4 8 7793 (h2: 8) +8 8 10 15701 (h1: 20) +8 8 10 19677 (h2: 18) +8 8 10 21121 (h2: 20) +8 8 10 25173 (h2: 18) +8 8 10 25636 (h2: 19) +8 8 10 28473 (h2: 20) +8 8 10 31628 (h2: 18) +8 8 10 5599 (h2: 17) +8 8 16 14392 (h2: 24) +8 8 16 25031 (h2: 24) +8 8 16 2700 (h2: 23) +8 8 16 27020 (h2: 23) +8 8 4 10041 (h1: 10) +8 8 4 1093 (h1: 9) +8 8 4 11071 (h2: 10) +8 8 4 11355 (h1: 10) +8 8 4 11355 (h2: 10) +8 8 4 12332 (h2: 9) +8 8 4 12400 (h1: 10) +8 8 4 13881 (h2: 9) +8 8 4 13936 (h2: 8) +8 8 4 15605 (h1: 9) +8 8 4 15605 (h2: 9) +8 8 4 16964 (h1: 9) +8 8 4 20245 (h1: 7) +8 8 4 20245 (h2: 7) +8 8 4 2025 (h1: 9) +8 8 4 2025 (h2: 9) +8 8 4 21823 (h2: 10) +8 8 4 21975 (h2: 7) +8 8 4 22199 (h1: 8) +8 8 4 22199 (h2: 8) +8 8 4 22366 (h1: 9) +8 8 4 23926 (h1: 7) +8 8 4 24376 (h2: 8) +8 8 4 26014 (h2: 8) +8 8 4 2639 (h1: 10) +8 8 4 26762 (h2: 8) +8 8 4 28291 (h2: 9) +8 8 4 30577 (h2: 11) +8 8 4 30613 (h2: 9) +8 8 4 30711 (h2: 10) +8 8 4 3085 (h2: 10) +8 8 4 31339 (h1: 8) +8 8 4 31339 (h2: 8) +8 8 4 3320 (h2: 10) +8 8 4 3559 (h2: 10) +8 8 4 4900 (h2: 8) +8 8 4 4986 (h1: 8) +8 8 4 4986 (h1: 8) +8 8 4 5030 (h2: 8) +8 8 4 5949 (h2: 8) +8 8 4 5988 (h1: 10) +8 8 4 6183 (h1: 10) +8 8 4 829 (h2: 8) +8 8 4 8665 (h1: 10) +8 8 8 14824 (h2: 15) +8 8 8 1489 (h2: 16) +8 8 8 15610 (h2: 14) +8 8 8 20262 (h2: 19) +8 8 8 23461 (h1: 17) +8 8 8 23461 (h2: 17) +8 8 8 28248 (h1: 16) +8 8 8 29853 (h1: 17) +8 8 8 31307 (h2: 15) +8 8 8 31586 (h2: 15) +8 8 8 6033 (h2: 16) +8 8 8 632 (h2: 17) +16 16 4 1199 (h2: 17) +16 16 4 12747 (h2: 19) +16 16 4 16762 (h2: 16) +16 16 4 17784 (h2: 18) +16 16 4 20739 (h2: 16) +16 16 4 25688 (h2: 18) +16 16 4 29043 (h2: 17) +16 16 4 3595 (h2: 19) +16 16 4 4552 (h2: 20) +16 16 4 8715 (h2: 17) +16 16 8 2925 (h2: 29) +3 3 4 30001 (h1: 4) +3 3 4 30001 (h2: 4) +3 3 8 12831 (h1: 5) +3 3 8 12831 (h2: 5) +3 3 8 12891 (h1: 4) +3 3 8 7096 (h1: 5) +3 3 8 7096 (h2: 5) +4 4 10 11135 (h1: 7) +4 4 10 11135 (h2: 7) +4 4 10 11196 (h1: 9) +4 4 10 11196 (h2: 9) +4 4 10 18982 (h1: 10) +4 4 10 18982 (h2: 10) +4 4 10 21895 (h1: 8) +4 4 10 26585 (h1: 10) +4 4 10 26585 (h2: 10) +4 4 10 27139 (h1: 8) +4 4 10 27139 (h2: 8) +4 4 10 27793 (h2: 9) +4 4 16 15048 (h1: 10) +4 4 16 15048 (h2: 10) +4 4 16 21518 (h1: 10) +4 4 16 21518 (h2: 10) +4 4 16 27610 (h1: 10) +4 4 16 27610 (h2: 10) +4 4 4 1089 (h2: 6) +4 4 4 1293 (h2: 5) +4 4 4 19021 (h1: 6) +4 4 4 22962 (h1: 5) +4 4 4 27765 (h1: 5) +4 4 4 2845 (h1: 6) +4 4 4 2845 (h2: 6) +4 4 4 5744 (h1: 5) +4 4 4 5744 (h2: 5) +4 4 4 7524 (h1: 5) +4 4 8 1420 (h1: 9) +4 4 8 1420 (h2: 9) +4 4 8 16874 (h2: 7) +4 4 8 25928 (h1: 7) +4 4 8 25928 (h2: 7) +4 4 8 3722 (h1: 9) +4 4 8 3722 (h2: 9) +4 4 8 8603 (h1: 9) +4 4 8 8603 (h2: 9) +8 8 10 10192 (h2: 18) +8 8 10 17877 (h1: 20) +8 8 10 23653 (h2: 20) +8 8 10 23660 (h1: 19) +8 8 10 23660 (h2: 19) +8 8 10 27684 (h2: 22) +8 8 10 5660 (h2: 18) +8 8 16 15390 (h2: 22) +8 8 16 18644 (h2: 24) +8 8 4 1044 (h2: 9) +8 8 4 11514 (h2: 10) +8 8 4 1276 (h2: 10) +8 8 4 12898 (h1: 10) +8 8 4 12898 (h2: 10) +8 8 4 1488 (h1: 9) +8 8 4 15559 (h1: 10) +8 8 4 15559 (h2: 10) +8 8 4 16082 (h2: 10) +8 8 4 17637 (h2: 9) +8 8 4 20457 (h2: 8) +8 8 4 21566 (h2: 11) +8 8 4 22549 (h2: 10) +8 8 4 25045 (h2: 9) +8 8 4 27315 (h2: 10) +8 8 4 27654 (h1: 10) +8 8 4 27654 (h2: 10) +8 8 4 27719 (h1: 8) +8 8 4 27719 (h2: 8) +8 8 4 27919 (h1: 11) +8 8 4 27919 (h2: 11) +8 8 4 28078 (h2: 10) +8 8 4 28536 (h1: 7) +8 8 4 28567 (h2: 8) +8 8 4 29660 (h2: 8) +8 8 4 30049 (h2: 8) +8 8 4 30239 (h1: 9) +8 8 4 31396 (h2: 10) +8 8 4 3259 (h1: 11) +8 8 4 3259 (h2: 10) +8 8 4 3360 (h1: 10) +8 8 4 3360 (h2: 10) +8 8 4 3612 (h2: 10) +8 8 4 7576 (h2: 11) +8 8 4 914 (h2: 8) +8 8 8 10087 (h1: 17) +8 8 8 10087 (h2: 17) +8 8 8 16149 (h2: 18) +8 8 8 18904 (h2: 18) +8 8 8 19447 (h2: 16) +8 8 8 22319 (h2: 18) +8 8 8 23399 (h2: 15) +8 8 8 25477 (h2: 16) +8 8 8 26199 (h2: 16) +8 8 8 26728 (h2: 16) +8 8 8 28639 (h2: 16) +8 8 8 29967 (h2: 18) +8 8 8 5152 (h2: 16) +8 8 8 6808 (h2: 19) +8 8 8 8012 (h1: 16) +8 8 8 8375 (h2: 17) +16 16 4 14252 (h2: 16) +16 16 4 14293 (h2: 17) +16 16 4 15621 (h1: 17) +16 16 4 15621 (h2: 16) +16 16 4 16716 (h2: 15) +16 16 4 17018 (h2: 17) +16 16 4 18172 (h2: 15) +16 16 4 20105 (h2: 16) +16 16 4 22607 (h2: 16) +16 16 4 25922 (h2: 18) +16 16 4 26202 (h2: 16) +16 16 4 27227 (h2: 17) +16 16 4 28222 (h2: 16) +16 16 4 31677 (h2: 17) +16 16 4 32428 (h2: 16) +16 16 4 5418 (h2: 17) +32 32 4 5482 (h2: 34)