Nome alternativo: ChessMoveQ
Dada uma lista de até 32 elementos, cada um composto por 4 elementos e uma segunda lista com 4 elementos, determine se o movimento detalhado na segunda entrada é um movimento válido de xadrez.
A primeira lista indica a posição de todas as 32 peças no quadro. Cada elemento seguirá a estrutura<colour>, <piece-name>, <x-coord>, <y-coord>
, como por exemplo ["W", "K", 5, 1]
, o que indica que o rei branco está ligado 5, 1
( e1
em um tabuleiro de xadrez normal). Todos os elementos da primeira entrada serão únicos. <x-coord>
e <y-coord>
sempre estará entre 1 e 8. Um exemplo seria:
[["B", "K", 3, 8], ["B", "Q", 1, 5], ["B", "N", 4, 7], ["B", "N", 7, 8],
["B", "B", 2, 4], ["B", "R", 4, 8], ["B", "R", 8, 8], ["B", "P", 1, 7],
["B", "P", 2, 7], ["B", "P", 3, 6], ["B", "P", 5, 6], ["B", "P", 6, 7],
["B", "P", 7, 7], ["B", "P", 8, 7], ["W", "K", 5, 1], ["W", "Q", 6, 3],
["W", "N", 3, 3], ["W", "B", 5, 2], ["W", "B", 6, 4], ["W", "R", 1, 1],
["W", "R", 8, 1], ["W", "P", 1, 3], ["W", "P", 2, 2], ["W", "P", 3, 2],
["W", "P", 4, 4], ["W", "P", 6, 2], ["W", "P", 7, 2], ["W", "P", 8, 3]]
o que representaria o conselho:
A segunda entrada consistirá nas mesmas estruturas que as sublistas da primeira, mas em vez das coordenadas x e y indicando onde a peça está, elas estão indicando para onde ela está tentando se mover.
Para o exemplo acima, uma movimentação válida pode ser ["W", "B", 4, 3]
(o bispo move um quadrado para frente e para a esquerda) e um movimento inválido pode ser ["B", "R", 4, 1]
a torre que teria que passar pelo cavaleiro e o peão para chegar ao quadrado. Como a movimentação pode se referir a várias peças às vezes, você deve testar se alguma das peças especificadas pode fazer a movimentação, não apenas uma delas. Por exemplo, o primeiro exemplo é válido para apenas um bispo, mas ainda é uma jogada válida. No entanto, nenhuma torre preta pode executar o segundo movimento, por isso é inválido.
Sua tarefa é determinar se o movimento detalhado na segunda entrada é um movimento de xadrez válido. A validade de uma regra varia, dependendo da peça que está sendo movida (clique no nome da peça para obter um diagrama de jogadas válidas):
- Qualquer peça : Nenhuma peça pode se mover para um quadrado já ocupado ou sair do tabuleiro, a menos que esse quadrado seja ocupado por uma peça da outra cor. Por exemplo, uma peça branca pode passar para um quadrado ocupado por uma peça preta, mas não uma peça branca. Além disso, nenhuma peça, exceto Cavaleiros, pode se mover para quadrados diretamente obstruídos por outra peça.
- Um movimento por parte B à estaca C é "directamente obstruída" por pedaço A , se A é directamente, numa linha recta (ortogonal ou diagonal), entre B e C .
- Qualquer peça : A posição do rei também pode afetar a validade do movimento de uma peça. Se uma dessas duas condições for atendida, a movimentação será inválida:
- Expor o rei para verificar, movendo uma peça do mesmo lado que o rei em perigo. Isso só se aplica se uma peça não-oponente fizer o movimento, ao invés de uma peça oponente que se move para colocar o rei em xeque.
- Deixando o rei sob controle, caso em que ele deve sair do controle. Portanto, se o rei estiver em xeque e o lance determinar que outra peça se mova, é um lance inválido, a menos que a outra peça esteja impedindo o xeque. Uma peça pode impedir o teste de duas maneiras: ou leva a peça a executar o teste ou obstrui o caminho entre a peça que executa o teste e o rei.
- Um "cheque" é uma situação em que o oponente do rei pode (se for a sua vez de se mover) legalmente mover uma peça para esse rei. Esta regra não se aplica recursivamente, ou seja, um rei está em xeque, mesmo que o movimento do oponente para esse rei deixe seu próprio rei em xeque.
- Peões : Um peão pode se mover para frente (ou seja, para cima se for branco, para baixo se for preto) um quadrado para um quadrado desocupado. Existem também três situações especiais:
- Se o peão ainda não se moveu (você pode determinar isso usando a coordenada Y; os peões brancos não se moveram se a coordenada Y for 2, os peões pretos não se moveram se a coordenada Y for 7), o peão é permitido mover dois quadrados para frente para um quadrado desocupado.
- Se houver uma peça do oponente na diagonal na frente do peão (ou seja, na praça a noroeste ou nordeste do peão, se for branca, ou ao sudoeste ou sudeste, se for preta), o peão pode passar para a praça ocupada em questão.
- Se um peão se mover para a coordenada Y final (8 para branco ou 1 para preto) nas regras normais de xadrez, ele deve ser promovido a uma rainha, torre, cavaleiro ou bispo da mesma cor. Para os fins desta pergunta, a escolha da promoção é irrelevante para o movimento ser válido ou não (e não pode ser expresso no formato de entrada), mas os movimentos de peão que resultariam em promoção devem ser permitidos.
- Bispos : os bispos podem se mover entre 1 e 8 quadrados ao longo de qualquer caminho intercardinal contínuo não obstruído (ou seja, diagonal).
- Cavaleiros : os cavaleiros podem se mover em uma
L
forma, consistindo em um dos seguintes movimentos (equivalentes):- Um único quadrado em qualquer direção cardinal, seguido de uma curva de 90/270 °, seguido de um movimento final de 2 quadrados à frente.
- 2 quadrados em qualquer direção cardinal, seguidos de uma volta de 90/270 °, seguida de um movimento final de um único quadrado para a frente.
- Torres : As torres podem se mover entre 1 e 8 quadrados ao longo de qualquer caminho cardinal contínuo não obstruído.
- Rainhas : as rainhas podem se mover entre 1 e 8 quadrados ao longo de qualquer caminho contínuo não obstruído, cardinal ou intercardinal (isto é, diagonal).
- Reis : Os reis se movem como rainhas, exceto que estão limitados a mover apenas um quadrado por movimento (ou seja, um rei só pode se mover para quadrados adjacentes cardinal ou diagonalmente). Como lembrete, você não pode fazer um movimento que deixe seu rei sob controle; portanto, você também não pode colocar seu rei em xeque.
As regras do xadrez também contêm jogadas especiais chamadas "rolagem" e "en passant". No entanto, como a legalidade dessas jogadas depende do histórico do jogo, não apenas da posição atual (e porque o castell exige mover duas peças ao mesmo tempo, o que não se encaixa no formato de entrada), você deve considerar nenhuma dessas jogadas existir (isto é, um movimento que seria arremessado ou passivo deveria ser considerado ilegal).
Você pode produzir dois resultados distintos para indicar a validade de uma movimentação e pode receber a entrada no método que desejar. Você também pode escolher indexação 0 em vez de indexação 1 para as posições, se preferir. Este é um código de golfe , então o código mais curto vence!
Casos de teste
Board
Move => Output (Reason)
[["B", "K", 3, 8], ["B", "Q", 1, 5], ["B", "N", 4, 7], ["B", "N", 7, 8], ["B", "B", 2, 4], ["B", "R", 4, 8], ["B", "R", 8, 8], ["B", "P", 1, 7], ["B", "P", 2, 7], ["B", "P", 3, 6], ["B", "P", 5, 6], ["B", "P", 6, 7], ["B", "P", 7, 7], ["B", "P", 8, 7], ["W", "K", 5, 1], ["W", "Q", 6, 3], ["W", "N", 3, 3], ["W", "B", 5, 2], ["W", "B", 6, 4], ["W", "R", 1, 1], ["W", "R", 8, 1], ["W", "P", 1, 3], ["W", "P", 2, 2], ["W", "P", 3, 2], ["W", "P", 4, 4], ["W", "P", 6, 2], ["W", "P", 7, 2], ["W", "P", 8, 3]]
["W", "R", 8, 2] => True (The rook on h1 can move forward one)
[['B', 'K', 6, 8], ['B', 'Q', 1, 7], ['B', 'N', 1, 3], ['B', 'N', 7, 1], ['B', 'B', 8, 8], ['B', 'B', 2, 5], ['B', 'R', 4, 3], ['B', 'R', 1, 5], ['B', 'P', 5, 5], ['B', 'P', 7, 2], ['B', 'P', 5, 7], ['B', 'P', 5, 6], ['B', 'P', 4, 4], ['W', 'K', 7, 3], ['W', 'Q', 3, 2], ['W', 'N', 4, 8], ['W', 'N', 7, 5], ['W', 'B', 1, 1], ['W', 'B', 8, 1], ['W', 'R', 1, 8], ['W', 'R', 3, 7], ['W', 'P', 8, 2], ['W', 'P', 6, 3], ['W', 'P', 4, 2], ['W', 'P', 1, 4], ['W', 'P', 8, 7]]
['W', 'N', 1, 5] => False (Neither knight to move to a5 from where they are)
[['B', 'K', 7, 3], ['B', 'Q', 2, 4], ['B', 'N', 5, 2], ['B', 'N', 1, 6], ['B', 'B', 7, 7], ['B', 'B', 1, 8], ['W', 'K', 7, 1], ['W', 'Q', 6, 1], ['W', 'N', 5, 6], ['W', 'N', 3, 3], ['W', 'B', 2, 2], ['W', 'B', 6, 5]]
['B', 'K', 8, 3] => False (The white bishop would put the king in check)
[['B', 'K', 7, 6], ['B', 'Q', 8, 3], ['B', 'N', 7, 7], ['B', 'N', 8, 7], ['B', 'B', 2, 2], ['B', 'B', 3, 8], ['B', 'R', 1, 1], ['B', 'R', 1, 6], ['B', 'P', 8, 5], ['B', 'P', 4, 3], ['B', 'P', 8, 6], ['W', 'K', 7, 8], ['W', 'Q', 7, 2], ['W', 'N', 5, 1], ['W', 'N', 4, 6], ['W', 'B', 1, 2], ['W', 'B', 2, 6], ['W', 'R', 4, 4], ['W', 'R', 3, 6], ['W', 'P', 5, 2], ['W', 'P', 6, 2]]
['B', 'N', 5, 8] => False (The white queen currently has the king in check, and this move doesn't prevent that)
[['B', 'K', 7, 6], ['B', 'Q', 8, 3], ['B', 'N', 7, 7], ['B', 'N', 8, 7], ['B', 'B', 2, 2], ['B', 'B', 3, 8], ['B', 'R', 1, 1], ['B', 'R', 1, 6], ['B', 'P', 8, 5], ['B', 'P', 4, 3], ['B', 'P', 8, 6], ['W', 'K', 7, 8], ['W', 'Q', 7, 2], ['W', 'N', 5, 1], ['W', 'N', 4, 6], ['W', 'B', 1, 2], ['W', 'B', 2, 6], ['W', 'R', 4, 4], ['W', 'R', 3, 6], ['W', 'P', 5, 2], ['W', 'P', 6, 2]]
['B', 'N', 7, 5] => True (The king is in check, and the knight blocks that)
[['B', 'K', 8, 3], ['B', 'Q', 6, 5], ['B', 'N', 7, 8], ['B', 'N', 3, 7], ['B', 'B', 4, 1], ['B', 'B', 1, 1], ['W', 'K', 7, 7], ['W', 'Q', 7, 1], ['W', 'N', 2, 2], ['W', 'N', 1, 3], ['W', 'B', 3, 5]]
['B', 'B', 2, 2] => True (takes the white knight)
[['B', 'K', 6, 1], ['B', 'Q', 6, 2], ['W', 'K', 8, 1]]
['B', 'Q', 7, 1] => True (Smallest checkmate possible, in terms of bounding box)
Esse desafio foi marcado na caixa de areia . Ele recebeu votos negativos, sem nenhuma explicação, então eu decidi publicá-lo de qualquer maneira
fonte
Respostas:
Python 2 (com python-xadrez ),
141 138 134 133 133132 bytesSem fazer nenhum código realmente interessante - mas talvez isso possa competir com os idiomas do golfe ou (ouso mencionar) o Mathematica?
Nota: python-xadrez é um PyPI pacote de instalá-lo em Python 2.7.9+ com:
python -m pip install python-chess
)Um programa completo que aceita entrada de três itens:
PRNBQK
)a1
está0
,b1
é1
, ...a2
é8
, ...,h8
é63
,O programa gera através do seu código de saída uma entrada válida:
1
se o movimento for válido (o programa gerou um erro - devido à divisão por zero);0
não é (o programa sai normalmente)(Não) Experimente online!(porque o pacote python-chess não está instalado lá e o TIO não permite conectividade com a Internet, portanto, o código de instalação do pip no cabeçalho não funciona).
Note-se que o operador poder em Python faz
1**1 == 1**0 == 0**0 == 1
, mas0**1 == 0
... daí
1/0**1
levanta uma divisão por zero erro enquanto1/1**1
,1/1**0
e1/0**0
todos conseguem(... e que em Python
False
eTrue
equivale a0
e1
respectivamente).fonte
str(S.piece_at(m.from_square))==p for
parap==str(S.piece_at(m.from_square))for
, isso deve salvar um byte.repr
usando backticks para substituirstr
para salvar ...Regex (PCRE2),
931925837 bytesEssa solução parte da declaração do problema em que dois estados da placa são passados para a regex, em vez de um estado da placa e uma mudança. A mudança é inferida a partir da diferença entre os dois estados do conselho. Então, eu fiz o trabalho do programa TIO em levar os casos de teste no formato fornecido por esta pergunta, encontrar todas as instâncias da peça descrita no quadro e, com cada uma, tentar movê-la para a posição de destino e avaliar a regex com essa possibilidade, descobrindo se algum é relatado pelo regex como válido. Se não estiver certo, me avise; é possível implementar uma regex como position + move, mas seria muito menos elegante e exigiria uma refatoração séria.
A placa está representada em 8 × 8 ASCII onde peças brancas são maiúsculas e minúsculas preto são: P aresta, k N ight, B ishop, R OOK, Q ueen, K ing. O lado das pretas (8ª posição) está no topo e o lado das brancas (1ª posição) está no fundo. Cada classificação é separada por uma nova linha e os quadrados vazios são marcados como
-
. As duas posições do quadro são separadas por uma nova linha extra.O objetivo real deste projeto é validar jogos inteiros, não apenas movimentos únicos. Veja abaixo o estado atual do progresso.
Experimente online!
Bastante impresso e parcialmente sem golfe (as refexs absolutas foram alteradas para relativas e os grupos de captura alterados para não captura ou, em alguns casos, atômicos por velocidade):
-88 bytes usando chamadas de sub-rotina não atômicas, redirecionando assim de PCRE1 para PCRE2
A versão acima foi modificada para não permitir passantes ou roque, mas o projeto completo está atualmente em um estado em que valida todo tipo de movimento, começando no estado inicial do tabuleiro (que deve ser a posição inicial do xadrez - o Chess960 não é suportado, pelo menos). As regras completas de en passant e castling são aplicadas.
Aqui está um exemplo de jogo validado pelo regex completo (PCRE1 - ainda não redirecionado) [regex101.com] .
Um movimento inválido fará com que todas as posições subseqüentes do quadro não sejam correspondidas / destacadas. A detecção de xeque-mate / impasse e, portanto, a detecção de quem é o vencedor (ou se é um empate), ainda não foram implementadas; é por isso que o estado final do quadro neste exemplo não é destacado.
Aqui está um programa C / C ++ que converte notação algébrica no formato reconhecido por este regex. Atualmente, a notação algébrica deve ser colocada na forma de uma matriz embutida no código-fonte, com seqüências separadas para cada movimento, mas lendo-a como uma sequência única de stdin ou um argumento da linha de comando, com toda a sequência de movimentos separados por espaços e números de movimentação terminados em pontos, está planejado.
Eu também comecei em um regex que valida um jogo completo apenas em notação algébrica de xadrez, com a posição inicial padrão sendo implícita. Tudo o que precisa é de uma "placa de rascunho" vazia anexada ao final da entrada (após a lista de movimentos). Tenho certeza de que é possível implementar isso na íntegra e planejo concluí-lo em algum momento.
fonte