Câu hỏi này là câu hỏi đầu tiên trong số những thử thách sinh nhật Brain-flak được thiết kế để chúc mừng sinh nhật đầu tiên của Brain-Flak! Bạn có thể tìm thêm thông tin về Sinh nhật của Brain-Flak tại đây
Mùa hè năm ngoái chúng tôi đã có Integer Metagolf Brain-flak và câu trả lời mà nó tạo ra rất hữu ích cho cộng đồng Brain-Flak kể từ đó. Điều chính làm cho Integer Metagolf trở nên hiệu quả là một kỹ thuật gọi là mã hóa nhân.
Trong phép nhân thời gian chạy Brain-Flak là cực kỳ tốn kém. Đoạn nhân ngắn nhất được biết đến là:
({}<>)({<({}[()])><>({})<>}{}<><{}>)
Được phát hiện bởi Megatom
Tuy nhiên, có một cách rất đơn giản để tạo phép nhân thời gian biên dịch. Ví dụ: đoạn mã sau sẽ nhân với 5:
(({})({})({})({}){})
Điều này hoạt động vì các biểu thức liên tiếp được thêm vào với nhau. Mỗi cái ({})
không làm gì với ngăn xếp ( {}
bật và (..)
đẩy nó trở lại ngay) và đánh giá bất cứ thứ gì ở trên cùng của ngăn xếp. Tất cả các biểu thức này cùng nhau tổng hợp tới năm lần bất cứ thứ gì nằm trên đỉnh của ngăn xếp.
Đối với bất kỳ n
biểu thức chuỗi nào sau đây sẽ tạo một đoạn mã sẽ nhân số đỉnh của ngăn xếp bằng cách n
:
"("+"({})"*(n-1)+"{})"
Điều này hoạt động bằng cách thực n
hiện các biểu thức mà tất cả đánh giá lên đầu ngăn xếp. Cái đầu tiên n-1
không thực sự thay đổi bất cứ thứ gì và cái cuối cùng sẽ loại bỏ đỉnh của ngăn xếp trước khi đẩy.
Đối với các số tổng hợp, bạn có thể xâu chuỗi nhiều biểu thức nhỏ hơn lại với nhau để lưu byte. Ví dụ: bạn có thể nhân với 25 bằng cách nhân 5 lần:
(({})({})({})({}){})(({})({})({})({}){})
Điều này khá đơn giản, và đối với một số con số, nó hoạt động khá tốt tuy nhiên có nhiều cách tốt hơn để làm điều này. Ví dụ, một phương pháp tôi đã đưa ra sử dụng biểu diễn nhị phân của số. ( Đây là một triển khai python ) Phương pháp mới này hiệu quả hơn nhiều so với biểu thức chuỗi đơn giản được hiển thị trước đó, nhưng nó không phải là kết thúc, có tất cả các cách thú vị để nhân mã hóa cứng và có lẽ là một tấn mà chưa ai phát hiện ra.
Vì vậy, tôi nghĩ rằng đã đến lúc để xem chúng ta có thể nhận được tốt như thế nào.
Tổng quan ngắn gọn về Brain-Flak
Dưới đây là một mô tả về tất cả mọi thứ bạn sẽ cần biết về Brain-Flak cho thử thách này.
Brain-Flak có "nilads" và "monads". Nilads là dấu ngoặc đơn không có gì bên trong chúng. Mỗi nilad làm một điều và trả về một giá trị. Đối với thử thách này, hai nilad chúng tôi quan tâm là {}
và <>
. {}
bật lên trên cùng của ngăn xếp hoạt động và trả về giá trị của nó. <>
chuyển ngăn xếp hoạt động và ngăn xếp hoạt động, để ngăn xếp hoạt động trở thành không hoạt động và ngăn xếp không hoạt động trở thành hoạt động, nó trả về không.
Monads là dấu ngoặc đơn với những thứ bên trong chúng. Họ lấy một đối số duy nhất, tổng của tất cả mọi thứ bên trong họ, đôi khi thực hiện một hành động và sau đó trả về một giá trị. Ba trong số chúng tôi quan tâm là (...)
, <...>
và [...]
. Đơn vị quan trọng nhất cho thử thách (...)
này lấy giá trị của bên trong và đẩy nó vào ngăn xếp hoạt động. Sau đó nó trả về đối số. <...>
và [...]
cả hai đơn nguyên "trơ", nghĩa là chúng không thực hiện bất kỳ hành động nào mà thay đổi giá trị mà chúng được thông qua. <...>
luôn trả về 0 bất kể đối số được thông qua. Trong khi đó [...]
luôn trả về thời gian đối số -1
.
Chương trình mẫu với lời giải thích
Nếu bạn chưa bao giờ lập trình trong Brain-Flak, có thể nên xem xét một số chương trình ví dụ sử dụng các thao tác được mô tả
({}{})
Điều này thêm hai số hàng đầu trên ngăn xếp. Mỗi {}
giá trị bật ra khỏi ngăn xếp và (...)
đẩy tổng của chúng trở lại.
({}[{}])
Tương tự, điều này sẽ trừ mục thứ hai trên ngăn xếp từ mục đầu tiên. Giống như trước mỗi {}
giá trị bật lên nhưng giá trị [..]
thứ hai khiến nó được thêm vào. Một lần nữa (...)
đẩy tổng.
({}<{}>)
Điều này loại bỏ giá trị thứ hai trên ngăn xếp giữ nguyên giá trị hàng đầu. Nó hoạt động giống như hai lần cuối ngoại trừ giá trị thứ hai bị tắt tiếng do <...>
đó việc đẩy chỉ đẩy giá trị đầu tiên trở lại.
(({}))
Điều này tạo ra một bản sao thứ hai của giá trị trên đỉnh của ngăn xếp. Nó thực hiện điều này bằng cách bật đỉnh của ngăn xếp với {}
giá trị của nó, đầu tiên (..)
sau đó đẩy nó trở lại đánh giá về giá trị của nó. Cái thứ hai (...)
lấy giá trị được trả về bởi cái thứ nhất và cũng đẩy nó vào stack. tạo một bản sao thứ hai.
Bài tập
Cho một số nguyên n
tạo một đoạn mã Brain-Flak ngăn xếp nhân lên gấp bội số đỉnh của ngăn xếp hiện tại n
.
Bạn được phép sử dụng các hoạt động Brain-Flak sau đây
(...) -> Push Monad, Pushes the result of its contents
<...> -> Zero Monad, Returns zero
[...] -> Negative Monad, Returns the opposite of its contents result
{} -> Pop nilad, Pops the TOS and returns its value
<> -> Switch nilad, Switches the active and inactive stack
Các hoạt động khác bị cấm cho mục đích của thách thức.
Chấm điểm
Điểm của bạn sẽ là độ dài tích lũy của tất cả các chương trình từ n=2
đến n=10000
. Hãy chắc chắn bao gồm một liên kết đến đầu ra của chương trình của bạn để xác minh.
[...]
, vì vậy đó là một sự khởi đầu.