Golf todos os 16 portões lógicos com 2 entradas e 1 saída!


63

Por exemplo, o portão A and Bé um portão lógico com 2 entradas e 1 saída.

Existem exatamente 16 deles, porque:

  • cada porta lógica recebe duas entradas, que podem ser verdadeiras ou falsas, fornecendo 4 entradas possíveis
  • das 4 entradas possíveis, cada uma pode ter uma saída de verdade e falsey
  • portanto, existem 2 ^ 4 portas lógicas possíveis, que são 16.

Sua tarefa é escrever 16 programas / funções que implementam todos eles separadamente.

Suas funções / programas devem ser independentes .

Eles são válidos desde que apresentem valores truthy / falsey, o que significa que você pode implementar A or Bno Python como lambda a,b:a+b, mesmo que 2seja produzido para A=Truee B=True.

Pontuação é o total de bytes usados ​​para cada função / programa.

Lista de portas lógicas

  1. 0,0,0,0 ( false)
  2. 0,0,0,1 ( and)
  3. 0,0,1,0 ( A and not B)
  4. 0,0,1,1 ( A)
  5. 0,1,0,0 ( not A and B)
  6. 0,1,0,1 ( B)
  7. 0,1,1,0 ( xor)
  8. 0,1,1,1 ( or)
  9. 1,0,0,0 ( nor)
  10. 1,0,0,1 ( xnor)
  11. 1,0,1,0 ( not B)
  12. 1,0,1,1 ( B implies A)
  13. 1,1,0,0 ( not A)
  14. 1,1,0,1 ( A implies B)
  15. 1,1,1,0 ( nand)
  16. 1,1,1,1 ( true)

Onde o primeiro número é a saída A=false, B=false, o segundo número é a saída A=false, B=true, o terceiro número é a saída A=true, B=false, o quarto número é a saída A=true, B=true.

Entre os melhores


2
Suas funções / programas podem compartilhar código. O que isto significa? Além disso, os programas podem estar em diferentes idiomas?
Lynn

2
Acho a explicação confusa: "das 4 entradas possíveis que cada uma pode ter e produzir verdade e falsidade". Isso não implica 8 (4 * 2) estados?
DavidC

4
Os nomes que estão faltando são os portões AND-NOT (A AND NOT B e B AND NOT A).
Mego

14
Então aconteceu de novo. Existem 18 respostas, a maioria simples e corretas, e do nada a pergunta se tornou "pouco clara o que você está perguntando". Eu não gosto de um desafio, vá em frente, pegue outro, não feche!
Edc65

4
@dorukayhan See: verdade vazia
Sp3000 15/06

Respostas:


110

Dominó , 122.000 bytes ou 72 blocos

A contagem de bytes é o tamanho do arquivo salvo que é 0.122 MB.

A computação dominó foi a inspiração. Eu testei tudo isso até simetria (e além!) Através de um jogo Steam de realidade virtual chamado Tabletop Simulator .

Detalhes

  • I / O
    • Iniciar - Isso está incluído para maior clareza (não contado no total) e é o que 'chama' ou 'executa' a função. Deve ser 'pressionado' após a entrada ser dada [Amarelo] .
    • Entrada A - Isso é incluído para maior clareza (não contado no total) e é 'pressionado' para indicar a 1e não pressionado de outra forma [Verde] .
    • Entrada B - É incluída para maior clareza (não contada no total) e é 'pressionada' para indicar a 1e não pressionada de outra forma [Azul] .
    • Saída - Isso é contabilizado no total. É o dominó que declara o resultado do portão lógico [preto] .
  • T / F
    • Um dominó de saída caído representa um resultado Trueou1
    • Um dominó de saída permanente representa um resultado Falseou0
  • Pressionando
    • Para dar entrada ou iniciar a cadeia, crie o mármore de metal
    • Defina a força de elevação para 100%
    • Levante o mármore acima do dominó desejado
    • Largue o mármore

insira a descrição da imagem aqui

Portões

  • falso, 1
    • insira a descrição da imagem aqui
  • e 6 4
    • insira a descrição da imagem aqui
  • A e não B, 4 3
    • insira a descrição da imagem aqui
  • A, 1
    • insira a descrição da imagem aqui
  • não A e B, 4 3
    • insira a descrição da imagem aqui
  • B 1
    • insira a descrição da imagem aqui
  • xor, 15 11
    • insira a descrição da imagem aqui
  • ou 1
    • insira a descrição da imagem aqui
  • nem 3 2
    • insira a descrição da imagem aqui
  • xnor, 17 13
    • insira a descrição da imagem aqui
  • não B, 2
    • insira a descrição da imagem aqui
  • B implica A, 7 6
    • insira a descrição da imagem aqui
  • não A, 2
    • insira a descrição da imagem aqui
  • A implica B, 7 6
    • insira a descrição da imagem aqui
  • nand, 16 15
    • insira a descrição da imagem aqui
    • verdade 1
    • insira a descrição da imagem aqui

TL; DR

Eu estava esperando / querendo um desafio de dominó e, quando vi isso, não pude deixar passar. O único problema era que aparentemente ninguém mais possui dominó! Então, finalmente, desisti e comprei um Double Twelve . Este conjunto possui 91 peças, o que me deu a idéia de ter uma 'chamada de função' / iniciar dominó em vez do método normal (longo) de 'atraso de tempo'. O crédito para a curva de 90 graus pertence ao canal dominoesdouble07 .

Depois de construí-las com dominós físicos, foi decidido que as soluções válidas deveriam ser digitais. Então eu recriei esses portões no Tabletop Simulator . Infelizmente, TS e realidade não concordam com a física de dominó. Isso exigiu que eu adicionasse 11 dominós, mas também salvei 8. No geral, os dominós virtuais são cerca de 150 vezes mais eficazes em termos de construção e teste ( Ctrl+ Z).

Atualizar

  • -9 [17-03-13] Encurtadoxor xnor nand
  • [17-03-04] Link adicionado ao arquivo do workshop
  • +11 [17-03-03] Adicionado digital xnorexor
  • -8 [17-03-03] Digitou todos os portões (exceto xore xnor). O bloqueio na mesa requer apenas 1 dominó, em vez de 2.
  • [16-09-23] Imagens reduzidas
  • -11 [16-09-18] Quase corte xor ao meio novamente. Obrigado a @DJMcMayhem pelo xnor e Joe pelo xor.
  • -31 [16-08-31] Atualizou algumas fotos e raspou alguns ladrilhos e cortou xor ao meio
  • [16-08-28] Adicionou fotos

43
+1 Precisamos de mais dominó no PPCG
Beta Decay


7
Uau. Esta é uma das respostas mais originais que eu já vi neste site.
DJMcMayhem

3
Parece que você pode tirar um dominó se esmagar o xnor e tiver 4 no topo, em vez de 5. Então, novamente, eu não testei nada.
DJMcMayhem

2
Obrigado por reservar um tempo para fazer desta uma resposta válida. No entanto, o link para o arquivo de origem é um pouco difícil de encontrar. Normalmente, o link no cabeçalho leva ao próprio idioma. Então, eu o vincularia ao jogo a vapor e colocaria o link para o "arquivo de origem" real em um link separado e claramente identificado em algum lugar do corpo da resposta.
Martin Ender

45

Hexagonia , 89 bytes

Agradecemos a FryAmTheEggman por alguma inspiração necessária para a solução XOR.

0000 !@
0001 ?.|@!
0010 #?#!)@
0011 ?!@
0100 +?|@!?
0101 ??!@
0110 ?<@!!<_\~(
0111 ?<<@!
1000 )\!#?@{
1001 (~?/@#!
1010 ??|@!)
1011 \#??!1@
1100 ?(~!@
1101 ?.|@!)
1110 ?$@#)!<
1111 1!@

Todos os programas usam 0para false e 1true.

Experimente online! Este não é um conjunto de testes, você deverá copiar os diferentes programas e entradas.

A solução acima está dentro de 2 bytes de otimização (a menos que relaxemos a interpretação da verdade / falsidade, eu acho). Eu deixei uma pesquisa de força bruta correr para perto de dois dias sobre todos os programas que se encaixam no lado de comprimento 2, ou seja, até 7 bytes (não completamente todos os programas - Eu fiz algumas suposições sobre o que todas as necessidades programa válido eo que não programa válido poderia ter). A pesquisa encontrou soluções para 15 dos 16 portões possíveis - e muitas vezes muito mais do que apenas um. Você pode encontrar uma lista de todas as soluções alternativas nesta pasta onde também as agrupei por comportamento equivalente. As que estou mostrando acima selecionei porque são a solução mais simples ou a mais interessante, e adicionarei explicações para elas amanhã.

Quanto ao 16º portão: XOR é o único portão que aparentemente não pode ser implementado em 7 bytes. Infelizmente, uma pesquisa de força bruta em programas maiores não é viável com o código que tenho atualmente. Então o XOR teve que ser escrito à mão. O mais curto que encontrei até agora é o programa de 10 bytes acima, que se baseia em uma tentativa falha (mas muito próxima) do FryAmTheEggman. É possível que exista uma solução de 8 ou 9 bytes, mas fora isso, todas as soluções devem ser ótimas.

Explicações

Aviso: parede de texto. Se alguém estiver interessado em saber como esses programas Hexagony altamente compactados realmente funcionam, incluí explicações abaixo para cada um deles. Tentei escolher a solução mais simples para cada porta nos casos em que existe mais de um programa ideal, a fim de manter as explicações razoavelmente curtas. No entanto, alguns deles ainda confundem a mente, então pensei que eles merecem um pouco mais de elaboração.

0000: False

Não acho que precisaremos de um diagrama para este:

 ! @
. . .
 . .

Como toda a grade de memória é inicializada em zeros, !simplesmente imprime um zero e @finaliza o programa.

Essa também é a única solução de 2 bytes.

0001: E

 ? .
| @ !
 . .

Isso basicamente implementa curto-circuito . O diagrama cinza abaixo mostra o início do programa, onde a primeira entrada é lida ?e o ponteiro de instrução (IP) envolve o canto esquerdo, onde o |espelho o reflete. Agora, o canto atua como condicional; portanto, existem dois caminhos de execução diferentes, dependendo do valor da primeira entrada. O diagrama vermelho mostra o fluxo de controle para A = 0e o diagrama verde para A = 1:

Eu Eu Eu

Como você pode ver, quando o Aé 0, simplesmente o imprimimos e terminamos (lembre-se de que todos .são não-ops). Mas quando Aé 1, o IP percorre a primeira linha novamente, lendo Be imprimindo isso.

No total, existem dezesseis soluções de 5 bytes para esse gate. Quatorze deles são essencialmente os mesmos que os anteriores, usando em >vez de |ou substituindo o .comando por um comando efetivamente não operacional ou colocando ?na segunda posição:

?.|@!    .?|@!    ?=|@!    =?|@!    ?_|@!    _?|@!    ?0|@!
?.>@!    .?>@!    ?=>@!    =?>@!    ?_>@!    _?>@!    ?0>@!

E existem outras duas soluções (que são equivalentes entre si). Eles também implementam a mesma lógica de curto-circuito, mas os caminhos de execução são um pouco mais loucos (e são deixados como um exercício para o leitor):

?<!@|
?<!@<

0010: A e não B

 # ?
# ! )
 @ .

Isso também implementa uma forma de curto-circuito, mas devido ao uso do #fluxo de controle é muito mais complicado. #é um comutador IP condicional. Na verdade, o Hexagony vem com seis IPs rotulados 0como 5, que começam nos seis cantos da grade, apontando ao longo de sua borda no sentido horário (e o programa sempre começa com IP 0). Quando a #é encontrado, o valor atual é obtido no módulo 6e o fluxo de controle continua com o IP correspondente. Não sei ao certo qual ataque de loucura me fez adicionar esse recurso, mas certamente permite alguns programas surpreendentes (como este).

Vamos distinguir três casos. Quando A = 0, o programa é bastante simples, porque o valor é sempre 0quando #é encontrado, de forma que nenhuma alternância de IP ocorre:

Eu

#não faz nada, ?A(ou seja, também não faz nada), #ainda não faz nada, !imprime 0, )incrementa (isso é importante, caso contrário, o IP não iria para a terceira linha), @finaliza o programa. Simples o suficiente. Agora vamos considerar o caso (A, B) = (1, 0):

Eu

O caminho vermelho ainda corresponde ao IP 0, e eu adicionei o caminho verde para o IP 1. Vemos que, após as ?leituras A( 1desta vez), as #opções para o IP iniciam no canto superior direito. Isso significa que ?pode ler B( 0). Agora )incrementa isso para 1, de modo que o #canto superior esquerdo não faça nada e permanecemos com IP 1. As !impressões 1e o IP envolvem a diagonal esquerda. #ainda não faz nada e @finaliza o programa.

Finalmente, o caso realmente estranho em que ambas as entradas são 1:

Eu

Desta vez, a segunda entrada também é 1e a )incrementa 2. Isso significa que o #canto superior esquerdo causa outro switch IP para IP 2, indicado em azul. Nesse caminho, primeiro incrementamos ainda mais 3(embora isso seja irrelevante) e depois passamos pela ?terceira vez. Como agora atingimos o EOF (ou seja, a entrada está esgotada), ?retorna 0, !imprime isso e @finaliza o programa.

Notavelmente, esta é a única solução de 6 bytes para esse gate.

0011: UMA

 ? !
@ . .
 . .

Isso é simples o suficiente para não precisarmos de um diagrama: ?A, !imprime, @termina.

Essa é a única solução de 3 bytes para esse gate. (Em princípio, também seria possível ,;@, mas a pesquisa não incluiu ;, porque acho que nunca poderá salvar bytes !para esta tarefa.)

0100: B e não A

 + ?
| @ !
 ? .

Este é muito mais simples que o seu "irmão" 0010. O fluxo de controle é realmente o mesmo que vimos acima para 0001(E). Se A = 0, o IP percorre a linha inferior, lendo Be imprimindo isso antes de terminar. Se, A = 1então, o IP percorrer a primeira linha novamente, também lendo B, mas +adiciona duas bordas de memória não utilizadas, de modo que tudo o que faz é redefinir o valor atual para 0, para que !sempre seja impresso 0.

Existem várias alternativas de 6 bytes para isso (42 no total). Primeiro, há uma tonelada de soluções equivalentes às anteriores. Podemos novamente escolher livremente entre |e >, e +podemos ser substituídos por qualquer outro comando que nos dê uma vantagem vazia:

"?|@!?    &?|@!?    '?|@!?    *?|@!?    +?|@!?    -?|@!?    ^?|@!?    {?|@!?    }?|@!?
"?>@!?    &?>@!?    '?>@!?    *?>@!?    +?>@!?    -?>@!?    ^?>@!?    {?>@!?    }?>@!?

Além disso, também podemos usar em ]vez de ?. ]move para o próximo IP (ou seja, seleciona IP 1), para que esse ramo reutilize o ?no canto superior direito. Isso dá outras 18 soluções:

"?|@!]    &?|@!]    '?|@!]    *?|@!]    +?|@!]    -?|@!]    ^?|@!]    {?|@!]    }?|@!]
"?>@!]    &?>@!]    '?>@!]    *?>@!]    +?>@!]    -?>@!]    ^?>@!]    {?>@!]    }?>@!]

E há outras seis soluções que funcionam de maneira diferente com níveis variados de loucura:

/[<@!?    ?(#!@]    ?(#>@!    ?/@#/!    [<<@!?    [@$\!?

0101: B

 ? ?
! @ .
 . .

Woohoo, outro simples: ler A, ler B, imprimir B, encerrar. Na verdade, existem alternativas para isso. Como Aé apenas um caractere, também podemos lê-lo com ,:

,?!@

E também há a opção de usar um único ?e um espelho para percorrê-lo duas vezes:

?|@!    ?>@!

0110: Xor

  ? < @
 ! ! < _
\ ~ ( . .
 . . . .
  . . .

Como eu disse acima, esse foi o único portão que não caberia no lado 2, então essa é uma solução escrita à mão por FryAmTheEggman e por mim e há uma boa chance de que não seja o ideal. Existem dois casos para distinguir. Se A = 0o fluxo de controle for bastante simples (porque, nesse caso, precisamos apenas imprimir B):

Eu

Começamos no caminho vermelho. ?A, <é um ramo que desvia o zero restante. O IP _passa para o fundo, então é outro espelho e, quando atinge o canto, ele passa para o canto superior esquerdo e continua no caminho azul. ?B, !imprime. Agora o (diminui. Isso é importante porque garante que o valor não seja positivo (seja agora 0ou seja -1). Isso faz com que o IP seja quebrado no canto direito, onde @finaliza o programa.

Quando as A = 1coisas ficam um pouco mais complicadas. Nesse caso, queremos imprimir not B, o que por si só não é muito difícil, mas o caminho da execução é um pouco complicado.

Eu

Dessa vez, ele <desvia o IP corretamente e, em seguida, <age apenas como um espelho. Portanto, o IP percorre o mesmo caminho ao contrário, lendo Bquando encontra ?novamente. O IP passa pelo canto direito e continua no caminho verde. It próximos encontros (~que é "decremento, multiplicar por -1", que troca 0e 1e, por conseguinte, calcula not B. \é apenas um espelho e !imprime o resultado desejado. Em seguida, ?tenta retornar outro número, mas retorna zero. O IP agora continua no canto inferior esquerdo no caminho azul. (diminui, <reflete,(diminui novamente, para que o valor atual seja negativo quando o IP atingir o canto. Ele se move pela diagonal inferior direita e, finalmente, pressiona @para finalizar o programa.

0111: Ou

 ? <
< @ !
 . .

Mais curto-circuito.

Eu Eu

O A = 0caso (o caminho vermelho) é um pouco confuso aqui. O IP é desviado para a esquerda, passa para o canto inferior esquerdo, é imediatamente refletido pelo <e retorna ?à leitura B. Em seguida, envolve o canto rígido, imprime Bcom !e termina.

O A = 1caso (o caminho verde) é um pouco mais simples. A <ramificação desvia o IP para a direita, então simplesmente imprimimos !, voltamos para o canto superior esquerdo e terminamos em @.

Existe apenas uma outra solução de 5 bytes:

\>?@!

Funciona essencialmente da mesma forma, mas os caminhos de execução reais são bem diferentes e usa um canto para ramificação em vez de a <.

1000: Nem

 ) \
! # ?
 @ {

Este pode ser o meu programa favorito encontrado nesta pesquisa. O mais interessante é que essa implementação norrealmente funciona para até 5 entradas. Vou ter que entrar um pouco nos detalhes do modelo de memória para explicar este. Assim, como uma atualização rápida, o modelo de memória do Hexagony é uma grade hexagonal separada, onde cada aresta possui um valor inteiro (inicialmente todo zero). Há um ponteiro de memória (MP) que indica uma aresta e uma direção ao longo dessa aresta (de modo que há duas arestas vizinhas na frente e atrás da aresta atual, com vizinhos significativos à esquerda e à direita). Aqui está um diagrama das arestas que usaremos, com o MP começando como mostrado em vermelho:

Eu

Vamos primeiro considerar o caso em que ambas as entradas são 0:

Eu

Começamos no caminho cinza, que simplesmente incrementa a borda A para 1que o #comutador para IP, 1que é o caminho azul, comece no canto superior direito. \não faz nada lá e ?lê uma entrada. Envolvemos no canto superior esquerdo, onde )incrementa essa entrada. Agora, desde que a entrada seja zero, isso resultará em um 1, para que #não faça nada. Em seguida, {move-se o MP para a esquerda, isto é, sobre a primeira iteração de um de B . Como essa borda ainda tem seu zero inicial, o IP volta ao canto superior direito e a uma nova borda de memória. Portanto, esse loop continuará enquanto ?lê zeros, movendo o MP ao redor do hexágono de Bpara C para D e assim por diante. Não importa se ?retorna um zero porque era uma entrada ou porque era EOF.

Após seis iterações através deste circuito, {retorna a um . Dessa vez, a borda já mantém o valor 1desde a primeira iteração; portanto, o IP é movido para o canto esquerdo e continua no caminho verde. !simplesmente imprime isso 1e @finaliza o programa.

Agora, e se alguma das entradas for 1?

Eu

Em seguida, ?lê isso 1em algum momento e o )incrementa para 2. Isso significa #que agora vamos mudar de IP novamente e continuaremos no canto direito no caminho vermelho. ?lê outra entrada (se houver), o que realmente não importa e {move uma borda ainda mais. Isso deve ser uma borda não utilizada, portanto, isso funciona para até 5 entradas. O IP passa para o canto superior direito, onde é imediatamente refletido e para o canto esquerdo. !imprime 0na borda não utilizada e #volta para IP 0. Esse IP ainda estava esperando no #sudoeste (caminho cinza), então ele imediatamente bate no @e termina o programa.

No total, existem sete soluções de 7 bytes para esse gate. 5 deles funcionam da mesma forma que isso e simplesmente usam outros comandos para mover para uma aresta não utilizada (e podem caminhar em torno de um hexágono diferente ou em uma direção diferente):

)\!#?@"    )\!#?@'    )\!#?@^    )\!#?@{    )\!#?@}

E há outra classe de soluções que funciona apenas com duas entradas, mas cujos caminhos de execução são ainda mais confusos:

?]!|<)@    ?]!|<1@

1001: Igualdade

 ( ~
? / @
 # !

Isso também faz um uso muito inteligente da seleção de IP condicional. Precisamos distinguir novamente entre A = 0e A = 1. No primeiro caso, queremos imprimir not B, no segundo, queremos imprimir B. Pois A = 0também distinguimos os dois casos para B. Vamos começar com A = B = 0:

Eu

Começamos no caminho cinza. (~pode ser ignorado, o IP passa para o canto esquerdo (ainda no caminho cinza) e lê Acom ?. (diminui isso, então obtemos um -1IP wrap no canto inferior esquerdo. Agora, como eu disse anteriormente, #pega o módulo de valor 6antes de escolher o IP, então um valor de -1realmente sai do IP 5, que começa no canto esquerdo no caminho vermelho. ?B, (diminui isso também, para que continuemos no IP 5quando acertarmos #novamente. ~nega o, de -1modo que o IP passe para o canto inferior direito, imprima 1e termina.

Eu

Agora, se Bfor o caso 1, o valor atual será 0quando atingirmos #a segunda vez; portanto, voltamos ao IP 0(agora no caminho verde). Isso atinge ?uma terceira vez, produzindo 0, !imprime e @termina.

Eu

Finalmente, o caso em que A = 1. Desta vez, o valor atual já é zero quando atingimos #pela primeira vez, portanto, isso nunca muda para IP 5em primeiro lugar. Simplesmente continuamos imediatamente no caminho verde. ?agora não basta dar um zero, mas retornar B. !imprime e @termina novamente.

No total, existem três soluções de 7 bytes para este gate. Os outros dois funcionam de maneira muito diferente (até um do outro) e fazem uso ainda mais estranho #. Em particular, eles leem um ou mais valores com ,(lendo um código de caractere em vez de um número inteiro) e depois usam esse valor módulo 6 para escolher um IP. É muito louco.

),)#?@!

?~#,~!@

1010: Não ser

 ? ?
| @ !
 ) .

Este é bastante simples. O caminho da execução é o ramo horizontal que já conhecemos andanteriormente. ??Ae depois imediatamente B. Após refletir |e ramificar, B = 0executaremos o ramo inferior, onde )incrementa o valor pelo 1qual é impresso !. No ramo superior (se B = 1), ?basta redefinir a borda para a 0qual também é impressa !.

Existem oito programas de 6 bytes para este gate. Quatro deles são praticamente iguais, usando em >vez de |ou em 1vez de )(ou ambos):

??>@!)    ??>@!1    ??|@!)    ??|@!1

Dois usam um único ?que é usado duas vezes devido a um espelho. A negação acontece como fizemos xorcom um (~ou outro ~).

?>!)~@    ?>!~(@

E, finalmente, duas soluções usam um comutador IP condicional, porque por que usar da maneira simples se a complicada também funciona:

??#)!@    ??#1!@

1011: B implica A

 \ #
? ? !
 1 @

Isso usa algumas opções de IP bastante elaboradas. Vou começar com o A = 1caso desta vez, porque é mais simples:

insira a descrição da imagem aqui

Começamos no caminho cinza, que lê Acom ?e depois bate no #. Desde Aé 1este muda para IP 1(caminho verde). Ele !imprime imediatamente que, o IP passa para o canto superior esquerdo, lê B(desnecessariamente) e termina.

Quando as A = 0coisas ficam um pouco mais interessantes. Primeiro vamos considerar A = B = 0:

insira a descrição da imagem aqui

Desta vez, o #não faz nada e permanecemos no IP 0(caminho vermelho a partir desse ponto). ?Be 1transforma em um 1. Depois de empacotar no canto superior esquerdo, atingimos #novamente, então terminamos no caminho verde, afinal, e imprimimos 1como antes, antes de terminar.

Finalmente, aqui está (A, B) = (0, 1)o caso falso:

insira a descrição da imagem aqui

Observe que removi o caminho cinza inicial para maior clareza, mas o programa começa da mesma maneira e terminamos no caminho vermelho como antes. Então desta vez o segundo ?retorna 1. Agora encontramos o 1. Neste ponto, é importante entender o que os dígitos realmente fazem no Hexagony (até agora os usamos apenas em zeros): quando um dígito é encontrado, o valor atual é multiplicado por 10 e, em seguida, o dígito é adicionado. Isso normalmente é usado para escrever números decimais literalmente no código-fonte, mas significa que B = 1na verdade é mapeado para o valor 11. Então, quando atingimos #, esse módulo é usado 6para dar 5e, portanto, passamos para IP 5(em vez de 1como antes) e continuamos no caminho azul. Batendo?uma terceira vez retorna um zero, então !imprime que, e depois de mais duas ?, o IP passa para o canto inferior direito onde o programa termina.

Existem quatro soluções de 7 bytes para isso e todas elas funcionam de maneira diferente:

#)/!?@$    <!?_@#1    \#??!1@    |/)#?@!

1100: Não A

 ? (
~ ! @
 . .

Apenas um linear simples: ler Acom ?, nega com (~, imprimir com !, termina com @.

Há uma solução alternativa, que é negar ~):

?~)!@

1101: A implica B

 ? .
| @ !
 ) .

Isso é muito mais simples do que a implicação oposta da qual acabamos de falar. É novamente um daqueles programas de ramificação horizontal, como esse and. Se Afor 0, simplesmente é incrementado para 1o ramo inferior e impresso. Caso contrário, a ramificação superior é executada novamente onde ?Be depois !imprime.

Há uma tonelada de alternativas aqui (66 soluções no total), principalmente devido à livre escolha de no-ops eficazes. Para começar, podemos variar a solução acima da mesma maneira que andpodemos e também podemos escolher entre )e 1:

?.|@!)    .?|@!)    ?=|@!)    =?|@!)    ?_|@!)    _?|@!)    ?0|@!)
?.|@!1    .?|@!1    ?=|@!1    =?|@!1    ?_|@!1    _?|@!1    ?0|@!1
?.>@!)    .?>@!)    ?=>@!)    =?>@!)    ?_>@!)    _?>@!)    ?0>@!)
?.>@!1    .?>@!1    ?=>@!1    =?>@!1    ?_>@!1    _?>@!1    ?0>@!1

E há uma versão diferente usando a seleção condicional de IP, onde o primeiro comando pode ser escolhido quase arbitrariamente, e também há uma opção entre )e 1para algumas dessas opções:

"?#1!@    &?#1!@    '?#1!@    )?#1!@    *?#1!@    +?#1!@    -?#1!@    .?#1!@    
0?#1!@    1?#1!@    2?#1!@    3?#1!@    4?#1!@    5?#1!@    6?#1!@    7?#1!@    
8?#1!@    9?#1!@    =?#1!@    ^?#1!@    _?#1!@    {?#1!@    }?#1!@

"?#)!@    &?#)!@    '?#)!@              *?#)!@    +?#)!@    -?#)!@    
0?#)!@              2?#)!@              4?#)!@              6?#)!@    
8?#)!@                        ^?#)!@    _?#)!@    {?#)!@    }?#)!@

1110: Nand

 ? $
@ # )
 ! <

O último complicado. Se você ainda está lendo, quase conseguiu. :) Vamos olhar A = 0primeiro:

insira a descrição da imagem aqui

?Ae depois batemos $. Este é um comando de salto (como o de Befunge #) que pula a próxima instrução para que não terminemos no @. Em vez disso, o IP continua em #. No entanto, uma vez que Aé 0, isso não faz nada. )o incrementa para 1que o IP continue no caminho inferior onde 1é impresso. Ele <desvia o IP para a direita, onde ele fica no canto esquerdo e o programa termina.

Em seguida, quando a entrada é apresentada, (A, B) = (1, 0)temos esta situação:

insira a descrição da imagem aqui

É essencialmente o mesmo que antes, exceto que no #que mudar para IP 1(caminho verde), mas desde que Bé 0que voltar para IP 0quando bateu #uma segunda vez (caminho agora azul), onde ele imprime 1como antes.

Finalmente, o A = B = 1caso:

insira a descrição da imagem aqui

Desta vez, #na segunda vez, o valor atual ainda é 1para que não alteremos o IP novamente. O <reflete e, na terceira vez que atingimos ?, obtemos um zero. Portanto, o IP passa para o canto inferior esquerdo, onde !imprime o zero e o programa termina.

Existem nove soluções de 7 bytes no total para isso. A primeira alternativa simplesmente usa, em 1vez de ):

?$@#1!<

Depois, há duas soluções que farão sua cabeça com a quantidade de comutação de IP que está acontecendo:

)?#_[!@    1?#_[!@

Isso realmente me impressionou: a parte interessante é que a comutação de IP pode ser usada como uma condicional adiada. As regras de comutação de IP do idioma são tais que o IP atual dá outro passo antes que o comutador aconteça. Se essa etapa passar por um canto, o valor atual decidirá em qual filial o IP continuará se voltarmos a ele. Exatamente isso acontece quando a entrada é A = B = 1. Embora tudo isso seja consistente com a maneira como eu projetei a linguagem, nunca estive ciente dessa implicação da especificação, por isso é bom quando minha linguagem me ensina alguns novos truques: D.

Depois, há uma terceira solução cuja quantidade de comutação de IP é ainda pior (embora não faça uso desse efeito condicional adiado):

>?1]#!@

E depois há outro:

?$@#)!<

E existem essas quatro soluções equivalentes, que usam alguma troca de IP não condicional e, em vez disso, implementam toda a lógica por meio de ramificações e cantos:

]<?<@!)    ]<?<@!1    ]|?<@!)    ]|?<@!1

1111: Verdadeiro

 1 !
@ . .
 . .

Você ganhou algo simples para o final: defina a borda para 1, imprima com !, encerre com @. :)

Claro, há uma alternativa:

)!@

Como sempre, todos os diagramas de fluxo de controle criados com o HexagonyColorer de Timwi e o diagrama de memória com seu EsotericIDE .


9
Aaaaaand o tl; dr prêmio vai para ... (brincando, obviamente, grande resposta e muito bem escrito, +1)
Bassdrop Cumberwubwubwub

4
Esta é a razão pela qual você não está mais ativo no chat ??
Optimizer

Meio tarde, mas você poderia adicionar um link ao seu código de força bruta?
nedla2004

@ nedla2004 Normalmente não os mantenho por perto, mas é sempre uma versão modificada deste script .
Martin Ender

40

APL, 22 20 18 bytes

As entradas verdadeiras e falsas são programas completos e as outras 14 são funções. (Obrigado a Adám.)

0000 false              0 (complete program)
0001 p and q            ∧
0010 p and not q        >
0011 p                  ⊣
0100 not p and q        <
0101 q                  ⊢
0110 xor                ≠
0111 p or q             ∨
1000 not p and not q    ⍱
1001 eq                 =
1010 not q              ~⊢
1011 p or not q         ≥
1100 not p              ~⊣
1101 not p or q         ≤
1110 not p or not q     ⍲
1111 true               1 (complete program)

Experimente aqui.


11
+1 Bom uso de atops! Você pode salvar dois bytes transformando 0000 e 1111 em trad-fns 0e 1.
Adám 15/06/16

Existe um consenso para permitir tfns, mas não para contar a primeira linha. Isso corresponde a não contar o nome do arquivo nos idiomas que usam arquivos como contêineres de programa com o nome do programa = nome do arquivo.
Adám 15/06/16


10
Geléia: 19 bytes. Isso: 18 bytes. Isso não significa que você superou Dennis ? +1 para isso.
NoOneIsHere

29

Xadrez / medíocre jogador de xadrez no final do jogo, 70 peças

Inspirado por essa resposta dominó, decidi que outro jogo deveria ter essa honra.

Observe que eu tomei algumas regras sobre como as peças se movem. Como não tenho vontade de estudar as jogadas ideais para todas as situações, as regras para jogadas brancas são simples: fique fora de controle, capture a parte mais alta do ranking que ele puder, enquanto perde o mínimo de material possível e pare um peão de promover, nessa ordem de prioridade. Se houver dois espaços para os quais ele possa se mudar, com o mesmo favorecimento, ele poderá se mudar para qualquer um deles (portanto, nesses, se ele puder se mover para mais de um quadrado, eles terão a mesma cor). Observe que o branco capturará com algo mesmo que seja capturado, se a peça que estiver atacando tiver um valor mais alto do que a perdida. Os valores estão aqui:pawn<knight=bishop<rook<queen

A entrada é se uma torre está presente ou não. Observe que as torres são rotuladas apenas com os nomes A e B quando importa: se o portão se comporta da mesma maneira quando as torres são trocadas, elas não são rotuladas.

A saída é a cor do quadrado branco rei termina em: Branco = 1, preto = 0

Antes das imagens, quero me desculpar por imagens ruins. Não sou muito bom em segurar a câmera com firmeza.

Falso, 4:

Falso

E 4:

insira a descrição da imagem aqui

A e não B, 5 (acho que posso reduzir para três, mas não tenho placa no momento):

insira a descrição da imagem aqui

A, 4:

insira a descrição da imagem aqui

Não A e B, 5 (acho que posso reduzir para três, mas não tenho placa no momento):

insira a descrição da imagem aqui

B, 4:

insira a descrição da imagem aqui

Xor, 5 (conheço uma maneira de fazer 4, mas não tenho o quadro no momento):

insira a descrição da imagem aqui

Ou 4:

insira a descrição da imagem aqui

Nem 4:

insira a descrição da imagem aqui

Xnor, 5 (conheço uma maneira de fazer 4, mas não tenho o quadro no momento):

insira a descrição da imagem aqui

Não B, 4:

insira a descrição da imagem aqui

B implica A, 5 (acho que posso reduzir para três, mas não tenho placa no momento):

insira a descrição da imagem aqui

Não A, 4:

insira a descrição da imagem aqui

A implica B, 5 (acho que posso reduzir isso para três, mas não tenho placa no momento):

insira a descrição da imagem aqui

Nand, 4:

insira a descrição da imagem aqui

Verdadeiro, 4:

insira a descrição da imagem aqui


11
Uau, eu não tinha ideia de que a programação no xadrez era possível ... Você poderia postar um vídeo / simulação de alguns deles em ação?
Beta Decay

2
hmmm, atualmente não tenho acesso ao tabuleiro de xadrez. Eu provavelmente diria que o A implica que B / B implica que a / etc é mais difícil de entender devido ao efeito dos peões no movimento dos reis. Provavelmente eu deveria acrescentar uma explicação melhor para esses dois
Destructible Lemon

Fico feliz em inspirar: D Se estou entendendo corretamente, o local do tabuleiro e da peça é equivalente a um programa. As torres são a entrada, para que eu possa colocá-las em qualquer quadrado, desde que seja da cor certa?
NonlinearFruit

Não, a opinião das torres é se elas estão presentes ou ausentes no tabuleiro. Eles são rotulados aeb quando não são portões simétricos (quando se trata dos diferentes aeb). Também percebi como poderia jogar 2 peças, mas não tenho o tabuleiro no momento. Pincel deve ser utilizado :)
destrutível limão

No seu caso "E", se você remover a torre certa, o que impede o rei de descer (para branco)?
Nathan Merrill

27

Geléia , 19 bytes

0 0 0 0 ¤  1 byte  Empty niladic chain. Returns default argument 0.
0 0 0 1 &  1 byte  Bitwise AND.
0 0 1 0 >  1 byte  Greater than.
0 0 1 1    0 bytes Empty link. Returns left argument.
0 1 0 0 <  1 byte  Less than.
0 1 0 1 ị  1 byte  At-index (x,y -> [y][x]). Returns right argument.
0 1 1 0 ^  1 byte  Bitwise XOR.
0 1 1 1 |  1 byte  Bitwise OR.
1 0 0 0 |¬ 2 byte  Logical NOT of bitwise OR.
1 0 0 1 =  1 byte  Equals.
1 0 1 0 ¬} 2 bytes Logical NOT of right argument.
1 0 1 1 *  1 byte  Exponentiation.
1 1 0 0 ¬  1 byte  Logical NOT of left argument.
1 1 0 1 >¬ 2 bytes Logical NOT of greater than.
1 1 1 0 &¬ 2 bytes Logical NOT of bitwise AND.
1 1 1 1 !  1 byte  Factorial.

Experimente online!


13
Eu amo o uso de fatorial para converter 0 ou 1 a 1.
Neil

O Jelly é UTF-8? Se sim, então ¤e ¬são 2 bytes, não 1.
Vi.

11
@Vi. O Jelly suporta UTF-8, mas também suporta uma página de código personalizada que codifica cada um dos 256 caracteres que entende como um único byte cada. O link de bytes no cabeçalho aponta para ele.
Dennis

0 0 1 0 > 1 byte Greater than.isso não falharia se a segunda entrada fosse negativa?
MD XF

@MFXF Podemos escolher qual a verdade e qual o valor falso que apoiamos.
Dennis

24

Portões lógicos NAND - 31 portões

Como criador da série original de perguntas do NAND gate , não pude deixar passar a oportunidade de usar esses portões para resolver outro problema do portão lógico.

insira a descrição da imagem aqui

Em cada um desses diagramas, a entrada superior é A enquanto a entrada inferior é B.


5
@xnor pode ser lisonjeado em saber que o seu porta lógica é a que requer mais portas NAND para fazer D:
Joe Z.

Você poderia pelo menos usar o Logisim para formatar seu código?
mbomb007

11
@ mbomb007 Vou editar isso mais tarde. Eu não sou tão experiente com o Logisim, por isso pode demorar um pouco.
Joe Z.

3
Mas eu gosto mais de letra.
Leaky Nun

11
Alternativamente, você pode mudar para nem portão e formatá-lo usando redstone ...
jimmy23013

22

Tag cíclico bit a bit , 118 bits = 14,75 bytes

O Bitwise Cyclic Tag é talvez o idioma mais completo de Turing já criado. Há uma fita de programa e uma fita de dados, ambas consistindo em uma lista de bits. A fita do programa é interpretada ciclicamente até que a fita de dados esteja vazia, da seguinte maneira:

  • 0: exclua o primeiro bit da fita de dados.
  • 1x: se o primeiro bit da fita de dados for 1, anexe-o xà fita de dados.

Inicializamos a fita de dados com 1 seguido dos dois bits de entrada (o 1 é necessário porque não há como criar um 1 se a fita de dados consiste inteiramente de 0s) e usamos o bit final de dados excluído como saída do gate .

  • 0,0,0,0 ( false):001
  • 0,0,0,1 ( and):1001001
  • 0,0,1,0 ( A and not B):0110100
  • 0,0,1,1 ( A):1001
  • 0,1,0,0 ( not A and B):0100
  • 0,1,0,1 ( B):0
  • 0,1,1,0 ( xor):0110110010
  • 0,1,1,1 ( or):0110
  • 1,0,0,0 ( nor):1101001000
  • 1,0,0,1 ( xnor):110101001100
  • 1,0,1,0 ( not B):1100100
  • 1,0,1,1 ( B implies A):110101101000
  • 1,1,0,0 ( not A):11010000
  • 1,1,0,1 ( A implies B):11010011001
  • 1,1,1,0 ( nand):10110100100010
  • 1,1,1,1 ( true):1100

Parabéns!
Freira vazada

É o arrasto 1sobre falsenecessário?
CalculatorFeline

@CalculatorFeline Sim, precisamos anexar 0a à fita para que ela possa ser excluída por último.
Anders Kaseorg

Ah Esqueceu sobre isso + embrulho. Esperto!
CalculatorFeline

20

Python 2, 137 bytes

[].sort
min
int.__rshift__
round
range
{}.get
cmp
max
lambda a,b:a<1>b
lambda a,b:a==b
lambda a,b:b<1
pow
{0:1,1:0}.get
{0:1}.get
lambda a,b:a+b<2
slice

Toma entradas como min(True,False)(ou como min(1,0)). Aproveita bastante as saídas, precisando apenas do valor Truthy-Falsey certo. Sempre que possível, usa um built-in para evitar um custo lambda. Eu usei o código para procurar por embutidos que funcionem.

O meu favorito é o {0:1}.getque pensei à mão. O dicionário {0:1}mapeia a chave 0para o valor 1. Seu getmétodo usa uma chave e um padrão, produzindo o valor correspondente à chave ou o padrão, se não houver essa chave. Portanto, a única maneira de gerar a 0é a {0:1}.get(1,0), com chave 1e padrão ausentes 0. Pode-se obter outras variantes com dicionários diferentes, mas apenas este foi o mais curto.

built_in_names = list(__builtins__) 

object_names = ["int","(0)","(1)"] + \
["True","False","0L","1L","0j","1j"] + \
["str", "''", "'0'","'1'","'a'"] + \
["list", "[]", "[0]", "[1]","['']","[[]]","[{}]"] + \
["set","set()","{0}","{1}","{''}"] + \
["dict","{}","{0:0}","{0:1}","{1:0}","{1:1}","{0:0,1:0}", "{0:0,1:1}","{0:1,1:0}","{0:1,1:1}"] + \
["id"]

object_method_names = [object_name+"."+method_name 
for object_name in object_names 
for method_name in dir(eval(object_name))]

additional_func_names = [
"lambda a,b:0",
"lambda a,b:1",
"lambda a,b:a",
"lambda a,b:b",
"lambda a,b:b<1",
"lambda a,b:a<1",
"lambda a,b:a+b",
"lambda a,b:a*b",
"lambda a,b:a==b",
"lambda a,b:a-b",
"lambda a,b:a<=b",
"lambda a,b:a>=b", 
"lambda a,b:a>b", 
"lambda a,b:a<b", 
"lambda a,b:a<1>b", 
"lambda a,b:a+b<2"]

func_names = built_in_names + object_method_names + additional_func_names

t=True
f=False

cases = [(f,f),(f,t),(t,f),(t,t)]

def signature(func):
    table = [bool(func(x,y)) for x,y in cases]
    table_string = ''.join([str(int(val)) for val in table])
    return table_string

d={}

for func_name in func_names:
    try:
        func = eval(func_name) 
        result = signature(func)
        if result not in d or len(func_name)<len(d[result]):
            d[result]=func_name
    except:
        pass

total_length = sum(len(func) for sig,func in d.items())

print total_length
print

for sig in sorted(d):
    print d[sig]

Você não pode usar métodos de built-ins como int __lt__ou __eq__? Isso diminuirá ainda mais a contagem de bytes: em int.__gt__vez de lambda a,b:b<1, em int.__eq__vez de lambda a,b:a==betc.
Gábor Fekete 29/07

@ GáborFekete Esses não existem no Python 2 porque intas comparações de descarregamento para cmp. Eu não tentei isso para o Python 3.
xnor 29/07

Oh agora eu vejo!
Gábor Fekete 29/07

Salvar 4 bytes usando a função notpara 0001, False- ideone
Jonathan Allan

11
@ JonathanAllan Isso é inteligente, mas acho que notisso não atende aos requisitos de uma função porque você não pode fazer isso f=not;f(3,4). A string notfunciona porque os argumentos da suposta função se parecem com uma tupla, da mesma forma 3+que funcionaria como 3+(4)se 3+não fosse uma função que pode ser 4usada como entrada.
xnor

20

Go (jogo), 33 pedras, 73 cruzamentos

Se dominó e xadrez são aceitáveis, então isso. Não pode ser muito complicado em um tabuleiro Go completo de 19x19. Então eu usei pequenas tábuas retangulares. A entrada é se as pedras marcadas 1 e 2 estão presentes. A saída é se o preto vence. Ele usa pontuação de área, 0,5 komi, superko situacional, sem suicídio. Tudo preto para jogar. Alguns recebem várias soluções.

Vitórias brancas (2, 1x5):

➊━━━➋

1 e 2 (3, 2x3):

➊◯➋
┗┷┛

1 e não 2 (2, 1x5):

╺➊━➁╸

1 (2, 1x5):

╺➊➁━╸ 
╺➊━━➁
➀━➁━╸

Não 1 e 2 (2, 1x5):

╺➋━➀╸

2 (2, 1x5):

╺➋➀━╸

1 xou 2 (2, 2x3):

➀┯➁
┗┷┛

1 ou 2 (2, 1x5):

╺➊━➋╸
➀━━━➁

1 nem 2 (2, 1x4):

➊━━➋
╺➀➁╸

1 = 2 (2, 1x7):

╺━➀━➁━╸

Não 2 (2, 1x3):

➀➁╸

1 ou não 2 (2, 1x4):

➀➁━╸
➀━➁╸
╺➊➁╸
➋➊━╸
➋━➊╸

Não 1 (2, 1x3)

➁➀╸

Não 1 ou 2 (2, 1x4):

➁➀━╸

1 e 2 (2, 1x3):

➊━➋

Vitórias negras (2, 1x3):

➊➋╸
➀━➁
➊━➁

Esta página me ajudou um pouco: http://www.mathpuzzle.com/go.html

Talvez alguém possa encontrar uma solução de 2 pedras para 1 e 2 em uma placa 1x9 ...


11
Quais são as suas regras para o suicídio? Não permitido? E o que acontece quando um lado preenche todo o tabuleiro? Isso é considerado suicídio?
Martin Ender

@MartinEnder Disallowed. E sim, isso é considerado suicídio.
precisa saber é o seguinte

A solução 1x7 parecia errada. Estou tentando corrigi-lo ...
jimmy23013

15

Javascript ES6, 124 bytes

a=>0
Math.min
parseInt
a=>a
a=>b=>a<b
a=>b=>b
a=>b=>a^b
Math.max
a=>b=>~a&~b
a=>b=>a==b
a=>b=>~b
Math.pow
a=>~a
a=>b=>a<=b
a=>b=>~a|~b
a=>1

Eu odeio seriamente lambdas agora.


11
Se eu estou autorizado a escrever alguns programas e algumas funções ... Eu acho que você poderia mudar a=>b=>0para a=>0e dizer a gramática chamado é (a=>0)(a,b), apenas para os 4 entradas.
jimmy23013

Ah sim, obrigada!
Mama Fun Roll

2
Math.minem vez de a=>b=>a&b. Math.maxem vez de a=>b=>a|b. Math.powem vez de a=>b=>a>=b.
Conor O'Brien

11
Além disso, como NaN é falsey, você pode fazer em parseIntvez de a=>b=>a>b.
Conor O'Brien

11
@algmyr !NaN=> true, !!NaN=>false
Mama Fun Roll

14

Retina , 62 39 bytes

23 bytes graças a @MartinEnder !

0000 false              1 byte : 2
0001 p and q            2 bytes: 11
0010 p and not q        2 bytes: 10
0011 p                  2 bytes: ^1
0100 not p and q        2 bytes: 01
0101 q                  2 bytes: 1$
0110 xor                5 bytes: 01|10
0111 p or q             1 byte : 1
1000 not p and not q    2 bytes: 00
1001 xnor               5 bytes: (.)\1
1010 not q              2 bytes: 0$
1011 p or not q         5 bytes: ^1|0$
1100 not p              2 bytes: ^0
1101 not p or q         5 bytes: ^0|1$
1110 not p or not q     1 byte : 0
1111 true               0 bytes: 

Toma entrada como PQ.

Produz um número inteiro entre 0a 3. 0é falsey, outros são verdadeiros.

Explicação

Eles são todos apenas regexes .

Por exemplo, 01|10apenas combina 01ou 10.

In 0000, 2nunca estará na entrada, portanto nunca coincide.

Em 1111, ele corresponde à string vazia, que existe 4.


^1|0$deve corresponder apenas a 1 sequência de caracteres. Oque esta acontecendo aqui?
CalculatorFeline

@CalculatorFeline Corresponde a [ 1no início da entrada] OU [ 0no final da entrada]. Levei um minuto para obtê-lo também ...
ETHproductions

Precedência, pessoal .... #
Leaky Nun

Eu acho que ^1|0$é mais difícil de ler do que 1.|.0. Parece para tornar a leitura mais difícil em todos
l4m2

10

Stack Cats , 67 + 64 = 131 bytes

Observe que o +64 é da aplicação dos -nmsinalizadores em cada programa. -nindica E / S numérica e -mreflete o código-fonte no último caractere - nem todos os envios precisam desses sinalizadores tecnicamente, mas por consistência e simplicidade, eu os escuto da mesma maneira.

-2 -2 -3 -3     !I                0 0 0 0     <I!+
-4 -4 -4  1     |!T*I             0 0 0 1     [>I=I_
-4 -4  3 -2     *I*_              0 0 1 0     :I*=I:
-2 -2  3  3     T*I               0 0 1 1     [<!>X
-2  1 -2 -2     _*T*I             0 1 0 0     *|!TI:
-2  1 -3  1     !-|_I             0 1 0 1     <!I!>X
-2  3  3 -2     ^T*I              0 1 1 0     ^:]<_I
-2  3  3  3     -_T*I             0 1 1 1     *I<-I!
 2 -3 -3 -3     -*|_I             1 0 0 0     ^{!:}I_
 2 -3 -3  2     _|*I              1 0 0 1     _|[<I!:
 1 -2  1 -2     :]I*:             1 0 1 0     _!:|]X
 1 -2  1  1     *I\<X             1 0 1 1     *>I>!I
 2  2 -3 -3     -*I               1 1 0 0     I^:!
 2  2 -3  2     _*I_              1 1 0 1     |I|^:!
 1  2  2 -1     |!:^I             1 1 1 0     -I*<*I
 1  1  1  1     *<X               1 1 1 1     +I+

()no Stack Cats verifica se um elemento é positivo ou não positivo (ou seja, 0 ou negativo), por isso estamos usando isso para verdade / falsidade, respectivamente. A segunda coluna é apenas para o interesse e lista os melhores portões com 0/ 1s como saídas (com pontuação total 90).

A entrada é bits separados por delimitador via STDIN. Experimente online!


Stack Cats é uma linguagem esotérica reversível, onde os programas têm simetria reflexiva. Dado um trecho f(por exemplo >[[(!-)/), a imagem espelhada (por exemplo \(-!)]]<) calcula o inverso f^-1. Assim, programas de comprimento par não fazem nada (ou ficam presos em um loop infinito), e os únicos programas não triviais têm comprimento ímpar, calculando f g f^-1onde gestá o operador central.

Como metade do código-fonte é sempre redundante, ele pode ser deixado de fora, e a execução do código com o -msinalizador indica que o código-fonte deve ser espelhado sobre o último caractere para recuperar o código-fonte real. Por exemplo, o programa *<Xé realmente *<X>*simétrico.

Jogar golfe no Stack Cats é altamente pouco intuitivo, portanto os programas acima tiveram que ser encontrados por força bruta. A maioria deles é surpreendentemente complexa, mas explicarei alguns e acrescentarei a essa resposta quando tiver tempo. Por enquanto, algumas explicações e soluções alternativas para as versões 0/ 1podem ser encontradas no repositório do Github aqui .


11
Note that the +64 is from applying the -nm flags to each program.3 * 16 = 48 ou 16 2 * = 32, 64 de qualquer forma é forma hai
gato

@cat As bandeiras custam 4 por programa, pois você também precisa contar o espaço.
FryAmTheEggman


Já faz mais de um ano. Você ainda tem tempo?
CalculatorFeline

8

Haskell, 78 76 75 bytes

  1. _#_=2<1
  2. &&
  3. >
  4. pure
  5. <
  6. _#b=b
  7. /=
  8. ||
  9. (not.).max
  10. ==
  11. _#b=not b
  12. >=
  13. a#_=not a
  14. <=
  15. (not.).min
  16. _#_=1<2

Edit: -1 byte graças a @cole.


Eu estava prestes a comentar "cara, _#_não é um operador padrão!" E então eu percebi ... Muito bem.
MathematicalOrchid

4 could bepure
cole

@ cole: Obrigado. Uau, purefoi introduzido Preludeem 2015, então estava disponível no momento deste desafio.
nimi 28/07

6

Braquilog , 36 34 bytes

0000 false              \     Backtrack (always false)
0001 p and q            1.    Unify input and output with 1
0010 p and not q        >.    Input > Output
0011 p                  1     Unify input with 1
0100 not p and q        <.    Input < Output
0101 q                  ,1.   Unify output with 1
0110 xor                '.    Input and output cannot unify
0111 p or q             1;1.  Unify input with 1 or unify output with 1
1000 not p and not q    0.    Unify input and output with 0
1001 eq                 .     Unify input with output
1010 not q              ,0.   Unify output with 0
1011 p or not q         >=.   Input >= Output
1100 not p              0     Unify input with 0
1101 not p or q         <=.   Input <= Output
1110 not p or not q     0;0.  Unify input with 0 or unify output with 0
1111 true                     Empty program (always true)

Isso espera 0como valor falso e 1como valor verdadeiro . Retorna trueou false. p é Inpute q é Output.


Como você insere a saída?
Leaky Nun

11
@LeakyNun Assim como a entrada. O principal predicado que você consulta possui dois argumentos, chamados Inpute Outputpor convenção, mas você pode definir valores para ambos ou retornar valores de ambos.
Fatalize

11
Esta é a ferramenta certa para o trabalho: P
Conor O'Brien

6

Prolog, 147 145 bytes

Ganhou 2 bytes graças a @SQB

a(a,a).       % 0000 false
b(1,1).       % 0001 P and Q
c(1,0).       % 0010 P and not Q
d(1,_).       % 0011 P
e(0,1).       % 0100 not P and Q
f(_,1).       % 0101 Q
g(P,Q):-P\=Q. % 0110 P xor Q
h(1,_).       % 0111 P or Q
h(0,1).
i(0,0).       % 1000 not P and not Q
j(P,P).       % 1001 P == Q                 
k(_,0).       % 1010 not Q
m(P,Q):-P>=Q. % 1011 P or not Q
n(0,_).       % 1100 not P              
r(P,Q):-P=<Q. % 1101 not P or Q         
s(0,_).       % 1110 not P or not Q
s(1,0).
t(_,_).       % 1111 true

Consulta x(P,Q).com xsendo a letra apropriada e Pe Qdefinido para 0 ou 1.
Returns trueou false.

Exemplo SWISH incluindo testes - entre runTest.para executar.


Suporta a(2,2).falso?
jimmy23013

@ jimmy23013 Eu acho que poderia se eu assumir que 2 é falso. Não tenho certeza se isso é aceitável.
Fatalize

@ jimmy23013 Na verdade, a(a,a).(ou qualquer outra letra) também funciona e anão é uma contribuição aceitável para a veracidade, então isso é bom. Obrigado pela sugestão.
Fatalize

6

NTFJ, 86 bytes

0000 false              ~
0001 p and q            |:|
0010 p and not q        :||:|
0011 p                  $
0100 not p and q        #{:||:|
0101 q                  #{$
0110 xor                :#{:#{:||#}:|||
0111 p or q             :|#{:||
1000 not p and not q    :|#{:||:|
1001 eq                 :#{:#{:||#}:|||:|
1010 not q              #{$:|
1011 p or not q         #{:||
1100 not p              $:|
1101 not p or q         :||
1110 not p or not q     |
1111 true               #

Experimente aqui! Mas leia abaixo primeiro.

A entrada está implícita na pilha. O resultado é deixado na pilha. Adicione 16 bytes (um *ao final de cada) se desejar 0x00ou 0x01produza representando 0 e 1. Adicione 160 bytes adicionais se desejar a 0ou a 1impressão. (Coloque ~~##~~~#{@antes de cada um *.)

O único operador binário do NTFJ é o NAND, portanto, cada um deles é escrito no formato NAND.

Vamos analisar cada um deles.

0: false

~

~representa um bit falso. Simples o suficiente. Como a entrada está implícita na parte inferior da pilha, ela é deixada na parte superior da pilha.

1: peq

|:|

NTFJ opera em uma pilha. :é o comando para duplicado. Observe-se que p and qnot (p nand q)e que not q = q nand q.

Command | Stack
        | p q
   |    | (p nand q)
   :    | (p nand q) (p nand q)
   |    | (p nand q) nand (p nand q)
        | => not (p nand q)
        | => p and q

(Note, então, :|pode ser considerado uma negação e |:|uma conjunção )

2: pe não q

:||:|

Observe que isso é apenas uma negação :|e uma conjunção |:|.

Command | Stack
        | p q
  :|    | p (not q)
  |:|   | p and (not q)

3: p

$

$aparece um item da pilha. Então sim.

4: não peq

#{:||:|

É a mesma coisa que 2, exceto com #{no início. #empurra 1 (o bit verdadeiro) e {gira a pilha para a esquerda uma vez. Simples o suficiente.

5: q

#{$

Gire para a esquerda uma vez e solte.

6: xor

:#{:#{:||#}:|||

Observar:

p xor q = (p and (not q)) or ((not p) and q)                ; by experimentation (trust me)
        = (not ((not p) nand q)) or (not (p nand (not q)))  ; by definition of nand
        = not (((not p) nand q) and (p nand (not q)))       ; by De Morgan's laws
        = ((not p) nand q) nand (p nand (not q))            ; by definition of nand

No entanto, não há como duplicar completamente a pilha. Então, vamos ter que trazer cada um p, qpara o topo e duplicá-lo.

Command | Stack
        | p q
   :    | p q q
  #{    | q q p
   :    | q q p p
  #{    | q p p q
  :|    | q p p (not q)
   |    | q p (p nand (not q))
  #}    | (p nand (not q)) q p
  :|    | (p nand (not q)) q (not p)
   |    | (p nand (not q)) (q nand (not p))
   |    | (p nand (not q)) nand (q nand (not p))

E assim, temos o nosso xor.

7: p ou q

:|#{:||

Negue o topo, traga de baixo para cima, negue isso e junte-os. Basicamente p or q = (not p) nand (not q).

8: não p e não q

:|#{:||:|

Isso é simplesmente a negação do 7. Fácil.

9: eq

:#{:#{:||#}:|||:|

Isso é apenas xnor , ou não xor. Simples de novo.

10: não q

#{$:|

Negação de 5.

11: p ou não q

#{:||

Negue p, nand. (not p) nand q = not ((not p) and q) = p or (not q) (by De Morgan's laws).

12: não p

$:|

Solte, pare e negue.

13: não p ou q

:||

Leis de De Morgan para salvar o dia, novamente! Mesmo processo que 11, apenas negando em qvez de p.

14: não p ou não q

|

Isso é apenas uma imitação.

15: true

#

# é o verdadeiro pedaço.


apenas por que ...> _>
Re:

idk exatamente como isso funciona, mas parece muito legal +1
Downgoat

Por que 5 não é apenas um programa vazio e 10 apenas :|?
Joffan

6

Minecraft, 89 blocos

Em todas as fotos a seguir, os blocos azuis são para a Entrada A e os blocos laranja são para a Entrada B

16. portão VERDADEIRO - 1 quadra

insira a descrição da imagem aqui

15. portão NAND - 1x2x3 = 6 blocos

insira a descrição da imagem aqui

14. A => B - 1x2x3 = 6 blocosinsira a descrição da imagem aqui

13. NÃO A - 2 quarteirões insira a descrição da imagem aqui

12. B => A - 1x2x3 = 6 blocosinsira a descrição da imagem aqui

11. NÃO B - 2 blocos insira a descrição da imagem aqui

10. XNOR - 1x3x4 = 12 blocos insira a descrição da imagem aqui

9. NOR - 1x2x3 = 6 blocosinsira a descrição da imagem aqui

8. OU - 1 bloco insira a descrição da imagem aqui

7. XOR - 1x3x4 = 12 blocos insira a descrição da imagem aqui

6. B - 1 bloco insira a descrição da imagem aqui

5.! A&B - 1x2x5 = 10 blocos insira a descrição da imagem aqui

4. A - 1 quadra insira a descrição da imagem aqui

3. A &! B - 1x2x5 = 10 blocos insira a descrição da imagem aqui

2. AND - 2x2x3 = 12 blocos insira a descrição da imagem aqui

1. FALSO - 1 quadra insira a descrição da imagem aqui


2
Na penúltima imagem (AND), você pode salvar 6 blocos colocando as tochas no topo, na parte de trás dos blocos, ou seja, opostas às alavancas. Troque a tocha no meio por um pedaço de poeira e remova a poeira na parte superior, reduzindo para 1x2x3 = 6 blocos.
Luca H #

5

Mathematica, 67 bytes

0>1&
And
#&&!#2&
#&
!#&&#2&
#2&
Xor
Or
Nor
Xnor
!#2&
#||!#2&
!#&
!#||#2&
Nand
1>0&

Cada uma delas avalia uma função, para que você possa usá-las como

#&&!#2&[True, False]
Xor[True, False]

Ah, se apenas números inteiros fossem verdadeiros / falsos no Mathematica, esses quatro mais longos poderiam ter sido encurtados consideravelmente.


Se os números inteiros não são verdadeiros / falsos, o que acontece quando você os coloca em uma instrução if?
Conor O'Brien

3
@ CᴏɴᴏʀO'Bʀɪᴇɴ permanece sem avaliação.
Martin Ender

5

MATL, 34 23 bytes

Espero ter acertado o pedido! Zero é falsey, diferente de zero é verdade. Cada função recebe duas entradas implícitas (embora possa ignorar algumas entradas). A primeira entrada é A e a segunda é B. Você pode inserir 0/ 1para verdadeiro / falso ou T/ F.

Aqui está um exemplo TryItOnline para o caso de teste 3.

Salvei 4 bytes usando *for ande outros 4 usando >/ em <vez de ~wY&/ w~Y&depois que eu vi a resposta de Dennis!

1.  0,0,0,0 0 (ignores input, just returns a zero)
2.  0,0,0,1 * (and)
3.  0,0,1,0 < (not-A and B)
4.  0,0,1,1 D (A)
5.  0,1,0,0 > (not-B and A)
6.  0,1,0,1 xD (discard A, display B)
7.  0,1,1,0 Y~ (xor)
8.  0,1,1,1 + (or)
9.  1,0,0,0 +~ (not-or)
10. 1,0,0,1 = (A=B)
11. 1,0,1,0 x~ (not-B)
12. 1,0,1,1 <~ (not-B or A)
13. 1,1,0,0 ~ (not-A)
14. 1,1,0,1 ~+ (not-A or B)
15. 1,1,1,0 *~ (not(A and B))
16. 1,1,1,1 1 (just returns 1)

10
O número seis acha engraçado.
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ O número 6 é o melhor, eu também gosto do número 12! xD!
David

Você não tem a função "desigual"?
Freira vazada

Não (pelo menos não creio) #
David David

2
@ David Acho que o número 7 pode ser substituído por-
Luis Mendo

5

dc, 37 bytes

dc("calculadora de mesa") é um comando unix padrão, uma calculadora postfix baseada em pilha. Faltam operações de bit e os operadores de comparação podem ser usados ​​apenas para executar macros (que não valem os bytes). A divisão inteira compensa parte disso.

Esses scripts esperam 0e 1valores na pilha e deixam o resultado na pilha.

0,0,0,0 (false)              0
0,0,0,1 (and)                *         a*b
0,0,1,0                      -1+2/     (a-b+1)/2
0,0,1,1 (A)                  r         reverse a, b: a now on top
0,1,0,0                      -1-2/     (a-b-1)/2
0,1,0,1 (B)                            (0 bytes) do nothing: b on top
0,1,1,0 (xor)                -         a-b
0,1,1,1 (or)                 +         a+b                  
1,0,0,0 (nor)                +v1-      sqrt(a+b) -1
1,0,0,1 (xnor)               +1-       a+b-1
1,0,1,0 (not B)              1-        b-1
1,0,1,1 (if B then A)        -1+       a-b+1
1,1,0,0 (not A)              r1-       a-1
1,1,0,1 (if A then B)        -1-       a-b-1            
1,1,1,0 (nand)               *1-       a*b - 1
1,1,1,1 (true)               1

5

Labirinto , 85 bytes

Agradecimentos ao Sp3000 por salvar 2 bytes.

!@
??&!@
??~&!@
?!@
?~?&!@
??!@
??$!@
??|!@
??|#$!@
??$#$!@
?#?$!@
?#?$|!@
?#$!@
?#$?|!@
??&#$!@
1!@

Todos esses são programas completos, lendo dois números inteiros 0ou 1de STDIN (usando qualquer separador que não seja um dígito) e imprimindo o resultado como 0ou 1para STDOUT.

Experimente online! (Não é um conjunto de testes, você precisará experimentar diferentes programas e entradas manualmente.)

Quanto às explicações, estas são todas bastante diretas. Todos os programas são lineares e os comandos em uso fazem o seguinte:

?   Read integer from STDIN and push.
!   Pop integer and write to STDOUT.
@   Terminate program.
&   Bitwise AND of top two stack items.
|   Bitwise OR of top two stack items.
$   Bitwise XOR of top two stack items.
~   Bitwise NOT of top stack item.
#   Push stack depth (which is always 1 when I use it in the above programs).
1   On an empty stack, this pushes 1.

Observe que eu estou usando #é sempre usado para combiná-lo com $, ou seja XOR 1, calcular ou, em outras palavras, negação lógica. Somente em alguns casos eu consegui usá-lo ~, porque o subsequente &descarta todos os bits indesejados do -1or ou resultante -2.


5

Código de máquina IA-32, 63 bytes

Hexdump do código, com a desmontagem:

0000  33 c0     xor eax, eax;
      c3        ret;

0001  91        xchg eax, ecx;
      23 c2     and eax, edx;
      c3        ret;

0010  3b d1     cmp edx, ecx;
      d6        _emit 0xd6;
      c3        ret;

0011  91        xchg eax, ecx;
      c3        ret;

0100  3b ca     cmp ecx, edx;
      d6        _emit 0xd6;
      c3        ret;

0101  92        xchg eax, edx;
      c3        ret;

0110  91        xchg eax, ecx;
      33 c2     xor eax, edx;
      c3        ret;

0111  8d 04 11  lea eax, [ecx + edx];
      c3        ret;

1000  91        xchg eax, ecx; // code provided by l4m2
      09 d0     or eax, edx;
      48        dec eax;
      c3        ret;

1001  3b ca     cmp ecx, edx;
      0f 94 c0  sete al;
      c3        ret;

1010  92        xchg eax, edx;
      48        dec eax;
      c3        ret;

1011  39 d1     cmp ecx, edx; // code provided by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1100  91        xchg eax, ecx;
      48        dec eax;
      c3        ret;

1101  3b d1     cmp edx, ecx; // code inspired by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1110  8d 44 11 fe   lea eax, [ecx+edx-2] // code provided by l4m2
      c3        ret;

1111  91        xchg eax, ecx;
      40        inc eax;
      c3        ret;

O código é mais longo do que poderia ser, porque usa uma convenção de codificação padrão: input in ecxe edx, e output in al. Isso pode ser expresso em C como

unsigned char __fastcall func(int, int);

Parece que o MS Visual Studio não entende o SALCcódigo de operação não documentado , então tive que usar o código dele, em vez do nome.

Obrigado l4m2 por melhorar algumas das amostras de código!


11
1110 8D4411FE LEA EAX, [ECX+EDX-2]
l4m2

5

C 34 bytes

#define g(n,a,b)((n-1)>>3-b-2*a)&1

Onde n é o número da função a ser usado, mas acho que seria recusado, então proponho este outro:

C 244 bytes (usando memória)

typedef int z[2][2];
z a={0,0,0,0};
z b={0,0,0,1};
z c={0,0,1,0};
z d={0,0,1,1};
z e={0,1,0,0};
z f={0,1,0,1};
z g={0,1,1,0};
z h={0,1,1,1};
z i={1,0,0,0};
z j={1,0,0,1};
z k={1,0,1,0};
z l={1,0,1,1};
z m={1,1,0,0};
z n={1,1,0,1};
z o={1,1,1,0};
z p={1,1,1,1};

usa matriz indexada dupla. n[0][1]é(A implies B)(0,1)

Quartos 138 bytes

Acabei de aprender Forth. Suponho que seja compatível com Ansi Forth, pois também é executado no gforth.

: z create dup , 1+ does> @ -rot 3 swap - swap 2* - rshift 1 and ; 
0 
z a z b z c z d z e z f z g z h z i z j z k z l z m z n z o z p 
drop

A função z cria uma nova função com o nome fornecido e, em seguida, coloca o número da porta lógica da parte superior da pilha no novo endereço da função. Ele deixa a próxima função de porta lógica (n + 1) na pilha para a próxima declaração.

você pode testá-lo:
e AB

0 0 b . cr 
0 1 b . cr
1 0 b . cr 
1 1 b . cr   

("." imprimir a parte superior da pilha "cr" é um retorno de cariage)


Você só precisa fornecer trechos de código para cada função.
CalculatorFeline

4

C, 268 bytes

#define c(a,b)0      // 0000 
#define d(a,b)a&b    // 0001 
#define e(a,b)a>b    // 0010 
#define f(a,b)a      // 0011 
#define g(a,b)a<b    // 0100 
#define h(a,b)b      // 0101 
#define i(a,b)a^b    // 0110 
#define j(a,b)a|b    // 0111 
#define k(a,b)!b>a   // 1000 
#define l(a,b)a==b   // 1001 
#define m(a,b)!b     // 1010 
#define n(a,b)!b|a   // 1011 
#define o(a,b)!a     // 1100 
#define p(a,b)!a|b   // 1101 
#define q(a,b)!b|!a  // 1110 
#define r(a,b)1      // 1111 

Macros parecem mais curtas que funções.


4

Brian & Chuck , 183 bytes

Agradecimentos ao Sp3000 por salvar 4 bytes.

Alguns dos programas contêm um caractere não imprimível. Em particular, todos \x01devem ser substituídos pelo <SOH>caractere de controle (0x01):

0000
?
#>.
0001
,-?,-?>?\x01
#}>.
0010
,-?,?>?\x01
#}>.
0011
,?\x01+?
#>.
0100
,?,-?>?\x01
#}>.
0101
,,?\x01+?
#>.
0110
,?>},?>?_\x01
#}+{>?_}>.
0111
,\x01?,?>?
#{>.
1000
,?,?>?\x01
#}>.
1001
,-?>},?>?_\x01
#}+{>>?_}>.
1010
,,-?\x01+?
#>.
1011
,\x01?,-?>?
#{>.
1100
,-?\x01+?
#>.
1101
,\x01-?,?>?
#{>.
1110
,\x01-?,-?>?
#{>.
1111
?
#>+.

A entrada e a saída usam valores de bytes , portanto, a entrada deve ter dois bytes de 0x00 ou 0x01 (sem separador) e a saída será um desses bytes. Essa também é, na verdade, a definição mais sensata de verdade / falsidade para B&C porque o único comando de fluxo de controle ?considera zeros como falsidade e tudo o resto.

Explicações

Primeiro, um rápido iniciador B&C:

  • Todo programa consiste em duas instâncias do tipo Brainfuck, cada uma escrita em sua própria linha. Chamamos o primeiro de Brian e o segundo de Chuck . A execução começa em Brian.
  • A fita de cada programa é o código-fonte do outro programa e o ponteiro de instruções de cada programa é a cabeça da fita do outro programa.
  • Somente Brian pode usar o ,comando (input byte) e apenas Chuck pode usar o .comando (output byte).
  • O []loop de Brainfuck não existe. Em vez disso, o único fluxo de controle que você possui é o ?que alterna o controle para a outra instância se o valor atual sob a cabeça da fita for diferente de zero.
  • Além de >e <, há {e }que são essencialmente equivalentes aos trechos de Brainfuck [<]e [>], isto é, eles movem a cabeça da fita para a próxima posição zero nessa direção. A principal diferença é que {também pode ser parado na extremidade esquerda da fita, independentemente do valor que ela possui.
  • Por conveniência, qualquer _s no código fonte é substituído por bytes nulos (pois são muito úteis em programas não triviais para capturar {e }).

Observe que em todos os programas, a fita de Chuck começa com a #. Isso poderia realmente ser qualquer coisa. ?funciona de forma que o cabeçote da fita mova uma célula antes de iniciar a execução (para que a própria condição não seja executada se for um comando válido). Portanto, nunca podemos usar a primeira célula do Chuck para código.

Existem cinco classes de programas, que explicarei em detalhes mais adiante. Por enquanto, estou listando-os aqui em ordem crescente de complexidade.

0000, 1111: Funções constantes

?
#>.
?
#>+.

Estes são muito simples. Mudamos para Chuck incondicionalmente. Chuck move a cabeça da fita para a célula não utilizada à direita e a imprime diretamente ou a incrementa primeiro para imprimir 1.

0011, 0101, 1010, 1100: Funções dependendo apenas uma entrada

,?\x01+?
#>.
,,?\x01+?
#>.
,,-?\x01+?
#>.
,-?\x01+?
#>.

Dependendo de começarmos ,ou ,,trabalharmos com Aou B. Vejamos o primeiro exemplo 0011(ie A). Depois de ler o valor, usamos ?como condicional esse valor. Se A = 1, isso muda para Chuck, que move a cabeça da fita para a direita e imprime o 1byte literalmente incorporado . Caso contrário, o controle permanece em Brian. Aqui, o byte de 1 é um no-op. Em seguida, incrementamos bem a entrada +para garantir que não seja zero e depois mudamos para Chuck com ?. Desta vez, >move-se para uma célula não utilizada à direita, que é impressa como 0.

Para negar um dos valores, simplesmente o diminuímos -. Esta transforma 1em 0e 0em -1, que é diferente de zero e, portanto, truthy tanto quanto ?está em causa.

0001, 0010, 0100, 1000: Funções binários com um resultado truthy

,-?,-?>?\x01
#}>.
,-?,?>?\x01
#}>.
,?,-?>?\x01
#}>.
,?,?>?\x01
#}>.

Esta é uma extensão da ideia anterior para trabalhar com duas entradas. Vejamos o exemplo de 1000(NOR). (Potencialmente) lemos as duas entradas com ,?. Se um desses for 1, o ?comutador para Chuck. Ele move a cabeça da fita até o fim com }(para a célula vazia após o código de Brian), move outra célula com >(ainda zero) e a imprime ..

No entanto, se as duas entradas forem zero, o controle ainda estará com Brian. >depois move a cabeça da fita para }que este comando não seja executado quando mudarmos para Chuck with ?. Agora tudo o que Chuck faz é >.que apenas se move para a 1célula -e imprime isso.

Podemos obter facilmente as outras três funções negando uma ou ambas as entradas, conforme necessário.

0111, 1011, 1101, 1110: Funções binários com três resultados truthy

,\x01?,?>?
#{>.
,\x01?,-?>?
#{>.
,\x01-?,?>?
#{>.
,\x01-?,-?>?
#{>.

Uma pequena modificação da idéia anterior, a fim de negar o resultado (ou seja, imprimir 0quando passamos por Brian e 1outros). Vejamos 0111(OR) como um exemplo. Observe que o 1byte incorporado é um no-op, então isso ainda começa com ,?,?. Se qualquer uma das entradas for 1, mudamos para Chuck, que move a cabeça da fita de volta ao início {. >.move a cabeça da fita para esse 1byte e a imprime.

Se as duas entradas forem zero, permaneceremos com Brian, mova a cabeça da fita {para pular e depois mude para Chuck. Quando ele executa >.esse tempo, ele se move para a célula vazia após o código de Brian e imprime o 0.

Novamente, obtemos facilmente as outras funções negando uma ou ambas as entradas.

0110, 1001: Funções binárias com dois resultados de verdade

,?>},?>?_\x01
#}+{>?_}>.
,-?>},?>?_\x01
#}+{>>?_}>.

Este é um pouco mais complicado. As funções anteriores eram razoavelmente simples porque podem estar em curto-circuito - o valor da primeira entrada pode decidir a saída e, se não, então examinamos a outra entrada. Para essas duas funções, sempre precisamos examinar as duas entradas.

A idéia básica é usar a primeira entrada para decidir se a segunda entrada escolhe entre 0e / 1ou entre 1e 0. Vamos tomar 0110(XOR) como um exemplo:

Considere A = 0. Neste caso, queremos produzir Bcomo estão. ,A, ?não faz nada. >passa para a próxima célula (diferente de zero), o que }nos leva ao _Chuck on. Aqui, podemos ler Bcom ,e usar ?novamente. Se Bfoi 0assim, ainda estamos no Brian. >pula o }Chuck e ?alterna para que >.imprima o 0incorporado no código-fonte de Brian. Se Bfoi 1, por outro lado, Chuck não executar o }que se move no _no código de Brian já, de modo que o >.então imprime o 1-byte vez.

Se A = 1, então, mudaremos imediatamente para Chuck, que executará }+{>?. O que isso faz é mover para o _código-fonte de Brian, transformá-lo em um 1também +e depois voltar ao início {e pular o de Brian ?movendo uma célula para a direita >antes de devolver o controle a ele. Desta vez, depois que Brian leu B, se B = 0e Chuck usa >.a célula ao lado de Brian, ?será em 1vez de 0. Além disso, quando B = 1Chuck }pula o que costumava ser uma lacuna e se move todo o caminho até o final da fita, de modo que >.imprime um zero. Dessa forma, estamos imprimindo not B.

Para implementar a equivalência, simplesmente negamos Aantes de usá-la como condição. Observe que, devido a isso, também precisamos adicionar outro >ao Chuck para pular isso -também ao voltar ao início.


4

ClojureScript, 88 84 76 74 bytes

nile falsesão falsas, todos os outros valores são verdadeiros. Booleanos coagem a 0/1 para aritmética e desigualdades. Funções podem receber o número errado de argumentos.

0000   nil?            ; previously: (fn[]nil)
0001   and
0010   <
0011   true?           ; previously: (fn[x]x)
0100   >
0101   (fn[x y]y)
0110   not=
0111   or
1000   #(= 0(+ % %2))
1001   =
1010   #(not %2)
1011   <=
1100   not
1101   >=
1110   #(= 0(* % %2))
1111   /               ; previously: (fn[]4), inc

Não é 0falso?
Leaky Nun

2
Não no ClojureScript.
MattPutnam

@LeakyNun Não na maioria dos Lisps ou linguagens de programação funcional, que Clojure é definitivamente
gato

@cat Sim, na maioria das linguagens de programação funcionais! O Python, por exemplo, avalia not not(0)como False, qual é o valor de falsey.
Erik the Outgolfer

3
@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Er ... Python não é puramente funcional nem o tipo de linguagem funcional de que estou falando. O Python é imperativo, principalmente, e com alguns aspectos funcionais menores (mal executados). Erlang, Haskell (eu acho), LISP comum, Clojure, Racket, Scheme, Factor, ML padrão, CAML Objetivo, etc 0 é apenas mais um valor e é como resultado truthy, eo símbolo para false ( #f, f, false, etc) é falso. Todos os outros valores são verdadeiros na maioria das linguagens funcionais.
cat

4

Brainfuck , 184 178 174 bytes

A entrada / saída usa U + 0000 e U + 0001.

0000 .
0001 ,[,[->+<]]>.
0010 ,[,-[+>+<]]>.
0011 ,.
0100 ,-[,[->+<]]>.
0101 ,,.
0110 ,>,[-<->]<[>>+<]>.
0111 ,-[,-[+>-<]]>+.
1000 ,-[,-[+>+<]]>.
1001 ,>,[-<->]<[>>-<]>+.
1010 ,,-[+>+<]>.
1011 ,-[,[->-<]]>+.
1100 ,-[+>+<]>.
1101 ,[,-[+>-<]]>+.
1110 ,[,[->-<]]>+.
1111 +.

Sua leitura de uma segunda entrada condicional parece cara. Por exemplo, para 0001você não poderia simplesmente fazer ,[,>]<.(dado um intérprete que permite ir para a esquerda da célula inicial)?
Martin Ender

@MartinEnder Imaginei que não iria apenas copiar a resposta de Dennis aqui.
Freira vazando

4

Flak cerebral , 418 , 316 bytes

Experimente online!

Deixe que as entradas sejam os dois principais números da pilha no início do programa (zero para falso um para verdadeiro) e a saída esteja no topo da pilha no final do programa (zero para falso ou falso).

false, 4 bytes (Cortesia de Leaky Nun )

(<>)

e 36 bytes

(({}{}[(())()])){{}{}(((<{}>)))}{}{}

A e não B, 40 bytes

((({}){}{}[(())()])){{}{}(((<{}>)))}{}{}

A, 6 bytes

({}<>)

não A e B, 38 bytes

((({}){}{}[(())])){{}{}(((<{}>)))}{}{}

B, 2 bytes

{}

xor, 34 bytes

(({}{}[(())])){{}{}(((<{}>)))}{}{}

ou 6 bytes

({}{})

nem 34 bytes

(({}{}<(())>)){{}{}(((<{}>)))}{}{}

xnor, 10 bytes

({}{}[()])

não B, 34 bytes

{}(({}<(())>)){{}{}(((<{}>)))}{}{}

B implica A, 14 bytes

(({}){}{}[()])

não A, 34 bytes

(({}<{}(())>)){{}{}(((<{}>)))}{}{}

A implica B, 16 bytes

(({}){}{}[()()])

e 12 bytes

({}{}[()()])

verdadeiro, 6 bytes

<>(())

Explicação

Como a maioria delas é muito parecida, não vou explicar exatamente como cada uma delas funciona. Tento o meu melhor para deixar claro, no entanto, como todos os dezesseis funcionam.

Primeiro, são os portões que retornam três do mesmo valor (ou seja, 2, 3, 5, 8, 9, 12, 14 e 15). Todos eles seguem o mesmo padrão. Primeiro, você converte a entrada em um número de dois bits com a como os dois lugares e B como esses. Isso é feito com este trecho (({}){}{}). Você subtrai o valor da entrada de dois bits que deseja isolar ({}[value]). (No código real, a subtração e a conversão são feitas em uma etapa para salvar bytes). Isto pode ser combinado com um não, se necessário: (({}<(())>)){{}{}(((<{}>)))}{}{}.

A seguir: e, nem, ou, xor e xnor. Estes funcionam de forma semelhante aos acima. De fato, alguns deles estão incluídos acima, porém esse método é mais curto. O truque que usei aqui é que cada um corresponde a uma soma de A B. Por exemplo, xor avalia como verdadeiro se A + B = 1 e falso de outra forma. Primeiro você adiciona AB e subtrai a quantia relevante. Expressado como ({}{}[0,1,2 or 3]). Então, se necessário, conduza um

A seguir: A, B, não A e não B. Estes são praticamente auto-explicativos. Começamos removendo o valor desnecessário e depois negamos ou terminamos.

Por fim, são os dois simplórios: verdadeiro e falso. Para estes, colocamos o valor correto na pilha off. O <>nilad retorna zero, para que possamos salvar dois bytes usando a opção como valor zero.

Não é a solução mais eficiente disponível no mercado (talvez a mais eficiente no Brain-Flak), mas me diverti bastante escrevendo isso e imploro que você tente encurtá-las.


(<>)é suficiente para false; Também, (<{}{}>)é de 8 bytes
gotejante Nun

Uau, eu tinha uma definição muito mais rigorosa do desafio. Obrigado. Vou reduzir muito isso
Assistente de trigo

O que você quer dizer?
Freira vazando

Eu pensei que tinha que remover as entradas existentes e colocar o resultado em seu lugar. (<>)deixará as entradas e colocará o zero na outra pilha.
Assistente de trigo

11
Não é <>suficiente falsedevido a zeros implícitos? Além disso, acho que apode ser o programa vazio. truepode ser <>[][](não salva bytes, mas parece legal: P).
CalculatorFeline

4

ProgFk , 18,5 17,5 bytes

Como as instruções do ProgFk são especificadas em mordidelas, o código abaixo é fornecido em hexadecimal, um portão lógico por linha e com espaços entre os bytes.

3
E1
DE 2D
<empty>
DE 1
1
E3
E2
E2 D
E3 D
1D
DE 2
D
DE 1D
E1 D
4

Explicação

ProgFk é um esolang baseado em fita (semelhante ao Brainfuck), em que cada célula é um pouco e as instruções são fornecidas como petiscos (4 bytes). As instruções operam na célula apontada pelo ponteiro da instrução. A entrada é fornecida na primeira e na segunda célula (com Ae Bsendo a primeira e a segunda células, respectivamente), e o ponteiro da instrução começa na primeira célula. A saída é armazenada na primeira célula.

Cada instrução usada é explicada abaixo.

1   Increment the instruction pointer.
2   Decrement the instruction pointer.
3   Set the current bit to 0.
4   Set the current bit to 1.
D   Perform a NOT on the current bit.
E   The next instruction is an extended instruction.

Extended instructions:
1   Set the current bit to the current bit AND the next bit.
2   Set the current bit to the current bit OR the next bit.
3   Set the current bit to the current bit XOR the next bit.
6   Swap the current bit and the next bit.

Guardou um byte graças a @LeakyNun!


4

Na verdade, 24 bytes

Esses programas recebem entrada como A\nB( \nrepresentando uma nova linha), que deixa B no topo da pilha, com A abaixo. Falseé representado por 0e Trueé representado por qualquer número inteiro positivo.

é0  (false: clear stack, push 0)
*   (and: multiply)
<   (A and not B: less-than)
X   (A: discard B)
>   (B and not A: greater-than)
@X  (B: discard A)
^   (A xor B: xor)
|   (A or B: or)
|Y  (A nor B: or, boolean negate)
=   (A xnor B: equals)
@XY (not B: discard A, boolean negate B)
≤   (if B then A: less-than-or-equal)
XY  (not A: discard B, boolean negate)
≥   (if A then B: greater-than-or-equal)
*Y  (A nand B: multiply, boolean negate)
é1  (true: clear stack, push 1)

Agradecimentos a Leaky Nun por 3 bytes

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.