Percursos
/
Python
Python
/
Exercícios
/
Análise de SGF
Análise de SGF

Análise de SGF

Médio

Instruções

Analisar uma string no formato Smart Game Format.

O SGF é um formato padrão para guardar ficheiros de jogos de tabuleiro, em particular o Go.

O SGF é um formato bastante simples. Normalmente, um ficheiro SGF contém uma única árvore de nós, em que cada nó é uma lista de propriedades. A lista de propriedades contém pares chave-valor; cada chave só pode ocorrer uma vez, mas pode ter vários valores.

Neste exercício vais analisar uma string SGF e devolver uma estrutura em árvore de propriedades.

Um ficheiro SGF pode ter este aspeto:

(;FF[4]C[root]SZ[19];B[aa];W[ab])

Esta é uma árvore com três nós:

  • O nó de nível superior tem três propriedades: FF[4] (chave = "FF", valor = "4"), C[root] (chave = "C", valor = "root") e SZ[19] (chave = "SZ", valor = "19"). (FF indica a versão do SGF, C é um comentário e SZ é o tamanho do tabuleiro.)
    • O nó de nível superior tem um único filho, que tem uma única propriedade: B[aa]. (As pretas jogam no ponto codificado como "aa", que é o ponto 1-1).
      • O nó B[aa] tem um único filho, que tem uma única propriedade: W[ab].

Como podes imaginar, um ficheiro SGF contém muitos nós com um único filho, e é por isso que existe uma forma abreviada de o escrever.

O SGF pode codificar variações de jogo. Os jogadores de Go fazem muitos retrocessos nas suas análises (vamos experimentar isto, não funciona, vamos experimentar aquilo) e o SGF suporta variações de sequências de jogadas. Por exemplo:

(;FF[4](;B[aa];W[ab])(;B[dd];W[ee]))

Aqui, o nó raiz tem duas variações. A primeira (que, por convenção, indica o que foi realmente jogado) é aquela em que as pretas jogam em 1-1. As pretas receberam este ficheiro do seu professor, que lhes apontou uma jogada mais sensata no segundo filho do nó raiz: B[dd] (ponto 4-4, uma abertura muito comum para ocupar o canto).

Uma chave pode ter vários valores associados. Por exemplo:

(;FF[4];AB[aa][ab][ba])

Aqui, AB (add black) é usado para adicionar três pedras pretas ao tabuleiro.

Todos os valores das propriedades serão do tipo Text do SGF. Não precisas de implementar qualquer outro tipo de valor. Embora possas ler a documentação completa do tipo Text, em baixo tens um resumo dos pontos importantes:

  • As quebras de linha são removidas se aparecerem imediatamente a seguir a uma \, caso contrário mantêm-se como quebras de linha.
  • Todos os carateres de espaçamento exceto a quebra de linha são convertidos em espaços.
  • A \ é o caráter de escape. Qualquer caráter que não seja de espaçamento a seguir a \ é inserido tal como está. Qualquer caráter de espaçamento a seguir a \ segue as regras acima. Nota que o SGF não tem sequências de escape para carateres de espaçamento como \t ou \n.

Tem cuidado para não confundir:

  • A string tal como é representada num literal de string nos testes
  • A string que é passada ao analisador de SGF

As sequências de escape nos literais de string podem já ter sido processadas pelo analisador sintático da linguagem de programação antes de serem passadas ao analisador de SGF.

Existem mais algumas complexidades no SGF (e na análise em geral) que podes, na sua maioria, ignorar. Deves assumir que a entrada está codificada em UTF-8, que os testes não vão conter uma propriedade de charset, por isso não te preocupes com isso. Além disso, podes assumir que todas as quebras de linha são no estilo unix (\n, não haverá \r nem \r\n nos testes) e que não haverá espaçamento opcional entre propriedades, nós, etc. nos testes.

Mensagens de exceção

Por vezes, é necessário lançar uma exceção. Quando o fazes, deves incluir sempre uma mensagem de erro significativa para indicar qual é a origem do erro. Isto torna o teu código mais legível e ajuda imenso na depuração. Quando souberes que a origem do erro será de um determinado tipo, podes optar por lançar um dos tipos de erro incorporados, mas deves continuar a incluir uma mensagem significativa.

Este exercício em particular exige que uses a instrução raise para "lançar" um ValueError se a entrada não tiver delimitadores adequados, não estiver em maiúsculas, não formar uma árvore com nós ou não formar uma árvore de todo. Os testes só passam se lançares a exception com raise e incluíres uma mensagem com ela.

Para lançar um ValueError com uma mensagem, escreve a mensagem como argumento do tipo exception:

# if the tree properties as given do not have proper delimiters.
raise ValueError("properties without delimiter")

# if the tree properties as given are not all in uppercase.
raise ValueError("property must be in uppercase")

# if the input does not form a tree, or is empty.
raise ValueError("tree missing")

# if the input is a tree without any nodes.
raise ValueError("tree with no nodes")
Editar via GitHub A ligação abre numa nova janela ou separador
Python Exercism

Estás pronto para começar Análise de SGF?

Inscreve-te no Exercism para aprenderes e dominares Python com 17 conceitos146 exercícios, e mentoria humana real, tudo grátis.