2013-08-08 32 views
7

Vì vậy, tôi đã thấy chủ đề thông minh này về "Câu đố lập trình và chơi mã": We're not strangers.... Câu trả lời hay nhất là mã PHP in lời bài hát của Never Gonna Give You Up. Nó chỉ dài 543 byte.Mã nén PHP thông minh

Tôi đã cố gắng hiểu mã PHP này, nhưng tôi không thể biết cách hoạt động của mã này. Tôi nghĩ rằng đó là một ngữ pháp dựa trên nén, nhưng tôi không có đầu mối làm thế nào người ta có thể sử dụng các hằng số không khai báo như trong

<?php range('-', T); 

Vì vậy, đây là mã. Cái này hoạt động ra sao?

<?=str_replace(range('-',T),split(q," 
I justCannaLE?2Gotta >u=Msta=.q 
Ng1Nlet? downNrun<rH=5desMt?N>cryNsayRoodbyeNtE< lie5hurt?q 

We'T3n [email protected] s8lSg6r hear9<ch: but6;Lo7hyL7BInsideCe both3Cha9Ro: S 
We3KeRa45we;QplBq1)O)NgiT, nPgiT 
(GqiT? upq howFJeel: 
q knowqmeq<= q 
YHq8sqo qt's beenqingq'req aqndqmake? q yHq othMqAqay it 
q wqDqellq I'mqGqouqIq fqLhq tqerq 
NPq 
(OohqeTrQqRSna q gqonqve"),"We; n7trangMsL8loT63Ke rules5s8d8I 
AJull commit4nt'sChatFKink: of6CHldn'tRetKisJrom<[email protected]/A= if?<sk 42DS'tLE 4?;Lo8bli=L7ee.. 
O,R1)O,R001)/-.."); 

Xem it working on Ideone.

Trả lời

7

Hãy phân tích từng thông số str_replace.

range('-',T) 

Hàm range() trả về mảng có các phần tử trải dài từ tham số đầu tiên đến thông số thứ hai. Nhân vật được xem xét giá trị ASCII của họ, vì vậy kết quả là

Array 
(
    [0] => - 
    [1] => . 
    [2] =>/
    [3] => 0 
    [4] => 1 
    [5] => 2 
    [6] => 3 
    [7] => 4 
    [8] => 5 
    [9] => 6 
    [10] => 7 
    [11] => 8 
    [12] => 9 
    [13] => : 
    [14] => ; 
    [15] => < 
    [16] => = 
    [17] => > 
    [18] => ? 
    [19] => @ 
    [20] => A 
    [21] => B 
    [22] => C 
    [23] => D 
    [24] => E 
    [25] => F 
    [26] => G 
    [27] => H 
    [28] => I 
    [29] => J 
    [30] => K 
    [31] => L 
    [32] => M 
    [33] => N 
    [34] => O 
    [35] => P 
    [36] => Q 
    [37] => R 
    [38] => S 
    [39] => T 
) 

Tại sao T thay vì "T"? PHP có một sự đáp ứng mà làm cho nó đánh giá các hằng số không xác định là các chuỗi có cùng nội dung với tên của hằng số. Hằng số T không được xác định vì vậy nó giống như "T" giúp tiết kiệm hai ký tự cho mục đích chơi mã. Tương tự như vậy cho q sau đó. Nếu máy chủ có báo cáo lỗi, nó sẽ hiển thị cảnh báo về một hằng số không xác định.

split(q,"I justCannaLE?2Gotta >u=Msta=.q..."); 

Việc này chia chuỗi thành một mảng tại q ký tự. Một lần nữa, điều này làm cho mã ngắn hơn so với sử dụng một mảng chữ. Kết quả:

Array 
(
    [0] => 
I justCannaLE?2Gotta >u=Msta=. 
    [1] => 
Ng1Nlet? downNrun<rH=5desMt?N>cryNsayRoodbyeNtE< lie5hurt? 
    [2] => 

We'T3n [email protected] s8lSg6r hear9<ch: but6;Lo7hyL7BInsideCe both3Cha9Ro: S 
We3KeRa45we;QplB 
    [3] => 1)O)NgiT, nPgiT 
(G 
    [4] => iT? up 
    [5] => howFJeel: 

    [6] => know 
    [7] => me 
    [8] => <= 
    [9] => 
YH 
    [10] => 8s 
    [11] => o 
    [12] => t's been 
    [13] => ing 
    [14] => 're 
    [15] => a 
    [16] => nd 
    [17] => make? 
    [18] => yH 
    [19] => othM 
    [20] => A 
    [21] => ay it 

    [22] => w 
    [23] => D 
    [24] => ell 
    [25] => I'm 
    [26] => G 
    [27] => ou 
    [28] => I 
    [29] => f 
    [30] => Lh 
    [31] => t 
    [32] => er 
    [33] => 
NP 
    [34] => 
(Ooh 
    [35] => eTrQ 
    [36] => RSna 
    [37] => g 
    [38] => on 
    [39] => ve 
) 

Thông số cuối cùng là chuỗi đích.

"We; n7trangMsL8loT63Ke rules5s8d8I 
AJull commit4nt'sChatFKink: of6CHldn'tRetKisJrom<[email protected]/A= if?<sk 42DS'tLE 4?;Lo8bli=L7ee.. 
O,R1)O,R001)/-.." 

Nếu bạn chuyển mảng vào str_replace() như kim và haystack, thay thế được thực hiện từng lần một. Vì mục đích đơn giản, chúng ta hãy chỉ cần "We; n7trangMs" làm chuỗi thẻ và bắt đầu thay thế từ ;.Bước đầu tiên sau khi thay "7" với "8s" (thay thế tương ứng trong mảng thứ hai):

"We; n8strangMs" 

Sau đó thay thế "8" với "o "

"We; no strangMs" 

";" với "'re"

"We're no strangMs" 

"M" với "er"

"We're no strangers" 

Tóm lại, đây là thuật toán nén cơ bản nơi bạn tìm chuỗi ký tự lặp lại bên trong văn bản gốc và thay thế bằng ký tự đơn. Khi giải nén ký tự đó được thay thế bằng chuỗi gốc. Bằng cách chạy tiến trình lặp lại, bạn có thể nén lại văn bản đã nén một lần nữa ("o s" =>"8s" =>"7").

+1

Cảm ơn câu trả lời rất tốt này. Những gì tôi đã mất ở đây là bạn thay thế nhiều lần. Cách đơn giản nhất để nén văn bản là gì? (Tác giả đã tìm thấy chuỗi nén như thế nào?) – Imateapot

+0

Tác giả có thể đã sử dụng một số thuật toán nén. Làm theo cách thủ công sẽ là rất nhiều công việc. – JJJ

+0

Tôi có thể tìm mã nén bằng cách 'đảo ngược' mã không nén? – Imateapot

1

Hãy dùng thử!

Hằng số không xác định được giả định là chuỗi. Đây là giao diện của thông báo được bật:

Notice: Use of undefined constant T - assumed 'T' in D:\www\htdocs\test\index.php on line 1 
Notice: Use of undefined constant q - assumed 'q' in D:\www\htdocs\test\index.php on line 1 
Deprecated: Function split() is deprecated in D:\www\htdocs\test\index.php on line 12 
We're no strangers to love 
You know the rules and so do I 
[...] 
Never gonna say goodbye 
Never gonna tell a lie and hurt you 
+0

Tôi đã thử nó và nó không đưa ra bất kỳ thông báo nào với 'T' và' q'. Nhưng nếu tôi thay thế hai hằng số đó bằng các chữ cái khác, thông báo sẽ xuất hiện. Mục đích của việc sử dụng hằng số không xác định là gì? – Imateapot

+0

Ồ, tôi hiểu, những điều này được hiểu là chuỗi và họ KHÔNG đưa ra thông báo (chúng được ẩn trên liên kết ideone). Nhưng còn phần nén thì sao? – Imateapot

+0

@Imateapot: mục đích được đặt theo các quy tắc của mã golf: sử dụng càng ít ký tự càng tốt - 'T' là hai ký tự ngắn hơn' 'T'' – cypherabe

Các vấn đề liên quan