Eu estava interessado em ver as respostas para essa pergunta (agora extinta) , mas ela nunca foi corrigida / aprimorada.
Dado um conjunto de dados Boggle de 6 lados (configuração roubada desta pergunta ), determine em dois minutos de tempo de processamento qual configuração do cartão permitirá a maior pontuação possível. (ou seja, quais dados em qual local com qual lado para cima permite o maior pool de palavras com pontuação?)
OBJETIVO
Seu código deve ser executado por não mais de 2 minutos (120 segundos). Nesse momento, ele deve parar automaticamente de executar e imprimir os resultados.
A pontuação final do desafio será a pontuação média do Boggle de 5 execuções do programa.
- Em caso de empate, o vencedor será o algoritmo que encontrou mais palavras.
- Caso ainda haja um empate, o vencedor será o algoritmo que encontrar mais palavras longas (8 ou mais) .
REGRAS / RESTRIÇÕES
Este é um desafio de código; o comprimento do código é irrelevante.
Consulte este link para obter uma lista de palavras (lista de uso
ISPELL "english.0"
- a lista SCOWL está faltando algumas palavras bastante comuns).- Esta listagem pode ser consultada / importada / lida no seu código da maneira que você desejar.
- Somente palavras correspondidas pelo regex
^([a-pr-z]|qu){3,16}$
serão contadas. (Somente letras minúsculas, de 3 a 16 caracteres, qu devem ser usadas como uma unidade.)
As palavras são formadas vinculando letras adjacentes (horizontal, vertical e diagonal) para soletrar as palavras na ordem correta, sem usar um único dado mais de uma vez em uma única palavra.
- As palavras devem ter 3 letras ou mais; palavras mais curtas não ganharão pontos.
- Cartas duplicadas são aceitáveis, mas não dados.
- Palavras que ultrapassam as bordas / cruzam de um lado para o outro não são permitidas.
A pontuação final do Boggle ( sem desafio ) é o total dos valores em pontos para todas as palavras encontradas.
- O valor do ponto atribuído a cada palavra é baseado no comprimento da palavra. (ver abaixo)
- As regras normais do Boggle deduziriam / descontariam palavras encontradas por outro jogador. Suponha que nenhum outro jogador esteja envolvido e todas as palavras encontradas contam para a pontuação total.
- No entanto, palavras encontradas mais de uma vez na mesma grade devem ser contadas apenas uma vez.
Sua função / programa deve ENCONTRAR o arranjo ideal; simplesmente codificar uma lista predeterminada não funciona.
Sua saída deve ser uma grade 4x4 do seu tabuleiro ideal, uma lista de todas as palavras encontradas para esse tabuleiro e a pontuação do Boggle para corresponder a essas palavras.
MORRER CONFIGURAÇÃO
A A E E G N
E L R T T Y
A O O T T W
A B B J O O
E H R T V W
C I M O T U
D I S T T Y
E I O S S T
D E L R V Y
A C H O P S
H I M N Qu U
E E I N S U
E E G H N W
A F F K P S
H L N N R Z
D E I L R X
MESA DE PONTUAÇÃO PADRÃO
Word length => Points
<= 2 - 0 pts
3 - 1
4 - 1
5 - 2
6 - 3
7 - 5
>= 8 - 11 pts
*Words using the "Qu" die will count the full 2 letters for their word, not just the 1 die.
EXEMPLO DE SAÍDA
A L O J
V U T S
L C H E
G K R X
CUT
THE
LUCK
HEX
....
140 points
Se precisar de mais esclarecimentos, pergunte!
fonte
4527
(1414
total de palavras), encontrada aqui: ai.stanford.edu/~chuongdo/boggle/index.html^([a-pr-z]|qu){3,16}$
(que excluiria incorretamente palavras de três letras com qu, mas não há nenhuma).Respostas:
C, com média de
500+15001750 pontosEste é um aprimoramento relativamente menor em relação à versão 2 (veja abaixo as notas nas versões anteriores). Existem duas partes. Primeiro: em vez de selecionar pranchas aleatoriamente da piscina, o programa agora repete todas as pranchas da piscina, usando cada uma delas antes de retornar ao topo da piscina e repetir. (Como o pool está sendo modificado enquanto essa iteração ocorre, ainda haverá placas escolhidas duas vezes seguidas, ou pior, mas isso não é uma preocupação séria.) A segunda alteração é que o programa agora rastreia quando o pool muda e se o programa demorar muito sem melhorar o conteúdo do pool, ele determina que a pesquisa "parou", esvazia o pool e inicia novamente com uma nova pesquisa. Ele continua fazendo isso até que os dois minutos terminem.
Inicialmente, pensei que estaria empregando algum tipo de pesquisa heurística para ir além da faixa de 1500 pontos. O comentário de @ mellamokb sobre um quadro de 4527 pontos me levou a supor que havia muito espaço para melhorias. No entanto, estamos usando uma lista de palavras relativamente pequena. O quadro de 4527 pontos estava usando o YAWL, que é a lista de palavras mais inclusiva do mercado - é ainda maior que a lista de palavras oficial do Scrabble dos EUA. Com isso em mente, examinei novamente as placas que meu programa havia encontrado e notei que parecia haver um conjunto limitado de placas acima de 1700. Por exemplo, eu tive várias execuções que descobriram uma placa com a pontuação de 1726, mas sempre foi exatamente a mesma placa que foi encontrada (ignorando rotações e reflexões).
Como outro teste, executei meu programa usando YAWL como dicionário e ele encontrou o quadro de 4527 pontos após cerca de uma dúzia de execuções. Diante disso, suponho que meu programa já esteja no limite superior do espaço de pesquisa e, portanto, a reescrita que eu estava planejando introduziria complexidade extra com muito pouco ganho.
Aqui está minha lista dos cinco quadros com maior pontuação que meu programa encontrou usando a lista de
english.0
palavras:Minha crença é que o "quadro grep" de 1772 (como passei a chamá-lo), com 531 palavras, é o quadro com a maior pontuação possível com esta lista de palavras. Mais de 50% das execuções de dois minutos do meu programa terminam com este quadro. Também deixei meu programa em execução durante a noite sem encontrar nada melhor. Portanto, se houver um quadro de pontuação mais alta, é provável que ele tenha algum aspecto que derrote a técnica de pesquisa do programa. Um quadro em que todas as pequenas alterações possíveis no layout causam uma enorme queda na pontuação total, por exemplo, nunca podem ser descobertas pelo meu programa. Meu palpite é que é improvável que exista tal placa.
Notas para a versão 2 (9 de junho)
Aqui está uma maneira de usar a versão inicial do meu código como um ponto de partida. As alterações nesta versão consistem em menos de 100 linhas, mas triplicaram a pontuação média do jogo.
Nesta versão, o programa mantém um "pool" de candidatos, composto pelos N quadros de maior pontuação que o programa gerou até o momento. Toda vez que um novo quadro é gerado, ele é adicionado ao pool e o quadro de menor pontuação do pool é removido (que pode muito bem ser o quadro que acabou de ser adicionado, se sua pontuação for menor do que o que já existe). O pool é preenchido inicialmente com painéis gerados aleatoriamente, após o qual mantém um tamanho constante durante toda a execução do programa.
O loop principal do programa consiste em selecionar um tabuleiro aleatório do pool e alterá-lo, determinar a pontuação desse novo tabuleiro e colocá-lo no pool (se tiver uma pontuação suficiente). Dessa maneira, o programa aprimora continuamente as placas de alta pontuação. A principal atividade é fazer melhorias incrementais passo a passo, mas o tamanho do pool também permite que o programa encontre aprimoramentos em várias etapas que pioram temporariamente a pontuação de um conselho antes que ele possa melhorar.
Normalmente, este programa encontra um bom máximo local rapidamente, após o que, presumivelmente, qualquer máximo melhor está muito distante para ser encontrado. E, mais uma vez, não faz sentido executar o programa por mais de 10 segundos. Isso pode ser melhorado, por exemplo, com o programa detectando essa situação e iniciando uma nova pesquisa com um novo pool de candidatos. No entanto, isso representaria apenas um aumento marginal. Uma técnica de pesquisa heurística adequada provavelmente seria uma avenida melhor de exploração.
(Nota: vi que esta versão estava gerando cerca de 5k placas / s. Como a primeira versão normalmente produzia 20k placas / s, fiquei inicialmente preocupado. Após a criação de perfis, no entanto, descobri que o tempo extra era gasto gerenciando a lista de palavras. Em outras palavras, isso se deveu inteiramente ao fato de o programa ter encontrado muito mais palavras por painel.Em vista disso, considerei mudar o código para gerenciar a lista de palavras, mas, como esse programa está usando apenas 10 dos 120 segundos alocados, uma otimização seria muito prematura.)
Notas para a versão 1 (2 de junho)
Esta é uma solução muito, muito simples. Tudo isso gera placas aleatórias e, depois de 10 segundos, produz aquela com a maior pontuação. (O padrão foi 10 segundos porque os 110 segundos extras permitidos pela especificação do problema geralmente não melhoram a solução final encontrada o suficiente para valer a pena esperar.) Portanto, é extremamente idiota. No entanto, ele possui toda a infraestrutura para constituir um bom ponto de partida para uma pesquisa mais inteligente e, se alguém desejar utilizá-la antes do prazo final, incentivo-os a fazê-lo.
O programa começa lendo o dicionário em uma estrutura em árvore. (O formulário não é tão otimizado quanto poderia ser, mas é mais do que suficiente para esses fins.) Após algumas outras inicializações básicas, ele começa a gerar quadros e a classificá-los. O programa examina cerca de 20 mil placas por segundo na minha máquina e, após cerca de 200 mil placas, a abordagem aleatória começa a ficar seca.
Como apenas uma placa está realmente sendo avaliada a qualquer momento, os dados da pontuação são armazenados em variáveis globais. Isso me permite minimizar a quantidade de dados constantes que precisam ser passados como argumentos para as funções recursivas. (Tenho certeza de que isso dará algumas pessoas para as pessoas e peço desculpas.) A lista de palavras é armazenada como uma árvore de pesquisa binária. Todas as palavras encontradas devem ser pesquisadas na lista de palavras, para que palavras duplicadas não sejam contadas duas vezes. A lista de palavras é necessária apenas durante o processo de avaliação, no entanto, é descartada depois que a pontuação é encontrada. Assim, no final do programa, o painel escolhido deve ser pontuado novamente, para que a lista de palavras possa ser impressa.
Curiosidade: a pontuação média de um painel Boggle gerado aleatoriamente, conforme pontuado por
english.0
, é de 61,7 pontos.fonte
VBA (média atualmente variando de 80 a 110 pontos, inacabada)
Aqui está o meu processo de trabalho, mas está longe de ser o melhor possível; minha melhor pontuação absoluta encontrada em qualquer placa após muitas execuções de teste é de cerca de 120. Ainda precisa haver uma limpeza geral melhor e tenho certeza de que há mais eficiências a serem obtidas em vários locais.
Isso provavelmente parece horrível para alguns de vocês, mas como eu disse, WIP. Sou muito aberto a críticas construtivas ! Desculpe pelo corpo muito longo ...
Módulo de classe de dados :
Módulo de classe de árvore :
Módulo de classe TreeNode :
Módulo principal :
fonte
Visualização rápida do tamanho do espaço de pesquisa.
Reduzindo para excluir a repetição em cada dado.
@breadbox armazena o dicionário como uma verificação da Tabela Hash O (1).
EDITAR
Melhor Diretor (eu testemunhei até agora)
fonte
Minha entrada está aqui no Dream.In.Code ~ 30ms por uma pesquisa de placa (em uma máquina com 2 núcleos, deve ser mais rápida com mais núcleos)
fonte
:
nohttp://
. ;-).NET
aVBA
não é muito difícil.