Você está na página 1de 12

Projeto Final

Para a entrega do projeto Final, você deverá obrigatoriamente fazer a Tarefa 1. A


Tarefa 2 é opcional, você poderá sugerir outra tarefa no lugar dela (outro tipo de
implementação, a discutir com a professora).
Tarefa 1:
Você conhece o jogo do NIM? Nesse jogo, n peças são inicialmente dispostas numa
mesa ou tabuleiro. Dois jogadores jogam alternadamente, retirando pelo menos 1 e
no máximo m peças cada um. Quem tirar as últimas peças possíveis ganha o jogo.

Existe uma estratégia para ganhar o jogo que é muito simples: ela consiste em deixar
sempre múltiplos de (m+1) peças ao jogador oponente.

Objetivo

Você deverá escrever um programa na linguagem Python, versão 3, que permita a


uma "vítima" jogar o NIM contra o computador. O computador, é claro, deverá seguir
a estratégia vencedora descrita acima.

Sejam n o número de peças inicial e m o número máximo de peças que é possível


retirar em uma rodada. Para garantir que o computador ganhe sempre, é preciso
considerar os dois cenários possíveis para o início do jogo:

• Se n é múltiplo de (m+1), o computador deve ser "generoso" e convidar o


jogador a iniciar a partida com a frase "Você começa!"
• Caso contrário, o computador toma a iniciativa de começar o jogo, declarando
"Computador começa!"

Uma vez iniciado o jogo, a estratégia do computador para ganhar consiste em deixar
sempre um número de peças que seja múltiplo de (m+1) ao jogador. Caso isso não
seja possível, deverá tirar o número máximo de peças possíveis.

Seu trabalho, então, será implementar o Jogo e fazer com que o computador se utilize
da estratégia vencedora.

Seu Programa

Uma dúvida que pode surgir nesse momento é como modelar o jogo de forma que
possa ser implementado em Python 3 correspondendo rigorosamente às
especificações descritas até agora.

Para facilitar seu trabalho e permitir a correção automática do exercício, apresentado


a seguir um modelo, isto é, uma descrição em linhas gerais de um conjunto de funções
que resolve o problema proposto. Embora sejam possíveis outras abordagens, é
preciso atender exatamente o que está definido abaixo para que a correção
automática do trabalho funcione corretamente.

O programa deve implementar:

• Uma função computador_escolhe_jogada que recebe, como parâmetros, os


números n e m descritos acima e devolve um inteiro correspondente à próxima
jogada do computador (ou seja, quantas peças o computador deve retirar do
tabuleiro) de acordo com a estratégia vencedora.
• Uma função usuario_escolhe_jogada que recebe os mesmos parâmetros,
solicita que o jogador informe sua jogada e verifica se o valor informado é
válido. Se o valor informado for válido, a função deve devolvê-lo; caso contrário,
deve solicitar novamente ao usuário que informe uma jogada válida.
• Uma função partida que não recebe nenhum parâmetro, solicita ao usuário
que informe os valores de n e m e inicia o jogo, alternando entre jogadas do
computador e do usuário (ou seja, chamadas às duas funções anteriores). A
escolha da jogada inicial deve ser feita em função da estratégia vencedora,
como dito anteriormente. A cada jogada, deve ser impresso na tela o estado
atual do jogo, ou seja, quantas peças foram removidas na última jogada e
quantas restam na mesa. Quando a última peça é removida, essa função
imprime na tela a mensagem "O computador ganhou!" ou "Você ganhou!"
conforme o caso.

Observe que, para isso funcionar, seu programa deve sempre "lembrar" qual é o
número de peças atualmente no tabuleiro e qual é o máximo de peças a retirar em
cada jogada.

Cuidado: o corretor automático não funciona bem se você tiver alguma chamada a
input() antes da definição de todas as funções do jogo (a menos que essa chamada
esteja dentro de uma função). Se seu programa usar input() sem que ele esteja dentro
de alguma função, coloque-o no final do programa.

Campeonatos

Como todos sabemos, uma única rodada de um jogo não é suficiente para definir
quem é o melhor jogador. Assim, uma vez que a função partida esteja funcionando,
você deverá criar uma outra função chamada campeonato. Essa nova função deve
realizar três partidas seguidas do jogo e, ao final, mostrar o placar dessas três partidas
e indicar o vencedor do campeonato. O placar deve ser impresso na forma

Placar: Você ??? X ??? Computador


Execução
Dado que é possível jogar partidas individuais ou campeonatos, seu programa deve
começar solicitando ao usuário que escolha se prefere jogar apenas uma partida
(opção 1) ou um campeonato (opção 2).

Atenção: o corretor automático vai verificar se você está utilizando exatamente as


mensagens pedidas, como "Você começa!", "O computador ganhou!" etc. Deixe para
usar a sua criatividade em outros lugares!

Veja um exemplo de como deve funcionar o jogo:


$ > python3 jogo_nim.py

Bem-vindo ao jogo do NIM! Escolha:

1 - para jogar uma partida isolada


2 - para jogar um campeonato 2

Voce escolheu um campeonato!

**** Rodada 1 ****

Quantas peças? 3
Limite de peças por jogada? 1

Computador começa!

O computador tirou uma peça.


Agora restam 2 peças no tabuleiro.

Quantas peças você vai tirar? 2

Oops! Jogada inválida! Tente de novo.


Quantas peças você vai tirar? 1

Você tirou uma peça.


Agora resta apenas uma peça no tabuleiro.

O computador tirou uma peça.


Fim do jogo! O computador ganhou!

**** Rodada 2 ****

Quantas peças? 3
Limite de peças por jogada? 2

Voce começa!

Quantas peças você vai tirar? 2


Voce tirou 2 peças.
Agora resta apenas uma peça no tabuleiro.

O computador tirou uma peça.


Fim do jogo! O computador ganhou!

**** Rodada 3 ****

Quantas peças? 4
Limite de peças por jogada? 3

Voce começa!
Quantas peças você vai tirar? 2
Voce tirou 2 peças.
Agora restam 2 peças no tabuleiro.

O computador tirou 2 peças.


Fim do jogo! O computador ganhou!

**** Final do campeonato! ****

Placar: Você 0 X 3 Computador

Tarefa 2:
Prólogo
Nesta parte do projeto, iremos praticar não só o que vimos até agora na disciplina,
mas também outra habilidade importante de um programador: utilizar e interagir com
código escrito por terceiros. Aqui, você não irá implementar o seu programa do zero.
Você irá partir de um programa já iniciado e irá completá-lo. Na verdade, esse é o
caso mais comum na indústria de software, onde muitos desenvolvedores trabalham
colaborativamente em um mesmo programa.

Introdução

Manuel Estandarte é monitor na disciplina Introdução à Produção Textual I na


Universidade de Pasárgada (UPA). Durante o período letivo, Manuel descobriu que
uma epidemia de COH-PIAH estava se espalhando pela UPA. Essa doença rara e
altamente contagiosa faz com que indivíduos contaminados produzam,
involuntariamente, textos muito semelhantes aos de outras pessoas. Após a entrega
da primeira redação, Manuel desconfiou que alguns alunos estavam sofrendo de
COH-PIAH. Manuel, preocupado com a saúde da turma, resolveu buscar um método
para identificar os casos de COH-PIAH. Para isso, ele necessita da sua ajuda para
desenvolver um programa que o auxilie a identificar os alunos contaminados.

Detecção de autoria

Diferentes pessoas possuem diferentes estilos de escrita; por exemplo, algumas


pessoas preferem sentenças mais curtas, outras preferem sentenças mais longas.
Utilizando diversas estatísticas do texto, é possível identificar aspectos que funcionam
como uma “assinatura” do seu autor e, portanto, é possível detectar se dois textos
dados foram escritos por uma mesma pessoa. Ou seja, essa “assinatura” pode ser
utilizada para detecção de plágio, evidência forense ou, neste caso, para diagnosticar
a grave doença COH-PIAH.

Traços linguísticos

Neste exercício utilizaremos as seguintes estatísticas para detectar a doença:

• Tamanho médio de palavra: Média simples do número de caracteres por


palavra.
• Relação Type-Token: Número de palavras diferentes utilizadas em um texto
divididas pelo total de palavras.
• Razão Hapax Legomana: Número de palavras utilizadas uma única vez dividido
pelo número total de palavras.
• Tamanho médio de sentença: Média simples do número de caracteres por
sentença.
• Complexidade de sentença: Média simples do número de frases por sentença.
• Tamanho médio de frase: Média simples do número de caracteres por frase.

Funcionamento do programa

A partir da assinatura conhecida de um portador de COH-PIAH, seu programa deverá


receber diversos textos e calcular os valores dos diferentes traços linguísticos desses
textos para compará-los com a assinatura dada. Os traços linguísticos que seu
programa deve utilizar são calculados da seguinte forma:

• Tamanho médio de palavra é a soma dos tamanhos das palavras dividida pelo
número total de palavras.
• Relação Type-Token é o número de palavras diferentes dividido pelo número
total de palavras. Por exemplo, na frase "O gato caçava o rato", temos 5 palavras no
total (o, gato, caçava, o, rato) mas somente 4 diferentes (o, gato, caçava, rato). Nessa
frase, a relação Type-Token vale 4/5 = 0.8.
• Razão Hapax Legomana é o número de palavras que aparecem uma única vez
dividido pelo total de palavras. Por exemplo, na frase "O gato caçava o rato", temos
5 palavras no total (o, gato, caçava, o, rato) mas somente 3 que aparecem só uma
vez (gato, caçava, rato). Nessa frase, a relação Hapax Legomana vale 3/5 = 0.6.
• Tamanho médio de sentença é a soma dos números de caracteres em todas as
sentenças dividida pelo número de sentenças (os caracteres que separam uma
sentença da outra não devem ser contabilizados como parte da sentença).
• Complexidade de sentença é o número total de frases divido pelo número de
sentenças.
• Tamanho médio de frase é a soma do número de caracteres em cada frase dividida
pelo número de frases no texto (os caracteres que separam uma frase da outra não
devem ser contabilizados como parte da frase).

Após calcular esses valores para cada texto, você deve compará-los com a assinatura
fornecida para os infectados por COH-PIAH. O grau de similaridade entre dois textos, a e b,
é dado pela fórmula:

Em que:

• Sab é o grau de similaridade entre os textos a e b;


• fi, a é o valor de cada traço linguístico i no texto a ; e
• fi, b é o valor de cada traço linguístico i no texto b .

No nosso caso, o texto b não é conhecido, mas temos a assinatura correspondente: a


assinatura de um aluno infectado com COH-PIAH. Ou seja, sabemos o valor de fi, b que é
dado como valor de entrada do programa.

Caso você não esteja acostumado com a notação matemática, podemos destrinchar essa
fórmula da seguinte maneira:

Para cada traço linguístico i (tamanho médio da palavra, relação type-token etc.) se quer a
diferença entre o valor obtido em cada texto dado (a) e o valor típico do texto de uma
pessoa infectada (b): fi,a - fi,b

Dessa diferença se toma o módulo (∣∣…∣∣), use a função abs do python.

Somamos os resultados dos 6 traços linguísticos

E por final dividimos por 6 (x/6 )

Perceba que quanto mais similares a e b forem, menor Sab será. Para cada texto, você deve
calcular o grau de similaridade com a assinatura do portador de COH-PIAH e, no final, exibir
qual texto mais provavelmente foi escrito por algum aluno infectado (ou seja, o texto com
assinatura mais similar à assinatura dada).
Exemplo:

$ > python3 coh_piah.py

Bem-vindo ao detector automático de COH-PIAH.

Informe a assinatura típica de um aluno infectado:

Entre o tamanho médio de palavra: 4.51

Entre a relação Type-Token: 0.693

Entre a Razão Hapax Legomana: 0.55

Entre o tamanho médio de sentença: 70.82

Entre a complexidade média da sentença: 1.82

Entre o tamanho médio de frase: 38.5

Digite o texto 1 (aperte enter para sair):

Num fabulário ainda por encontrar será um dia lida esta fábula: A uma bordadora dum país
longínquo foi encomendado pela sua rainha que bordasse, sobre seda ou cetim, entre
folhas, uma rosa branca. A bordadora, como era muito jovem, foi procurar por toda a parte
aquela rosa branca perfeitíssima, em cuja semelhança bordasse a sua. Mas sucedia que
umas rosas eram menos belas do que lhe convinha, e que outras não eram brancas como
deviam ser. Gastou dias sobre dias, chorosas horas, buscando a rosa que imitasse com
seda, e, como nos países longínquos nunca deixa de haver pena de morte, ela sabia bem
que, pelas leis dos contos como este, não podiam deixar de a matar se ela não bordasse a
rosa branca. Por fim, não tendo melhor remédio, bordou de memória a rosa que lhe haviam
exigido. Depois de a bordar foi compará-la com as rosas brancas que existem realmente
nas roseiras. Sucedeu que todas as rosas brancas se pareciam exactamente com a rosa que
ela bordara, que cada uma delas era exactamente aquela. Ela levou o trabalho ao palácio e
é de supor que casasse com o príncipe. No fabulário, onde vem, esta fábula não traz
moralidade. Mesmo porque, na idade de ouro, as fábulas não tinham moralidade nenhuma.
Digite o texto 2 (aperte enter para sair):

Voltei-me para ela; Capitu tinha os olhos no chão. Ergueu-os logo, devagar, e ficamos a
olhar um para o outro... Confissão de crianças, tu valias bem duas ou três páginas, mas
quero ser poupado. Em verdade, não falamos nada; o muro falou por nós. Não nos
movemos, as mãos é que se estenderam pouco a pouco, todas quatro, pegando-se,
apertando-se, fundindo-se. Não marquei a hora exata daquele gesto. Devia tê-la marcado;
sinto a falta de uma nota escrita naquela mesma noite, e que eu poria aqui com os erros de
ortografia que trouxesse, mas não traria nenhum, tal era a diferença entre o estudante e o
adolescente. Conhecia as regras do escrever, sem suspeitar as do amar; tinha orgias de
latim e era virgem de mulheres.

Digite o texto 3 (aperte enter para sair):

Senão quando, estando eu ocupado em preparar e apurar a minha invenção, recebi em


cheio um golpe de ar; adoeci logo, e não me tratei. Tinha o emplasto no cérebro; trazia
comigo a idéia fixa dos doidos e dos fortes. Via-me, ao longe, ascender do chão das turbas,
e remontar ao Céu, como uma águia imortal, e não é diante de tão excelso espetáculo que
um homem pode sentir a dor que o punge. No outro dia estava pior; tratei-me enfim, mas
incompletamente, sem método, nem cuidado, nem persistência; tal foi a origem do mal
que me trouxe à eternidade. Sabem já que morri numa sexta-feira, dia aziago, e creio haver
provado que foi a minha invenção que me matou. Há demonstrações menos lúcidas e não
menos triunfantes. Não era impossível, entretanto, que eu chegasse a galgar o cimo de um
século, e a figurar nas folhas públicas, entre macróbios. Tinha saúde e robustez. Suponha-
se que, em vez de estar lançando os alicerces de uma invenção farmacêutica, tratava de
coligir os elementos de uma instituição política, ou de uma reforma religiosa. Vinha a
corrente de ar, que vence em eficácia o cálculo humano, e lá se ia tudo. Assim corre a sorte
dos homens.

Digite o texto 4 (aperte enter para sair):

O autor do texto 2 está infectado com COH-PIAH

Funções de suporte

Para facilitar seu trabalho, fornecemos para você um esqueleto do programa completo
como base. Use-o! As funções definidas nele devem ser utilizadas no seu programa;
algumas já estão implementadas, outras devem ser implementadas por você (conforme
indicado pelo comentário "IMPLEMENTAR"). Sinta-se livre para criar funções adicionais,
caso necessário.

import re

def le_assinatura():
'''A funcao le os valores dos tracos linguisticos do modelo e devolve uma assinatura a ser comparada com
os textos fornecidos'''
print("Bem-vindo ao detector automático de COH-PIAH.")
print("Informe a assinatura típica de um aluno infectado:")

wal = float(input("Entre o tamanho médio de palavra:"))


ttr = float(input("Entre a relação Type-Token:"))
hlr = float(input("Entre a Razão Hapax Legomana:"))
sal = float(input("Entre o tamanho médio de sentença:"))
sac = float(input("Entre a complexidade média da sentença:"))
pal = float(input("Entre o tamanho medio de frase:"))

return [wal, ttr, hlr, sal, sac, pal]

def le_textos():
'''A funcao le todos os textos a serem comparados e devolve uma lista contendo cada texto como um
elemento'''
i=1
textos = []
texto = input("Digite o texto " + str(i) +" (aperte enter para sair):")
while texto:
textos.append(texto)
i += 1
texto = input("Digite o texto " + str(i) +" (aperte enter para sair):")
return textos

def separa_sentencas(texto):
'''A funcao recebe um texto e devolve uma lista das sentencas dentro do texto'''
sentencas = re.split(r'[.!?]+', texto)
if sentencas[-1] == '':
del sentencas[-1]
return sentencas

def separa_frases(sentenca):
'''A funcao recebe uma sentenca e devolve uma lista das frases dentro da sentenca'''
return re.split(r'[,:;]+', sentenca)

def separa_palavras(frase):
'''A funcao recebe uma frase e devolve uma lista das palavras dentro da frase'''
return frase.split()

def n_palavras_unicas(lista_palavras):
'''Essa funcao recebe uma lista de palavras e devolve o numero de palavras que aparecem uma unica vez'''
freq = dict()
unicas = 0
for palavra in lista_palavras:
p = palavra.lower()
if p in freq:
if freq[p] == 1:
unicas -= 1
freq[p] += 1
else:
freq[p] = 1
unicas += 1

return unicas

def n_palavras_diferentes(lista_palavras):
'''Essa funcao recebe uma lista de palavras e devolve o numero de palavras diferentes utilizadas'''
freq = dict()
for palavra in lista_palavras:
p = palavra.lower()
if p in freq:
freq[p] += 1
else:
freq[p] = 1
return len(freq)

def compara_assinatura(as_a, as_b):


'''IMPLEMENTAR. Essa funcao recebe duas assinaturas de texto e deve devolver o grau de similaridade nas
assinaturas.'''

def calcula_assinatura(texto):
'''IMPLEMENTAR. Essa funcao recebe um texto e deve devolver a assinatura do texto.'''

def avalia_textos(textos, ass_cp):


'''IMPLEMENTAR. Essa funcao recebe uma lista de textos e uma assinatura ass_cp e deve devolver o numero
(1 a n) do texto com maior probabilidade de ter sido infectado por COH-PIAH.'''

Você também pode gostar