Calcular pontuação do Doppelkopf


9

Introdução

Doppelkopf é um jogo de cartas tradicional alemão para 4 jogadores. O baralho é composto por 48 cartas (9, 10, Valete, Dama, Rei, Ás de cada naipe, enquanto todas as cartas estão no jogo duas vezes), para que cada jogador receba 12 no início de uma rodada.

Sempre existem duas equipes que são determinadas pela distribuição do Queens of Clubs. Os 2 jogadores que estão segurando o Queens formam um time e jogam contra os outros 2 jogadores. A equipe do Queens of Clubs é chamada de "Re", a equipe que não tem é a "Contra".
No início da rodada, ninguém sabe quem está em qual time. A distribuição da equipe será revelada no andamento da rodada, o que adiciona muita estratégia ao jogo.

O jogo consiste em 12 truques. Os jogadores que vencem um truque recebem todas as 4 cartas. Cada carta tem um certo valor (o rei conta 4, o ás conta 11, por exemplo), todas as cartas somam 240 pontos, que é o resultado mais alto possível.

No final de uma rodada, os pontos são contados e a equipe com a maior quantidade de pontos vence a rodada. Então começa a próxima rodada ...

O desafio

Cada rodada tem uma certa pontuação, que é determinada pela quantidade de pontos que a equipe vencedora obteve e possíveis anúncios. Você terá que escrever um programa que considere a distribuição de pontos e os anúncios em potencial (veja a explicação abaixo) como entrada e saída da pontuação da rodada e do vencedor.

O cálculo da pontuação

Como mencionado, há uma equipe de Re e Contra. Também há um máximo de 240 pontos possíveis em uma rodada. A Re-equipe tem 121 pontos para vencer, enquanto a Contra-equipe precisa apenas de 120. Há também a possibilidade de anunciar "Re" ou "Contra" no início da rodada, se você acha que vai ganhar o jogo. . Ao fazer isso, você está aumentando a pontuação.

Aqui estão as regras de pontuação:

  • +1 para ganhar o jogo
  • +1 se o time perdedor tiver menos de 90 pontos ("Keine 90")
  • +1 se o time perdedor tiver menos de 60 pontos ("Keine 60")
  • +1 se o time perdedor tiver menos de 30 pontos ("Keine 30")
  • +1 se o time perdedor tiver 0 pontos ("Schwarz")
  • +2 para um anúncio de Contra
  • +2 para um anúncio de Re
  • +1 se a equipe Contra vencer ("Gegen die Alten")

Nota: Re / Contra-anúncios sempre se aplicam, independentemente do vencedor. Veja exemplos nas caixas de teste abaixo.

Entrada e saída

A contribuição para o programa será a pontuação da Re-equipe e os possíveis anúncios de Re ou Contra. Como sempre existem 240 pontos no jogo, você pode facilmente calcular a pontuação do Contra-time.

A entrada será uma única sequência que terá a pontuação do Re-time primeiro, seguida pelos anúncios em potencial, enquanto "R" é para Re e "C" é para Contra. Se ambos foram anunciados, Re sempre virá em primeiro lugar.

A saída será a pontuação do jogo seguida pela equipe vencedora ("C" para Contra, "R" para Re)

Regras

  • Seu envio pode ser um programa completo ou uma função. Se você escolher o último, inclua um exemplo de como invocá-lo.
  • A entrada pode ser fornecida por argumentos de função ou de linha de comando ou entrada do usuário.
  • A saída pode ser fornecida como valor de retorno ou impressa na tela.
  • Brechas padrão se aplicam.
  • O menor número de bytes vence!

Casos de teste

Input -> Output (Explanation)

145R  -> 3R  (Re won, +1 for winning, +2 for Re-Announcement)
120   -> 2C  (Contra won, +1 for winning, +1 for winning as Contra)
80C   -> 5C  (Contra won, +1 for winning, +1 for no 90, +1 for winning as Contra, +2 for Contra-Announcement)
240R  -> 7R  (Re won, +1 for winning, +1 for no 90, +1 for no 60, +1 for no 30, +1 for no points for the losing team, +2 for Re-announcedment)
90    -> 2C  (Contra won, +1 for winning, +1 for winning as Contra)
110RC -> 6C  (Contra won, +1 for winning, +1 for winning as Contra, +2 for Re-Announcement, +2 for Contra-Announcement)
110R  -> 4C  (Contra won, +1 for winning, +1 for winnins as Contra, +2 for Re-Announcement)
184C  -> 5R  (Re won, +1 for winning, +1 for no 90, +1 for no 60, +2 for Contra-Announcement)

Nota curta: deixei de fora algumas regras (como solos e pontos de bônus) de propósito para manter o desafio simples. Então, se você já está familiarizado com o jogo, não fique confuso :)

Feliz codificação!

Respostas:


4

CJam, 47 46 bytes

L~]_,2*\0=:S121<:AS240S-e<_g3@30/-Te>--+A"RC"=

Execute todos os casos de teste.

Hmm, conceitualmente esse desafio é realmente simples, mas é surpreendentemente complicado para o golfe.


Concordo que, quando tentei jogar golfe, cheguei a cerca de 100 bytes com uma linguagem de golfe. Desisti logo depois.
TheCoffeeCup 23/01

4

Labirinto , 136 103 94 92 87 84 76 74 69 61 bytes

 (}?
;)
,)
`
2
0:
 {
_-+}}82"
}"     {{"(#0/#--!.@
 -=-)}67 )

Experimente online!

Ahh, já faz muito tempo desde que eu usei o Labyrinth. É sempre uma alegria jogar golfe. :)

Explicação

Isso está um pouco desatualizado agora. A estrutura geral do programa ainda é a mesma, mas alguns detalhes foram alterados. Vou atualizar isso mais tarde. Esta é a solução anterior, para referência:

 (}?
;)
,)
`
2
0 }82{_240{- ("
{ ;        #;`"~#0/#--!.@
:}-"-))}67{{
  ;#

Vamos detalhar um pouco a pontuação:

  • Se contarmos os caracteres após o número na entrada, vamos chamá-lo M, então haverá 2M+1pontos na pontuação final, para ganhar, Re e Contra.
  • Se a pontuação for 120 ou menos, Contra vence e a pontuação é incrementada por 1.
  • Observando a pontuação perdida, podemos (inteiro) dividir por 30 para determinar os pontos adicionais. Porém, isso tem três problemas: 1. o valor aumenta na direção errada; portanto, precisamos subtraí-lo da pontuação (e adicionar 3 a ele para corrigir isso). 2. Isso fornece um ponto adicional para um resultado de exatamente 120, do qual precisamos nos livrar. 3. Ele ainda não lida com um resultado de 0 (para o lado perdedor), mas podemos incluí-lo transformando 0 em -1 (uma vez que a divisão inteira do Labyrinth se aproxima -∞).

É assim que o código funciona. O Sp3000 postou uma boa cartilha para o Labyrinth hoje, então decidi roubá-lo. :)

  • O labirinto é baseado em pilha e bidimensional, com a execução iniciando no primeiro caractere reconhecido. Existem duas pilhas, uma pilha principal e uma pilha auxiliar, mas a maioria dos operadores trabalha apenas na pilha principal. Ambas as pilhas são sem fundo, preenchidas com zeros.
  • Em todas as ramificações do labirinto, a parte superior da pilha é verificada para determinar para onde ir a seguir. Negativo é virar à esquerda, zero é reto e positivo é virar à direita.
  • Os dígitos não se pressionam (como em Befunge,> <> ou Prelude) - em vez disso, "se anexam" ao topo da pilha, multiplicando o topo por 10 e somando-se.

Portanto, a execução começa na (primeira linha, com o ponteiro de instrução (IP) indo para a direita. (apenas transforma o topo da pilha principal -1e a }desloca para a pilha auxiliar, onde podemos esquecê-la. O programa realmente começa com o ?que lê o número inteiro de STDIN. O IP atinge um beco sem saída e se vira.

}muda a entrada para a pilha auxiliar e (diminui outro zero para -1. Essa será a pontuação final. Agora entramos em um loop muito apertado no sentido horário:

;)
,)

Os ))incrementos o placar por dois (por isso a primeira vez que vamos através do laço, a pontuação torna-se 1, a pontuação para ganhar). Então ,lê um personagem. Desde que não seja EOF, o loop continua. ;devoluções do personagem, porque não importava se era Rou Ce ))adiciona dois para a pontuação novamente. Isso repetirá 0, 1 ou 2 vezes, dependendo da entrada.

Deixamos o loop, quando atingimos o EOF, o topo da pilha será -1. Em seguida, executamos esta parte linear:

`20{:}-

A `negação é unária, então conseguimos 1, depois a 20transforma em a 120. {:}obtém uma cópia do número inteiro de entrada da pilha auxiliar e -calcula a diferença com 120. Podemos usar o sinal desse resultado para determinar quem ganhou.

  1. Se o resultado for negativo, Re venceu e seguimos o caminho norte, executando:

    ;}82{_240{-#;
    

    ;descarta esse resultado, }muda a pontuação, 82coloca-se (código de caractere de R) na parte inferior da pilha principal, {coloca a pontuação no topo, _240{-subtrai a entrada inteira de 240 para que possamos trabalhar com os pontos de Contra (do lado perdedor).

    O #;é apenas para garantir que tenhamos um valor diferente de zero na pilha, para que possamos unir os dois caminhos de maneira confiável.

  2. Se o resultado for positivo, Contra venceu e seguimos o caminho sul, executando:

    ;#"-))}67{{#;
    

    O #empurra a profundidade da pilha que é 1. Este fica subtraído do placar antes de adicionar 2com )). 67se coloca (código de caractere de C) na parte inferior da pilha principal. {{retorna os outros valores.

  3. Se o resultado for zero, o Contra ainda venceu. No entanto, esse é o caso 120/120, para o qual precisamos adicionar um ponto extra à pontuação final (veja acima). É por isso que esse caminho não pressiona 1 #, mas apenas deixa o zero, de modo que -simplesmente remove esse zero da pilha.

As pilhas agora estão reunidas novamente e contabilizamos tudo, exceto a parte em que dividimos por 30. Mas, primeiro, precisamos transformar uma pontuação zero em -1. É isso que esse pequeno desvio faz:

("
`"~

O `não afeta um zero, "é um no-op e ~é uma negação bit a bit. O NOT de bit a bit 0é -1conforme necessário. Se a pontuação foi positiva, `torna-a negativa, (diminui-a 1e ~desfaz as duas operações de uma só vez.

#0/#--!.@

A profundidade da pilha agora é 3 (o personagem do lado vencedor, a pontuação total até agora e os pontos do lado perdedor), então #empurra 3. 0transforma em um 30, /faz a divisão. #empurra outro 3que é subtraído e esse resultado é subtraído da pontuação final. !imprime como um número inteiro, .imprime o lado vencedor como um caractere e @finaliza o programa.


3

JavaScript (ES6), 106

Cerca de 100 bytes com uma linguagem que não seja de golfe.

x=>([,r,t]=x.match`(\\d+)(.*)`,t=1+t.length*2,w=r>120?(r=240-r,'R'):(++t,'C'),t+!r+(r<30)+(r<60)+(r<90)+w)

Teste

f=x=>(
  [,r,t]=x.match`(\\d+)(.*)`,
  t=1+t.length*2,
  w=r>120?(r=240-r,'R'):(++t,'C'),
  t+!r+(r<30)+(r<60)+(r<90)+w
)

console.log=x=>O.textContent+=x+'\n'

test=[
['145R', '3R'], //(Re won, +1 for winning, +2 for Re-Announcement)
['120',  '2C'], //(Contra won, +1 for winning, +1 for winning as Contra)
['80C',  '5C'], //(Contra won, +1 for winning, +1 for no 90, +1 for winning as Contra, +2 for Contra-Announcement)
['240R', '7R'], //(Re won, +1 for winning, +1 for no 90, +1 for no 60, +1 for no 30, +1 for no points for the losing team, +2 for Re-announcedment)
['90',   '2C'], //(Contra won, +1 for winning, +1 for winning as Contra)
['110RC','6C'], //(Contra won, +1 for winning, +1 for winning as Contra, +2 for Re-Announcement, +2 for Contra-Announcement)
['110R', '4C'], //(Contra won, +1 for winning, +1 for winnins as Contra, +2 for Re-Announcement)
['184C', '5R'], //(Re won, +1 for winning, +1 for no 90, +1 for no 60, +2 for Contra-Announcement)
]
  
test.forEach(t=>{
  var i=t[0],k=t[1],r=f(i)
console.log((k==r?'OK ':'KO ')+i+' -> '+r+(k!=r?' (expected: '+k+')':''))
})
<pre id=O></pre>


Apenas cerca de duas vezes a contagem de bytes da resposta CJam ... não é mau ^^
Denker

2

ES6, 92 bytes

s=>(p=s.match(/\d+|./g),n=+p[0],r=n>120,p.length*2-r+!(n%120)+3-((r?240-n:n)/30|0)+"CR"[+r])

p.length*2superestima a pontuação em 1 se Re vencer, então eu tenho que subtrair rnovamente. !(n%120)+3-((r?240-n:n)/30|0)foi o que descobri para encapsular as regras para a pontuação de "Keine"; Eu gostaria que as fronteiras fossem 31, 61 e 91, pois isso teria feito a fórmula 4-((r?269-n:29+n)/30|0).

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.