最短的自毁循环


61

你的任务是写一个完整的程序或功能,它没有任何投入和运行任何类型的循环(中whileforforeachdodo-whiledo-loopgoto,递归等),将在导致一个错误,这意味着程序必须自行停止运行,并结束出口。

规则:

  1. 该错误必须是运行时错误,未处理的异常或任何使程序本身终止的错误。
  2. 该错误必须使程序停止并退出程序,而无需exit;在某个时刻显式(或等效)调用。
  3. 诸如Warning:Notice:等之类的不会导致程序本身结束的消息是无效的。例如,在PHP中被零除会产生一条Warning消息,但程序不会停止并且仍会运行,这不是有效答案。
  4. 循环必须至少运行一个完整周期。换句话说,错误可能会在第二个周期开始或更远的时间发生。这是为了避免使用不正确的代码语法导致错误:该代码在语法上必须正确。
  5. for(;;);如果遵循上述规则,则该循环甚至可以是无限循环(示例),但是结束运行时错误必须花费不超过2分钟。
  6. 无尾调用优化的递归是无效的(12)。
  7. 这是因此最短的代码获胜。
  8. 禁止出现标准漏洞

C#示例(在线测试):

using System;
public class Program {
    public static void Main() {
        int i;
        int[] n;
        n = new int[5];
        for(i=0; i<7; i++) {
            n[i] = i;
            Console.WriteLine(n[i]);
        }
    }
}


Output: 

0
1
2
3
4
Run-time exception (line 9): Index was outside the bounds of the array.

Stack Trace:

[System.IndexOutOfRangeException: Index was outside the bounds of the array.]
  at Program.Main(): line 9

排行榜:

var QUESTION_ID=104323,OVERRIDE_USER=59718;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important;font-family:Arial,Helvetica; font-size:12px}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

感谢Martin Ender提供的排行榜摘要


只是要清楚一点,只要错误与过多的递归无关,就可以使用没有TCO的递归,对吗?(例如,在第二次递归中出错的递归函数)
ETHproductions 2016年

@ETHproductions丹尼斯在聊天中建议:“在[递归]的情况下,可能很难决定是否已完成一个完整的周期。出现错误。[...]我说没有TCO的递归无效。”
马里奥

for(a;b;c)d;,wich语句结束后的第一个循环?中断第一次c陈述评估是否有效?
Hedi

1
@Hedi我的拙见(不是OP):所有条目必须完成一个完整的周期,这意味着它们必须进入第二个周期。这意味着至少有一个语句第二次运行。由于示例中的执行顺序为a, b, d, c, b, d, c, ...,因此b是循环的开始,必须至少运行第二次。
ETHproductions's

2
我不想引起任何麻烦,但是由于该程序的功能不应该接受任何输入,因此具有参数的所有递归解决方案均无效,因为已输入了参数。
BrainStone

Answers:


33

MATL5 1字节

观点取自@MartinEnder的CJam答案

`

在线尝试!

`    % Do...while loop
     % Implicit end. The loop continues if the top of the stack is true.
     % After the first iteration, since the stack is empty, the program 
     % implicitly tries to take some non-existing input, and finishes
     % with an error

旧版本

2:t"x

在线尝试!

2:   % Push [1 2]
t    % Duplicate
"    % For each (i.e. do the following twice)
  x  %   Delete top of the stack. Works the first time. The second it tries to
     %   implicitly take some non-existing input, and finishes with an error

3
也可以离线工作。没有输入意味着您可以假定输入为空。
丹尼斯

@Dennis Hm脱机程序将继续等待用户输入。输入是交互式的,即在脱机版本中根据需要进行输入。因此程序将无限期等待。不确定计数吗?
路易斯·门多

不能完全确定MATL在内部如何工作,但是如果您在无法请求输入的环境(例如TIO的后端)中执行它,它将无法获得任何输入。同样,应允许按Ctrl-D或与操作系统相关的等效键来发送空输入。
丹尼斯

35

Python,16个字节

不感兴趣的0除法:

for x in 1,0:x/x

第一次迭代计算1 / 1,效果很好。第二次迭代尝试计算0 / 0,结果ZeroDivisionError被抛出。

17个字节(个人收藏)

i=1
while i:del i

最初,i=1这是事实,因此进入了循环。

第一次运行循环时,将i删除该变量。

这意味着第二次i不再是变量,因此评估失败NameError: name 'i' is not defined.


另一个15字节的解决方案是def _():_()(newline)_(),因为Python不会优化尾递归。但是,这违反了规则6。


如果替换while i为17字节的解决方案,也可以使用,while 1因为它尝试i再次删除。
user6245072

2
@ user6245072是的,可以对两个摘要进行微不足道的修改以适用于许多工作解决方案
FlipTack

您可以使用del内置的技巧来剃除更多的毛发:while 1:del id
DSM


18

果冻3 2字节

Ṿß

通过耗尽内存来杀死自己。大约100秒后,本地执行此操作。

在线尝试!调试抽屉中的死亡证书)

这个怎么运作

Ṿß  Main link. Argument: x. Implicit first argument: 0

Ṿ   Uneval; yield a string representation of x.
 ß  Recursively call the main link.
    Jelly uses TCO, so the first cycle finishes successfully before entering
    the next one.

前几次迭代产生:

'0'
'”0'
'””,”0'
'””,””,”,,””,”0'
'””,””,”,,””,””,”,,””,”,,”,,””,””,”,,””,”0'
'””,””,”,,””,””,”,,””,”,,”,,””,””,”,,””,””,”,,””,”,,”,,””,””,”,,””,”,,”,,””,”,,”,,””,””,”,,””,””,”,,””,”,,”,,””,””,”,,””,”0'

在那之后,它变得非常丑陋,非常快。


果冻的记忆极限是多少?
tuskiomi

Jelly没有明确的内存限制,因此任何Python都可以解决。但是,每次迭代使用的内存都会翻倍,因此这应该很快耗尽所有可用内存。
丹尼斯

28
因此,每2年,我们将能够执行另一个迭代
tuskiomi

那么在具有大量RAM的慢速计算机上是否会导致条件5失败?
疯狂物理学家

@MadPhysicist正确。但是,这是时间限制所固有的问题。遵从性在很大程度上取决于程序在哪台计算机上运行。
丹尼斯

13

V,2个字节

òl

在线尝试!

对于V来说,这是完美的挑战,因为我一直都在这样做!实际上,V甚至没有任何条件,它只有在出错时会中断的函数。在这种情况下,ò“永远重复”的l意思是“向右移动” 的意思。

在空缓冲区(无输入)中,这将在第一次通过时中断并且不产生输出。如果输入,它会破坏我们一旦移动后输入的最后一个字符,并输出所有输入的(使这也是猫节目)


3
等待,l意思是“向右移动”?不是“移动l”?
科纳·奥布莱恩

1
@ ConorO'Brien是的。实际上,有一些良好的历史原因
DJMcMayhem

3
挑战要求答案在第二次或更晚的迭代中崩溃,而不是在第一次迭代中崩溃。
马丁·恩德

11

JavaScript(ES6),13个字节

f=_=>f(_?a:1)

这是一个递归函数,可以运行一次,然后抛出ReferenceError: a is not defined并退出。

这是15字节的非ES6版本:

for(i=0;;)i=i.a

一次运行正常,然后抛出TypeError: i is undefined并退出。


10

Bash 4.2,22个字节

exec $0 $@ $[2**$#%-1]

在TIO中不起作用,因为它具有Bash 4.3,并且我所依赖的错误终于得到修复。

验证

$ xxd -c 22 -g 22 self-destruct
0000000: 6578656320243020244020245b322a2a2423252d315d  exec $0 $@ $[2**$#%-1]
$ ./self-destruct
Floating point exception

一旦程序尝试计算2 63 mod -1,这就会崩溃,由于已知的错误,它在Bash 4.2和更旧的版本中崩溃。


10

PHP,22 21 20 18字节

这依赖于PHP,允许PHP给变量赋一个函数名并尝试运行它。

这只需将pi函数名称串联两次。这会用杀死PHP Fatal Error: Uncaught Error: Call to undefined function pipi() in [...][...]

while($x.=pi)$x();

这与我的旧答案类似。


旧答案,20个字节

PHP允许您使用递增运算符来递增字符。它仅适用于a-z范围,但足够。

for($x=pi;;)$x=$x();

我相信这可以满足所有要求的点,并且循环不会运行一次。

您可以查看是否会收到错误消息Fatal error: Function name must be a string


这是如何工作的,分步进行:

  • 分配pi$x
    由于pi被用作常量,PHP将检查是否存在。
    由于不存在,PHP显示警告语Use of undefined constant pi - assumed 'pi'(基本上:由于常量不存在,因此假定为字符串)
  • 第一次循环
    • 运行功能$x()
      由于$x具有值pi,它将运行该功能pi()
  • 将值存储在中$x
    $x现在有π而不是pi
  • 第二次循环
    • 运行功能$x()
      由于$x具有π,它将运行函数3.14159...()
    • π不是字符串,此时使用杀死程序Fatal Error

感谢@Titus找到pi()功能,为我节省了1个字节!


不错,但我认为这无效。它实际上并没有运行一次循环。您可以$x增加到abt循环体运行之前。您可以通过循环增加来解决此问题。
aross

我想到了一种不同的方法
ross

@aross Duh,你是对的,这是无效的。增量在错误的位置。它正在按现在的方式工作。您可以尝试运行for($x=abs;;++$x)echo$x,$x();进行测试。它应该显示abs0abt Fatal error[...]。或类似。
Ismael Miguel

1
您可以使用pi代替abs。在引发致命事故之前,这甚至没有发出警告。
泰特斯

@Titus我完全忘记了该功能!我知道该功能_是在某些系统中定义的,但并不可靠。但是,谢谢您找到它!
伊斯梅尔·米格尔

10

GNU sed15 13 5字节

-2感谢seshoumara
-8感谢齐柏林飞艇

H;G;D
  1. 将换行符和保留空间附加到模式空间。
  2. 将换行符和模式空间追加到保留空间。
  3. 删除最多第一行,然后重新开始。

这样很快就会耗尽内存:

$ time (echo|sed 'H;G;D')
sed: couldn't re-allocate memory

real    0m1.580s
user    0m0.545s
sys     0m1.012s

嗨,怎么样s:a\?:&a:g?它少1个字节,并且每次迭代的模式大小也加倍。
seshoumara

@seshoumara我认为模式空间为空时不会匹配任何内容,因此它将永远不会进行第一个替换。
莱利

@seshoumara echo -n | sed 's:a\?:&a:g',没有任何输出。它将sed 's::a:'与什么都不匹配相同。
莱利

随着echo -n绝对没有被传递给sed的,但没有sed的设计输入无法启动。检查此元链接以了解这echo|sed是开始接受sed的方法,以解决调用无输入规则的挑战。
seshoumara

@seshoumara我认为它仍然会给它一个空字符串。那似乎行得通。谢谢!
莱利

9

R,22 25 22 20 18字节

编辑:感谢@Mego指出R不支持尾部调用优化。

Edit4:找到了一个甚至更短的解决方案,它简单而复杂。

repeat(ls(T<-T-1))

答案使用内置的布尔值真实变量,T该变量在重复循环中无限期递减。该函数ls()称为每次迭代,该迭代列出了当前环境中的所有对象。但是,第一个参数name指定从哪个环境列出对象。从R文档中,我们发现:

name参数可以指定一种环境,从该环境中可以采用以下几种形式之一获取对象名称:整数(search列表中的位置);作为搜索列表中元素的字符串名称;或作为显式的environment(包括sys.frame用于访问当前活动的函数调用)。

这原则上意味着在第一次迭代中,我们将运行ls(-1)返回值character(0)(尝试访问everything-except-the-first任何字符类型对象的不存在元素时为标准)。在第二次迭代中,T递减二,然后我们调用ls(-3),依次返回错误:

Error in as.environment(pos) : invalid 'pos' argument

这是因为我们尝试列出everything-except-the-third元素,但本地环境此时仅包含变量T(因此,ls()1在此迭代中返回长度列表),并返回错误。


1
如果存在递归限制,这听起来不像是通过尾调用优化来完成递归。
Mego

@Mego经过一番挖掘,我发现R确实不支持尾部调用优化,因此此答案无效(之前从未听说过该概念)。稍后将更改为有效答案。
Billywob

9

Befunge-93,3个字节(可能是1或0)

!%!

在线尝试!

在循环的第一次迭代中,堆栈为空,这等于所有零。因此,!(非)操作将堆栈顶部转换为1,而%(模)操作将计算0 mod 1,保留0。!在程序计数器回绕并再次开始循环之前,下一个操作将0转换为1。

在第二次迭代中,第一个!操作将现在位于堆栈顶部的1转换为0。%然后,该操作将计算0 mod 0,这将在参考解释器上产生除以零的错误,从而终止程序。

还有一个更无聊的1字节答案,尽管我不确定这是否有效。

"

在线尝试!

"命令开始一个字符串,因此该行其余部分上的每个空格都被压入堆栈,直到程序计数器回绕并遇到"再次关闭该字符串为止。然后,需要重新包装一下,以重复该过程,开始另一个字符串,并将另外79个空格推入堆栈。最终,这将耗尽内存(参考解释器行为)或产生堆栈溢出。

现在,如果您想真正遵循规则,那么从技术上讲还有一个零字节的解决方案。


如果您认为解释意味着任何解释器都定义了该语言(此处有很多解释者),那么我们可以暂时假设Befunge语言是由该解释器定义的。该解释器的“功能”之一是,在执行空白程序时,它会将Playfield的每个循环的Undefined值压入堆栈。如果有足够的时间,它将最终耗尽内存。

发生的速度取决于计算机的速度,可用内存和使用的浏览器。在我的机器上,我发现Microsoft Edge效果最好,但是即使如此,两分钟后它还是“仅”使用500MB。直到大约15分钟标记(使用了数GB数据),Edge才决定终止进程并刷新选项卡。因此,不太可能在两分钟的时间限制内完成任务,但是在正确的条件下,这不一定是不可能的。


8

FALSE,8个字节

我真的很喜欢这种语言。

1[$][.]#

这会推送一个1,然后[$][.]#$true时循环(堆栈顶部重复),然后(.)将其输出。打印单曲后,此解释器崩溃1(循环至少运行了一次的证据。)这似乎是该解释器中的错误。以下9字节程序应在所有兼容的解释器中运行:

1[$][..]#

您还应该尝试DUP,它基本上是FALSE的超集。那就是我用来做RETURN的东西。
Mama Fun Roll

@MamaFunRoll哦,是的,我忘了你取得了回报!我得试试那个。:D
科纳·奥布莱恩

@MamaFunRoll我爱DUP,我刚刚写了一个DUP解释器,我正在玩它。
ML

@ ConnorO'Brien:我想说您的第一个解决方案应该使任何解释器崩溃。我只是使用自己的解释器进行了调试运行,很明显第一个.清空了数据堆栈,而第二个循环$试图复制空堆栈的顶部元素,这将导致错误(嗯,我的解释器确实)。第二个版本应该无效,因为它甚至没有完成第一个循环,因为它已经尝试过早地访问空堆栈。
ML

对于第二个示例,是我的DUP解释器的全彩色调试转储。一旦您看到数据堆栈(ds)和返回堆栈(rs)的工作原理就很明显,但是后者在FALSE中不是透明的。
ML

8

C,21个字节

i;f(){for(;1/!i++;);}

i保证从这里开始0

可以确认,它一次运行如下:

i;f(){for(;1/!i++;)puts("hi");}
main(){f();}

在我的机器上,结果是:

llama@llama:...code/c/ppcg104323loop$ ./a.out 
hi
zsh: floating point exception (core dumped)  ./a.out

我能找到的最短的递归解决方案是22个字节

f(i){f(i-puts(""-i));}

gcc只有在达到-O2或更高级别时才进行尾部调用消除,这时我们需要调用一个函数puts来防止整个事物被优化。确认这有效:

llama@llama:...code/c/ppcg104323loop$ cat loop.c       
main(){f();}
f(i){f(i-puts(""-i));}
llama@llama:...code/c/ppcg104323loop$ gcc -O2 -S loop.c 2>/dev/null
llama@llama:...code/c/ppcg104323loop$ grep call loop.s
    call    puts
    call    f

以下是一个完整的程序,它假定在不使用命令行参数的情况下以22个字节进行调用:

main(i){for(;1/i--;);}

等效于相同长度的函数:

f(i){for(i=1;1/i--;);}

这样的功能是否像main一样对待?如果是,则第一个参数是参数列表的长度(即1,即用于调用它的名称)。
莱利

或者,参数寄存器仍然具有从主调用那里获得的值。
莱利

@Riley Ahh,后一种理论似乎是正确的,这一事实证明了事实,即随着命令行参数的增加,数字会增加。感谢您的见解!
门把手

我不确定您是如何第一次猜到它的,但是我应该与调用f的函数的第一个参数相同。
莱利

是的,蒂奥
莱利

6

MATLAB,18个字节

这可以作为脚本运行:

for j=1:2;j(j);end

第一次迭代就很好了,因为j(1)1。第二次迭代会由于j(2)超出范围的数组(超出j1x1数组的尺寸)而崩溃。

也可以将其作为脚本运行,但仅在首次运行时才有效。尽管如此,这还是对MATLAB预定义常量的一种充分的滥用,我认为我会包括在内。它也是18个字节。

while i/i;i={};end

i在尚未定义变量的工作空间中运行时,假定i是虚数单位,因此i/i = 1。在第一个循环中,分配i={}创建了一个名为的空单元格数组i。在第二次迭代中,该循环以“类型为“ cell”的输入参数的未定义运算符'/'退出”。


两者都很棒!您可能知道这一点,但j(2)通常会使用0+1i
Stewie Griffin

谢谢!我认为在Octave中是正确的,但在MATLAB中却不正确
MattWH

6

Perl 6、13个字节

loop {5[$++]}

在无限循环中索引整数文字。
依赖于这样的事实:在标量值上,数组索引语法可以与索引一起使用0(返回值本身),但Index out of range对任何其他索引都会引发错误。


6

QBasic,17个字节

这段代码很奇怪。

DO
i=11+a(i)
LOOP

这个怎么运作

在QBasic中,变量是预先初始化的。像i这里一样,没有任何类型后缀的常规变量都被预先初始化为零。

除非您尝试像数组一样下标到该变量...在这种情况下,它是一个11个零的数组。*

因此,第一次通过循环i0a是一个数组。a(i)给出数组的第零个元素(即0)。一切都很好。我们设置i11和循环。但是现在11不是该数组的有效索引a,并且程序暂停Subscript out of range

一个19字节的版本可以更好地显示正在发生的情况:

DO
?a(i)
i=i+1
LOOP

这将0在出错之前打印11次。


*从概念上讲,它是一个10元素的数组。QBasic中的大多数东西都是1索引的,但是数组不是,可能是出于实现的原因。为了使程序员能够按预期工作,QBasic会添加一个额外的条目,以便您可以使用索引1到10。但是,索引0仍然可以很好地访问。去搞清楚。


QBasic和数组,乐趣在哪里停止!
steenbergh

由于错误不会要在第二循环中,不能这样做i=1+a(i)
Quelklef

@Quelklef不,您必须这样做i=i+1+a(i)。否则,索引永远不会超过1,这不是错误。
DLosc

@DLosc哦,您是对的。
Quelklef

5

Haskell,15个字节

f(a:b)=f b
f"a"

f"a"通过删除第一个字符,以递归方式在字符串“ a”中运行,并最终在其末尾失败并发生Non-exhaustive patterns in function f异常,因为f它仅针对非空字符串定义。


5

C#,71 38个字节

由于您在C#中提供了示例,因此这里提供了另一个版本

还要感谢pinkfloydx33

void c(){checked{for(uint i=1;;i--);}}

比关键字短Parse.ToString(),甚至比Parse($"{c--}") 我精打细算还短checked。坚韧肯定比Parse(c.ToString())

原始答案

class p{static void Main(){for(int c=0;;c--)uint.Parse(c.ToString());}}

c=0当导致以下情况时c=-1,它将开始然后递减uint.Parse

Unhandled Exception: System.OverflowException: Value was either too large or too small for a UInt32.

非高尔夫版本,并验证该循环至少运行一次

class p {
    static void Main() {
        for(int c=0;;c--) {
            System.Console.Write(c);
            uint.Parse(c.ToString());
        }
    }
}

for(int c=0;;)uint.Parse($"{c--}");
pinkfloydx33'2013/

1
checked{for(uint c=1;;)c--;}
pinkfloydx33'2013/

好吧,哇!不知道'$'速记!
MrPaulch '16

4

CJam,4个字节

1{}g

在线尝试!

{}g循环的第一次迭代会弹出1,告诉它继续。第二次迭代尝试弹出另一个条件,但是堆栈为空,因此程序崩溃。


4

x86汇编(AT&T语法),40字节

f:
mov $1,%eax
A:
div %eax
dec %eax
je A

声明一个函数f,该函数在其第一次迭代中将1除以1,然后尝试将0除以0并返回错误。


您可以通过切换至Intel语法来节省4个字节:)
mriklojn

6
通常,我们根据生成的字节码的大小(而不是人类可读的指令)对汇编进行评分。
丹尼斯

@Dennis组装程序集是机器语言。但是,可以用机器语言的形式来简化。
杰森

摆脱f标签和mov。交换dec和div,您可以摆脱更多的麻烦。
清晰的时间为

4

CJam,4个字节

P`:~

P`生成字符串3.141592653589793:~计算每个字符。3是CJam中的有效代码,仅返回3。在下一次迭代中,将.导致错误,因为它需要一个数字或一个运算符在其后。




4

批处理,22 20字节

:a
set i=%i%1
goto a

说明

这是一个无限循环,它将a附加1到最初为空的字符串上。最终,这将超过8192的最大字符串长度并崩溃。在我的机器上,这大约需要30秒。


真好!您可以使用Unix行尾节省2个字节。
briantist

您可以使用%0(而不是标签和goto)作为文件名。
YourDeathIsComing '17

我不确定这是否违反了尾递归规则。
SomethingDark

4

JavaScript,9个字节

for(;;i);

这将运行一次,然后抛出ReferenceError: i is not defined以停止循环。

// With a console.log(1) to see that it runs once.
for(;;i)console.log(1);


以以下示例为例,是<increment>第一个循环的结束还是第二个循环的开始?

0:for(<init>;<test>;<increment>)
1:{
2:  <statement>;
3:}

1 /我看到了

从第0行到第3 行,然后回到第0行,感觉好像已经完成了一个完整的循环。
那将成为<increment>第二个周期的开始。
-第一个周期:<init>-> <test>-> <statement>
-第二个周期:<increment>-> <test>-><statement>

2 / While当量

0:<init>;
1:while(<test>)
2:{
3:  <statement>;
4:  <increment>;
5:}

在该等效while<increment>是第一个周期的结束,感觉就像是用相同的for
那将<increment>结束第一个周期。
-第一个周期:<test>-> <statement>-> <increment>
-第二个周期:<test>-> <statement>-><increment>

3 /两次遇到陈述

当两次遇到一个语句时,将完成一个完整的循环。
遇到两次的第一个语句是<test>
那将<increment>结束第一个周期。
-第一个周期:<test>-> <statement>-> <increment>
-第二个周期:<test>-> <statement>-><increment>

4 /这是一个设置

<init>刚刚建立无论是需要的第一个周期。
<increment>刚刚建立无论是需要在第二个周期。
那将成为<increment>第二个周期的开始。
-第一个周期:<init as a setup>-> <test>-> <statement>
-第二个周期:<increment as a setup>-> <test>-><statement>


ECMAScript®2016语言规范

的运行时间 for(<init>;<test>;<increment>)<statement>;

令varDcl为评估结果<init>
ReturnIfAbrupt(varDcl)。
返回?ForBodyEvaluation( ,,<test> ,«»,labelSet)。<increment><statement>

共有三种形式,因此我在这里采用了最短的形式,没有什么区别:
-不管<init>它不是第一次迭代的一部分。
-相关的是ForBodyEvaluation。

ForBodyEvaluation的详细信息(<test><increment><statement>,«»,labelSet)

0令V不确定。
1执行?CreatePerIterationEnvironment(perIterationBindings)。
2重复
3如果不是[empty],则
4使testRef为求值结果<test>
5让testValue为?GetValue(testRef)。
6如果ToBoolean(testValue)为false,则返回NormalCompletion(V)。
7让结果为评估结果<statement>
8如果LoopContinues(result,labelSet)为false,则返回Completion(UpdateEmpty(result,V))。
9如果result。[[Value]]不为空,则使V为result。[[Value]]。
10执行?CreatePerIterationEnvironment(perIterationBindings)。
11如果不是[empty],则
12使incRef为评估的结果<increment>
13执行?GetValue(incRef)。

6 /我看到了

一个完整的循环重复部分的完整运行。
那将<increment>结束第一个周期。
-第一个循环:<test>-> <statement>-> <increment>/换句话说,从第3行到第13行
-第二个循环:<test>-> <statement>-> <increment>/换句话说,从第3行到第13行

7 /一个循环是一个迭代

循环开始于CreatePerIterationEnvironment
因此,当CreatePerIterationEnvironment遇到新的循环时,就结束了前一个循环。
那将成为<increment>第二个周期的开始。
-第一个循环:<test>-> <statement>/换句话说,从第1行到第9行
-第二个循环:<increment>-> <test>-> <statement>/换句话说,从第10行循环直到第9行


<increment>第一个周期的结束还是第二个周期的开始?

正确的解释是6或7。


8
我认为我更倾向于将增量归因于第一次迭代的结束,而不是归因于第二次迭代的开始或两者都不进行。我认为这是一个模棱两可的问题。

1
由于for(a;b;c)d;大致等于a;while(b){d;c;},我倾向于说在第一次迭代中仍然抛出错误(在第二次检查循环条件之前)。
ETHproductions 2016年

@Hurkyl第一次迭代从初始化开始,因此我认为增量应该是第二次迭代的开始。
Hedi

4
如果您阅读了规范,则可以看到增量操作是迭代的最后一部分,因此,它仍属于第一次迭代。
Nit

3
@Hedi我根本不知道这有什么关系。显然,增量操作是循环的第一次运行的一部分。换句话说,调用增量操作时,循环尚未完成一次完整运行。
Nit

4

INTERCAL,12个字节

(1)DO(1)NEXT

在线尝试!

NEXT是INTERCAL-72的主控制流命令。(后来引入了更高的修订版本COME FROM,该修订版本变得更为著名,但是它不是该语言的原始版本;对于所有完成的INTERCAL实现,我都知道支持NEXT向后兼容,除了默认情况下,所有版本都启用对它的支持。因此我觉得不需要在标题中专门命名INTERCAL-72。)

NEXT用来形成循环时,您应该使用RESUMEFORGET来释放它用来记住程序所在位置的空间。RESUME追溯地使之NEXT类似于函数调用(尽管您可以从所处的函数之外的函数返回),FORGET而使之类似于GOTO语句。如果您不执行任何操作(并且此程序也未执行),则该程序将在80次迭代后崩溃(此行为实际上是在INTERCAL规范中指定的)。

这是否算作无限递归(在问题中不允许),这有点模棱两可。您当然可以使用这种方法NEXT来实现函数调用,在这种情况下,它实际上是一个递归函数,但是这里没有足够的信息来确定我们是否在进行函数调用。至少,我无论如何都会发布此内容,因为它不会明确违反规则,而优化了“尾调用”的INTERCAL实现不仅会违反规范,而且还会导致大多数现有程序中断,因为从“错误的函数”是执行IF语句等效项的主要方法。

这是由C-INTERCAL生成的结果错误消息:

ICL123I PROGRAM HAS DISAPPEARED INTO THE BLACK LAGOON
    ON THE WAY TO 1
        CORRECT SOURCE AND RESUBNIT

(请注意,第二行以一个制表符缩进,第三行以八个空格缩进。这在终端或几乎所有具有制表符停止位为8的倍数的程序中看起来都是正确的。但是,Markdown的制表符停止位为8的倍数。第四,违反了大多数旧版程序对制表符的假设,因此错误消息在这里有点格式错误。)


错误真的在说CORRECT SOURCE AND RESUBNIT吗?如原始C-INTERCAL错误消息中的错字?
Andrakis

1
@Andrakis:是的,确实如此。那个错字已经被精心保存了多年。

3

Pyth,3个字节

W1w

在线尝试。

W1只是while 1:在Python中。循环主体打印从STDIN读取的行,当使用空输入运行代码时,该行在第二次迭代时崩溃。

如果使用#(loop-until-error)的循环被禁止(我认为是这样),我认为这是最短的循环。


3

Python 3,29个字节

i=1
def x(n):del i;x(i)
x(i)

真的很简单。在第二次调用x时,我不在那儿,Python抱怨它。


3

迷宫,3字节

#(/

在线尝试!

像大多数2D语言一样,迷宫没有任何显式的循环结构。取而代之的是,布置成可连续执行多次的任何代码都是这些语言的循环。就迷宫而言,一个简单的线性程序充当循环,因为指令指针将在其上来回反弹。如果程序是abc(对于某些命令abc),然后实际执行将abcbabcbabcb...所以它运行abcb在一个无限循环。

至于为什么该特定程序在此循环的第二次迭代时崩溃,这是各个命令的作用。请注意,迷宫的堆栈在底部包含一个隐含的无限数量的零:

#   Push stack depth.   [... 0]
(   Decrement.          [... -1]
/   Divide.             [... 0]
(   Decrement.          [... -1]
#   Push stack depth.   [... -1 1]
(   Decrement.          [... -1 0]
/   Divide.             Crashes with division-by-zero error.

3

Bash,11岁(边界线不竞争)

exec $0 1$@

该脚本自身递归执行,并附1加到每次迭代传递的args上。我认为这可算作TCO,因为exec重用了进程空间,但不会占用堆栈。这是边缘竞争,因为它花了大约10分钟时间才在我的计算机-YMMV上被杀死。


1
exec $0 1$@$@ 终止速度更快,但要长两个字符。
杰森

3

cmd,34个字节

for /l %i in (0,1,10) do color %i0

这将%i在0到10之间循环。(古老的)color命令将愉快地接受任何具有2个(十六进制)十进制数字的参数。使用参数100将失败,打印帮助消息并将其设置ERRORLEVEL为1。

循环证明至少运行了一次:您的外壳颜色将有所不同!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.