Pokerface de Leo


13

Expressão impassível

Introdução

Leo gosta de jogar pôquer, mas seu trabalho na Tech Inc. é muito exigente para ele aprender a jogar bem. Leo, sendo um cientista da computação, não desanima. Ele decide levar mais tempo do que seria necessário para aprender pôquer e usá-lo para escrever um bot de pôquer para ajudá-lo a jogar melhor. Mas agora Leo tem um problema: para entender como jogar um pouco melhor, Leo precisa observar vários jogos de várias "pessoas", mas as "pessoas" precisam de diferentes estilos de jogo para melhorar a qualidade e a realidade do jogo.

O desafio

Leo lembra que na verdade existe um site dedicado aos desafios de programação e está solicitando sua ajuda! Seu trabalho é escrever um programa que reproduza "Pokerface", uma versão modificada do pôquer de 5 cartas. O programa receberá a entrada como uma mão de 5 cartas, em qualquer formato que você desejar, após o qual o programa produzirá:

  • Exatamente (com distinção entre maiúsculas e minúsculas) "verdadeiro" "1" ou "t" se o jogador desejar trocar cartões, qualquer outra saída não vazia de outra forma.
  • Se verdadeiro, lista de índices de cartas e / ou nomes de cartas que o jogador deseja trocar.
  • Um único número entre 0 e 3, que especifica quantas cartas adicionais o jogador deseja.
  • Imprima a mão que o jogador deseja usar.

(Veja a formatação abaixo)

Regras do Pokerface

  • Como o pokerface é um jogo de aventura baseado em texto, as cartas devem ser apresentadas de maneira consistente. As cartas são representadas por dois códigos de caracteres, o primeiro caractere é o naipe e o segundo é o nome da carta.
    • Cartões:
      • 2-9 = 2-9
      • 10 = T
      • Jack = J
      • Rainha = Q
      • King = K
      • Ace = A
    • Ternos:
      • Espadas = S
      • Clubes = C
      • Corações = H
      • Diamante = D

Então o ás de espadas seria SA, o 10 de copas é HT, o quarto de diamantes é D4, etc.

  • Uma única rodada do Pokerface consiste em quatro etapas:
    • O baralho é embaralhado e uma mão de cinco cartas é distribuída para cada jogador.
    • Cada jogador tem a chance de trocar quantas cartas quiser.
    • Cada jogador tem a chance de ganhar até mais três cartas.
    • Cada jogador deve revelar sua melhor mão.
  • A melhor mão vence e ganha um ponto para o jogador. Em caso de empate, os dois jogadores ganham um ponto.
  • Em um único jogo, dez rodadas são disputadas e o jogador com mais pontos ganha e ganha um único "ponto de vitória". Em caso de empate, os dois jogadores ganham um ponto de vitória.
  • Leo realmente não tem uma grande quantidade de dinheiro, então seu bot pode assumir que este é um mundo perfeito sem apostas.

Mãos

  • As mãos têm exatamente 5 cartas de comprimento (entrada inicial e saída final).
  • As mãos são classificadas de acordo com as regras descritas aqui .

Entrada / Saída

  • Leo conhece apenas Java, portanto, seu programa deve ser executável por meio da API de processos (linha de comando) e usar STDIN e STDOUT para entrada e saída, respectivamente.
  • Para cada etapa de entrada e saída detalhada acima, cada entrada e saída devem existir em uma linha.
  • Deve haver pelo menos uma nova linha após a saída final. (Isso ocorre devido à maneira como a entrada é lida em STDIN)
  • Nenhuma entrada / saída estranha é permitida, exceto espaços à direita e à direita. O analisador simplesmente não entende coisas como final_hand=...ou draw 0.
  • Ao desenhar, a saída é um único número inteiro, quando a saída da troca é uma lista de números inteiros e / ou cartões definidos abaixo e, ao receber a mão original, a saída é uma lista de cartões definidos abaixo.
  • Todos os números de entrada / saída devem ser números inteiros positivos na base 10.
  • Você pode definir o formato para a entrada do cartão (consulte o formato da postagem abaixo).
  • True é definido como exatamente "true", "1" ou "t" e false é qualquer outro valor não vazio.
  • Durante a etapa de troca:
    • Os índices do cartão devem ser impressos com pelo menos um espaço entre eles (por exemplo 3 4 0)
    • Os nomes dos cartões devem ser impressos com pelo menos um espaço entre eles (por exemplo H4 S8)
    • Os nomes e índices do cartão podem ser misturados na saída (por exemplo 0 H7 3 D3)
    • Espaços à direita e à esquerda são permitidos.
    • A entrada resultante do reprodutor acima será formatada conforme especificado pelo bot.jlscarquivo, na mesma ordem solicitada
  • O número de cartas que um jogador deseja adicionar à sua mão pode ter espaços iniciais e finais.
  • As mãos devem ser produzidas com pelo menos um espaço entre elas (por exemplo H4 D5 CA), espaços à direita e à esquerda são permitidos.
  • As mãos não precisam ser produzidas na ordem correta (por exemplo, H4 D4 C4 DA SAe H4 DA D4 SA C4ambas representam 4, 4, 4, Ás, Ás, que é um full house).
  • Se você deseja construir uma estratégia analisando as mãos dos oponentes, pode armazenar dados em um <botname>/datadiretório.
    • Depois que os bots concorrentes exibirem suas mãos, eles serão gravados em todos os diretórios de dados de bots, em hands.txt, com cada mão em uma nova linha (separada por \ n). O arquivo será codificado em US_ASCII.
  • Depois que seu bot solicitar novos cartões ou trocar cartões, os cartões serão inseridos dependendo do formato que você especificar no bot.jlscarquivo.

Formato da postagem

  • Cada postagem deve incluir duas coisas:
    • O código-fonte do seu bot ou um link para um repositório público.
    • Um arquivo zip contendo:
      • A versão compilada / executável do seu bot (se o arquivo for um arquivo .exe ou outro arquivo não descompilável, inclua apenas instruções de compilação na sua publicação).
      • Um bot.jlscarquivo, veja abaixo (nota lateral: a extensão .jlsc é apenas por causa de um projeto paralelo meu, um formato de configuração. O arquivo abaixo corresponde à sintaxe apropriada, portanto, não se preocupe).
    • O arquivo .zip deve ter o mesmo nome do seu bot.
  • Se você não tiver acesso ao Windows ou algum outro utilitário de zipagem ou não puder criar um .zip por qualquer motivo, inclua o texto do arquivo bot.jlsc na sua postagem

arquivo bot.jlsc:

name= "Botty"
link= "example.com"
cmd= "java -jar Botty.jar"
input_hand= "${0} ${1} ${2} ${3} ${4}"
input_1= "${0}"
input_2= "${0} ${1}"
input_3= "${0} ${1} ${2}"
input_4= "${0} ${1} ${2} ${3}"

Onde:

  • "cmd" é o comando de linha de comando do Windows para executar seu bot. Note que seu bot estará no diretório <botname>, então ajuste o comando de acordo.
  • "nome" é o nome do seu bot.
  • "link" é o link para sua resposta. Você precisará editá-lo depois de postar.
    • "input_hand" é como você deseja que o negócio original seja formatado (com $ {#} representando os cartões de 0 a 4).
  • "input_1" é como você deseja que a entrada de um cartão adicional seja formatada.
  • "input_2" é como você deseja que a entrada de dois cartões adicionais seja formatada.
  • "input_3" é como você deseja que a entrada de três cartões adicionais seja formatada.
  • "input_4" é como você deseja que a entrada de quatro cartões adicionais seja formatada.

Específicos

  • Essas brechas não são permitidas (consulte "armadilhas comuns")
  • Você não pode escrever um bot, sempre exibirá a melhor mão possível, sempre, dentro do conjunto de regras. (ou seja, sem bots de força bruta de longa duração, nada deve ser tão "bom" quanto o LeoBot)
  • Seu bot deve rodar em ~ 100 ms ou menos (neste momento, máximo de ~ 1 segundo)
  • Qualquer saída do bot após a mão escolhida será ignorada.
  • As brechas padrão não são permitidas.
  • Sim, eu sei que o Linux é melhor, mas eu tenho um PC com Windows, portanto, certifique-se de que a versão compilada / executável do seu programa possa ser executada na linha de comando do Windows.
    • Eu já tenho python e java instalado no meu computador, mas estou disposto a atualizar para novas versões e instalar outros ambientes; portanto, especifique que tipo de ambiente o seu programa exige.
  • Você não pode escrever um bot que faça o mesmo que outro bot em todos os casos. Bots de spam são permitidos, mas desencorajados.
  • Seu bot pode usar apenas cartões que possui. Os cartões perdidos em troca ou não negociados no início são inválidos na mão final.
  • Entrada e saída podem conter apenas caracteres ASCII.

Torneios

  • Os torneios ocorrerão quando eu chegar no horário (minha agenda é quase tão cheia quanto a de Leo, então isso é um pouco raro. Desculpe pelo inconveniente.).
  • Os bots serão disputados entre si em jogos para 4 pessoas, e haverá um jogo para cada subconjunto possível de bots (ou seja, muitos jogos).
    • Este processo será repetido cinco vezes.
    • Devido à maneira como o manipulador do torneio faz os grupos de bots, até três bots de preenchimento serão adicionados para tornar o número de bots divisível por 4. Esses bots simplesmente retornarão a mão em que foram distribuídos originalmente.
  • Após cada rodada e jogo, a pontuação dos bots será calculada com base no número de jogos que eles venceram.
    • Vários bots podem compartilhar uma posição (empates pela primeira vitória e pela primeira postagem).
  • Após o término de um torneio, as pontuações serão anexadas ao final deste post.

Pontuação

Regras normais de KoTH. Os bots que vencem mais jogos vencem o desafio.

LeoBot

O bot de Leo é bem esperto. Ele não troca cartas, é muito difícil, mas exige o número máximo de cartas adicionais e determina a melhor mão possível que ele pode fazer e joga essa mão. A principal lógica do leobot está abaixo.

package com.gmail.socraticphoenix.pokerface.leobot;

import com.gmail.socraticphoenix.pokerface.lib.card.Card;
import com.gmail.socraticphoenix.pokerface.lib.card.Deck;
import com.gmail.socraticphoenix.pokerface.lib.rule.HandRegistry;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class LeoBot {

    public static void main(String[] args) {
        List<Card> hand = new ArrayList<>();

        Scanner scanner = new Scanner(System.in);
        hand.addAll(Card.parseHand(scanner.nextLine()));
        System.out.println(false);

        System.out.println(3);
        hand.addAll(Card.parseHand(scanner.nextLine()));

        List<List<Card>> possibleHands = LeoBot.getSubsets(hand, 5);
        System.out.println(Deck.toString(possibleHands.stream().sorted((a, b) -> HandRegistry.determineWinner(b, a).comparable()).findFirst().get()));
    }

    private static <T> void getSubsets(List<T> superSet, int k, int idx, List<T> current, List<List<T>> solution) {
        if (current.size() == k) {
            solution.add(new ArrayList<>(current));
            return;
        }
        if (idx == superSet.size()) return;
        T x = superSet.get(idx);
        if (!current.contains(x)) {
            current.add(x);
        }
        getSubsets(superSet, k, idx + 1, current, solution);
        current.remove(x);
        getSubsets(superSet, k, idx + 1, current, solution);
    }

    public static <T> List<List<T>> getSubsets(List<T> superSet, int k) {
        List<List<T>> res = new ArrayList<>();
        getSubsets(superSet, k, 0, new ArrayList<T>(), res);
        return res;
    }

}

Observe que, se o LeoBot vencer consistentemente os torneios e houver uma boa quantidade de entradas, eu pararei de incluí-lo na corrida.

Links importantes

aviso Legal

Leo e Tech Inc. são elementos da história e qualquer semelhança com empresas ou pessoas da vida real é puramente não intencional. (No entanto, quando a 'situação' de Leo adiciona ou subtrai condições da pergunta, elas realmente fazem parte da pergunta ...)


1
@SocraticPhoenix Eu recomendo pesar agora ou nunca. Seria realmente injusto para os jogadores ajustar a pontuação após o envio já estar classificado.
Nathan Merrill

2
@DestructibleWatermelon melhor? Apenas para sua informação, isso esteve na caixa de areia por uns 2 a 3 dias ... Ninguém comentou. Quero dizer, é tudo bem legal
Socratic Phoenix

2
Além disso, @NathanMerrill provavelmente ainda está certo sobre a vitória idiota do bot. Depois de investigar o que é um código, um programa de 5 bytes "f"q+atende aos requisitos mínimos. Se houver 10 pessoas em competição, isso provavelmente supera todas as entradas não idiotas (a entrada não idiota provavelmente tem> 75 caracteres, 5 * 10 (pontuação do bot idiota, por último) = 50 <75 (pontuação do bot inteligente muito pequeno (em primeiro lugar))). Thusly, você provavelmente deve remover codegolf deste desafio
Destrutível Lemon

2
mesmo que o Cjam não possa ser usado, o ponto é que os dumbbots serão uma estratégia razoável e a remoção do codegolf remove todas as dificuldades de equilibrar o tamanho do desempenho VS
Destructible Lemon

1
Código morto de golfe até a morte ...
Phoenix socrático

Respostas:


1

(Python), Pairbot, não muito competitivo (não sei como fazer comandos e coisas do cmd)

O Pairbot competirá assim que alguém ajudar com os arquivos bot.jlsc e zip, etc.


O Pairbot sabe que nem sempre você tem boas mãos. Ele sabe que boas mãos são raras. Pairbot sabe pares e outras duplicatas são algumas das melhores mãos. O pairbot também sabe que a mão mais baixa que você pode obter é um sete alto, então ele sabe se tem 6 altos, isso é na verdade um straight (o pairbot não sabe por que ele sabe disso). Ele também sabe se sua carta mais baixa é 10, (sem pares), isso também é uma sequência (o pairbot sabe que pode obter royal flush dessa maneira). O Pairbot verifica principalmente se há o mesmo número de fraudes, mas também verifica dois tipos de retas em casos especiais.

card_values={"2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8,
             "9":9, "T":10, "J":11, "Q":12, "K":13, "A":14,}
straight=False
def card_valuing(item):
    return card_values[item[1]]

input_list=input().split()
pairs_to_keep=[]
for item in input_list:
    if sum(item[1]==card[1] for card in input_list)>1:
        pairs_to_keep+=[item]
cards_to_remove=input_list
for item in pairs_to_keep:cards_to_remove.remove(item)#we want to remove all non pairs
hand=pairs_to_keep
if pairs_to_keep==[]:
    input_list.sort(key=card_valuing, reverse=True)
    if card_values[input_list[0][1]]==6:
        straight=True
        hand=input_list
    elif card_values[input_list[-1][1]]==10:
        straight=True
        hand=input_list
    else:
        print("true\n"+" ".join(input_list[1:]))
        hand+=input_list[0]+input().split()
elif input_list!=[]:
    print("true\n"+" ".join(input_list))
    hand+=input().split()
else:print(0, end=', ')
if straight:print("0\n0\n"+" ".join(hand))
else:
    print("3")
    hand+=input().split()
    same_number_dict={} #holds the amount of each type (A, 2, 3, etc.)

    def dict_value(item):
        return int(same_number_dict[item[1]])*100+card_values[item[1]]

    for card in hand:
        same_number_dict[card[1]]=sum(card[1] == item[1] for item in hand)

    hand=list(sorted(hand, key=dict_value, reverse=True))
    final_hand =[]
    last_number=hand[0][1]
    hand_taken=0
    while hand_taken < 5:
        if last_number==hand[0][1]:
            final_hand+=[hand[0]]
            hand=hand[1:]
            hand_taken+=1
        else:
            for card in hand:
                if same_number_dict[card[1]]>5-hand_taken:
                    same_number_dict[card[1]]=5-hand_taken
            hand=list(sorted(hand, key=dict_value, reverse=True))
            last_number=hand[0][1]
    print(" ".join(final_hand))

O formato da entrada é o mesmo do exemplo: separado por espaços


Se o Socratic Phoenix pudesse ajudar com os arquivos, isso seria bom


Esperto! Portanto, o arquivo que você vai querer é aqui , eu vou editar o post principal para fazer o opcional .zip real ...
socrático Phoenix

Além disso, +1 para FGITW
Socratic Phoenix

Mais como FGITLOSG (arma mais rápida na terra de armas lentas).
Destructible Lemon

Verdade. Não tenho certeza de que a entrada / saída esteja na forma correta. Quando insiro uma mão, o programa imprime "True" e, em seguida, sua mão atual. Acredito que você queira apenas imprimir "false", pois "True" indica que deseja trocar cartões. Em segundo lugar, o programa precisa imprimir um único número inteiro ao desenhar ou números inteiros separados por espaços ao trocar. Não é "empate 0." Vou tentar esclarecer o post principal.
Socratic Phoenix

[Então conta como competindo agora?] Não viu novas mensagens. Vou corrigir bot imediatamente
Destructible Lemon

1

Encanador, Python

Encanador é tudo sobre descargas. Encanador também prioriza cartas de maior valor (o que significa que às vezes ele pode receber straight flushes, principalmente os da realeza (caso ocorram).) O encanador receberá descarga cerca de 20% do tempo, se os cálculos de Sherlock9 estiverem corretos

hand=input().split()
suit_in_hand={"S":0,"C":0,"D":0,"H":0}
card_values={"2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8,
             "9":9, "T":10, "J":11, "Q":12, "K":13, "A":14,}
def value_sort(x):
    return card_values[x[1]]
def suit_sort(x):
    return suit_in_hand[x[0]]

for card in hand:
    suit_in_hand[card[0]]+=1

hand.sort(key=suit_sort, reverse=True)

print(" ".join(hand[suit_in_hand[hand[0][0]]:]))
hand=hand[:suit_in_hand[hand[0][0]]]

for new_card in input().split():
    hand+=[new_card]
    suit_in_hand[new_card[0]]+=1

print(3)

for new_card in input().split():
    hand+=[new_card]
    suit_in_hand[new_card[0]]+=1
hand.sort(key=value_sort, reverse=True)
hand.sort(key=suit_sort, reverse=True)
print(" ".join(hand[:5]))

Também recebe entrada separada por espaços como outros meus dois bots


Nota: Alterei ligeiramente as regras de saída devido a um erro no meu próprio programa de torneios. Agora deve haver pelo menos uma nova linha após a saída final.
Socratic Phoenix

1

LadyGaga, Python 3

  • É um pouco cego para ternos
  • Tem um vestido cheio de insetos
  • E gosta de jogar Poker Face de vez em quando

    from math import ceil as f
    M=lambda A:max(set(A),key=A.count)
    K=lambda A:A.count(M(A))
    O=lambda A:range(len(A))
    J=lambda A:A[0]+str(U(A[1]))
    X={"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"T":10,"J":11,"Q":12,"K":13,"A":14}
    def V(A):return([A[0]]+[int(X[A[1]])])
    def U(c):
     if c==10:c='T'
     if c==11:c='J'
     if c==12:c='Q'
     if c==13:c='K'
     if c==14:c='A'
     return(c)
    def P(A):
     S=[];C=[];t=len(A)
     for x in A:S.append(x[0]);C.append(x[1])
     B=[0]*9;q=len(set(C));p=K(C);D=list(set(C));D.sort()
     B[2]=1/f(13**(4-p));B[6]=1/f(13**(3-p));B[8]=1/f(13**(2-p))
     if (p,q)==(2,4):B[3]=1/1100;B[7]=5/34
     if (p,q)==(3,3):B[3]=1/169;B[7]=1/169
     if (p,q)==(4,2):B[3]=1/13;B[7]=1
     if (p,q)==(2,3):B[3]=5/169;B[7]=1
     if (p,q)==(3,2):B[3]=1;B[7]=1
     for x in O(D):D[x]-=x
     j=M(D);h=K(D)-5;B[5]=13**h
     for x in O(D):
      if j+h<D[x]<j-h and D[x]!=j:B[5]*=13
     W=K(S);B[4]=(4**(W-t))*(13-W)/52
     return(B,M(S))
    def E(B,h,u):
     x=0;D=[];C=[]
     while 1:
      k=list(C)
      C=[]
      while 1:
       p=list(B);del p[x]
       if len(D)==3:break
       if P(p)[0][h]>=P(B)[0][h]:C.append(B[x])
       x+=1
       if x>len(p):break
      if len(C)==0:break
      for x in O(C):
       if k==C or not((u in C[x])and(len(C)-1)):D.append(C[x]);del B[B.index(C[x])]
     return(D)
    s=input()
    A=s.split(' ')
    b=list(map(V,A));G,u=P(b);F=[649739,72192,4164,693,508,254,46.3,20,1.4];H=[]
    for x in O(F):F[x]=1-((1-(1/F[x]))**4)
    for x in O(F):H.append(G[x]-F[x])
    Y=H.index(max(H));p=[]
    e=E(list(b),Y,u);g=list(e)
    for x in O(e):e[x]=J(e[x])
    print(' '.join(e)if len(e)else'')
    for x in g:
     if x in b:del b[b.index(x)]
    s=input()
    if len(s):
     A=s.split(' ')
     b+=list(map(V,A))
    print(3)
    s=input()
    A=s.split(' ')
    b+=list(map(V,A));G,u=P(b);H=[]
    for x in O(F):H.append(G[x]-F[x])
    Y=H.index(max(H))
    e=E(list(b),Y,u)
    for x in e:
     if x in b:del b[b.index(x)]
    for x in O(b):b[x]=J(b[x])
    print(' '.join(b[:5]))
    print()
    
    • (E / S) modelada após o PlumberBot -Edit: correções extensivas de erros graças ao Destructible Watermelon -Edit: Devido a novas regras, uma nova linha após a saída final

Você pode querer usar um dicionário em vez de toda aquela coisa complicada para os valores das cartas
Destrutível Lemon

Tudo o que foi compactado em uma matriz já foi do meu conhecimento. Qual seção de código eu posso reduzir?
Magenta

def V(A): b=[A[0]];c=A[1] if c=='T':c=10 if c=='J':c=11 if c=='Q':c=12 if c=='K':c=13 if c=='A':c=14 return (b + [int(c)]) para x={"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"T":10,"J":11,"Q":12,"K":13,"A":14,} def V(A):return(A[0] + x[A[1]])
Destructible Lemon

Pairbot é apenas mais do que o seu programa, e isso é porque é legível
Destrutível Lemon

Eu sei. Maus hábitos de codegolfing.
Magenta

0

LuckyBot, Python

Pairbot convidou seu amigo Luckybot, que teve a chance. Luckybot assistiu a um monte de pôquer ficcional e calculou que descobrira o segredo do pôquer: sorte. Todo mundo sabe que os profissionais de verdade (James Bond, por exemplo) realmente confiam e obtêm boas mãos, não habilidade. Por isso, ele não olha para as cartas e tenta colocar o máximo de sorte possível nelas.


lucky_number=24 #IMPORTANT

from random import randint as roll


def lucky_shuffle(i):
    return sorted(i, key=lucky_dice)


def lucky_dice(seed):
    return sum(roll(1,6)for i in range(roll(1,6)))


hand=lucky_shuffle(input().split())

throw=lucky_dice(lucky_number)%5
print("true\n"+" ".join(hand[throw:]))

hand=hand[:throw]+lucky_shuffle(input().split())

hand=lucky_shuffle(hand)
hand=lucky_shuffle(hand)
#One more for good luck
hand=lucky_shuffle(hand)
#maybe one more
hand=lucky_shuffle(hand)
#I got a good feeling about this one
hand=lucky_shuffle(hand)

hand=lucky_shuffle(hand)
#I think I'm done
hand=lucky_shuffle(hand)
#for real this time


hand=lucky_shuffle(hand)

print("3")
hand=hand+lucky_shuffle(input().split())
#All right, I got a real good feeling about this,
#let me shuffle some more luck into them cards!


def extra_super_lucky_shuffle(item):
 return lucky_shuffle(lucky_shuffle(lucky_shuffle(\
    lucky_shuffle(lucky_shuffle(lucky_shuffle(\
        lucky_shuffle(lucky_shuffle(lucky_shuffle(item)))))))))


def super_duper_extra_ultra_uber_luckyshuffle(item):
    return extra_super_lucky_shuffle(extra_super_lucky_shuffle(\
        extra_super_lucky_shuffle(extra_super_lucky_shuffle(item))))


hand=super_duper_extra_ultra_uber_luckyshuffle(super_duper_extra_ultra_uber_luckyshuffle(hand))
#cmoooooooooooooooon
print(hand[:5])
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.