O problema geral de SAT (satisfação booleana) é NP-completo. Mas 2-SAT , onde cada cláusula tem apenas 2 variáveis, está em P . Escreva um solucionador para 2-SAT.
Entrada:
Uma instância 2-SAT, codificada em CNF da seguinte maneira. A primeira linha contém V, o número de variáveis booleanas e N, o número de cláusulas. Em seguida, seguem N linhas, cada uma com 2 números inteiros diferentes de zero, representando os literais de uma cláusula. Inteiros positivos representam a variável booleana especificada e inteiros negativos representam a negação da variável.
Exemplo 1
entrada
4 5
1 2
2 3
3 4
-1 -3
-2 -4
que codifica a fórmula (x 1 ou x 2 ) e (x 2 ou x 3 ) e (x 3 ou x 4 ) e (não x 1 ou não x 3 ) e (não x 2 ou não x 4 ) .
A única configuração das 4 variáveis que tornam toda a fórmula verdadeira é x 1 = falso, x 2 = verdadeiro, x 3 = verdadeiro, x 4 = falso , portanto, seu programa deve gerar a única linha
resultado
0 1 1 0
representando os valores verdadeiros das variáveis V (em ordem de x 1 a x V ). Se houver várias soluções, você poderá gerar qualquer subconjunto não vazio, um por linha. Se não houver solução, você deve produzir UNSOLVABLE
.
Exemplo 2
entrada
2 4
1 2
-1 2
-2 1
-1 -2
resultado
UNSOLVABLE
Exemplo 3
entrada
2 4
1 2
-1 2
2 -1
-1 -2
resultado
0 1
Exemplo 4
entrada
8 12
1 4
-2 5
3 7
2 -5
-8 -2
3 -1
4 -3
5 -4
-3 -7
6 7
1 7
-7 -1
resultado
1 1 1 1 1 1 0 0
0 1 0 1 1 0 1 0
0 1 0 1 1 1 1 0
(ou qualquer subconjunto não vazio dessas três linhas)
Seu programa deve lidar com todos os N, V <100 em um tempo razoável. Tente este exemplo para garantir que seu programa possa lidar com uma grande instância. O menor programa vence.
Respostas:
Haskell, 278 caracteres
Não força bruta. É executado em tempo polinomial. Resolve o problema difícil (60 variáveis, 99 cláusulas) rapidamente:
E, na verdade, a maior parte desse tempo é gasta compilando o código!
Arquivo de origem completo, com casos de teste e testes de verificação rápida disponíveis .
Ungolf'd:
Na versão golf'd,
satisfy
eformat
foram incorporadosreduce
, embora, para evitar a passagemn
,reduce
retorne uma função de uma lista de variáveis ([1..n]
) para o resultado da string.s
um operador, melhor manipulação da nova linha∮
como operador!★
então teste agora renomeado∈
fonte
J,
119103Passa em todos os casos de teste. Sem tempo de execução perceptível.Edit: Eliminado
(n#2)
en=:
, assim , assim como eliminando algumas parênteses de classificação (obrigado, isawdrones). Tácito-> explícito e diádico-> monádico, eliminando mais alguns caracteres cada.}.}.
para}.,
.Edit: Opa. Isso não é apenas uma solução para N grande, mas
i. 2^99x
-> "erro de domínio" para adicionar insulto à estupidez.Aqui está a versão original não destruída e uma breve explicação.
input=:0&".;._2(1!:1)3
corta a entrada nas novas linhas e analisa os números em cada linha (acumulando os resultados na entrada).n
, matriz de cláusulas atribuída aclauses
(não precisa da contagem de cláusulas)cases
é 0..2 n -1 convertido em dígitos binários (todos os casos de teste)(Long tacit function)"(_,1)
é aplicado a cada casocases
com todosclauses
.<:@|@[{"(0,1)]
obtém uma matriz dos operandos das cláusulas (pegando abs (número da operação) - 1 e desreferenciando do caso, que é uma matriz)*@>:@*@[
obtém uma matriz em forma de cláusula de bits 'not not' (0 para not) via abuso de signum.=
aplica os bits não aos operandos.[:*./[:+./"1
aplica+.
(e) nas linhas da matriz resultante e*.
(ou) no resultado disso.*@+/
aplicado aos resultados fornece um 0 se houver resultados e 1 se não houver nenhum.('UNSOLVABLE'"_)
`(#&cases) @.(*@+/) results
executa a função constante fornecendo 'UNSOLVABLE' se 0 e uma cópia de cada elemento 'solução' dos casos se 1.echo
imprime mágico o resultado.fonte
"(_,1)
para"_ 1
.#:
funcionaria sem o argumento esquerdo.K - 89
O mesmo método que a solução J.
fonte
Ruby, 253
Mas é lento :(
Muito legível, uma vez expandido:
fonte
OCaml + baterias,
438436 caracteresRequer um nível superior de pilhas OCaml incluídas:
Devo confessar que esta é uma tradução direta da solução Haskell. Em minha defesa, que por sua vez é um direto de codificação do algoritmo apresentado aqui [PDF], com a mútua
satisfy
-eliminate
recursão rolado em uma única função. Uma versão não ofuscada do código, menos o uso de baterias, é:(o
iota k
trocadilho que espero que você perdoe).fonte