一路向下压缩文件
发布于2010年3月18日,星期四。
一位著名的科学家(有人说是伯特兰·罗素)曾就天文学做过一次公开演讲。 他描述了地球是如何围绕太阳公转的,以及太阳是如何围绕着被称为我们星系的众多恒星的中心公转的。 演讲结束时,教室后面的一位小老太太站起来说:“你告诉我们的都是废话。世界真的是一个由一只巨大的乌龟背上支撑的平板。”科学家笑得很好,然后回答说:“乌龟站在什么上面?”“你很聪明,年轻人,很聪明。” 老太太说。 “但这是一路下来的乌龟!”
自我复制程序
在大学里,在玩电子游戏之前,我们会通过摆姿势进行编程练习来娱乐自己。 其中最受欢迎的是编写最短的自产程序。 因为这是一个脱离现实的练习,所以常用的工具是FORTRAN。实际上,FORTRAN是首选语言,原因与三种种族受欢迎的原因相同。
更准确地说,问题是要编写一个源程序,当编译和执行时,它将生成源的精确副本作为输出。 如果你从未这样做过,我建议你自己尝试一下。 如何做到这一点的发现是一个启示,它远远超过了被告知如何做到的任何益处。关于“最短”的部分只是一种激励,以展示技能并决定胜利者。
>>>打印' 你好 ' 你好
>>>打印“ 打印“hello” " 打印“hello”
>>>s=' 打印%s '; 打印s%repr 打印“打印%s”
>>>s=' s=%s; 打印s%%repr '; 打印s%repr s='s=%s; 打印s%%repr’; 打印s%repr
“前面加上引语会产生谬误” 在引用之前会产生错误。
打印此内容,然后打印其报价: 打印此内容,然后打印其报价:
(λ(x)` ( ,x个 ' ,x个 ) ) ' (λ(x)`(,x',x)) )
/*去奎因*/ 成套设备总管 导入“ 柔性制造技术 " 函数main(){ fmt公司。 打印(“ %s%c%s%c\n “,q,0x60,q,x60) } var q=` /*去奎因*/ 成套设备总管 导入“fmt” 函数main(){ fmt公司。 打印(“%s%c%s%c\n”,q,0x60,q,x60) } 变量q= `
自我复制Lempel-Ziv程序
$gunzip<r.gz>r $cmp r r.gz $
| ||||
| ||||
| ||||
|
| |||
|
| |||
|
| |||
|
| |||
|
|
|
| |||
|
| |||
|
| |||
|
| |||
|
| |||
|
|
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
||||
|
||||
|
|
|||
|
|
|||
|
|
自我复制zip文件
-
马吕斯·格德米纳斯 (2010年3月18日上午9:22) 它是 之前已完成 ,但我更喜欢你的作品。
-
塔夫斯 (2010年3月18日上午9:46) 在Mac OS X上的Safari中,设置了“下载后打开“安全”文件”选项(默认为打开),它会不断解压缩和填充我的磁盘。 “安全”的确…
-
亚伦·戴维斯 (2010年3月18日下午1:59) > #!/ 箱子/猫 很不错的。 我有点偏爱“十大清单”,我自己。。。。
-
沙姆斯 (2010年3月18日下午3:46) 这有点作弊,但在Python中,您可以编写任意的自重复程序,非常简单(如果您也假设使用标准库): 进口检查系统 打印inspect.getsource(系统模块['__main__']),
-
伊桑(EthanG) (2010年3月18日下午4:39) @tafs:至少它会响应下载窗口中的取消按钮。 在我杀死它之前,我的垃圾箱里有了r-962(963个解包),总共有3.8MB的垃圾。
-
尼克 (2010年3月18日下午6:23) 此帖子已被作者删除。
-
尼克 (2010年3月18日下午6:25) 也许r.zip可以包含 二 自身的副本。。。 让我想起了“我不能在X号录音机上播放”。。。
-
卢克 (2010年3月19日上午7:18) C对字符串的处理使它有点烦人,但并不过于复杂。。。 我想知道是否有人能想出更短的(但仍然是裸C)。 char qs[160]; char*q(char*s){char*rs=qs;do{if(*s==0x22)*(rs++)=0x5C;*(rs++)=*s;}while(*(s++)); 返回qs;} int main(){char*s=“char qs[160];char*q(char*s){char*rs=qs;do{if(*s==0x22)*(rs++)=0x5C;*(rs++)=*s;}while(*(s++));return qs;}int main; 打印f(s,q(s));}
-
卢克 (2010年3月19日上午7:21) 尽管有一些与字符串处理相关的注释,但C版本相对较短(最接近我编写的IOCCC候选者;): char qs[160]; char*q(char*s){char*rs=qs;do{if(*s==0x22)*(rs++)=0x5C;*(rs++)=*s;}while(*(s++)); 返回qs;} int main(){char*s=“char qs[160];char*q(char*s){char*rs=qs;do{if(*s==0x22)*(rs++)=0x5C;*(rs++)=*s;}while(*(s++));return qs;}int main; 打印f(s,q(s));}
-
卢克 (2010年3月19日上午7:22) 很抱歉,我的浏览器在第一次尝试时返回404。。。
-
蛛形纲 (2010年3月19日上午9:19) 考虑到crc32问题,您有什么建议可以告诉您如何编写一个版本,将其解压缩为一个更大的版本吗?
-
俄罗斯考克斯 (2010年3月19日上午10:08) @蜘蛛侠:我想你可以设计一个序列,当插入到一个特定的位置时(无论多少次),它都不会影响crc。 但我还没有做数学题。
-
尼克约翰逊 (2010年3月19日上午10:13) 不久之后,我就想到了这一点。 原则上,这不难,因为CRC只纠正小错误。 如果序列是一组自身打印两次的指令,那么您将被排序!
-
阿贾尚卡尔 (2010年3月22日下午12:40) 迷人的帖子! 有可能创建一个不使用L0 no-ops的纯LZ奎因(没有页眉或页脚)吗?
-
阿贾尚卡语 (2010年3月23日上午10:39) 根据记录,答案是肯定的,可以用这个16位操作码的奎因来完成(你最容易解释的解决方案是20位): 二级缓存二级缓存 二级缓存二级缓存 二级缓存二级缓存 R4,3 L4 R4,3 L4 R4.3 L4 4.3兰特 我找到的最短的是14个操作码: L0级 L4 L0 L4 L0L4 L0级 4.3兰特 L4 R4,3 L4 R4.3 L4 4.3兰特
-
俄罗斯考克斯 (2010年3月23日12:05 PM) 整洁。 如果你从上面的核心模式开始,你可以在两端插入L1L1L1L1,而不是L0L0L0,但这甚至更长。 第一条注释中的链接可以归结为这条9指令。 它利用了这样一个事实,即你可以有一个比备份更长的重复长度 L0级 L2 L0 L2级 L0级 2.3兰特 L2 R2,3 L2级 2,3 (R2,3==返回2个字节并复制3:如果当前输出以xy结尾,则附加xyx。)
-
阿贾尚卡尔 (2010年3月23日12:20 PM) 该死,真是鬼鬼祟祟。 我喜欢它。在我对试图找到一个纯3,2的解决方案感到沮丧之后,我偶然采用了4,3的方法。 但我从未想过要做2、3。
-
米西 (2010年3月24日下午2:56) 关于CRC:您可以修改您的程序,使其在某处包含任意的4字节序列(只需一次)。 通过修改这4个字节,可以使CRC成为任意值。 因此,您首先选择了CRC(例如为0x00000000),创建了自己制作的存档,最后选择了4个字节,这样CRC就是您想要的。因此,完全避免了递归问题。
-
k5用户 (2010年3月25日上午11:54) 游戏已经很晚了,但递归zip已经存在很长时间了。 反病毒世界已经知道它们至少8年了。 有人可能会对AV产品发起拒绝服务攻击,该产品设置为通过发送死亡zip来扫描压缩文件。 为了解决这个问题,许多AV程序在文件中设置了一些可配置的“深度”后停止处理。
-
米西 (2010年3月27日上午9:12) 所以,我说的是: 记录_固定.gz 它是一个gzip奎因,其中字节102-105是“定点”。 也就是说,您可以将它们更改为您想要的任何内容,文件仍将解压缩到自身。 (当然,如果您更改了它们,CRC将不会检出。) 因此,我创建了这个文件,将gzip页脚中的CRC设置为全部0,然后“反向计算”这四个字节中的CRC,因此整个文件的CRC实际上为0。 我相信,基于这个想法,可以创建一个中间有一个部分的文件,它可以在压缩时复制自己,而CRC保持不变。 我写完后会把它贴在这里。 您可能还需要查看此文件的内部,因为它基于与您的想法略有不同的想法。 例如,我不依赖于“repeat”操作码为5个字节。 有一个“源代码”可能稍微容易阅读: 记录_固定.lgz
-
米西 (2010年3月27日下午3:47) 这里是: 记录导出.gz . 它有一个32字节的块,在解压缩时重复,CRC总是正确的(和0)。 不幸的是,gzip页脚还包含大小字段,这当然是不正确的。。。 直到解压缩文件27次。:) 此时,复制块的大小将变为4GB,32位大小字段被设置为余数。 (但我没有检查。:) 考虑到这一点,我意识到有一种更简单(但有点作弊)的方法可以创建“成长的gzip quine”。 您只需复制整个文件。 由于gzip只是将连接的输入的输出连接起来,因此它可以在不太注意大小或crc字段的情况下工作。 因此,这里有一个文件,其gunzipping与将其与自身连接是一样的: 记录_上传.gz (“源”位于同一目录中。)
-
马克·鲁夫 (2010年5月1日凌晨1:57) 你好, 非常有趣的研究和很棒的写作! 继续努力。 当做, 马克
-
用户未知 (2010年5月1日下午3:23) 这是我不太熟悉的奎因: 导入java.math。 大整数; /** (c) Stefan Wagner,GPLv3.0 */ 奎因级 { 公共静态void main(String[]参数) { BigInteger b=新的BigIntiger( "3125672623196693767569686149189009633452 2377871159551965921417137170609691214223 9208376749605139774443708326203800130556 5247549291738666720120851102563432688661 2425053632619026133552590824825360959495 9103568388341399920152904163137391991148 8600579488934249116624219425362354637760 9935667840623358056717110027295132562103 94002527688367391286 17742678124740473856 7878670179316536315099060433926849016933 4865116792986969613917692005305319947405 7778267800604078704652663104779321903695 4971735707525104532138973326414147694788 6144049586837524382107377428450195285880 0467794888319592557310425481240448120408 1531669064199685228190893676717975716990 4846241527401973665847012561439332697517 5470668411522967977332908759408086343490 26570"); 整数i=0; for(字节c:b.toByteArray()) { ++i; 如果(i==159) 系统输出打印(b); System.out.print((char)c); } } } 这里是我最短的bash-quine:。 是的,确实如此。 也许你没有看到它——以下是你制作它的方法: 触摸_; chmod a+x _/_
-
斯特芬茨 (2010年5月2日上午10:02) 在Perl中(一行没有换行符): $q=chr(39)$ s='$q=chr(39)$ s=%s%s%s; 打印f$s,$q,$s,$q;'; 打印f$s,$q,$s,$q;
-
斯特芬茨 (2010年5月3日凌晨3:18) C版本也一样(一行没有换行符): main(){char q=34;char*s=“main(; 打印f(s,q,s,q);}
-
达格温 (2010年5月19日4:31 AM) Hioefukky任何在固定深度后停止的防病毒程序都会将该文件标记为恶意软件,而不是将其视为良性的。 主要原因是黑客显然只会将恶意软件隐藏在比阈值深一层的嵌套ZIP文件中。
-
邓肯 (2010年5月25日上午5:52) “我很遗憾,我找不到任何坚持无限次递归解压缩这些文件的程序。看着它们蠕动会很有趣,但看起来不那么复杂的拉链炸弹破坏了乐趣。” 恐怕我发现了炸弹。 我觉得这很有趣,所以上周我给几个同事发了一封r.zip的电子邮件。今天邮件服务器崩溃了。 我们的电子邮件是Lotus Notes,McAfee是病毒扫描程序。 看起来,虽然桌面版的McAfee在解压缩时只扫描zip文件,但服务器版本会检查每一封电子邮件的zip文件。。。 似乎花了一周的时间来填充光盘。
-
弗兰兹 (2010年11月4日上午5:25) 一直以来的计算机科学家 漂亮的帖子,谢谢! 但我发现购物车的比喻很容易误导人。 钥匙 对于奎因来说,就是拥有包含 自身的表示(要打印的字符串)。 最后,行动 表示表示(执行“打印”指令) 使表示真实(一个新程序,与它的 父级)。 大车圈中没有大车的表示。 其他艺术背景有制作奎因的潜力,因为它们 模糊了现实与其表现之间的界限。 我在想 关于埃舍尔的一些绘画,皮兰德罗的“六个角色 寻找作者”,或艾伦的《开罗的紫玫瑰》。 然而,它们都不是奎因,因为艺术作品不是 代表自己(例如,“开罗紫玫瑰”的代表是 关于埃及的电影,而不是大萧条的故事)。 更接近真正奎因的例子(可能是偶然的)是 “13楼”。 (前扰流板) 在电影中,洛杉矶的一组计算机科学家创建了一个 模拟洛杉矶,却发现他们就是自己 洛杉矶团队进行的计算机模拟的一部分 科学家。 愚蠢的作者在三个层面上停止了这部电影(在 洛杉矶最深处的年份是1937年,没有 计算机)。 但只要等待足够的(cpu)时间。。。 这将是 一路走来的计算机科学家!
-
亚伦·戴维斯 (2010年11月4日上午5:36) 也 eXistenZ公司 当然现在 开端 .在书中,有 树叶屋 还有鲍杰斯和纳巴科夫的各种作品。
-
AndyMm公司 (2010年11月29日下午2:00) 在Javascript中使用整数。 c=[59,21,51,,,53,19,62,71,74,0,57,21,58,21,51,53,19.57,20,14,13,19,57,3,15,38,21,57,54,11,23, 43,76,74,65,70,63,6,62,74,71,69,27,64,57,74,27,71,60,61,0,59,51,3,57,53,3,12,8,1,18,59,19]; 对于(a=b=[];a<65;a++)b+=a^3? 字符串.fromCharCode(c[+a]+40):c; 使用RegExp。 看到人们以更疯狂的方式使用RegExp,但这里有一个简单的方法。 unescape(q=/unescape%28q=%2FQ%2F%5B-1%5D%29.替换%28%2FQ%2F,q%29/[-1]).替换(/q/,q)
-
莱茵托 (2011年1月7日下午1:50) 《13楼》是丹尼尔·加卢耶(Daniel Galouye)的一本书《Simulacron 3》的电影版。 http://en.wikipedia.org/wiki/Simulacron-3 法斯宾德也拍了一部电影。
-
迈克尔·摩尔 (2011年3月8日上午8:44) 在罗塞塔代码,我们 有关于奎因的网页 .
-
卡科伊 (2011年3月15日凌晨2:47) 我正在尝试编译您的代码,以便修改它以获得与此类似的结果 http://www.steike.com/code/useless/zip-file-quine网站/ ,但我遇到了以下错误: rgzip.go:347:未定义:字节。 添加 rgzip.go:700:panic:panic的参数太多(“无法编码REP”,n) rgzip.go:710:未定义:扁平。 新放气阀 rgzip.go:1057:不能在函数参数中使用&f.codebits(type*[19]int)作为type[]int 作为新手,你能给我指出正确的方向吗?
-
匿名 (2011年4月7日上午6:49) @卡科伊: 字节。 添加已从语言中删除。 更改为附加 panic将文字解释为两个参数。 删除“,n” 扁平。 NewDeflater不再存在。 改为平板电脑。 NewWriter(新作者) codebits[numCodes]int让程序疯狂。 更改为codebits[]int 现在编译。 不知道它是否有效。
-
匿名 (2011年4月7日上午6:59) @卡科伊: 字节。 添加已从语言中删除。 更改为附加 panic将文字解释为两个参数。 删除“,n” 扁平。 NewDeflater不再存在。 更改为扁平。 NewWriter(新作者) codebits[numCodes]int让程序疯狂。 更改为codebits[]int 现在编译。 不知道它是否有效。
-
匿名 (2011年6月10日下午7:39) 我采纳了你的建议,并尝试自己创建一个。 我用php进行了尝试,结果发现它微不足道。 简单地说: 会做到的。 但我想你是想表达不同的观点。
-
匿名 (2011年6月10日下午7:40) 我采纳了你的建议,并尝试自己创建一个。 我用php尝试了一下,结果发现它很简单。 简单地说: <? php(电话) 打印(文件获取内容(__file_)); ?> 会做到的。 但我想你是想表达不同的观点。
-
沈浩浪 (2011年7月17日上午9:48) Unix外壳: z=\'a='z=\$z a=$z$a$z \; eval echo\$a'; 评估echo$a
-
科迪 (2011年11月21日上午5:52) 前几天我写了这篇文章。 至于C版本,其中一些版本存在不符合C标准的问题(例如,main的返回类型没有int)。 另一个例子是printf的隐式声明(no#include<stdio.h>) 所以我也修复了这个问题(希望它能粘贴好): #包括<stdio.h> int main(){char*p=“#include<stdio.h>%cint main(”{char*p=%c%s%c;printf(p,10,34,p,34,10,10);返回0;%c}%c“; 打印(p,10,34,p,34,10,10); 返回0; } wc在该源文件上运行,其价值是: 3 16 173奎因 (对于windows用户,这意味着:3行,16个单词,173个字符) 至于在php中尝试并直接包含该文件的人,事实上这一点非常不同。 那是作弊,不是奎因。 如果您通过在源代码中读取文件来包含该文件,那么(正如您所指出的)这几乎不是一个挑战。 对于这篇文章的作者来说,谢谢你——很有趣。 (我是通过查找zip文件格式找到它的,因为我现在记不得了;我认为是从wiki中引用的吗?)
-
科迪 (2011年11月21日上午6:04) 还有一件事我忘了回答。 关于抗病毒和递归zip文件:至少从我所看到的来看,它通常是一个用户定义的变量。 它不是硬编码的。 所以它并没有真正的缺陷。 事实上,有些事情在第一眼就很难判断是否正常(有些av可能会报告正常,而其他av则可能报告不正常,以此类推)。 即使是反贿赂技巧也能让防病毒检测引擎在不考虑恶意软件的情况下认为它是恶意软件。 当然,更“可怕”的把戏是背驮——在av引擎扫描文件时,恶意软件会感染文件/其他任何东西。 尽管如此,在安全性方面,假阳性和假阴性一样糟糕(另一个类似的事情——配置糟糕的防火墙可能真的很糟糕)。 事情就是这样发展的,有时我们都要好好利用。 当然,如果一个文件被压缩多次,可能会引起怀疑,也许应该这样做。 他们必须隐藏什么? 因此,归根结底,这是一个运用常识、理解事物如何工作的问题,如果所有病毒协同工作,抗病毒也会发挥相当好的作用。
-
大卫·瓦格纳 (2012年1月28日10:10 PM) 这太棒了! 谢谢你发布这个谜题。 我很高兴看到简化版,其中只允许使用L n个 和R n个 操作码(R n、 米 不允许)。 我很好奇最短的奎因是什么。 为了好玩,我决定扔一个SAT解算器。以下是我的发现。 最短的奎因是16字节长: L0 L0 L0-L2 L0-L0-L2-L0-L2-R3-R2 L2-R3-R3-R2 或者,以解析形式: L0级 L0级 10个 L2 L0 L0级 L2 L0 L2级 R3级 R2级 L2 R3 R2级 R3级 R2级 假设我的SAT代码是正确的,就没有短的奎因了。 也没有长度为17的奎因。 然而,似乎有更大长度的奎因。 如果你好奇我是如何将其编码为SAT的,这是我用来搜索五分长度的方法 n个 : 我定义了一个 n个 -未知字节数组,调用它In,所以In( 我 )是 我 输入的第个字节。 (我们将添加约束以强制它也成为 我 输出的第个字节。) 然后,我定义了一个( n个 +1) x个( n个 +1) 布尔未知值数组,active(.,.),其中 活动( 我 , j个 )如果In(0。。 我 -1) 是一个解析良好的字节序列(即,它不会在未完成的字符串文字中间结束),并解压缩in(0。。 我 -1) 产生输出In(0。。 j个 -1). 写下一组约束并不太难,这些约束根据in(.)的条目定义active(.,.)的条目的条目。 然后我发出约束以要求active(0,0)为true,并要求该active( n个 , n个 )是真的。 然后我调用SAT解算器来找到一个考虑所有这些约束的解决方案。 这很有趣! 谢谢你分享这个谜题。