โบสถ์ Booleans


33

โบสถ์บูลีน

โบสถ์บูลเป็นฟังก์ชันที่ผลตอบแทนxสำหรับความจริงและyเท็จที่xเป็นอาร์กิวเมนต์แรกฟังก์ชั่นและyเป็นอาร์กิวเมนต์ที่สองให้กับฟังก์ชั่น ฟังก์ชั่นเพิ่มเติมสามารถประกอบได้จากฟังก์ชั่นเหล่านี้ซึ่งเป็นตัวแทนของการดำเนินงานand not or xorและimpliesตรรกะ

ท้าทาย

สร้าง booleans ริสตจักรและand not or xorและimpliesประตูโบสถ์ในภาษาที่คุณเลือก and orและxorควรใช้สองฟังก์ชั่น (แทนบูลีนของโบสถ์) และส่งคืนฟังก์ชัน (แทนบูลีนของโบสถ์อื่น) ในทำนองเดียวกันnotควรกลับฟังก์ชั่นที่ใช้และimpliesประตูควรดำเนินการบูลีนหมายถึงตรรกะที่อาร์กิวเมนต์แรกimpliesที่สอง

เกณฑ์การให้คะแนน

ความยาวรวมของรหัสทั้งหมดที่จำเป็นในการสร้างคริสตจักรtrueและfalseในภาษาของคุณand not or xorและimpliesประตูคริสตจักรและไม่รวมชื่อฟังก์ชั่น (ตัวอย่างเช่นfalse=lambda x,y:yใน Python จะเป็น 13 ไบต์) คุณสามารถใช้ชื่อเหล่านี้ในภายหลังในรหัสของคุณโดยนับ 1 ไบต์ไปยังผลรวมไบต์ของเกตนั้น

ตัวอย่างโค้ดหลอก:

ฟังก์ชั่นที่คุณสร้างควรจะสามารถเรียกได้ในภายหลังในรหัสของคุณเช่นนั้น

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

2
เราต้องปฏิบัติต่อฟังก์ชั่นอินพุต (หรือตัวสำรองที่ใกล้เคียงที่สุด) เป็นฟังก์ชั่นกล่องดำหรือเราสามารถตรวจสอบโค้ดภายในได้หรือไม่? และค่าตอบแทนของการดำเนินการทางตรรกะต้องเป็นฟังก์ชันเดียวกันกับที่นิยามไว้ก่อนหน้านี้เป็น booleans ของศาสนจักรหรือพวกเขาสามารถเป็นอย่างอื่นซึ่งทำสิ่งเดียวกันได้หรือไม่?
สตริงที่ไม่เกี่ยวข้อง

1
@JanathanAllan ฉันแก้ไขให้ถูกต้อง พรอมต์เป็นตามที่ควรจะเป็นในขณะนี้
Ryan Schaefer

2
เราสามารถใช้รายการเป็นข้อโต้แย้ง (เช่นtrue([x, y]), and([true, true])([x, y]))?
ar4093

2
@RyanSchaefer ฉันคิดว่าคุณควรพิจารณาอนุญาตให้ข้อโต้แย้งอยู่ในรายการที่สั่งซื้อเนื่องจากคุณสามารถตัดอาร์กิวเมนต์ที่จุดเริ่มต้นของการแก้ปัญหา ฉันไม่คิดว่าจะต้องทำอะไรเพื่อพัฒนาความท้าทายนี้ (อันที่จริงฉันคิดว่ามัน จำกัด ศักยภาพการเล่นกอล์ฟที่น่าสนใจ) แน่นอนนี่เป็นเพียงความเห็นของฉันและมันก็โอเคถ้าคุณไม่เห็นด้วย
FryAmTheEggman

1
การให้คะแนนค่อนข้างสับสน คงจะดีกว่าไหมถ้าให้คนส่งฟังก์ชั่นนิรนาม แต่ถ้าพวกเขาใช้มันในส่วนอื่น ๆ พวกเขาต้องมอบหมายมันเหมือนปกติ
Jo King

คำตอบ:


14

แคลคูลัสแลมบ์ดาไบนารี , 13.875 12.875 ไบต์ (103 บิต)

แลมบ์ดาแคลคูลัสภาษา (BLC) โดย John Tromp นั้นเป็นรูปแบบการจัดลำดับที่มีประสิทธิภาพสำหรับแลมบ์ดาแคลคูลัส มันเหมาะอย่างยิ่งสำหรับงานนี้เนื่องจากสัญกรณ์ของโบสถ์เป็นแม้แต่วิธี "สำนวน" ในการทำงานกับ booleans ใน BLC

ฉันใช้ฟังก์ชั่นแลมบ์ดาต่อไปนี้สำหรับ combinators ซึ่งฉันคัดลอกและเล่นกอล์ฟจากคำตอบของ Haskell:ซึ่งพบได้จากการค้นหาแบบละเอียดซึ่งมีขีด จำกัด การพิสูจน์ที่ 20 β-reduction สำหรับแต่ละกรณี มีโอกาสที่ดีสิ่งเหล่านี้สั้นที่สุด

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 ไบต์) พวกเขาไม่จำเป็นต้องจัดตำแหน่งให้สอดคล้องกับขอบเขตไบต์ที่จะใช้ภายในโปรแกรมดังนั้นจึงเหมาะสมที่จะนับจำนวนไบต์

ไม่มีการใช้รหัสซ้ำระหว่าง Combinators เนื่องจากไม่มีตัวแปร / การอ้างอิง / ชื่อใน BLC - ทุกอย่างต้องถูกคัดลอก แต่ถึงกระนั้นประสิทธิภาพของการเข้ารหัสก็ยังคงเป็นตัวแทนที่ค่อนข้างสั้น


1
ฉันไม่รู้ blc แต่จะAnd: (\a \b a b a)ใช้ได้ไหม
tsh

ใช่มันใช้งานได้ จริง ๆ แล้วฉันใช้สูตรนี้สำหรับลำดับรหัสของฉัน ฉันแค่ลืมปรับปรุงฟังก์ชั่นแลมบ์ดาที่สอดคล้องกัน (ตอนนี้แก้ไข) \a \b a a bฟังก์ชั่นการทำงานสำหรับเทียบเท่าหรือ: มันมีความยาวมากกว่าที่ฉันใช้ใน BLC
Pavel Potoček

25

Haskell , 50 - 6 = 44 ไบต์

ขอบคุณ -1 ไบต์กับ Khuldraeseth na'Barya และ -1 ไบต์ขอบคุณ Christian Sievers

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

ลองออนไลน์!


2
หมายเหตุด้านข้าง: คุณสามารถกำหนดShowอินสแตนซ์สำหรับconstและconst idและพิมพ์ booleans ของโบสถ์โดยตรง ลองออนไลน์! .
nimi


4
ทำไมไม่มีใครใช้f=n t?
Christian Sievers

3
คุณสามารถบันทึกไบต์โดยใช้แทนt=pure t=const
Joseph Sible

4
@JosephSible ฉันลองใช้ครั้งแรก แต่น่าเสียดายที่t=pureจะทำให้เกิดข้อผิดพลาดเมื่อฉันพยายามที่จะใช้a, o, xหรือiไป ประกาศประเภทของการแก้ไขปัญหาค่าใช้จ่ายนี้ไบต์มากกว่าเพียงแค่ใช้t t=const
Nitrodon

9

Python 2 , (-3?)  101  95 ไบต์

David Beazleyกินหัวใจของคุณออกไป!

-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เพราะผมไม่ได้นำมาใช้ฟังก์ชั่นA, XหรือIแต่ฉันจะใช้เพียงครั้งเดียว=สำหรับการกำหนด (ในด้านหน้าของlambda) บางทีฉันไม่สามารถลบได้ บางทีฉันอาจลบ 3.5?


@Ryan Schaefer ฉันสามารถลบสามหรือใช้งานของexecฉันหมายความว่าฉันไม่สามารถ? ฉันสามารถเห็นวิธีใดวิธีหนึ่ง - ฉันไม่ใช้ A, X หรือฉันซ้ำ แต่รหัสจะไม่ทำงานหากไม่มีพวกเขา (บางทีฉันอาจลบ 3.5 ได้ด้วย!)
Jonathan Allan


ขอบคุณ @Chas! เครื่องหมายจุดคู่ที่ลื่นผ่านเน็ต :) ทำได้ดีในการแทนที่ -1 BTW
Jonathan Allan

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)

ลองออนไลน์! ลิงก์มีกรณีทดสอบพื้นฐาน แก้ไข: บันทึกแล้ว6 9 ไบต์ขอบคุณ @tsh


1
ดูเหมือนว่าคุณจะไม่สามารถเรียกร้องนี้เป็น -7 ตั้งแต่t, f, nมีการใช้
TSH

1
@tsh นั่นไม่ใช่วิธีที่ฉันเข้าใจระบบการให้คะแนน มันแยกชื่อในนิยามอย่างชัดเจนแม้ว่าชื่อในการใช้จะมีราคา 1 ไบต์
Neil

@Neil คุณจะไม่สามารถเรียกร้องส่วนลดไบต์สำหรับชื่อฟังก์ชั่นที่เรียกได้ว่าเป็นรหัสของคุณ ( t, fและnในกรณีของคุณ)
asgallant

2
@ เลขที่ ไม่มีไบต์สำหรับชื่อและ 1 ไบต์เมื่อใช้ในภายหลัง 'T fnaox i' ไม่ใช่ไบต์แล้ว 1 ไบต์เมื่อใช้ในภายหลัง ฉันต้องการที่จะปรับปรุงการอ่าน แต่ตอนนี้ฉันรู้ว่าฉันควรจะทิ้งมันไว้อย่างเต็มที่กอล์ฟและมันก็สายเกินไปที่จะเปลี่ยนมันตอนนี้
Ryan Schaefer

@RyanSchaefer กฎนั้นอยู่ที่ไหน ฉันไม่เคยเห็นมันทำแบบนั้น
asgallant

6

Python 2 , 133 - 6 = 127 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:')

ลองออนไลน์!

ขโมยความคิดลับ ๆ ล่อๆเบื้องหลังคำตอบของ Jonathan Allan ; ไม่มีการหักไบต์


ฉันจะโพสต์คำตอบสำหรับคำถามของฉันเอง แต่ฉันไม่แน่ใจว่าสิ่งนี้ได้รับอนุญาตหรือไม่และฉันคิดว่านี่เป็นสิ่งที่ขัดต่อจิตวิญญาณของมัน ดังนั้นฉันคิดว่าฉันจะแนะนำคุณแทน แทนที่จะใช้รายการคุณสามารถใช้ฟังก์ชั่นที่ป้อนข้อมูลด้วยตนเองได้หรือไม่และใช้วิธีการเฉพาะที่ส่งคืนอินพุตเพื่อย่อโค้ดหรือไม่
Ryan Schaefer

ฉันพนันได้เลยว่าแม้ว่าคำตอบคือใช่ แต่มันจะนานกว่านี้ใน Python
สตริงที่ไม่เกี่ยวข้อง


@ Mr.Xcoder คุณถูกต้องฉันมีจำนวนไบต์ที่ไม่ถูกต้องสำหรับฟังก์ชั่นตัวอย่าง พวกเขาจะได้รับอนุญาตให้ลบ 6 ไบต์ แต่สำหรับชื่อของฟังก์ชั่น
Ryan Schaefer

@นาย. Xcoder: แก้ไขตามข้อสังเกตของคุณ
Chas Brown

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)

วากยสัมพันธ์คำวิเศษณ์มาหลังจากคำกริยาและคำสันธานไประหว่างพวกเขา ดังนั้นจะ "ไม่ได้" คำกริยาfที่คุณทำf nและ "และ" คำกริยาfและคุณgf a g


4

ภาษา Wolfram (Mathematica) , 61-7 = 54 ไบต์

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

ลองออนไลน์!

un-golfed: แรงบันดาลใจจาก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]

ค่อนข้างมั่นใจว่าจำเป็นต้องมีการขึ้นบรรทัดใหม่เพื่อแยกนิยามฟังก์ชัน นอกจากนี้คุณอ้างอิง tf และ n ในนิยามฟังก์ชันอื่น ๆ ดังนั้นคุณจึงไม่สามารถหักค่าเหล่านั้นได้ดังนั้น 61-4 = 57
Jonathan Allan

@JanathanAllan ฉันได้อ่านคำแนะนำการให้คะแนนอีกครั้งและยอมรับว่าขึ้นบรรทัดใหม่ควรนับขอบคุณ ฉันไม่เห็นด้วยกับส่วนที่สองของคุณ: เมื่อฉันใช้ชื่อซ้ำฉันจะนับเป็น "1 ไบต์ต่อจำนวนไบต์ทั้งหมดของประตูนั้น" ซึ่งเป็นนัยที่นี่เมื่อฉันใช้ชื่อ 1 ไบต์ เมื่ออ่านคำแนะนำของฉันไปแล้วไม่มีการเอ่ยถึงการนับพวกมันเป็นหนึ่งไบต์ต่อจำนวนคำจำกัดความดั้งเดิมทั้งหมดเช่นกัน ดังนั้นฉันจะไปกับ N-7 ไบต์ นอกจากนี้ความคิดเห็นอื่นโดย OP ยังชี้แจงว่า: "มันไม่มีไบต์สำหรับชื่อและ 1 ไบต์เมื่อมีการใช้ในภายหลัง"
โรมัน

ฉันอ่าน "1 ไบต์ต่อมา" เพื่อหมายถึงการใช้งานภายในฟังก์ชั่นอื่นมีค่าใช้จ่ายต่อไบต์ สิ่งนี้สอดคล้องกับวิธีการที่คนอื่นได้ทำคะแนนด้วย
Jonathan Allan

@JanathanAllan ฉันสนใจน้อยลงในการอธิบายและอื่น ๆ ในการตีกอล์ฟรหัส
โรมัน

4

อันเดอร์ , 56 52 ไบต์

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

ลองออนไลน์! (รวมถึง Testuite และข้อความระบุส่วนของโปรแกรม)

คะแนนนี้น่าแปลกใจที่ดีสำหรับ esolang ระดับต่ำมาก (ตัวเลขโบสถ์, คริสตจักร booleans ฯลฯ มักใช้ใน Underload ด้วยเหตุผลนี้ภาษาไม่มีตัวเลขและ booleans ในตัวและนี่เป็นวิธีหนึ่งที่ง่ายกว่าในการจำลองพวกเขา เข้ารหัส booleans เป็นเลขคริสตจักรที่ 0 และ 1)

สำหรับผู้ที่สับสน: Underload ช่วยให้คุณกำหนดฟังก์ชั่นที่นำกลับมาใช้ใหม่ได้ แต่ไม่อนุญาตให้คุณตั้งชื่อพวกมันในวิธีปกติพวกเขาเพียงแค่ลอยไปรอบ ๆ บนอาร์กิวเมนต์สแต็ก (ดังนั้นถ้าคุณกำหนดฟังก์ชันที่ห้า คุณกำหนดไว้คุณต้องเขียนฟังก์ชั่นใหม่ที่มีอาร์กิวเมนต์ห้าตัวและเรียกใช้ฟังก์ชันที่ห้าจากนั้นเรียกมันว่ามีอาร์กิวเมนต์ที่ไม่เพียงพอจำนวนมากเพื่อที่จะหาอาร์กิวเมนต์ว่างที่จะใช้) การโทรหาพวกเขาจะทำลายพวกเขาตามค่าเริ่มต้น แต่คุณสามารถแก้ไขการโทรเพื่อทำให้มันไม่ทำลาย (ในกรณีง่าย ๆ คุณเพียงแค่เพิ่มโคลอนในการโทรถึงแม้ว่ากรณีที่ซับซ้อนนั้นเป็นเรื่องธรรมดามากกว่าเพราะคุณต้องแน่ใจว่าสำเนา บนสแต็คไม่ได้รับในทางของคุณ) ดังนั้นการสนับสนุนฟังก์ชั่นของ 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 ซึ่งคุณไม่ได้ตรวจสอบข้อมูลของคุณเลยคุณเพียงแค่เปลี่ยนวิธีการทำงานของมันโดยการเตรียมสิ่งต่างๆก่อนและหลังการเขียนด้วย ในกรณีนี้เราปรับเปลี่ยนฟังก์ชั่นเพื่อแลกเปลี่ยนการขัดแย้งก่อนที่จะทำงาน

และ

:((!)~^)*
 (     )   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 x y = (not x) false yความหมายที่นี่คือ กล่าวอีกนัยหนึ่งถ้า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 ถ้าเป็นจริงช่วยลดความยุ่งยากนี้คือnot false trueหาก y เป็นเท็จสิ่งนี้จะลดความซับซ้อนลงnot xดังนั้นให้ตารางความจริงที่เราต้องการ

ในกรณีนี้เรากำลังใช้notอีกครั้งคราวนี้โดยเขียนรหัสใหม่แทนที่จะอ้างอิง มันเขียนโดยตรง(~)~*โดยไม่ต้องใส่วงเล็บล้อมรอบมันจึงถูกเรียกมากกว่าที่นิยามไว้

xor

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

เวลานี้เรากำลังประเมินเพียงหนึ่งในสองข้อโต้แย้งของเราและใช้เพื่อพิจารณาว่าจะเรียบเรียงอะไรกับอาร์กิวเมนต์ที่สอง อันเดอร์โหลดช่วยให้คุณเล่นอย่างรวดเร็วและหลวมด้วย arity ดังนั้นเราจึงใช้อาร์กิวเมนต์แรกเพื่อเลือกระหว่างสองฟังก์ชันสองอาร์กิวเมนต์สองอาร์กิวเมนต์ การแลกเปลี่ยนอาร์กิวเมนต์ที่ส่งกลับทั้งสอง แต่ในลำดับที่ตรงกันข้ามและฟังก์ชั่นตัวตนที่ส่งกลับพวกเขาทั้งสองในลำดับเดียวกัน

เมื่ออาร์กิวเมนต์แรกเป็นความจริงดังนั้นเราจึงผลิตฉบับแก้ไขของอาร์กิวเมนต์ที่สองที่แลกเปลี่ยนอาร์กิวเมนต์ก่อนที่จะใช้คือ precompose ด้วย "ข้อโต้แย้งแลกเปลี่ยน" notคือ อาร์กิวเมนต์แรกจริงหมายถึงเราคืนnotค่าอาร์กิวเมนต์ที่สอง ในทางตรงกันข้ามอาร์กิวเมนต์แรกที่ผิดพลาดหมายถึงเราเขียนด้วยฟังก์ชั่นตัวตนคือไม่ทำอะไรเลย xorผลที่ได้คือการดำเนินการของ


or x y = x x yor x y = x true yช่วยประหยัดบางไบต์มากกว่า
Nitrodon

Underload มักตอบโต้ง่าย ๆ เมื่อมันมาถึงการแทนที่ตัวอักษรด้วยตัวแปรที่นำมาใช้ใหม่ แต่ในกรณีนี้การแปลงนั้นจะช่วยประหยัดไบต์ได้มากกว่าที่คาดไว้แทนที่จะน้อยกว่า ขอบคุณสำหรับการปรับปรุง!
ais523


3

Java 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. อย่างไรก็ตามมันใช้งานได้ .. อาจจะเล่นกอล์ฟสักหน่อยที่นี่และที่นั่น แก้ไข: ตกลงไม่ใช่ฟังก์ชั่นที่ใช้ซ้ำ แต่เพียงแค่การทำซ้ำวิธีเดียวกันนั้นมีราคาถูกกว่ามากในแง่ของจำนวนไบต์สำหรับ 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 ไบต์

linebreaks ไม่จำเป็น (นอกเหนือจากสองครั้งแรก)

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

แต่คำตอบของโรมันชี้ไปที่เวอร์ชันที่สั้นกว่า แจ้งให้ทราบว่าขณะนี้not_(std::plus<>)อยู่ในรูปแบบที่ไม่ดีที่เดิมมันก็เท่ากับstd::plus<>; แต่เนื่องจากstd::plus<>ไม่ "เป็นตัวแทนของบูลีนของโบสถ์" ฉันคิดว่าพฤติกรรมอย่างใดอย่างหนึ่งก็ไม่เป็นไรตามกฎ


ไม่ควรอัปเดต "นอกเหนือจากอันแรก" เป็น "อื่นที่ไม่ใช่อันแรก"?
LF

@LF: ถูกต้องอย่างแน่นอน 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 ;

ลองออนไลน์!

-4 ไบต์ขอบคุณ Quuxplusone

ตอนแรกฉันคิดอย่างนี้อย่างมากเมื่อพิจารณาถึงสิ่งต่าง ๆ เช่นมาโครและตัวอักษร แต่แล้วฉันก็ตระหนักว่าถ้าฉันกำหนดสิ่งต่าง ๆ ในแง่ของความจริงและเท็จ (เช่นฉันควรทำตั้งแต่แรก) มันจะง่ายขึ้นมาก

คำอธิบายรหัส

\ 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
คุณทำซ้ำคำยาวexecuteสามครั้ง การกำหนดชวเลข: j execute ;จะช่วยให้คุณประหยัด 4 ไบต์
Quuxplusone

1

SKI-แคลคูลัส + C combinator ขนาด 36 ไบต์

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

จริง ๆ แล้วฉันไม่ทราบว่ามีล่ามที่ช่วยให้คุณกำหนด combinators เพิ่มเติมในแง่ของคนที่ผ่านมาดังนั้นฉันต้องทดสอบโดยใช้http://ski.aditsu.net/โดยวางใน combinators ที่ต้องการเช่นCCKK(SK)pqเอาท์พุทqแสดงให้เห็นว่าไม่ได้หมายความถึงKSK


1

Julia 1.0 , 36 ไบต์

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

ฉันไม่ทราบว่ามีค่าหรือไม่ฉันจริง ๆ แค่โหลดBoolประเภทพื้นเมืองมากเกินไปเพื่อให้สามารถเรียกใช้ได้ดังนั้นฉันจึงได้ประตูตรรกะส่วนใหญ่ฟรี น่าเสียดายที่จูเลียไม่มีimpliesประตูดังนั้นฉันจึงต้องเขียนฟังก์ชั่นของตัวเอง

ลองออนไลน์!


ฉันคิดว่าคุณยังคงต้องรวมโอเปอเรเตอร์ที่มีการโอเวอร์โหลดในการส่งของคุณ ... แต่การให้คะแนนไม่นับรวม ดังนั้นจะเป็น6 ไบต์จากบรรทัดใหม่หรือไม่ ฉันไม่แน่ใจว่าการให้คะแนนทำงานอย่างไรกับความท้าทายนี้
โจคิง

ฉันไม่แน่ใจ 100% ว่ามันทำงานอย่างไร แต่ต้องมีรหัสที่ไม่มีอะไรทำให้ฉันรู้สึกว่า
user3263164

แม้ว่ารหัสจะถูกประกาศไปแล้ว แต่คุณก็ยังต้องใส่รหัสนั้นมิฉะนั้นการส่งภาษาอื่น ๆ ของการเล่นกอล์ฟจะเป็นศูนย์ไบต์ คุณไม่ต้องมอบหมายอะไรให้กับคุณเลย
โจคิง


1

C ++ 17, 202−49 = 153 193 - 58 = 135 ไบต์

แรงบันดาลใจจากการแสดงความคิดเห็นการสนทนาของสิ่งที่นับเป็นฟังก์ชั่น 2-ary ต่อไปนี่คือ แกงกะหรี่รุ่นก่อนหน้าของฉัน C ++ 17 วิธีการแก้ปัญหา มันสั้นกว่าจริงเพราะเราสามารถใช้มาโครตัวเดียวกันเพื่อกำหนดnot_ฟังก์ชั่นอื่น ๆ ได้!

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

ลองออนไลน์!

อันนี้มีการทดสอบด้วยการยืนยันเช่น

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

สังเกตว่า or_มีการกำหนดไว้อย่างมีประสิทธิภาพ

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

เราสามารถกำหนด or_เพิ่มเติม "รัดกุม" เป็น

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

แต่นั่นจะทำให้เราเสียค่าใช้จ่ายเพราะเราจะไม่ใช้Dแมโครอีกต่อไป


เนื่องจาก C ++ เป็นตัวพิมพ์เล็กและตัวพิมพ์ใหญ่วิธีการเกี่ยวกับการใช้TrueและFalseแทนtrue_และfalse_? และคล้ายกันสำหรับผู้ประกอบการรายอื่น ที่จะประหยัด 12 ไบต์
G. Sliepen

@ G.Sliepen: อัลกอริทึมการให้คะแนนของ OP คำนึงอยู่แล้วว่าตัวระบุมีความยาวหนึ่งตัวอักษรอย่างมีประสิทธิภาพ อ้างอิง: "ความยาวรวมของรหัสทั้งหมดที่จำเป็นในการทำให้คริสตจักรเป็นจริงและเท็จในภาษาของคุณและและหรือไม่หรือ xor และนัยประตูคริสตจักรยกเว้นชื่อของฟังก์ชั่น (เช่น false = lambda x, y: y ใน Python จะเป็น 13 ไบต์) คุณสามารถใช้ชื่อเหล่านี้ในภายหลังในรหัสของคุณโดยนับ1 ไบต์ไปยังผลรวมไบต์ของเกตนั้น "
Quuxplusone

อาฉันคิดถึงเรื่องนั้น
G. Sliepen

0

APL (dzaima / APL) , 47 ไบต์SBCS

อยู่บนพื้นฐานของโยนาห์เจแก้ปัญหา

trueและfalseเป็นฟังก์ชั่นมัดnotเป็นตัวดำเนินการต่อท้ายและส่วนที่เหลือเป็นตัวดำเนินการมัด

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

ตาม OP สิ่งนี้นับทุกอย่างจากและรวมถึงจุดสิ้นสุดของแต่ละบรรทัดและนับแต่ละการเรียกคำจำกัดความก่อนหน้านี้เป็นไบต์เดียว

ลองออนไลน์!

จริงและเท็จเป็นฟังก์ชันตัวตนด้านซ้ายและขวา

not เพียงแลกเปลี่ยนอาร์กิวเมนต์ของฟังก์ชันตัวถูกดำเนินการ

ส่วนที่เหลือใช้แผนผังการตัดสินใจ:

andใช้ฟังก์ชั่น righthand เพื่อเลือกผลลัพธ์ของฟังก์ชัน lefthand ถ้าเป็นจริงมิฉะนั้นผลลัพธ์ของfalseฟังก์ชัน

orใช้ฟังก์ชั่นด้านซ้ายมือเพื่อเลือกถ้าเป็นจริงอื่นผลของฟังก์ชั่นขวามือtrue

xorใช้ฟังก์ชั่น righthand เพื่อเลือกผลลัพธ์ที่ไม่ได้ผลของฟังก์ชัน lefthand ⍶notถ้าเป็นจริงมิฉะนั้นผลลัพธ์ของฟังก์ชัน lefthand

impliesใช้ฟังก์ชัน lefthand เพื่อเลือกผลลัพธ์ของฟังก์ชั่น righthand หากเป็นจริงมิฉะนั้นผลลัพธ์ของtrueฟังก์ชัน


0

Stax , 34 ไบต์

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

เรียกใช้และแก้ไขปัญหาได้ที่ staxlang.xyz!

ผลักพวงบล็อกไปยังสแต็ก แต่ละบล็อกคาดว่าอาร์กิวเมนต์สุดท้ายจะอยู่บนสแต็กตามด้วยลำดับที่เหลือ

คลายการแพค (41 ไบต์):

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

แต่ละคู่{ }เป็นบล็อก ฉันใช้การลงทะเบียน X และ Y ทั้งสองเพื่อระงับtrueและnotเพื่อให้ฉันสามารถเข้าถึง 'em ได้อย่างง่ายดายในภายหลัง แต่น่าเสียดายที่falseไม่สามารถเป็นแบบไม่ต้องเสียเวลาได้เพราะจะทำให้กองซ้อนรกและทำให้เป็นกรณี XOR เดียว

ชุดทดสอบแสดงความคิดเห็น

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 ไบต์

เล่นต่อไปด้วยความคิดของ "ฟังก์ชั่น" ในภาษาที่ไม่มีฟังก์ชั่น ... นี่คือรุ่น booleans ของโบสถ์ Befunge-98!

ในภาษาที่ จำกัด ของ Befunge-98 โปรแกรมนี้ประกอบด้วยชุดของ "บรรทัด" หรือ "ฟังก์ชั่น" ซึ่งแต่ละโปรแกรมเริ่มต้นด้วย>คำสั่ง (ไปทางขวา) ในคอลัมน์ x = 0 แต่ละฟังก์ชั่นสามารถระบุได้ด้วยหมายเลขบรรทัด (พิกัด y) ฟังก์ชั่นสามารถรับอินพุตผ่านสแต็คของ Befunge ได้ตามปกติ

บรรทัด 0 เป็นพิเศษเนื่องจาก (0,0) เป็น IP เริ่มต้น ในการสร้างโปรแกรมที่รันบรรทัด L เพียงวางคำสั่งบนบรรทัด 0 ที่เมื่อดำเนินการให้ชี้ตัวชี้คำสั่งไปที่ (x = L, y = 0)

ความมหัศจรรย์ที่เกิดขึ้นในสาย 1. สาย 1 เมื่อดำเนินการปรากฏตัวเลขจากสแต็คและกระโดดไปยังหมายเลขบรรทัดL L(ก่อนหน้านี้บรรทัดนี้เคยถูก> >>0{{2u2}2}$-073*-\xซึ่งสามารถ "กระโดดข้ามสัมบูรณ์" ไปยังบรรทัดใดก็ได้ แต่ฉันเพิ่งรู้ว่าเนื่องจากฉันรู้ว่าบรรทัดนี้ถูกตรึงไว้กับบรรทัดที่ 1 เราจึงสามารถ "กระโดดข้ามสัมพัทธ์" L-1บรรทัดได้ในรหัสที่น้อยลง)

บรรทัดที่ 2 FALSEเป็นตัวแทนของคริสตจักร เมื่อดำเนินการจะปรากฏตัวเลขสองtและจากสแต็คแล้วบินไปยังหมายเลขบรรทัดff

บรรทัดที่ 3 TRUEแสดงให้เห็นถึงคริสตจักร เมื่อดำเนินการจะปรากฏตัวเลขสองtและจากสแต็คแล้วบินไปยังหมายเลขบรรทัดft

บรรทัดที่ 6 เป็นตัวแทนของคริสตจักรXORเป็นนวัตกรรม เมื่อดำเนินการมันจะปรากฏตัวเลขสองตัวaและbจากสแต็กแล้วบินไปตามบรรทัดที่aมีอินพุตสแต็NOT EXEC bก ดังนั้นหากaแสดงถึงคริสตจักรTRUEผลลัพธ์ของความa NOT EXEC bประสงค์จะเป็นNOT b; และถ้าaหมายถึงคริสตจักรFALSEผลลัพธ์ของการจะเป็นa NOT EXEC bEXEC 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^

ขอให้สังเกตว่าการกำหนดฟังก์ชั่นในภาษานี้คุณไม่ได้พูดถึงชื่อเลย "ชื่อ" ของมันถูกกำหนดโดยตำแหน่งของแหล่งที่มา ในการเรียกฟังก์ชันคุณพูดถึง "ชื่อ" ของมัน ตัวอย่างเช่นXOR( 6) ถูกกำหนดในแง่ของNOTและEXEC( 5และ1) แต่ "ชื่อฟังก์ชั่น" ทั้งหมดของฉันใช้เวลาเพียงหนึ่งไบต์ในการเป็นตัวแทน ดังนั้นวิธีนี้จึงไม่มีการปรับคะแนน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.