Rebmu : 79 ký tự HOẶC (37 + chiều dài (p1) + 2 * max (chiều dài (p2), chiều dài (p3)))
Trước tiên tôi sẽ đưa ra giải pháp 79 ký tự hỏi bạn phải học ngôn ngữ nào? (entropy 4.0, 30 chữ cái không bao gồm ?
) và cung cấp cho bạn các đề xuất của Rebol và [Red] :
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} pp{{[RReebdo]l}}
Một chiến thuật độc đáo có sẵn ở đây mà không phải bằng các ngôn ngữ khác xuất phát từ việc lợi dụng thực tế là niềng răng xoăn là một dấu phân cách chuỗi không đối xứng, có thể lồng nhau một cách hợp pháp:
my-string: {"It's cool," said {Dr. Rebmu}, "for MANY reasons--like less escaping."}
Điều đó cho phép tôi tạo ra một giải pháp tổng quát, có thể hoạt động dễ dàng trên bất kỳ chương trình nào không sử dụng trình tự thoát. Phiên bản 79 ký tự đủ đơn giản để tắt, nhưng để chứa đúng nguồn chương trình tùy ý cho các chương trình p2 và p3 bạn cần mẫu đầy đủ. Nếu chúng ta sử dụng nó, nó sẽ có 87 ký tự:
DD 11 DD :do dd {dd {p{Which languages must you learn?}qt}} ddoo{{pp{{[RReebdo]l}}}}
Các mô hình cho việc sử dụng hình thức chung này là nếu bạn có ba văn bản nguồn gốc của nhân vật tuần tự có độ dài biến (hãy sử dụng một ví dụ như AAA
, BBBBB
, CCCCCCC
), bạn có thể mã hóa chúng như một cái gì đó dọc theo dòng:
DD 11 DD :do dd {dd {AAAqt}} ddoo{{BCBCBCBCBC C C}}
(Lưu ý: Mặc dù mô hình này sẽ không hoạt động mà không điều chỉnh các chương trình sử dụng ký tự thoát, nhưng đây không phải là một lỗ hổng nghiêm trọng. Bắt một dấu ngoặc trái không khớp trong một chuỗi được phân định bởi dấu ngoặc yêu cầu một cái gì đó như {Foo ^{ Bar}
... nhưng bạn có thể dễ dàng viết lại bằng cách sử dụng ký hiệu chuỗi thay thế "Foo { Bar"
và các trường hợp kết hợp có thể được quản lý bằng cách dán cùng một hỗn hợp các chuỗi không thoát.)
Vậy ... một ví dụ thì sao? Khi hình thức chung đã có sẵn, chương trình 573 ký tự này đã được lắp ráp chỉ trong vài phút từ 3 giải pháp golf mã trước đó:
DD 11 DD: làm dd {dd {rJ N 0% rN Wa1m2j S {\ x /} D00 Hc & [u [Ze? Wa Qs ~ rpKw [isEL00c [skQd2k] [eEV? KQ [tlQ]] pcSeg - b00 eZ 1 5] 3] prRJ [si ~ dSPscSqFHs] eZ 1 [s + dCa + wM2cNO]]] Va | [mpAp2j] prSI ~ w { } Ls2w Wl h01tiVsb01n -1 chRV [sn [{N sbeo [tIt0l1eV} 0e5gXN1 01L {5s0} C {1} 0 {0 Do5f0 0bMe1e0r0} 0 [0 [0 [0 [0 [0 [0] [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[] {K, j} b P {. } lf EZ - - n [N m {G otothestoreandbuysome more}] {T akeencedownandpassitar ound} c B w P lf]]}}
Nếu bất cứ ai muốn thử viết chương trình đó bằng ngôn ngữ của họ và nghĩ rằng họ có thể đánh bại 573, hãy cho tôi biết. Tôi sẽ trả lại cho bạn một danh tiếng lớn nếu bạn làm thế - giả sử ngôn ngữ bạn chọn không phải là Rebmu, vì tôi biết những chương trình đó không phải là tối thiểu. :-)
Khoảng cách "lãng phí" mà bạn nhận được ở cuối là những gì xảy ra khi p2 và p3 có độ dài không cân bằng. Nhưng cả 3 chương trình đều có kích cỡ khác nhau trong trường hợp này, vì vậy không có một cặp đôi tốt nào để chọn cho p2 / p3. (Tôi đã chọn những dữ liệu này vì không có dữ liệu bên ngoài làm đầu vào, chẳng hạn như mê cung hoặc bất cứ thứ gì, không phải chúng có độ dài tương tự nhau. bạn không phải viết chương trình mới ...)
Làm thế nào nó hoạt động
(Lưu ý: Tôi đã bắt đầu với một cách tiếp cận "sáng tạo" hơn, không được sắp xếp hợp lý nhưng trông thú vị hơn. Tôi đã chuyển nó sang một mục trên blog của mình vì mô tả phương pháp này đã dài.)
Một chìa khóa ở đây là thủ thuật "mã eval như một chuỗi" như một số mục khác, nó chỉ có con át chủ bài của dấu phân cách chuỗi không đối xứng. Tôi sẽ bắt đầu bằng cách giải thích hoạt động của trường hợp 80 ký tự.
Đây là chương trình "toàn bộ", điều chỉnh khoảng trắng cho khả năng đọc của trường hợp này:
DD 11 ; assign 11 to dd (about to overwrite again)
DD :do ; make dd a synonym for DO (a.k.a. "eval")
; eval a string as source code that ends with QUIT (QT)
dd {dd {p{Which languages must you learn?}qt}}
; we'll never get here, but whatever's here must be legally parseable
pp{{[RReebdo]l}}
Ở đây chúng tôi kết thúc việc đặt DD thành một từ đồng nghĩa với DO (còn gọi là "eval"). Nhưng mẹo nhỏ là khi các chương trình giảm một nửa chạy, chúng sẽ chạy mã chạy với tác dụng duy nhất là xác định D thành chữ 1 vô hại.
Đây là những gì mã chars lẻ tạo ra, khoảng trắng lại được điều chỉnh:
D 1 ; assign 1 to d
D d ; assign d to itself, so it's still 1
d ; evaluates to integer, no side effect
{d pWihlnugsms o er?q} ; string literal, no side effect
p {Rebol} ; print "Rebol"
Và đây là mã chars chars:
D 1 ; assign 1 to d
D:od ; URL-literal (foo:...), no side effect
d ; evaluates to integer, no side effect
{{hc agae utyulan}t} ; string literal (well-formed!), no side effect
p {[Red]} ; print "[Red]"
Đó thực sự là trường hợp đối với chương trình không giảm một nửa, dd {dd {(arbitrary code)qt}}
sẽ thực thi bất kỳ mã nào bạn muốn. Tuy nhiên, có hai cuộc gọi để đánh giá thay vì chỉ một. Đó là bởi vì trong khi các dấu ngoặc nhọn lồng nhau hoạt động tốt trong mã xen kẽ, chúng làm rối tung hành vi xấu của DO. Bởi vì:
do {{print "Hello"}}
Sẽ tải chuỗi dưới dạng một chương trình, nhưng chương trình đó kết thúc chỉ là hằng chuỗi {print "Hello"}
. Do đó, mẹo tôi sử dụng ở đây là lấy DD của tôi (giữ cùng giá trị hàm với DO) và chạy nó hai lần. Người bán hàng nhai ở các phần khác nhau của chuỗi nhưng họ không nhai cả nếu độ chẵn / lẻ là chính xác cho nội dung và bởi vì những gì còn lại bên ngoài chuỗi sau khi chia đôi chỉ là hằng số tích phân d
mà chúng vô hại.
Với mẫu này, không có thách thức nào trong việc viết hành vi chương trình khi nó không bị cắt làm đôi - bạn có thể đặt bất cứ thứ gì miễn là độ dài ký tự của mã là chẵn (lẻ nếu bạn đang đếm QT, là QUIT). Nếu bạn cần lấy số chẵn từ một số lẻ, hãy ném vào một khoảng trắng (vì vậy thực sự có +1 trong công thức của tôi ở trên p1 cho độ dài chương trình lẻ của p1) . Thủ thuật dường như sẽ viết mã xen kẽ đó sau đó, phải vượt qua trình phân tích cú pháp nếu nó không bị giảm một nửa. (Nó sẽ không được chạy vì QT, nhưng nó phải được LOAD trước khi nó được thực thi.)
Trường hợp này là tầm thường; pp
tải tốt như một biểu tượng mặc dù nó không được xác định và được chia thành p
để in trong mỗi nửa chương trình. Nhưng chúng ta có thể thực hiện một mẹo khác chỉ bằng cách sử dụng một chuỗi ký tự một lần nữa. Các chương trình giảm một nửa vẫn có DO được định nghĩa bình thường, vì vậy chúng tôi cũng có thể nói:
ddoo{{pp{{[RReebdo]l}}}}
Bằng cách có phần duy nhất được trình phân tích cú pháp chọn trong toàn bộ trường hợp là từ tượng trưng ddoo
và chuỗi ký tự, sau đó chúng ta có thể xen kẽ bất kỳ hai chương trình nào chúng ta muốn bên trong chuỗi đó theo nghĩa đen và không chọc giận trình phân tích cú pháp. Các phiên bản giảm một nửa sẽ chỉ nói:
do{p{Rebol}}
..và ...
do{p{[Red]}}
Như tôi nói, phần này có vẻ quen thuộc với các giải pháp khác coi các chương trình là chuỗi và đánh giá chúng. Nhưng trong trường hợp của cuộc thi, khi các chương trình bạn đóng gói chứa các chuỗi lồng nhau, sẽ ném vào các cờ lê cho chúng. Ở đây, điều duy nhất khiến bạn gặp rắc rối là sử dụng lối thoát thông qua dấu mũ ( ^
) ... có thể dễ dàng làm việc xung quanh.
(Ghi chú 'gian lận' nhỏ: Tôi đã thêm QT cho "QUIT" để đối phó với vấn đề này. Thực ra, tôi đã cố tình xóa từ viết tắt để bỏ trước đó ... bởi vì bằng cách nào đó tôi nghĩ rằng nó chỉ tốt cho việc sử dụng bảng điều khiển và chỉ sử dụng không gian hai chữ cái nếu nó không có trong REPL. Tôi thêm nó vào vì tôi thấy tôi đã sai, đặc biệt là không thêm nó vào trường hợp này. Tuy nhiên, trước khi thay đổi đó, nó sẽ dài hơn 2 ký tự. Khi tôi lần đầu tiên đăng giải pháp, có một lỗi trong Rebmu khiến nó không thực sự hoạt động mặc dù nó đáng lẽ phải ... bây giờ nó hoạt động.)
x0=00;;
. Thử thách lớn!