【问题标题】:Smart PHP compression code智能PHP压缩代码
【发布时间】:2013-08-08 13:07:09
【问题描述】:

所以我在“编程难题和代码高尔夫”上看到了这个聪明的话题:We're not strangers...。最好的答案是 PHP 代码打印 Never Gonna Give You Up 的歌词。它只有 543 字节长。

我试图理解这段 PHP 代码,但我不明白它是如何工作的。我认为这是一种基于语法的压缩,但我不知道如何使用未声明的常量,如

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

所以这里是代码。这是如何工作的?

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

We'T3n each@Jor 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<ny@Ruy-/A= if?<sk 42DS'tLE 4?;Lo8bli=L7ee..
O,R1)O,R001)/-..");

it working on Ideone

【问题讨论】:

    标签: php compression


    【解决方案1】:

    我们来一一分析str_replace参数。

    range('-',T)
    

    range() 函数返回一个数组,其中包含从第一个参数到第二个参数的元素。字符是按其ASCII值来考虑的,所以结果是

    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 而不是"T"? PHP 有一个错误特性,它使未定义的常量评估为与常量名称具有相同内容的字符串。常量T 未定义,因此它与"T" 相同,后者为代码高尔夫目的保存了两个字符。稍后的q 也是如此。如果服务器有错误报告,它将显示关于未定义常量的警告。

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

    这会将字符串拆分为q 字符处的数组。同样,这使得代码比使用数组文字更短。结果:

    Array
    (
        [0] => 
    I justCannaLE?2Gotta >u=Msta=.
        [1] => 
    Ng1Nlet? downNrun<rH=5desMt?N>cryNsayRoodbyeNtE< lie5hurt?
        [2] => 
    
    We'T3n each@Jor 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
    )
    

    最后一个参数是目标字符串。

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

    如果您将数组作为针和干草堆传递给str_replace(),则替换是一次完成一个。为简单起见,我们只取"We; n7trangMs" 作为标记字符串并从; 开始替换。将"7"替换为"8s"后的第一步(第二个数组中对应的替换):

    "We; n8strangMs"
    

    然后将"8"替换为"o "

    "We; no strangMs"
    

    ";""'re"

    "We're no strangMs"
    

    "M""er"

    "We're no strangers"
    

    简而言之,它是一种基本的压缩算法,您可以在其中找到在原始文本中重复的字符序列并将它们替换为单个字符。解压缩时,该字符将替换为原始序列。通过迭代运行进度,您可以再次压缩曾经压缩过的文本 ("o s" => "8s" => "7")。

    【讨论】:

    • 感谢这个非常好的答案。我在这里缺少的是您多次替换。压缩文本的最简单方法是什么? (作者是如何找到压缩字符串的?)
    • 作者可能使用了一些压缩算法。手动操作会很麻烦。
    • 我可以通过“反转”解压缩代码来找到压缩代码吗?
    【解决方案2】:

    试试吧!

    未定义的常量被假定为字符串。这是启用通知后的样子:

    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
    

    【讨论】:

    • 我试过了,它并没有引起Tq 的任何通知。但是如果我用其他字母替换这两个常量,就会出现通知。使用未定义常量的目的是什么?
    • 哦,我明白了,这些被解释为字符串,它们确实会发出通知(它们被隐藏在 ideone 链接上)。但是压缩部分呢?
    • @Imateapot:目的是由代码高尔夫规则设定的:使用尽可能少的字符-T'T'短两个字符
    • 是的,当然!但是我不知道T会被解释为'T',我不明白这段代码是如何输出歌词的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 2012-02-26
    • 2011-08-31
    相关资源
    最近更新 更多