Phép trừ nhà thờ


12

Phép trừ nhà thờ

Tính toán Lambda luôn là một niềm đam mê của tôi và các hành vi mới nổi của việc truyền các chức năng vào nhau rất phức tạp. Các số của nhà thờ là các đại diện của các số tự nhiên được tạo ra từ ứng dụng lặp lại của một hàm (thông thường là phép cộng một hằng số). Ví dụ, số 0 trả về x và "bỏ qua" hàm đầu vào, một là f(x), hai là f(f(x))và vv:

ident = lambda x: x
zero = lambda f: ident
succ = lambda n: lambda f: lambda x: f(n(f)(x))
one = succ(zero)
add1 = lambda x: x + 1
to_int = lambda f: f(add1)(0)
print(to_int(one))
>>> 1

Từ đó chúng ta có thể dễ dàng thấy rằng bổ sung được thực hiện bằng cách áp dụng hàm đầu tiên cho x sau đó áp dụng hàm thứ hai cho x:

add = lambda m: lambda n: lambda f: lambda x: n(f)(m(f)(x))
print(to_int(add(one)(two)))
>>> 3

Ngoài ra là tương đối dễ hiểu. Tuy nhiên, đối với một người mới đến, có thể không thể nghĩ ra được phép trừ trong hệ thống số được mã hóa của Giáo hội. Điều gì có thể có nghĩa là không áp dụng một chức năng?

Thử thách

Thực hiện chức năng trừ trong hệ thống số được mã hóa của Giáo hội. Trong đó phép trừ thực hiện phép toán monus và không áp dụng nthời gian hàm nếu kết quả sẽ lớn hơn 0 hoặc 0. Đây là mã golf nên mã ngắn nhất sẽ thắng.

Đầu vào

Hai chữ số của Giáo hội đã được mã hóa trong lựa chọn ngôn ngữ của bạn. Các đầu vào có thể là vị trí hoặc curried. Để chứng minh đây là những chữ số Giáo Hội chân chính họ sẽ phải thực hiện trong bất kỳ chức năng và áp dụng chúng nhiều lần ( add1được đưa ra trong ví dụ nhưng nó có thể add25, mult7hoặc bất kỳ chức năng unary khác.)

Đầu ra

Một số nhà thờ. Cần lưu ý rằng nếu m < nsau đó m - nluôn luôn giống như chức năng nhận dạng.

Ví dụ:

minus(two)(one) = one
minus(one)(two) = zero
...

cũng chấp nhận được:

minus(two, one) = one
minus(one, two) = zero

Tín dụng:

Github này đã cho tôi một con trăn thực hiện Chữ số nhà thờ.


1
(Nhận xét trong ý chính là sai; tất nhiên là exp(m, n)tính toán m^n.)
Neil

1
Tôi không chắc ý của bạn là "đầu vào có thể là vị trí hoặc bị cong". Có thể xác định chức năng chính là lambda m,n,f:apply f m-n times(hoặc thậm chí lambda m,n,f,x:apply f m-n times to x) thay vì lambda m,n:lambda f:...? Hay điều này chỉ áp dụng cho hai đầu vào mn?
xnor

Ngoài ra, chúng ta có thể tranh luận mntheo thứ tự khác? Điều này sẽ giúp với cà ri.
xnor

@xnor miễn là bạn có thể chứng minh nó trừ hai chữ số nhà thờ thì bạn có thể lấy đầu vào theo bất cứ cách nào bạn muốn.
Ryan Schaefer

Câu trả lời:


9

Haskell , 35 byte

(r%s)f x=s(x:)(iterate f x)!!r(+1)0

Hãy thử trực tuyến!

Nói rằng rslà mã hóa nhà thờ của mn. Chúng tôi muốn r%sáp dụng f m-nthời gian cho một số giá trị ban đầu x. Đầu tiên chúng tôi tạo danh sách vô hạn

iterate f x = [x, f x, f (f x), f (f (f x)), ...]

sau đó sử dụng s(x:)để trả trước các nbản sao của x, nghĩa là thay đổi từng nchỉ số giá trị :

s(x:)(iterate f x) = [x, x, x, ...,  x, f x, f (f x), f (f (f x)), ...]

Sau đó, chúng tôi tính toán mtrực tiếp dưới dạng r(+1)0và lấy mphần tử thứ của danh sách đó làm !!r(+1)0. Thay vào đó head$r tail$..., một giải pháp không có chỉ mục có thể làm , đó là bỏ phần tử đầu tiênm và sau đó lấy phần tử đầu tiên, nhưng cú pháp lập chỉ mục ngắn hơn nhiều.

Lưu ý rằng giải pháp cổ điển không hoạt động trong Haskell mà không có tiện ích mở rộng vì kiểu gõ mạnh của nó không thể đại diện cho hoạt động của người tiền nhiệm.


3

Con trăn 2 , 82 80 byte

eval('!u:!v:v(!n:!f:!x:n(!g:!h:h(g(f)))(!u:x)(!u:u))(u)'.replace('!','lambda '))

Hãy thử trực tuyến!

2 byte thx đến Nick Kennedy lưu ý một cặp parens không cần thiết.

Hàm ẩn danh thực hiện trừ.

Hầu hết đây chỉ là nén định nghĩa được tìm thấy ở trang Wikipedia; không giống như tôi thực sự hiểu mã chưa. Nhưng thú vị!


Dựa trên ý chính mà OP đã đề cập, !u:!v:v(!n:!f:!x:n(!g:!h:h(g(f)))(!y:x)(!x:x))(u)dường như tiết kiệm được 2 byte, nhưng tôi không thực sự hiểu mã!
Nick Kennedy

@NickKennedy ginstallharper.de/2012/08/30/ nếu bạn quan tâm
Ryan Schaefer

@Ryan Schaefer: "Thủ thuật" hay!
Chas Brown

3

Python 2 , 77 byte

lambda r,s:s(lambda r:lambda f:lambda x:r(lambda(_,x):(x,f(x)))((x,x))[0])(r)

Hãy thử trực tuyến!

Chúng tôi thực hiện phân rã Church bằng cách theo dõi giá trị trước đó cho mỗi lần lặp và xuất ra giá trị đó ở cuối. 39% chiều dài mã là "lambda"...


đẹp! Tôi đã chờ đợi một câu trả lời trăn golf mà không chỉ nhìn vào việc thực hiện ý chính. Bạn đã nghĩ về việc sử dụng eval như câu trả lời khác để chơi gôn này chưa?
Ryan Schaefer

@RyanSchaefer Tôi đã kiểm tra eval / thay thế khi tôi thấy câu trả lời khác, nhưng thực tế nó dài hơn 2 byte ở đây với 5 lambdas để thay thế. Thật không may, Python thực sự khó hiểu ở cả hai chức năng xác định và thao tác chuỗi. Và nó thiếu một "sáng tác" tích hợp, sẽ tiết kiệm được một lớp lambdas.
xnor

2

C ++ (tiếng kêu) , 112 byte

#define L(x,y)[&](auto x){return y;}
auto m=L(u,L(v,v(L(n,L(f,L(x,n(L(g,L(h,h(g(f)))))(L(u,x))(L(u,u))))))(u)));

Hãy thử trực tuyến!

Đây là mã C ++ khó hiểu nhất mà tôi từng viết. Điều đó nói rằng, tôi nghĩ rằng việc không mã hóa mã này sẽ chỉ làm cho nó tồi tệ hơn.


2

Tải trọng , 37 byte

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

Hãy thử trực tuyến!

Bên trong (((!())~):*^(~!:(:)~*(*)*)~^^!)predchức năng, được thực hiện thông qua các cặp:

(               ( start pred function )!
  (
    (!())~      ( push zero below argument )!
  ):*^          ( do that twice )!

  (             ( start pair-increasing function )!
    ~!          ( remove second argument)!
    :           ( duplicate first argument )!
    (:)~*(*)*   ( increment first return value )!
  )
  ~^^           ( run pair-increasing function n times )
  !             ( remove first in returned pair )!
)


1

JavaScript (Node.js) , 87 85 81 76 74 byte

f=>g=>h=>x=>f(([x,[g,a]])=>[g(x),a])([x,g(a=>[x=>x,a])(f(a=>[h,a])())])[0]

Hãy thử trực tuyến! Sẽ không giành được bất kỳ giải thưởng nào, nhưng tôi nghĩ tôi sẽ thử một cách tiếp cận khác.

a=>[h,a]là một giai đoạn áp dụng h, trong khi đó a=>[x=>x,a]là một giai đoạn không áp dụng h. Chúng tôi áp dụng lần chức năng đầu tiên fvà lần chức năng thứ hai g. Chúng tôi sau đó áp dụng ([f,[g,a]])=>[g(x),a] fthời gian chức năng nghịch đảo . Điều này bỏ qua các ggiai đoạn thứ hai và thực hiệnf-g giai đoạn đầu tiên như mong muốn. Nó vẫn còn để trích xuất giá trị cuối cùng.

Các bộ dữ liệu tất nhiên có thể được chuyển đổi thành các hàm lambda dẫn đến biểu thức sau:

f=>g=>h=>x=>f(e=>e(x=>d=>d(g=>a=>e=>e(g(x))(a))))(e=>e(x)(g(a=>e=>e(x=>x)(a))(f(a=>e=>e(h)(a))())))(x=>a=>x)

1

J , 56 byte

c=:3 :0
t=.^:y
5!:1<'t'
)
m=.2 :'c 0>.(>:u 5!:0->:v 5!:0)0'

Hãy thử trực tuyến!

Lưu ý: -3 byte giảm số lượng TIO chom=.

Hàm bậc cao hơn trong J đạt được bằng cách sử dụng trạng từ và liên từ. Ở đây, một số nhà thờ là hình thức gerund của trạng từ được hình thành bằng cách kết hợp "sức mạnh của" kết hợp (liên tục áp dụng một động từ) và một số nguyên. Động từ sau c(cho "tạo") sử dụng Biểu diễn nguyên tử của J để biến đổi một số nguyên thành một gerund như vậy:

c=:3 :0
t=.^:y
5!:1<'t'
)

Toán tử "trừ" của chúng tôi (là kết hợp) trừ số nhà thờ gerund bên phải từ bên trái. Tuy nhiên, nó không giả định bất kỳ triển khai cụ thể nào về số nhà thờ, bao gồm cả số từ cđộng từ của chúng tôi . Thay vào đó, nó dựa vào định nghĩa chung và biến mỗi chữ số nhà thờ gerund trở lại thành trạng từ bằng cách đảo ngược nó với 5!:0, sau đó áp dụng trạng từ đó cho động từ tăng dần >:, sau đó áp dụng số đó thành 0.

Sau đó, nó trừ và lấy tối đa bằng 0, và áp dụng cđể có kết quả cuối cùng: một số nhà thờ gerund mới.


1

Ngôn ngữ Wolfram (Mathicala) , 55 48 47 39 byte (33 ký tự)

#2[(fx#[g#@g@f&][x&][#&])&]@#&

Hãy thử trực tuyến!

Biểu tượng is là 0xF4A1, một điểm mã Mathicala đặc biệt biểu thị một mũi tên phải cho \[Function]. Xem ở đây để giải thích thêm. Đây là những gì mã trông giống như trong giao diện Mathicala:

nhập mô tả hình ảnh ở đây

Chúng tôi có thể làm điều đó trong 40 byte / 32 ký tự , có thể ngắn hơn tùy thuộc vào sơ đồ đo:#2[n⟼f⟼x⟼n[g⟼#@g@f&][x&][#&]]@#&

Phiên bản không chơi gôn là bản dịch theo nghĩa đen của định nghĩa cổ điển về tiền thân :

pred = n \[Function] f \[Function] x \[Function] n[g \[Function] h \[Function] h[g[f]]][u \[Function] x][u \[Function] u];
subtract[m_, n_] := n[pred][m]

trông giống như thế này trong giao diện Mathicala:

nhập mô tả hình ảnh ở đây

Hàm trừ này hoạt động với các số Church được định nghĩa bằng

c@0=#& &;c@n_=#@*c[n-1][#]&

(không chơi gôn: c[0] = Identity &; c[n_] = Function[a, a@*c[n-1][a]] )

để chúng ta có

Table[c[n][f][x], {n, 0, 6}]
(*    {x, f[x], f[f[x]], f[f[f[x]]], f[f[f[f[x]]]], f[f[f[f[f[x]]]]], f[f[f[f[f[f[x]]]]]]}    *)

subtract[c[7],c[5]][f][x]
(*    f[f[x]]    *)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.