Isso é código-golfe .
Neste desafio, escreveremos programas / funções que resolvem quebra-cabeças " Cavaleiros e Cavaleiros ".
fundo
Você encontra-se em uma ilha ... etc ... cada pessoa na ilha, exceto para você ou é um cavaleiro ou de um patife .
Cavaleiros só podem fazer afirmações verdadeiras .
Knaves só podem fazer declarações falsas .
Não quero definir rigorosamente "afirmação", mas diremos que uma afirmação é qualquer coisa que seja "verdadeira" ou "falsa". Observe que isso exclui sentenças paradoxais.
Para os propósitos deste desafio, você encontrará grupos de ilhéus; eles farão declarações para você.
Sua tarefa é determinar quem é um cavaleiro e quem é um valete.
Entrada:
Você receberá (em qualquer formato razoável) as seguintes informações:
Uma lista das pessoas presentes. Eles serão nomeados com caracteres do alfabeto em maiúsculas "AZ". O limite do número de pessoas imposto por isso não será excedido.
As declarações que cada pessoa faz. Veja abaixo detalhes importantes sobre isso.
Resultado
Você então produzirá (em qualquer formato razoável) o que cada pessoa é. Por exemplo, se houvesse jogadores A B C D
e A
fosse um cavaleiro, mas o resto fosse um cavaleiro, você poderia produzir
A: 1
B: 0
C: 0
D: 0
Detalhes importantes:
Os caracteres do alfabeto em maiúsculas AZ referem-se aos ilhéus.
Os caracteres
0
(zero) e1
(um) referem-se a um "Valete" e um "Cavaleiro", respectivamente. (Você pode outros dois caracteres que não sejam AZ, desde que você especifique)Cada ilhéu presente pode fazer qualquer número natural de declarações ou optar por não dizer nada.
Os operadores lógicos normais podem ser usados em instruções ( IS *, AND, OR, NOT ). Além disso, as Leis e Condicionais de De Morgan podem ser usadas. A seguir, exemplos de como eles podem ser apresentados em um quebra-cabeça falado, seguidos de como eles podem ser inseridos no seu programa.
(* em uma nota mais técnica. O operador "IS" é realmente usado como contenção (o que não é um operador lógico). Quando digo "A é um cavaleiro", quero dizer realmente "A é um membro do conjunto de Knights ". O verdadeiro operador usado seria 'ϵ'. Por uma questão de simplicidade, usaremos '='.)
Eu uso o seguinte (você pode usar o que for, desde que seja razoável e consistente):
^
Ev
OU=
É~
NÃO=>
IMPLIESX:
A pessoa X afirma que ...
A pessoa Z pode fazer qualquer combinação de qualquer um dos seguintes tipos de declarações:
A pessoa Z diz que ...
A pessoa A é um cavaleiro.
Z: A = 1
A pessoa Q é um valete.
Z: Q = 0
Eu sou um cavaleiro.
Z: Z = 1
A pessoa A é um cavaleiro OU a pessoa B é um cavaleiro.
Z: ( A = 1 ) v ( B = 1)
A pessoa C é um cavaleiro E eu sou um valete.
Z: ( C = 1 ) ^ ( Z = 0 )
A pessoa R NÃO é um cavaleiro.
Z: ~( R = 1 )
Além disso, as informações também podem usar as Leis de De Morgan
NÃO é verdade que a pessoa A e a pessoa B são escravas
Z: ~( ( A = 0 ) ^ ( B = 0 ) )
É falso que a pessoa A ou B seja um cavaleiro
Z: ~( ( A = 1 ) v ( B = 1) )
Finalmente, condicionais e suas negações podem ser usados
Se eu sou um Cavaleiro, a pessoa B é um Valete
Z: ( Z = 1 ) => ( B = 0 )
NÃO é verdade que, se a pessoa B é um cavaleiro, a pessoa C é um valete.
Z: ~( ( B = 1 ) => ( C = 0 ) )
Notas sobre condicionais
Confira a Wikipedia para mais informações.
Uma declaração condicional assume a forma p => q , onde p e q são elas mesmas. p é o "antecedente" e q é o "conseqüente". Aqui estão algumas informações úteis
A negação de uma condição é assim: ~ (p => q) é equivalente a p ^ ~ q
Uma premissa falsa implica qualquer coisa. Ou seja: se p for falso, qualquer afirmação p => q é verdadeira, independentemente do que seja q . Por exemplo: "se 2 + 2 = 5, então eu sou o Homem-Aranha" é uma afirmação verdadeira.
Alguns casos de teste simples
Esses casos são apresentados da seguinte maneira (1) como colocaríamos o problema na fala (2) como poderíamos colocá-lo no computador (3) a saída correta que o computador poderia fornecer.
A pessoa A e a pessoa B abordam você na estrada e fazem as seguintes declarações:
A: B é um cavaleiro ou eu sou um cavaleiro.
B: A é um cavaleiro.
Responda:
B é um cavaleiro e A é um cavaleiro.
Entrada:
A B # Cast of Characters
A: ( B = 0 ) v ( A = 1)
B: A = 1
Resultado:
A = 1 B = 1
As pessoas A, B e F se aproximam de você na estrada e fazem as seguintes declarações:
A: Se eu sou um Cavaleiro, então B é um Valete.
B: Se isso é verdade, então F também é um valete.
Responda:
A é um cavaleiro, B é um valete, F é um cavaleiro.
Entrada
A B F
A: ( A = 1 ) => ( B = 0 )
B: ( A = 1 ) => ( F = 0 )
Resultado:
A = 1 B = 0 F = 1
Q, X e W se aproximam de você na estrada e faça as seguintes declarações:
W: Não é verdade que Q e X são cavaleiros.
P: Isso é verdade.
X: Se o que W diz é verdadeiro, o que Q diz é falso.
Responda:
W e Q são cavaleiros. X é um valete.
Entrada
Q X W
W: ~( ( Q = 1 ) ^ ( X = 1 ) )
Q: W = 1
X: ( W = 1 ) => ( Q = 0 )
Resultado
W = 1 Q = 1 X = 0
Há um desafio semelhante de 3 anos atrás que se concentra na análise e não contém condicionais ou de De Morgan. E, portanto, eu diria, é diferente o suficiente no foco e na implementação para evitar que isso seja um engodo.
Este desafio foi brevemente encerrado como um tolo. Desde então, foi reaberto.
Afirmo que esse desafio é, em primeiro lugar, diferente em foco. O outro desafio se concentra na análise em inglês, isso não acontece. Segundo, ele usa apenas AND e OR, enquanto isso usa condicionais e permite a solução de muitos outros quebra-cabeças. No final das contas, a questão é se as respostas desse desafio podem ou não ser trivialmente substituídas por essa, e acredito que a inclusão de condicionais e negações condicionais adiciona complexidade suficiente para que mudanças mais robustas precisem ser feitas para que para se encaixar nesse desafio.
(B=1)=>(C=0)
?~((B=1)=>(C=0))
ou(B=1)=>(C=1)
ou algo mais?OR
, pode serA:1 B:1
ouA:1 B:0
porque os BB=1
podem ser falsos enquanto A ainda é verdadeiro.(B=1)^(C=1)
acordo com o modo como os condicionais são normalmente tratados.Respostas:
Python 3,
450342307 bytesEdit: Acontece que eu esqueci uma importação ...
Minha primeira solução tira vantagem de ter nomes flexíveis para consultas
Você pode ligar para o acima com
O próximo aqui usa o mesmo formato de consultas do OP, mas também não possui algumas das modificações que fiz no primeiro. É 417 bytes porque converte entre os dois formatos.
E pode ser chamado por:
Ambos retornam
Explicação Ungolfed:
Além disso, a segunda solução precisa de 3,5 (não 3,4) devido ao uso do PEP 448
fonte
Mathematica, 80 bytes
Explicação
A função
F
usa dois argumentos,c
é uma lista dos nomes de todos os personagens,s
é uma lista de declarações, cada uma das quais contém duas partes - quem diz o quê.Por exemplo, existem três caracteres, Q, X e W.
E eles dizem:
onde
True
eFalse
significa Cavaleiros e Cavaleiros, respectivamente. Entãodará
{{q->True, x->False, w->True}}
, o que significa que há apenas uma solução que Q e W são cavaleiros enquanto X é um valete. Se houver mais de uma solução, a saída será semelhante a{{...},{...},...}
O algoritmo é muito simples.
{True,False}~Tuples~Length@c
dá todas as combinações possíveis de cavaleiros e cavaleiros entre os personagens. Em seguida,Thread[c->#]&/@
construa uma matriz de regras com base nessas combinações. No caso de dois caracteres A e B, a matriz seráSubstituindo as instruções por uma linha dessas regras, obteremos uma matriz semelhante a
A primeira coluna dessa matriz é a identidade dos alto-falantes e a segunda coluna indica se suas declarações são verdadeiras ou falsas. Uma solução válida exige o acordo entre as identidades dos oradores e suas declarações. A matriz acima significa que essa combinação não é uma solução, pois o segundo orador, um Knight, faz uma declaração incorreta.
faz as substituições e seleciona as combinações que atendem à condição.
fonte
Ruby, 128
Este é o mesmo algoritmo que todos os outros, tente todas as combinações possíveis de knaves e knights e veja quais paus. Tenho outro em que estou trabalhando, mas acho que será mais longo (embora mais interessante).
As entradas da instrução devem ser:
&
E|
OU==
É!
NÃO>
IMPLIESX:
A pessoa X afirma que ...Também exijo que cada declaração e sub-declaração esteja entre parênteses. O único problema com esta versão é que ela passa por no máximo 2 ^ 26 iterações e, se não forem todos knaves, pelo menos 2 ^ (26-n) iterações ! Para colocar isso em perspectiva, isso significa que, se houver duas pessoas, e pelo menos uma não for um knave, serão necessárias no mínimo 16.777.216 iterações !
Para limitar isso, envio o seguinte em 168 bytes. Submarino
26
para#{o.size}
reduzi-lo a 161.Mas se eu puder usar um conjunto de pessoas e um mapa de declarações, por exemplo:
Então eu diminuo para 128.
fonte