Booleanos da Igreja

33

Booleanos da igreja

Um booleano de igreja é uma função que retorna xpara verdadeiro e ypara falso onde xé o primeiro argumento para a função e yé o segundo argumento para a função. Outras funções podem ser compostas a partir dessas funções, que representam as operações and not or xore implieslógicas.

Desafio

Construir as booleans Igreja e and not or xore impliesPortas da igreja em um idioma de sua escolha. and ore xordeve assumir duas funções (representando os booleanos da Igreja) e retornar uma função (representando outro booleano da Igreja). Da mesma forma, notdeve inverter a função necessária e o impliesgate deve executar booleano implica lógica onde o primeiro argumento é implieso segundo.

Pontuação

O comprimento total de todo o código necessário para fazer Igreja truee falsena sua língua eo and not or xore impliesIgreja portões excluindo o nome da função. (por exemplo, false=lambda x,y:yem Python seria 13 bytes). Você pode reutilizar esses nomes posteriormente no seu código, contando 1 byte no total de bytes desse gate.

Exemplos de pseudo-código:

As funções que você cria devem poder ser chamadas posteriormente em seu código, assim.

true(x, y) -> x
false(x, y) -> y
and(true, true)(x, y) -> x
and(true, false)(x, y) -> y
# ... etc
Ryan Schaefer
fonte
2
Temos que tratar as entradas de função (ou substitutos mais próximos) como funções de caixa preta ou podemos inspecionar o código? E os valores de retorno das operações lógicas devem ter as mesmas funções definidas anteriormente como os booleanos da Igreja, ou podem ser outra coisa que faz a mesma coisa?
String não relacionada
1
@ JonathanAllan Eu editei para que estivesse correto. O prompt é como deveria ser agora.
Ryan Schaefer
2
Podemos tomar listas como argumentos (por exemplo true([x, y]), and([true, true])([x, y]))?
ar4093 20/08
2
@RyanSchaefer Acho que você deve reconsiderar a permissão de que os argumentos estejam em uma lista ordenada, pois é possível simplesmente agrupar os argumentos no início das soluções. Não acho que exigir isso faça algo para melhorar esse desafio (na verdade, acho que limita o potencial interessante do golfe). Obviamente, essa é apenas a minha opinião, e tudo bem se você não concorda.
FryAmTheEggman 20/08
1
A pontuação é bastante confusa. Não seria melhor permitir que as pessoas enviassem funções anônimas, mas se as usarem em outras partes, elas terão que atribuí-las, como de costume
Jo King

Respostas:

14

Cálculo lambda binário , 13,875 12,875 bytes (103 bits)

A linguagem de cálculo binário lambda (BLC) de John Tromp é basicamente um formato de serialização eficiente para o cálculo lambda. É uma ótima opção para essa tarefa, pois a notação da Igreja é até a maneira "idiomática" de trabalhar com booleanos no BLC.

Usei as seguintes funções lambda para os combinadores, algumas das quais copiei e joguei na resposta Haskell:, que foram encontradas por uma pesquisa exaustiva com um limite de prova de 20 β-reduções para cada caso. Há uma boa chance de que sejam os mais curtos possíveis.

True:  (\a \b a)
False: (\a \b b)
Not:   (\a \b \c a c b)
And:   (\a \b b a b)
Or:    (\a a a)
Xor:   (\a \b b (a (\c \d d) b) a)
Impl:  (\a \b a b (\c \d c))

Isso se traduz nas seguintes seqüências de código BLC (binárias):

 bits |  name | BLC
------+-------+---------
    7 | True  | 0000 110
    6 | False | 0000 10
   19 | Not   | 0000 0001 0111 1010 110
   15 | And   | 0000 0101 1011 010
    8 | Or    | 0001 1010
   28 | Xor   | 0000 0101 1001 0111 0000 0101 0110
   20 | Impl  | 0000 0101 1101 0000 0110

As funções acima têm no total 111 bits de comprimento (13,875 bytes) e 103 bits de comprimento (12,875 bytes). Eles não precisam estar alinhados aos limites de bytes para serem usados ​​dentro de um programa; portanto, faz sentido contar bytes fracionários.

Não há reutilização de código entre os combinadores, porque não há variáveis ​​/ referências / nomes no BLC - tudo teve que ser copiado. Ainda assim, a eficiência da codificação cria uma representação bastante concisa.

Pavel Potoček
fonte
1
Eu não sei blc, mas vai And: (\a \b a b a)funcionar?
tsh
Sim, funciona. Na verdade, eu usei essa fórmula para minhas seqüências de código. Esqueci de atualizar a função lambda correspondente (agora corrigida). A função equivalente trabalha para Ou: \a \b a a b. É mais longo que o que eu usei no BLC.
Pavel Potoček em
25

Haskell , 50 - 6 = 44 bytes

-1 byte graças a Khuldraeseth na'Barya e -1 byte graças a Christian Sievers.

t=const
f=n t
n=flip
a=n n f
o=($t)
x=(n>>=)
i=o.n

Experimente online!

Nitrodon
fonte
2
Nota lateral: você pode definir Showcasos de conste const ide imprimir as booleans igreja diretamente. Experimente online! .
nimi
apode ser encurtado.
Khuldraeseth na'Barya
4
Por que ninguém está usando f=n t?
Christian Sievers
3
Você pode salvar um byte usando em t=purevez de t=const.
Joseph Sible-Reinstate Monica
4
@ Josephphible Eu tentei isso inicialmente. Infelizmente, t=purecausará um erro quando tento aplicar a, o, x, ou ipara ele. Declarar o tipo de tcorreção isso custa mais bytes do que apenas usar t=const.
Nitrodon 20/08
9

Python 2 , (-3?)  101  95 bytes

David Beazley come seu coração!

-6 graças a Chas Brown (moveu o repetido :para o texto de junção>. <)

exec'=lambda x,y=0:'.join('F y;T x;N x(F,T);A x(y,F);O x(T,y);X x(N(y),y);I O(y,N(x))'.split())

Experimente online!

Eu acho que pode ser 95 - 3porque eu não reutilizar as funções A, Xou I, mas eu uso um único =para a atribuição (em frente lambda). Talvez eu não consiga remover nenhum; talvez eu até consiga remover 3.5?

Jonathan Allan
fonte
@Ryan Schaefer posso remover três ou meu uso de execmeios que não posso? Eu posso ver indo de qualquer maneira - não reutilizo A, X ou I, mas o código não funcionará sem eles. (Talvez eu até consiga remover 3.5 ?!)
Jonathan Allan
Obrigado @Chas! Os dois pontos que deslizaram pela rede :) Bom trabalho na substituição de -1 BTW
Jonathan Allan
7

JavaScript (Node.js) , 92 86 83 - 7 = 76 bytes

t=p=>q=>p
f=t(q=>q)
n=p=>p(f)(t)
a=p=>n(p)(f)
o=p=>p(t)
x=p=>p(n)(f())
i=p=>n(p)(t)

Experimente online! O link inclui casos de teste básicos. Editar: salvou 6 9 bytes graças a @tsh.

Neil
fonte
1
Parece que você não pode reivindicar isso como -7 desde t, f, nsão usados.
tsh
1
@tsh Não é assim que eu entendo o sistema de pontuação; exclui explicitamente o nome na definição, embora o nome no uso custe 1 byte.
Neil
@Neil você não pode reivindicar o desconto byte para nomes de funções que são chamados por seu código ( t, fe, nno seu caso).
asgallant 20/08
2
@asgallant no. Não há bytes para o nome e 1 byte quando usado posteriormente. 'T fnaox i' não tem bytes, então 1 byte quando usado mais tarde. Eu queria melhorar a legibilidade, mas agora percebo que deveria ter deixado o jogo completamente e é tarde demais para mudar agora
Ryan Schaefer
@RyanSchaefer, onde está essa regra? Eu nunca vi isso feito assim.
asgallant 22/08
6

Python 2 , 133 - 6 = 127 94 bytes

exec"t!u;f!v;n!u(f,t);a!u(v,f);o!u(t,v);x!u(n(v),v);i!o(v,n(u))".replace('!','=lambda u,v=0:')

Experimente online!

Roubando descaradamente a ideia furtiva por trás da resposta de Jonathan Allan ; embora não sejam deduzidos bytes.

Chas Brown
fonte
Eu ia postar uma resposta para minha própria pergunta, mas não tinha certeza se isso era permitido e acho que isso é contra o espírito dela. Então, acho que vou apenas guiá-lo. Em vez de usar listas, existe alguma maneira de usar as funções que estão sendo inseridas e a maneira específica pela qual elas retornam suas entradas para encurtar o código?
Ryan Schaefer
Eu apostaria que, embora a resposta seja sim, seria consideravelmente mais longa em Python.
String não relacionada
Estou corrigido
String não relacionado
@ Mr.Xcoder você está correto, eu tinha o número errado de bytes para a função de exemplo. Eles teriam permissão para remover 6 bytes para os nomes das funções.
Ryan Schaefer
@Sr. Xcoder: modificado conforme suas observações.
Chas Brown
4

J , 67 bytes - 7 = 60

t=.[
f=.]
n=.~
a=.2 :'u v]'
o=.2 :'[u v'
x=.2 :'u~v u'
i=.2 :'v u['

Experimente online!

Vale nada:

Funções de ordem superior funcionam de maneira diferente em J do que em uma linguagem funcional. Para criar um novo verbo a partir de 1 ou 2 verbos existentes, você precisa usar um advérbio (no caso de 1) ou uma conjunção (no caso de 2).

Sintaticamente, advérbios vêm após um verbo e conjunções vão entre eles. Assim, para "não" um verbo que fvocê faz f n, e para "e" verbos fe g, você f a g.

Jonah
fonte
4

Wolfram Language (Mathematica) , 61-7 = 54 bytes

t=#&
f=#2&
a=#2~#~f&
o=t~#~#2&
n=f~#~t&
x=n@#~#2~#&
i=#2~#~t&

Experimente online!

sem golfe: inspirado na Wikipedia ,

t[x_, y_] := x
f[x_, y_] := y
and[x_, y_] := x[y, f]
or[x_, y_] := x[t, y]
not[x_] := x[f, t]
xor[x_, y_] := y[not[x], x]
imply[x_, y_] := x[y, t]
romano
fonte
Certamente as novas linhas são necessárias para separar as definições de funções. Você também faz referência a tf e n em outras definições de funções para não deduzir essas, portanto 61-4 = 57.
Jonathan Allan
@ JonathanAllan Reli as instruções de pontuação e concordo que as novas linhas devem contar, obrigado. Não concordo com a sua segunda parte: quando reutilizo os nomes, de fato os conto como "1 byte em relação ao total de bytes desse gate", o que está implícito aqui quando uso nomes de 1 byte. Conforme minha leitura das instruções, não há menção de contá-las como um byte para o total da definição original também. Então, eu vou com N-7 bytes. Além disso, outro comentário do OP esclarece: "Não há bytes para o nome e 1 byte quando usado posteriormente".
Roman
Eu li "1 byte later" para significar que o uso dentro de outra função custa um byte. Isso está alinhado com a forma como os outros também marcaram.
Jonathan Allan
@ JonathanAllan Estou menos interessado em exegese e mais em código de golfe 😀
Roman
4

Carga insuficiente , 56 52 bytes

(~!)(!)((~)~*):((!)~^)*(:^)(~(!)~^(~)~*)(()~(~)~^~*)

Experimente online! (inclui um conjunto de testes e um texto que identifica partes do programa)

Isso é surpreendentemente bom para um esolang de nível muito baixo. (Numerais da igreja, booleanos da igreja etc. são muito comumente usados ​​no Underload por esse motivo; o idioma não possui números e booleanos incorporados, e essa é uma das maneiras mais fáceis de simulá-los. Dito isso, também é comum codificar booleanos como os números 0 e 1. da Igreja)

Para quem está confuso: Underload permite definir funções reutilizáveis, mas não permite que você as nomeie da maneira normal, elas meio que flutuam na pilha de argumentos (por isso, se você definir cinco funções e depois chamar a primeira) você definiu, precisa escrever uma nova função que use cinco argumentos e chame o quinto deles, depois chame-a com argumentos insuficientemente para que procure argumentos extras a serem usados). Chamá-los destrói-os por padrão, mas você pode modificar a chamada para torná-la não destrutiva (em casos simples, você só precisa adicionar dois pontos à chamada, embora os casos complexos sejam mais comuns porque você precisa garantir que as cópias na pilha não atrapalha), então o suporte às funções do Underload tem todos os requisitos que precisamos da pergunta.

Explicação

verdade

(~!)
(  )  Define function:
 ~      Swap arguments
  !     Delete new first argument (original second argument)

Essa é bem direta; nos livramos do argumento que não queremos e o argumento que queremos permanece lá, servindo como valor de retorno.

falso

(!)
( )   Define function:
 !      Delete first argument

Este é ainda mais direto.

não

((~)~*)
(     )  Define function:
    ~*     Modify first argument by pre-composing it with:
 (~)         Swap arguments

É divertido: notnão chama de argumento, apenas usa uma composição de função. Esse é um truque comum no Underload, no qual você não inspeciona seus dados, apenas altera a forma como eles funcionam pré e pós-compondo as coisas com ele. Nesse caso, modificamos a função para trocar seus argumentos antes da execução, o que claramente nega um numeral da Igreja.

e

:((!)~^)*
 (     )   Define function:
     ~^      Execute its first argument with:
  (!)          false
               {and implicitly, our second argument}
        *  Edit the newly defined function by pre-composing it with:
:            {the most recently defined function}, without destroying it

A questão permite definir funções em termos de outras funções. Definimos "e" a seguir, porque quanto mais recentemente "não" tiver sido definido, mais fácil será usá-lo. (Isso não subtrai nossa pontuação, porque não estamos nomeando "não", mas economiza bytes ao escrever a definição novamente. Essa é a única vez que uma função se refere a outra, porque se refere a qualquer função mas o definido mais recentemente custaria muitos bytes.)

A definição aqui é and x y = (not x) false y. Em outras palavras, se not xretornarmos false; caso contrário, retornamos y.

ou

(:^)
(  )  Define function:
 :      Copy the first argument
  ^     Execute the copy, with arguments
          {implicitly, the original first argument}
          {and implicitly, our second argument}

O @Nitrodon apontou nos comentários que or x y = x x ynormalmente são menores que or x y = x true ye que também estão corretos no Underload. Uma implementação ingênua disso seria(:~^) , mas podemos obter um byte adicional observando que não importa se executamos o primeiro argumento original ou a cópia dele, o resultado é o mesmo.

Underload não suporta curry no sentido usual, mas definições como essa fazem com que pareça! (O truque é que argumentos não consumidos permanecem por aí, então a função que você chama os interpretará como seus próprios argumentos.)

implica

(~(!)~^(~)~*)
(           )  Define function:
 ~               Swap arguments
     ~^          Execute the new first (original second) argument, with argument:
  (!)              false
                   {and implicitly, our second argument}
       (~)~*     Run "not" on the result

A definição usada aqui é implies x y = not (y false x). Se y for verdadeiro, isso simplifica para not false, ie true. Se y for falso, isso simplifica anot x , fornecendo a tabela de verdade que queremos.

Nesse caso, estamos usando notnovamente, desta vez reescrevendo seu código em vez de fazer referência a ele. É apenas escrito diretamente como(~)~* sem parênteses, portanto é chamado e não definido.

xor

(()~(~)~^~*)
(          )  Define function:
   ~   ~^       Execute the first argument, with arguments:
    (~)           "swap arguments"
 ()               identity function
         ~*     Precompose the second argument with {the result}

Desta vez, estamos avaliando apenas um dos nossos dois argumentos e usá-lo para determinar o que compor no segundo argumento. Underload permite que você jogue rápido e livre com aridade, então estamos usando o primeiro argumento para escolher entre duas funções de dois argumentos e dois retornos; a troca de argumentos que retorna os dois, mas na ordem oposta, e a função de identidade que retorna os dois na mesma ordem.

Quando o primeiro argumento é verdadeiro, produzimos uma versão editada do segundo argumento que troca seus argumentos antes da execução, ou seja, pré-compõe com "argumentos de troca", ou seja not. Portanto, um verdadeiro primeiro argumento significa que retornamos noto segundo argumento. Por outro lado, um primeiro argumento falso significa que compomos com a função de identidade, ou seja, não fazemos nada. O resultado é uma implementação de xor.

ais523
fonte
or x y = x x ysalva alguns bytes or x y = x true y.
Nitrodon
A subcarga frequentemente é contra-intuitiva quando se trata de substituir literais por variáveis ​​reutilizadas, mas nesse caso, essa transformação acaba salvando mais bytes do que o esperado, em vez de menos. Obrigado pela melhoria!
ais523 23/08
3

Ruby , 82 - 4 = 78 bytes

f,t,a,n,i,o,x=%w(y:y x:x f:y t:f t:y y:t y:n[y]).map{|s|eval"->x,y=0{x==f ?#{s}}"}

Experimente online!

GB
fonte
3

Java 8, score: 360 358 319 271 233 (240-7) bytes

interface J<O>{O f(O x,O y,J...j);}J t=(x,y,j)->x;J f=(x,y,j)->y;J n=(x,y,j)->j[0].f(y,x);J a=(x,y,j)->j[0].f(j[1].f(x,y),y);J o=(x,y,j)->j[0].f(x,j[1].f(x,y));J x=(x,y,j)->j[0].f(j[1].f(y,x),j[1].f(x,y));J i=(x,y,j)->j[0].f(j[1].f(x,y),x);

Isso foi mais difícil de realizar do que eu pensava quando comecei. Especialmente o implies . Enfim, funciona .. Provavelmente pode ser jogado um pouco aqui e ali.EDIT: Ok, não reutilizar funções, mas apenas duplicar a mesma abordagem é muito mais barato em termos de contagem de bytes para Java .. E eu recebo o bônus total de -7 por não usar nenhuma das funções também.

Experimente online.

Explicação:

// Create an interface J to create lambdas with 2 Object and 0 or more amount of optional
// (varargs) J lambda-interfaces, which returns an Object:
interface J<O>{O f(O x,O y,J...j);}

// True: with parameters `x` and `y`, always return `x`
J t=(x,y,j)->x;
// False: with parameters `x` and `y`, always return `y`
J f=(x,y,j)->y;

// Not: with parameters `x`, `y`, and `j` (either `t` or `f`), return: j(y, x)
J n=(x,y,j)->j[0].f(y,x);

// And: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//      j1(j2(x,y), y);
J a=(x,y,j)->j[0].f(j[1].f(x,y),y);

// Or: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//     j1(x, j2(x,y))
J o=(x,y,j)->j[0].f(x,j[1].f(x,y));

// Xor: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//      j1(j2(y,x), j2(x,y))
J x=(x,y,j)->j[0].f(j[1].f(y,x),j[1].f(x,y));

// Implies: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//          j1(j2(x,y), x)
J i=(x,y,j)->j[0].f(j[1].f(x,y),x);
Kevin Cruijssen
fonte
2

C ++ 17, 207−49 = 158 195 - 58 = 137 bytes

As quebras de linha são desnecessárias (exceto as duas primeiras).

#define A auto
#define D(v,p)A v=[](A x,A y){return p;};
D(true_,x)
D(false_,y)
A not_=[](A f){return f(false_,true_);};
D(and_,x(y,false_))
D(or_,x(true_,y))
D(xor_,x(not_(y),y))
D(implies,x(y,true_))

Experimente online!

Testado em unidade com afirmações como:

static_assert('L' == true_('L', 'R'));
static_assert('R' == not_(true_)('L', 'R'));
static_assert('L' == and_(true_, true_)('L', 'R'));
static_assert('L' == or_(true_, true_)('L', 'R'));
static_assert('R' == xor_(true_, true_)('L', 'R'));
static_assert('L' == implies(true_, true_)('L', 'R'));

ATUALIZADO: anteriormente eu tinha

A not_=[](A f){return[f](A x,A y){return f(y,x);};};

mas a resposta de Roman apontou o caminho para a versão mais curta. Observe que agora not_(std::plus<>)está mal formado, onde antigamente era equivalente std::plus<>; mas como std::plus<>"não representa um booleano da Igreja", acho que um ou outro comportamento é bom pelas regras.

Quuxplusone
fonte
"Diferente do primeiro" não deve ser atualizado para "diferente dos dois primeiros"?
LF
@LF: Absolutamente correto. Atualizada. :)
Quuxplusone 20/08
2

Quarto (gforth) , 133 bytes - 7 = 126 122

: j execute ;
: t drop ;
: f nip ;
: n ['] f ['] t rot j ;
: a dup j ;
: o over j ;
: x 2dup a n -rot o a ;
: m over n -rot a o ;

Experimente online!

-4 bytes graças a Quuxplusone

Inicialmente, pensei demais sobre isso, considerando coisas como macros e literais, mas depois percebi que se eu definir as coisas em termos de verdadeiro e falso (como eu deveria ter feito em primeiro lugar), fica muito mais simples.

Explicação do código

\ Helper function to save some bytes
: j        \ define a new word
  execute  \ execute the word at the provided address
;          \ end word definition

\ True
: t        \ define a new word
  drop     \ drop the second argument
;          \ end the word

\ False
: f        \ define a new word
  nip      \ drop the first argument
;          \ end the word

\ Not - The "hardest" one because we have to reference true and false directly
: n        \ define a new word
  ['] f    \ get address of false
  ['] t    \ get the address of true
  rot      \ stick the input boolean back on the top of the stack
  j        \ call the input boolean, which will select the boolean to return
;          \ end the word

\ And 
: a        \ define a new word
  dup      \ duplicate the 2nd input value
  j        \ call the 2nd input on the first and second input
;          \ end the word

\ Or
: o        \ define a new word
  over     \ duplicate the 1st input value
  j        \ call the 1st input on the first and second input
;          \ end the word

\ Xor
: x        \ define a new word
  2dup     \ duplicate both of the inputs
  a n      \ call and, then not the result (nand)
  -rot     \ move the result behind the copied inputs
  o a      \ call or on the original inputs, then call and on the two results
;          \ end the word

\ Implies
: m        \ define a new word
  over     \ duplicate the 1st input value
  n        \ call not on the 1st input value
  -rot     \ move results below inputs
  a o      \ call and on the two inputs, then call or on the two results
;          \ end the word
reffu
fonte
1
Você repete a palavra longa executetrês vezes. Definir a abreviação : j execute ;economizaria 4 bytes.
Quuxplusone
1

Combinado SKI-calculus + C, 36 bytes

true=K
false=SK
not=C
and=CC(SK)
or=CIK
xor=C(CIC)I
implies=CCK

Na verdade, eu não conheço nenhum intérprete que permita definir combinadores adicionais em termos dos anteriores, então tive que testar isso usando http://ski.aditsu.net/ colando nos combinadores desejados, por exemplo , CCKK(SK)pqsaídas q, mostrando que Knão implica SK.

Neil
fonte
1

Julia 1.0 , 36 bytes

(b::Bool)(x,y)=b ? x : y;i(x,y)=!x|y

Não sei se isso conta, na verdade estou sobrecarregando o Booltipo nativo para que seja possível chamar, por isso recebo a maioria dos portões lógicos de graça. Infelizmente, Julia não tem um impliesportão, então tive que escrever minha própria função.

Experimente online!

user3263164
fonte
Acho que você ainda precisa incluir os operadores sobrecarregados em sua submissão ... mas a pontuação não os conta, pois são apenas nomes? Então seria +6 bytes das novas linhas? Não tenho muita certeza de como a pontuação funciona com esse desafio
Jo King
Também não tenho 100% de certeza de como isso funciona, mas ter que incluir código que literalmente não faz nada não faz sentido para mim.
user3263164
Mesmo se o código já estiver declarado, você ainda precisará incluí-lo; caso contrário, todos os outros envios de idiomas de golfe terão zero bytes. Você simplesmente não precisa atribuí-lo a nada
Jo King
1

Perl 6 , 120 106 102 101 bytes

-1 byte graças a Jo King

my (\t,\f,&n,&a,&o,&i,&x)={@_[0]},{@_[1]},|<f,t &^v,f t,&^v &^v,t n(&^v),&v>>>.&{"&\{\&^u($_)}".EVAL}

Experimente online!

Nwellnhof
fonte
1

C ++ 17, 202−49 = 153 193 - 58 = 135 bytes

Inspirado pela discussão-comentário sobre o que conta como uma função de 2 árias de qualquer maneira, aqui está uma versão atualizada da minha solução anterior do C ++ 17. Na verdade, é mais curto, porque podemos usar a mesma macro para definir not_e definir todas as outras funções!

#define D(v,p)auto v=[](auto x){return[=](auto y){return p;};};
D(true_,x)
D(false_,y)
D(not_,x(false_)(true_)(y))
D(and_,x(y)(false_))
D(or_,x(true_)(y))
D(xor_,x(not_(y))(y))
D(implies,x(y)(true_))

Experimente online!

Este é testado com afirmações como

static_assert('R' == and_(true_)(false_)('L')('R'));
static_assert('L' == or_(true_)(false_)('L')('R'));

Observe que or_é definido como efetivamente

auto or_=[](auto x){return[=](auto y){return x(true_)(y);};};

Poderíamos definir de forma or_mais "concisa" como

auto or_=[](auto x){return x(true_);};

mas isso nos custaria porque não poderíamos mais usar a Dmacro.

Quuxplusone
fonte
Como o C ++ diferencia maiúsculas de minúsculas, que tal usar Truee em Falsevez de true_e false_? E semelhante para os outros operadores. Isso economizará 12 bytes.
G. Sliepen
@ G.Sliepen: O algoritmo de pontuação do OP já leva em consideração que os identificadores possuem efetivamente um caractere. Citação: "O comprimento total de todo o código necessário para tornar a Igreja verdadeira e falsa no seu idioma e a not not ou xor e implica portões da Igreja excluindo o nome da função. (Por exemplo, false = lambda x, y: y em Python 13 bytes). Você pode reutilizar esses nomes posteriormente em seu código, contando 1 byte no total de bytes desse gate ".
Quuxplusone
Ah, eu senti falta disso.
G. Sliepen
0

APL (dzaima / APL) , 47 bytes SBCS de

Baseado em solução J de Jonah .

truee falsesão funções infix, noté um operador de sufixo e o restante são operadores infix.

true←⊣
false←⊢
and←{⍺(⍶⍹false)⍵}
not←⍨
or←{⍺(true⍶⍹)⍵}
xor←{⍺(⍶not⍹⍶)⍵}
implies←{⍺(⍹⍶true)⍵}

De acordo com o OP, isso conta tudo, inclusive e até o final de cada linha, e cada chamada é uma definição anterior como um byte único.

Experimente online!

verdadeiro e falso são as funções de identidade esquerda e direita.

not simplesmente troca os argumentos de sua função de operando.

O restante implementa a árvore de decisão:

and usa a função da mão direita para selecionar o resultado da função mão esquerda, se verdadeiro, caso contrário, o resultado da falsefunção.

or usa a função esquerda à para selecionar truese verdadeiro, caso contrário, o resultado da função à direita .

xor usa a função da mão direita para selecionar o resultado negado da função mão esquerda, ⍶notse verdadeiro, caso contrário, o resultado da função mão esquerda.

impliesusa a função mão esquerda para selecionar o resultado da função mão direita, se verdadeiro, caso contrário, o resultado da truefunção.

Adão
fonte
0

Stax , 34 bytes

¿S£↓♣└²≡é♫Jíg░EèΩRΦ♂°┤rà╝¶πï╡^O|Θà

Execute e depure-o em staxlang.xyz!

Empurra um monte de blocos para a pilha. Cada bloco espera seu último argumento no topo da pilha, seguido na ordem inversa pelo resto.

Descompactado (41 bytes):

{sd}Y{d}{y{d}a!}X{ya!}{b!}{cx!sa!}{sx!b!}

Cada par de { }é um bloco. Usei os dois registradores X e Y para armazenar truee, notassim, poderia acessá-los facilmente mais tarde. Infelizmente,false não poderia ser simplesmente um não-op, pois isso deixaria a pilha confusa e atrapalharia um único caso XOR.

Conjunto de teste, comentado

false
{sd}    stack:   x y
 s      swap:    y x
  d     discard: y

true
{d}    stack:   x y
 d     discard: x

not
{y{d}a!}    stack:  p
 y{d}       push:   p f t
     a      rotate: f t p
      !     apply:  p(f,t)

and
{ya!}    stack:  p q
 y       push:   p q f
  a      rotate: q f p
   !     apply:  p(q,f)

or
{b!}    stack:  p q
 b      copies: p q p q
  !     apply:  p q(q,p)

xor
{cx!sa!}    stack:  p q
 c          copy:   p q q
  x!        not:    p q nq
    s       swap:   p nq q
     a      rotate: nq q p
      !     apply:  p(nq,q)

implies
{sx!b!}    stack:  p q
 s         swap:   q p
  x!       not:    q np
    b      copies: q np q np
     !     apply:  q np(np,q)
Khuldraeseth na'Barya
fonte
0

Befunge-98 , 105 77 65 bytes

Brincando ainda mais com a noção de "função" em idiomas sem funções ... aqui está uma versão Befunge-98 dos booleanos da Igreja!

Nesse dialeto restrito do Befunge-98, um programa consiste em uma série de "linhas" ou "funções", cada uma das quais começa com uma >instrução (Vá para a direita) na coluna x = 0. Cada "função" pode ser identificada com seu número de linha (coordenada y). Funções podem receber entrada através da pilha do Befunge , como de costume.

A linha 0 é especial, porque (0,0) é o IP inicial. Para criar um programa que execute a linha L, basta colocar instruções na linha 0 que, quando executada, mova o ponteiro da instrução para (x = L, y = 0).

A mágica acontece na linha 1. A linha 1, quando executada, exibe um número Lda pilha e salta para o número da linha L. (Essa linha tinha sido anteriormente > >>0{{2u2}2}$-073*-\x, o que pode "saltar absoluto" para qualquer linha; mas acabei de perceber que, como sei que essa linha está atrelada à linha 1, podemos "saltar relativo"L-1 linhas com muito menos código.)

A linha 2 representa a Igreja FALSE . Quando executado, ele exibe dois números te fda pilha e depois voa para o número da linha f.

A linha 3 representa a Igreja TRUE . Quando executado, ele exibe dois números te fda pilha e depois voa para o número da linha t.

A linha 6, representando a Igreja XOR, é inovadora. Quando executado, ele exibe dois números ae bda pilha e depois voa para alinhar acom a entrada da pilha NOT EXEC b. Então, se arepresenta Igreja TRUE, o resultado de a NOT EXEC bserá NOT b; e se arepresenta igrejaFALSE , o resultado a NOT EXEC bserá EXEC b.


Aqui está a versão não destruída com equipamento de teste. Na linha 0, configure a pilha com sua entrada. Por exemplo, 338significa IMPLIES TRUE TRUE. Certifique-se de que o fechamentox apareça exatamente (x, y) = (0,15) ou então nada funcionará! Verifique também se a configuração da pilha começa com ba, para que o programa realmente termine com alguma saída.

Experimente online!

>  ba 334  0f-1x
> >>1-0a-\x             Line 1: EXEC(x)(...) = goto x
> $^< <            <    Line 2: FALSE(t)(f)(...) = EXEC(f)(...)
> \$^                   Line 3: TRUE(t)(f)(...) = EXEC(t)(...)
> 3\^                   Line 4: OR(x)(y)(...) = EXEC(x)(TRUE)(y)(...)
> 3\2\^                 Line 5: NOT(x)(...) = EXEC(x)(FALSE)(TRUE)(...)
> 1\5\^                 Line 6: XOR(x)(y)(...) = EXEC(x)(NOT)(EXEC)(...)
> 2>24{\1u\1u\03-u}^    Line 7: AND(x)(y)(...) = EXEC(x)(y)(FALSE)(...)
> 3^                    Line 8: IMPLIES(x)(y)(...) = EXEC(x)(y)(TRUE)(...)

> "EURT",,,,@
> "ESLAF",,,,,@

Aqui está a versão cujos bytes eu contei.

>>>1-0a-\x
>$^<< }u-30\<
>\$^
>3\^\
>3\2^
>1\5^
>2>24{\1u\1u^
>3^

Observe que, para definir uma função nesse dialeto, você não menciona seu nome; o seu "nome" é determinado pela sua localização de origem. Para chamar uma função, você menciona seu "nome"; por exemplo, XOR( 6) é definido em termos de NOTe EXEC( 5e 1). Mas todos os meus "nomes de funções" já levam apenas um byte para representar. Portanto, esta solução não recebe ajustes de pontuação.

Quuxplusone
fonte