教会ブール


33

教会のブール値

A 教会ブールは戻って、その関数でx真のためにとy偽のためには、どこxの関数の最初の引数で、y関数の第二引数です。さらに機能が表現これらの関数から構成することができるand not or xorimpliesの論理演算を。

チャレンジ

教会のブール値および構築and not or xorimpliesお好みの言語で教会の門を。and orそしてxor、2つの関数(Churchブール値を表す)を取り、関数(別のChurchブール値を表す)を返す必要があります。同様に、notそれがとる関数を反転し、impliesゲートがブール値を実行する必要があります。impliesが2番目の。

得点

教会を作成するために必要なすべてのコードの全長、trueおよびfalseあなたの言語and not or xorimplies教会の門は、機能の名前を除きます。(たとえば、false=lambda x,y:yPythonでは13バイトになります)。これらの名前は、コードの後半で再利用でき、そのゲートの合計バイト数に1バイトをカウントします。

擬似コードの例:

作成する関数は、コードの後半で呼び出すことができるはずです。

true(x, y) -> x
false(x, y) -> y
and(true, true)(x, y) -> x
and(true, false)(x, y) -> y
# ... etc

2
関数入力(または最も近い代替)をブラックボックス関数として扱う必要がありますか、それとも内部のコードを検査できますか?そして、論理演算の戻り値は、以前に教会ブール値として定義されたものと同じ関数である必要がありますか?
関連のない文字列

1
@JonathanAllan私はそれが正しいように編集しました。プロンプトは現在の状態のままです。
ライアンシェーファー

2
我々は、引数としてリストを取ることができます(例えばtrue([x, y])and([true, true])([x, y]))?
ar4093

2
@RyanSchaefer解決策の最初に引数を単純にラップできるため、引数を順序付きリストに含めることを再検討する必要があると思います。それを要求することは、この挑戦​​を改善するために何もしないとは思いません(実際、興味深いゴルフの可能性を制限すると思います)。もちろん、これは私の意見であり、同意しない場合は問題ありません。
FryAmTheEggman

1
得点はかなりわかりにくい。匿名の関数を送信できるようにした方が良いのではありませんが、他の部分でそれらを使用する場合は、通常のように割り当てる必要があります
Jo King

回答:


14

バイナリラムダ計算13.875 12.875バイト(103ビット)

John Trompのバイナリラムダ計算言語(BLC)は、基本的にはラムダ計算の効率的なシリアル化形式です。教会表記法は、BLCでブール値を操作する「イディオマティック」な方法であるため、このタスクに最適です。

コンビネータには次のラムダ関数を使用しましたが、その一部はHaskellの回答からコピーしてゴルフしたものです。これらが可能な限り短い可能性があります。

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))

これらは、次の(バイナリ)BLCコードシーケンスに変換されます。

 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

上記の関数は、合計で111ビット長(13.875バイト) 103ビット長(12.875バイト)です。プログラム内で使用するためにバイト境界に揃える必要はありません。そのため、小数バイトをカウントすることは理にかなっています。

BLCには変数/参照/名前がないため、コンビネーター間でコードを再利用することはできません。すべてをコピーする必要がありました。それでも、エンコードの効率は非常に簡潔な表現になります。


1
blcはわかりませんが、And: (\a \b a b a)動作しますか?
tsh

はい、動作します。実際にコードシーケンスにこの式を使用しました。対応するラムダ関数を更新するのを忘れました(現在修正済み)。同等の機能はOr:で機能します\a \b a a b。ただし、BLCで使用したものよりも長いです。
パベルポトチェク

25

ハスケル、50から6 = 44のバイト

Khuldraeseth na'Baryaに-1バイト、Christian Sieversに-1バイト。

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

オンラインでお試しください!


2
サイドノート:あなたが定義することができるShowのインスタンスをconstし、const id直接教会のブール値を印刷します。オンラインでお試しください!
nimi


4
なぜ誰も使用していf=n tないのですか?
クリスチャンシーバーズ

3
t=pure代わりにを使用してバイトを保存できますt=const
ジョセフ・シブル・レステート・モニカ

4
@JosephSible私は最初にそれを試しました。残念ながら、t=pure私は適用しようとするとエラーが発生しますaox、またはiそれに。tこれを修正するためにのタイプを宣言すると、単にを使用するよりも多くのバイトがかかりますt=const
ニトロドン

9

Python 2、(-3?) 101  95バイト

デビッド・ビーズリーはあなたの心を外に食べます!

-6 Chas Brownに感謝(繰り返し:を結合テキストに移動>。<)

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())

オンラインでお試しください!

私はそれがかもしれないと思う95 - 3私は、機能を再利用していないためAXまたはI、私は単一を使う=(の前に割り当てるためlambda)。たぶん削除できません。3.5を削除することもできますか?


@Ryan Schaeferは3つ削除execできますか?私はどちらの方向にも進むことができます-A、X、または私は再利用しませんが、コードはそれらなしでは機能しません。(3.5を削除することもできますか?!)
ジョナサンアラン


ありがとう@Chas!ネットをすり抜けたコロン:) -1 BTWの交換で良い仕事
ジョナサンアラン

7

JavaScript(Node.js)92 86 83-7 = 76バイト

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)

オンラインでお試しください!リンクには基本的なテストケースが含まれています。編集:@tshのおかげで6 9バイトを保存しました。


1
あなたがよう-7以来、これを主張することはできませんようでtfn使用されています。
9

1
@tshそれは私が採点システムを理解する方法ではありません。使用中の名前のコストは1バイトですが、定義内の名前は明示的に除外されます。
ニール

@Neil tではf、コード(、、およびn)によって呼び出される関数名のバイトディスカウントを請求できません。
アスガルント

2
@asgallant no。名前用のバイトはなく、後で使用する場合は1バイトです。「T fnaox i」はバイトではなく、後で使用する場合は1バイトです。読みやすさを改善したかったのですが、今では完全にゴルフのままにしておくべきであり、今では変更するには遅すぎることに気付きました
ライアンシェーファー

@RyanSchaeferそのルールはどこですか?私はそれがそのように行われるのを見たことがない。
アスガルント

6

パイソン2133 - = 127 6 94のバイト

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:')

オンラインでお試しください!

ジョナサンアランの答えの背後にある卑劣なアイデアを恥知らずに盗む。ただし、バイトは差し引かれません。


私は自分の質問への回答を投稿するつもりでしたが、これが許可されているかどうかはわかりませんでした。だから私は代わりにあなたを案内するだけだと思う​​。リストを使用する代わりに、入力されている関数と、コードを短縮するために入力を返す特定の方法を使用できるのでしょうか?
ライアンシェーファー

答えはイエスですが、Pythonではかなり長くなると思います。
関連のない文字列

私は訂正します
無関係な文字列

@ Mr.Xcoderあなたは正しいです、例の関数のバイト数が間違っていました。関数の名前については、6バイトを削除できます。
ライアンシェーファー

@氏。Xcoder:観測に従って変更されました。
チャスブラウン

4

J、67バイト-7 = 60

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

オンラインでお試しください!

注目に値する:

高階関数は、関数型言語とJでは動作が異なります。1つまたは2つの既存の動詞から新しい動詞を作成するには、副詞(1の場合)または接続詞(2の場合)を使用する必要があります。

Syntactically, adverbs come after a verb, and conjunctions go between them. Thus to "not" a verb f you do f n, and to "and" verbs f and g, you f a g.


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&

Try it online!

un-golfed: inspired by 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]

Pretty sure the newlines are necessary to separate function definitions. Also you reference t f and n in other function definitions so you cannot deduct those ones, so 61-4=57.
Jonathan Allan

@JonathanAllan I've re-read the scoring instructions and agree that the newlines should count, thanks. I disagree with your second part: when I reuse the names, I do indeed count them as "1 byte toward the byte total of that gate", which is implicit here as I use 1-byte names. As my reading of the instructions goes, there is no mention of further counting them as one byte toward the total of the original definition as well. So I'm going with N-7 bytes. Also, another comment by the OP clarifies: "It’s no bytes for the name and 1 byte when it is used later."
Roman

I read "1 byte later" to mean usage within another function costs a byte. This aligns with how others have scored too.
Jonathan Allan

@JonathanAllan I'm less interested in exegesis and more in code golfing 😀
Roman

4

Underload, 56 52 bytes

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

Try it online! (includes a testsuite and text identifying parts of the program)

This scores surprisingly well for a very low-level esolang. (Church numerals, Church booleans, etc. are very commonly used in Underload for this reason; the language doesn't have numbers and booleans built in, and this is one of the easier ways to simulate them. That said, it's also common to encode booleans as the Church numerals 0 and 1.)

混乱している場合:Underloadを使用すると、再利用可能な関数を定義できますが、通常の方法でそれらに名前を付けることはできません。それらは、引数スタック上で並べ替えられます(したがって、5つの関数を定義してから定義した場合、5つの引数を取り、5番目の引数を呼び出す新しい関数を作成し、使用する予備の引数を探すために引数が不十分な状態で呼び出す必要があります)。それらを呼び出すとデフォルトでそれらを破壊しますが、呼び出しを変更して非破壊にすることができます(単純な場合は、呼び出しにコロンを追加する必要がありますが、コピーを確認する必要があるため、複雑な場合がより一般的ですスタック上では邪魔になりません)、Underloadの関数サポートには、質問から必要なすべての要件があります。

説明

本当

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

これはかなり簡単です。不要な引数を取り除き、必要な引数をそのまま保持し、戻り値として使用します。

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

これはさらに簡単です。

じゃない

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

これは楽しいです。not引数をまったく呼び出さず、関数構成を使用するだけです。これは、Underloadの一般的なトリックです。Underloadでは、データをまったく検査せずに、事前に事後構成することで機能を変更するだけです。この場合、実行する前に引数を交換するように関数を変更します。これは明らかに教会の数字を無効にします。

そして

:((!)~^)*
 (     )   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

この質問は、他の関数に関して関数を定義することを許可します。「and」を定義するのは、最近「not」を定義するほど使用しやすくなるためです。(これは「not」という名前を付けていないため、スコアから差し引かれませんが、定義を書き直すことでバイトを節約できます。これは、ある関数がただし、最後に定義されたバイト数は多すぎます。)

ここでの定義はand x y = (not x) false yです。つまり、ifの場合not x、戻りfalseます。それ以外の場合は、を返しyます。

または

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

@Nitrodon or x y = x x yは、通常はより短いコメントで指摘しましたor x y = x true yが、Underloadでも正しいことがわかりました。その素朴な実装はになります(:~^)が、元の最初の引数を実行するか、そのコピーを実行するかは問題ではなく、結果はどちらの場合も同じであることに注意することで、追加のバイトを捨てることができます。

アンダーロードは、通常の意味でのカリー化を実際にはサポートしていませんが、このような定義により、カリー化はサポートされているように見えます!(トリックは、消費されていない引数がそのまま残るため、呼び出す関数はそれらを独自の引数として解釈します。)

含意する

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

ここで使用される定義はimplies x y = not (y false x)です。yがこの簡素化、trueの場合not false、すなわちtrue。yがfalseの場合、これはに整理されnot x、必要な真理値表が得られます。

この場合、not今回はコードを参照するのではなく書き換えて、再び使用しています。(~)~*かっこなしで直接記述されているため、定義されるのではなく呼び出されます。

xor

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

今回は、2つの引数のうち1つだけを評価し、それを使用して2番目の引数に何を構成するかを決定します。アンダーロードを使用すると、アリティで高速かつ緩やかに再生できるため、最初の引数を使用して2つの2つの引数を持つ2つの戻り関数を選択します。両方を返すが反対の順序で返す引数スワップ、および両方を同じ順序で返す恒等関数。

したがって、最初の引数がtrueの場合、実行前に引数を交換する2番目の引数の編集バージョンを作成しますnot。つまり、「引数をスワップ」で事前構成します。したがって、真の最初の引数はnot、2番目の引数を返すことを意味します。一方、偽の最初の引数は、恒等関数で構成する、つまり何もしないことを意味します。結果はの実装ですxor


or x y = x x yいくつかのバイトを節約しますor x y = x true y
ニトロドン

アンダーロードは、リテラルを再利用された変数で置き換えることになると直観に反することがよくありますが、この場合、その変換は少ないよりもむしろ予想よりも多くのバイトを節約することになります。改善してくれてありがとう!
ais523


3

ジャワ8、スコア:360 358 319 271 233(240から7)バイト

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);

これは、開始時に思ったよりも達成するのが難しいものでしたimplies。とにかく、それは動作します。多分あちこちでゴルフをすることができます。編集:OK、関数を再利用せず、同じアプローチを複製するだけで、Javaのバイトカウントの点ではるかに安価になります。また、関数をまったく使用しないことで、完全な-7ボーナスが得られます。

オンラインでお試しください。

説明:

// 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);

2

C ++ 17、207-49 = 158 195-58 = 137バイト

改行は不要です(最初の2つ以外)。

#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_))

オンラインでお試しください!

次のようなアサーションでユニットテスト済み:

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'));

更新済み:以前は持っていた

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

but Roman's answer pointed the way to the shorter version. Notice that now not_(std::plus<>) is ill-formed, where formerly it was equivalent to std::plus<>; but since std::plus<> doesn't "represent a Church boolean," I think either behavior is okay by the rules.


Shouldn't "other than the first one" be updated to "other than the first two"?
L. F.

@L.F.: Absolutely correct. Updated. :)
Quuxplusone

2

Forth(gforth)133バイト-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 ;

オンラインでお試しください!

Quuxplusoneのおかげで-4バイト

最初はマクロやリテラルなどを考慮してこれを大幅に見直しましたが、真と偽(最初に行うべきだったように)の観点から物事を定義すると、はるかに簡単になることに気付きました。

コードの説明

\ 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

1
長い単語をexecute3回繰り返します。速記: j execute ;を定義すると、4バイト節約できます。
Quuxplusone

1

SKI計算+ Cコンビネータ、36バイト

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

私はこの使用してテストしていたので、私は実際には、あなたが以前のものの観点で追加コンビネータを定義することができます任意の通訳を知らないhttp://ski.aditsu.net/を希望コンビネータなどに貼り付けてCCKK(SK)pq出力qすることを示し、K含意しませんSK


1

ジュリア1.0、36バイト

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

それがBool重要かどうかはわかりませんが、実際にはネイティブ型を呼び出し可能にオーバーロードしているだけなので、ほとんどの論理ゲートを無料で入手できます。残念ながら、ジュリアにはimpliesゲートがありません。そのため、独自の関数を作成する必要がありました。

オンラインでお試しください!


オーバーロードされた演算子を提出に含める必要があると思いますが、スコアは名前にすぎないため、それらはカウントされませんか?だから、改行から+6バイトでしょうか?私はないんだけど、あまりにも確認得点はこの課題にどのように動作するか
ジョー・キング

I'm not 100% sure how it works either, but having to include code that literally does nothing doesn't make any sense to me.
user3263164

Even if the code is already declared, then you still have to include it, otherwise every other golfing language submission would be zero bytes. You just don't have to assign it to anything
Jo King

1

Perl 6, 120 106 102 101 bytes

-1 byte thanks to 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}

Try it online!


1

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

Inspired by the comment-discussion of what counts as a 2-ary function anyway, here's a curried version of my previous C++17 solution. It's actually shorter because we can use the same macro to define not_ as to define all the other functions!

#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_))

Try it online!

This one is tested with assertions like

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

Notice that or_ is defined as effectively

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

We could define or_ more "concisely" as

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

but that would cost us because we wouldn't get to use the D macro anymore.


Since C++ is case-sensitive, how about using True and False instead of true_ and false_? And similar for the other operators. That will save 12 bytes.
G. Sliepen

@G.Sliepen: OP's scoring algorithm already takes into account that identifiers are effectively one character long. Quote: "The total length of all of the code required to make Church true and false in your language and the and not or xor and implies Church gates excluding the function's name. (for example, false=lambda x,y:y in Python would be 13 bytes). You can reuse these names later in your code with them counting 1 byte toward the byte total of that gate."
Quuxplusone

Ah, I missed that.
G. Sliepen

0

APL (dzaima/APL), 47 bytesSBCS

Based on Jonah's J solution.

true and false are infix functions, not is a suffix operator, and the rest are infix operators.

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

As per OP, this counts everything from and including to the end of each line, and counts each call a previous definition as a single byte.

Try it online!

true and false are the left and right identity functions.

not simply swaps the arguments of its operand function.

The rest implement the decision tree:

and uses the righthand function to select the result of the lefthand function if true, else the result of the false function.

or uses the lefthand function to select the true if true, else the result of the righthand function .

xor uses the righthand function to select the the negated result of the lefthand function ⍶not if true, else the result of the lefthand function.

implies uses the lefthand function to select the result of the righthand function if true, else the result of the true function.


0

Stax, 34 bytes

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

Run and debug it at staxlang.xyz!

Pushes a bunch of blocks to the stack. Each block expects its last argument atop the stack, followed in reverse order by the rest.

Unpacked (41 bytes):

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

Each pair of { } is a block. I used the two registers X and Y to hold true and not so I could access 'em easily later. Unfortunately, false couldn't simply be a no-op, as that would leave the stack cluttered and mess up a single XOR case.

Test suite, commented

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)

0

Befunge-98, 105 77 65 bytes

Playing further with the notion of "function" in languages without functions... here's a Befunge-98 version of Church booleans!

In this constrained dialect of Befunge-98, a program consists of a series of "lines" or "functions," each of which begins with a >(Go Right) instruction in column x=0. Each "function" can be identified with its line number (y-coordinate). Functions can take input via Befunge's stack, as usual.

Line 0 is special, because (0,0) is the starting IP. To make a program that executes line L, just place instructions on line 0 that, when executed, fly the instruction pointer to (x=L, y=0).

The magic happens on line 1. Line 1, when executed, pops a number L from the stack and jumps to line number L. (This line had previously been > >>0{{2u2}2}$-073*-\x, which can "absolute jump" to any line; but I just realized that since I know this line is pegged to line 1, we can "relative jump" L-1 lines in a heck of a lot less code.)

Line 2 represents Church FALSE. When executed, it pops two numbers t and f from the stack and then flies to line number f.

Line 3 represents Church TRUE. When executed, it pops two numbers t and f from the stack and then flies to line number t.

Churchを表す6行目XORは革新的です。実行されるab、スタックから2つの数字をポップaし、スタック入力で行に飛びますNOT EXEC b。したがって、a教会を表す場合TRUE、結果は次のa NOT EXEC bようになりNOT bます。そしてa教会を代表するならFALSE、結果はa NOT EXEC bなるでしょうEXEC b


これは、テストハーネスを備えたバージョンではありません。行0で、入力を使用してスタックをセットアップします。たとえば、338はを意味しIMPLIES TRUE TRUEます。終了xが正確に(x、y)=(0,15)に表示されていることを確認してください。そうでない場合は何も機能しません。またba、プログラムが実際に何らかの出力で終了するように、スタックのセットアップがで始まることを確認してください。

オンラインでお試しください!

>  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",,,,,@

バイトをカウントしたバージョンは次のとおりです。

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

Notice that to define a function in this dialect you don't mention its name at all; its "name" is determined by its source location. To call a function, you do mention its "name"; for example, XOR (6) is defined in terms of NOT and EXEC (5 and 1). But all my "function names" already take only one byte to represent. So this solution gets no scoring adjustments.

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.