Có cách nào để rút ngắn chức năng mũi tên chất béo?


15

Từ những gì tôi đã thấy trong suốt thời gian ở đây trên PPCG, hầu hết các mục nhập JavaScript liên quan đến các chức năng mũi tên béo có xu hướng là một trong hai phe:

  1. Những câu đơn giản có khả năng chạy như một câu lệnh và trả lời một câu trả lời, tắt ngay con dơi, như x=(a,b)=>a*a+b

  2. Những cái phức tạp hơn thường có dấu ngoặc nhọn do sử dụng các vòng lặp và kết quả là yêu cầu sử dụng một returncâu lệnh .. nhưp=b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

Lấy ví dụ trên từ loại 2 với khái niệm niềng răng xoăn làm bằng chứng khái niệm ... Liệu có cách nào để đánh lại mã này (hoặc tương tự) như thế này để loại bỏ các dấu ngoặc nhọn cũng như returnkhông? Tôi chỉ hỏi điều này vì điều này có thể có khả năng (không nói điều này sẽ xảy ra mọi lúc) loại bỏ 8 byte khỏi mã của người chơi JS. Có bất kỳ kỹ thuật mà người ta có thể sử dụng trong trường hợp này? Tôi đã thử đệ quy, nhưng m=btuyên bố đã được chứng minh là một chút lỗi, vì tôi dường như không thể lắc nó.

Đối với đoạn mã trên, làm thế nào một golf sẽ tiến xa hơn để loại bỏ returntuyên bố, bất kể nó có ngắn hơn hay không?

Câu trả lời:


18

Sử dụng đệ quy

Tôi đã thấy rằng đệ quy là (hầu như) luôn luôn ngắn hơn eval+ for. Cách chung để chuyển đổi từ for sang eval là:

for(a=n;b;c);d
(f=a=>b?f(c):d)(n)

Vì vậy, hãy xem ví dụ của bạn:

b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

Trước tiên chúng ta có thể đơn giản hóa nó thành:

for(m=b,a=1;~-m;--m,a*=m*m)a%b;

Chúng ta đã làm gì ở đây? Vâng, chúng tôi chỉ đơn giản là di chuyển mọi thứ bên trong bản fortuyên bố, điều này giúp chúng tôi giảm số lượng dấu chấm phẩy không trực tiếp tốt hơn mà hầu như luôn dẫn đến một số golf.


Chúng ta hãy đặt nó trong eval và so sánh nó với phiên bản đệ quy:

b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}
b=>eval('for(m=b,a=1;~-m;--m,a*=m*m)a%b')
b=>(f=a=>~-m?(--m,f(a*=m*m)):a%b)(1,m=b)

Phần đầu tiên của vòng lặp for ( a=n), chúng ta có thể bắt đầu điều đó bằng cách chuyển các biến đó thành đối số. Các điều kiện đơn giản là: b?(c,f(a)):dở đâu dlà giá trị trả về. Thông thường cchỉ cần sửa đổi ađể nó có thể được hợp nhất vào nó. Vì vậy, chúng ta có thể chơi gôn nhiều hơn bằng cách sử dụng những gì tôi đã đề cập:

b=>(f=a=>~-m?(--m,f(a*=m*m)):a%b)(1,m=b)
b=>(f=a=>~-m?f(a*=--m*m):a%b)(1,m=b) // --m moved into a*=
b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b) // --m moved to condition

Điều đó nói rằng, như được lưu ý bởi @Niel đang đơn giản hóa thuật toán của bạn. Một thuật toán golfy trong một ngôn ngữ có thể không phải là golf trong một ngôn ngữ khác, vì vậy hãy đảm bảo thử các thuật toán khác nhau và so sánh chúng.


1
Bạn đã bỏ lỡ một khoản tiết kiệm lớn trong việc đơn giản hóa mã gốc. ~-mm-1, vì vậy vòng lặp có thể for(m=b,a=1;--m;a*=m*m)a%b;và phiên bản đệ quy có thể (chưa được kiểm tra)b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b)
Peter Taylor

1
Đôi khi bạn chỉ cần sử dụng một thuật toán khác nhưng trong trường hợp này, điều tốt nhất tôi có thể làm là có cùng độ dài với câu trả lời của @ PeterTaylor:b=>b>1&(f=a=>--a<2||b%a&&f(a))(b)
Neil

11

Lạm dụng tệ nạn.

Thật đơn giản. Thay vì:

f=n=>{for(i=c=0;i<n;i++)c+=n;return c}

Sử dụng

f=n=>eval("for(i=c=0;i<n;i++)c+=n;c")

Eval trả về tuyên bố đánh giá cuối cùng. Trong trường hợp này, vì câu lệnh được đánh giá cuối cùng sẽ là c+=n, cdù sao đi nữa, chúng ta sẽ để lại hai byte.

f=n=>eval("for(i=c=0;i<n;i++)c+=n")

Nói chung:

f=n=>eval("code;x")

ngắn hơn cái này, bởi một byte:

f=n=>{code;return x}

Lưu ý, sử dụng graves để gọi eval để có thể lưu byte không hoạt động, vì:

eval`string`

tương đương với

["string"]

Hữu ích cho việc xáo trộn! Không quá nhiều cho mã golf.


2
foo`string`luôn luôn tương đương với foo(["string"]), chỉ có nhiều hàm sau đó đưa mảng trở lại chuỗi mong muốn.
Neil

@Neil ơi, thật thú vị!
Conor O'Brien
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.