Самый короткий авторазрушающий цикл


61

Ваша задача состоит в том, чтобы написать полную программу или функцию , которая не принимает никакого ввода и запускает любой тип цикла ( while, for, foreach, do, do-while, do-loop, goto, рекурсия и т.д.) , который закончится в возникновении ошибки, а это означает , что программа должна остановить себя бег и Выход.

Правила:

  1. Ошибка должна быть ошибкой во время выполнения, необработанным исключением или чем-то, что приводит к завершению самой программы.
  2. Ошибка должна вызывать остановку и выход из программы без явного exit;(или эквивалентного) вызова в какой-то момент.
  3. Сообщения типа Warning:, Notice:и т. Д., Которые не приводят к завершению программы, являются недействительными. Например, в PHP деление на ноль выдает Warningсообщение, но программа не остановится и все равно будет работать, это неверный ответ.
  4. Цикл должен выполняться как минимум один полный цикл. Другими словами, ошибка может произойти, начиная со второго цикла и далее. Это делается для того, чтобы избежать возникновения ошибки при использовании неправильного синтаксиса кода: код должен быть синтаксически правильным.
  5. Цикл может быть даже бесконечным (пример for(;;);), если он соблюдает вышеупомянутые правила, но должен занять не более 2 минут, чтобы завершиться ошибкой во время выполнения.
  6. Рекурсия без Tail Call Optimization недействительна ( 1 , 2 ).
  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

Leaderboard:

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>

Спасибо Мартину Эндеру за фрагмент таблицы лидеров


Просто чтобы быть понятным, рекурсию без TCO можно использовать, если ошибка не связана с слишком большой рекурсией, верно? (Например, рекурсивная функция, которая
выдает

@ETHproductions Было предложено Деннисом в чате: «Может быть трудно решить, завершился ли полный цикл в этом случае [рекурсии]. Хвостовая рекурсия вроде бы отвечает всем требованиям, но только TCO действительно завершает цикл, если выполнение прерывается ошибкой. [...] Я бы сказал, что рекурсия без TCO недействительна. "
Марио

Во for(a;b;c)d;, после чего постановка заканчивается первым циклом? Допустимо ли нарушать первую оценку cутверждения?
Хеди

1
@ Хеди Вот мое скромное мнение (не ОП): все записи должны завершить один полный цикл, то есть они должны войти во второй цикл; это означает, что по крайней мере один оператор выполняется во второй раз. Так как порядок выполнения в вашем примере a, b, d, c, b, d, c, ..., bэто начало цикла, и должен быть запущен по крайней мере , во второй раз.
ETHproductions

2
Я не хочу начинать какие-либо проблемы, но так как программа (в этом отношении функции) не должна принимать никаких входных данных, все рекурсивные решения, которые имеют параметр, являются недействительными, потому что параметр является входным.
BrainStone

Ответы:


33

MATL , 5 1 байт

Идея взята из CJam ответа @ MartinEnder

`

Попробуйте онлайн!

`    % 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 Хм автономная программа будет продолжать ждать ввода пользователя. Ввод является интерактивным, т.е. запрашивается по мере необходимости в автономной версии. Так что программа будет ждать бесконечно. Не уверен, что это имеет значение?
Луис Мендо

Не совсем уверен, как MATL работает внутри, но если вы выполните его в среде, неспособной запросить ввод (такой как серверная часть TIO), он не сможет получить какой-либо ввод. Кроме того, нажатие Ctrl-D или OS-зависимого эквивалента должно позволять отправлять пустой ввод.
Деннис

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 _():_()(новая строка) _(), потому что Python не оптимизирует хвостовую рекурсию. Однако это нарушает правило № 6.


Решение 17 байт также работает , если вы замените while iс , 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

Так что провалится условие № 5 на медленной машине с большим количеством оперативной памяти?
Безумный физик

@MadPhysicist Это правильно. Это внутренняя проблема с ограничениями по времени. Соответствие очень сильно зависит от того, на каком компьютере запущена программа.
Деннис

13

V , 2 байта

òl

Попробуйте онлайн!

Это идеальный вызов для V, потому что я уже делаю это все время! На самом деле, V даже не имеет никаких условных выражений, у него есть только функции, которые выходят из строя при ошибке. В этом случае òозначает «повторить навсегда» и lозначает «двигаться вправо».

В пустом буфере (без ввода) это прервется при первом проходе и не даст вывода. Если есть вход, он сломается , как только мы переходим выкладываю последний символ ввода и вывода всех входных данных (делая это также программу для кошек)


3
Подождите, lзначит «двигайся вправо»? Не "двигайся lнаверх"?
Конор О'Брайен,

1
@ ConorO'Брайен, да. На самом деле для этого есть несколько веских исторических причин .
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

Баш 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, позволяющий дать имя функции переменной и попытаться запустить ее.

Это просто объединяет имя 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

Я подумал о другом подходе
aross

@aross Дух, ты прав, это было не правильно. Приращение находится не в том месте. Работает как надо сейчас. Вы можете попробовать запустить for($x=abs;;++$x)echo$x,$x();тестирование. Это должно показать abs0abt Fatal error[...]. Или похожие.
Исмаэль Мигель

1
Вы могли бы использовать piвместо abs. Это даже не дает предупреждение, прежде чем он бросает роковой.
Тит

@ Titus Я полностью забыл об этой функции! Я знаю, что функция _определена в некоторых системах, но она ненадежна. Но спасибо, что нашли это!
Исмаэль Мигель

10

GNU sed , 15 13 5 байт

-2 благодаря сешумаре
-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 echo -n | sed 's:a\?:&a:g'и не получил выходной. Это было бы так же, как то, sed 's::a:'что не соответствует ничему.
Райли

С echo -nsed ничего не передается в sed, но sed не может начаться без ввода дизайна. Проверьте эту мета-ссылку, чтобы увидеть, что echo|sedэто приемлемый способ запуска sed для вызовов, вызывающих правило отсутствия ввода.
Сешумара

@seshoumara Я думал, что это все равно даст пустую строку. Это, кажется, работает тогда. Спасибо!
Райли

9

R, 22 25 22 20 18 байт

Редактировать: Спасибо @Mego за указание, что R не поддерживает оптимизацию хвостового вызова.

Edit4: нашел еще более короткое решение, простое, но довольно сложное.

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

В ответе используется встроенная логическая переменная truey, 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)

!%!

Попробуйте онлайн!

На первой итерации цикла стек пуст, что является эквивалентом всех нулей. Операция !(not), таким образом, преобразует верхнюю часть стека в 1, а %операция (modulo) вычисляет 0 mod 1, оставляя 0. Следующая !операция преобразует это 0 в 1 до того, как счетчик программ обернется и снова начнет цикл.

На второй итерации первые !операции преобразуют 1, который сейчас находится на вершине стека, в 0. Затем %операция вычисляет 0 mod 0, что приводит к ошибке деления на ноль в эталонном интерпретаторе и, таким образом, завершает программу.

Есть также более скучный 1-байтовый ответ, хотя я не уверен, что это считается действительным.

"

Попробуйте онлайн!

Эта "команда запускает строку, поэтому каждый пробел в оставшейся части строки помещается в стек до тех пор, пока счетчик программы не перевернется и не встретит "снова закрывающую строку. Затем нужно будет обернуть его во второй раз, чтобы повторить процесс, начинающий другую строку и помещающий в стек еще 79 пробелов. В конечном итоге это либо исчерпает память (поведение эталонного интерпретатора), либо приведет к переполнению стека.

Теперь, если вы действительно хотите придерживаться правил, технически есть решение с нулевым байтом.


Если вы принимаете это постановление для обозначения того, что любой интерпретатор определяет язык (как многие здесь делают), то мы можем предположить, что язык Befunge определен этим интерпретатором . И одна из «особенностей» этого интерпретатора заключается в том, что он помещает неопределенное значение в стек для каждого цикла игрового поля при выполнении пустой программы. Если у вас будет достаточно времени, в конце концов не хватит памяти.

Как быстро это произойдет, будет зависеть от скорости компьютера, доступной памяти и используемого браузера. На моей машине я обнаружил, что Microsoft Edge работает лучше всего, но даже тогда он «только» использовал 500 МБ через две минуты. Только после пятнадцатиминутной отметки (с использованием нескольких гигабайт) Эдж решил убить процесс и обновить вкладку. Так что вряд ли удастся сделать это в течение двухминутного срока, но с правильными условиями, которые не обязательно могут быть исключены.


8

ЛОЖЬ, 8 байтов

Мне очень нравится этот язык.

1[$][.]#

Это нажимает на a 1, затем [$][.]#зацикливается, пока $true (дублирует вершину стека) и ( .) выводит его. Этот интерпретатор аварийно завершает работу после того, как сингл 1напечатан (свидетельство того, что цикл запущен хотя бы один раз). Кажется, это ошибка в этом интерпретаторе. Следующая 9-байтовая программа должна работать во всех совместимых интерпретаторах:

1[$][..]#

Вам также следует попробовать DUP, который в основном является надмножеством FALSE. Это то, что я использовал, чтобы сделать возврат.
Мама 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--;);}

Обрабатывается ли эта функция как основная? Если это так, первый аргумент - это длина списка аргументов (1, имя, которое использовалось для его вызова).
Райли

Или, регистр аргумента все еще имеет значение, которое было там от основного вызова.
Райли

@Riley Ааа, последняя теория, кажется, имеет место, о чем свидетельствует тот факт, что число увеличивается с добавлением аргументов командной строки. Спасибо за понимание!
Дверная ручка

Я не был уверен, как вы вызывали это в моем первом предположении, но я должен быть таким же, как первый аргумент функции, которая вызывает f.
Райли

Да, tio
Райли

6

MATLAB, 18 байт

Это можно запустить как скрипт:

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

Первая итерация в порядке, так как j(1)это просто 1. Вторая итерация завершается с ошибкой выхода за пределы массива, которая j(2)превышает размеры j, равные массиву 1x1.

Это также можно запустить как скрипт, но он работает только при первом запуске. Тем не менее, это довольно смешное злоупотребление предопределенными константами MATLAB, и я решил включить его. Это также 18 байтов.

while i/i;i={};end

При запуске в рабочей области, в которой переменная iеще не определена, предполагается, iчто это мнимая единица, поэтому i/i = 1. В первом цикле присваивание i={}создает пустой массив ячеек с именем i. На второй итерации цикл завершается с «неопределенным оператором» / для входных аргументов типа «ячейка».


Оба из них потрясающие! Вы, наверное, знаете это, но j(2)обычно 0+1i
Стьюи Гриффин,

Спасибо! Это верно в Октаве, но не в 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 нулей. *

В первый раз через цикл, следовательно, iесть 0и aесть массив. a(i)дает нулевой элемент массива (который есть 0). Все хорошо. Мы установили iв 11и петли. Но теперь 11это недопустимый индекс для массива a, и программа останавливается с Subscript out of range.

19-байтовая версия, которая лучше показывает, что происходит:

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

Это напечатает 0одиннадцать раз перед ошибкой.


* Концептуально это массив из 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=-1uint.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

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

Ок вау Не знал о сокращении '$'!
MrPaulch

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 и ошибки.


Вы можете сэкономить 4 байта, переключившись на синтаксис Intel :)
mriklojn

6
Мы обычно оцениваем сборку по размеру сгенерированного байтового кода, а не по понятным для человека инструкциям.
Деннис

@ Денис в ассемблере - это машинный язык. но да, это может быть заявлено гораздо короче в форме машинного языка.
Jasen

Избавьтесь от F-метки и мов. Поменяйте местами dec и div, и вы сможете избавиться от еще большего.
Яснее

4

CJam, 4 байта

P`:~

P`генерирует строку 3.141592653589793. :~оценивает каждого персонажа. 3является допустимым кодом в CJam, который просто возвращает 3. На следующей итерации .вызывает ошибку, потому что для этого требуется цифра или оператор после нее.




4

Пакет, 22 20 байтов

:a
set i=%i%1
goto a

объяснение

Это бесконечный цикл, который добавляет 1к изначально пустой строке. В конечном итоге это пройдет максимальную длину строки 8192 и произойдет сбой. На моей машине это занимает около 30 секунд.


Приятно! Вы можете сохранить 2 байта, используя окончания строк Unix.
Бриантист

Вы можете использовать% 0, который является именем файла вместо метки и перехода.
YourDeathIsComing

Я не был уверен, нарушило ли это правило рекурсии хвоста.
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>, <increment>, <statement>, «», labelSet).

Существует три формы, поэтому я выбрал самую короткую, здесь нет разницы:
- Как бы то ни было, <init>это не часть первой итерации.
- Что актуально в ForBodyEvaluation.

Детали ForBodyEvaluation ( <test>, <increment>, <statement>, «», labelSet)

0 Пусть V не определено.
1 Выполнить? CreatePerIterationEnvironment (perIterationBindings).
2 Повторите
3 Если не [пусто], то
4 Позвольте testRef быть результатом оценки <test>.
5 Пусть testValue будет? ПолучитьЗначение (testRef).
6 Если ToBoolean (testValue) имеет значение false, вернуть NormalCompletion (V).
7 Пусть результат будет результатом оценки <statement>.
8 Если LoopContinues (result, labelSet) имеет значение false, вернуть Completion (UpdateEmpty (result, V)).
9 Если результат. [[Значение]] не пуст, пусть V будет результатом. [[Значение]].
10 Выполнить? CreatePerIterationEnvironment (perIterationBindings).
11 Если не [пусто], то
12 Пусть incRef будет результатом вычисления <increment>.
13 Выполнить? ПолучитьЗначение (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

@Hurkyl Первая итерация начинается с инициализации, поэтому я думаю, что приращение должно быть началом второй итерации.
Хеди

4
Если вы прочитаете спецификацию , вы увидите, что операция приращения является последней частью итерации и, как таковая, все еще принадлежит первой итерации.
Nit

3
@ Хеди, я не понимаю, насколько это актуально. Операция приращения очень четко является частью первого цикла цикла. Перефразируя, когда вызывается операция приращения, цикл не завершил ни одного полного прогона.
Нить

4

INTERCAL , 12 байт

(1)DO(1)NEXT

Попробуйте онлайн!

NEXTявляется основной командой управления потоком INTERCAL-72. (Позже были представлены ревизии COME FROM, которые стали более известными, но их не было в оригинальной версии языка; и во всех законченных реализациях INTERCAL мне известна поддержка NEXTобратной совместимости, причем все, кроме одной, поддерживают ее по умолчанию. Я не чувствую необходимости называть INTERCAL-72 конкретно в названии.)

При использовании NEXTдля формирования цикла, вы должны использовать RESUMEили FORGETдля того, чтобы освободить пространство, которое он использует, чтобы запомнить, где была программа; 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 есть табуляции с кратными В-четвертых, нарушая допущения, которые большинство старых программ делают относительно вкладок, поэтому сообщение об ошибке здесь немного искажено.)


Ошибка действительно говорит CORRECT SOURCE AND RESUBNIT? Как в опечатке в исходном C-INTERCAL сообщении об ошибке?
Андракис

1
@Andrakis: Да, это так. Эта опечатка тщательно сохранялась годами.

3

Pyth, 3 байта

W1w

Попробуйте онлайн.

W1просто while 1:в Python. Тело цикла печатает строку, считанную из STDIN, которая вылетает во второй итерации, когда код запускается с пустым вводом.

Если использование циклов #(loop-till-error) запрещено (я так полагаю), я думаю, что это самый короткий путь, который он может получить.


3

Python 3, 29 байт

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

Действительно просто. При втором вызове x меня там нет, и Python жалуется на это.


3

Лабиринт , 3 байта

#(/

Попробуйте онлайн!

Как и большинство 2D-языков, Labyrinth не имеет явных циклических конструкций. Вместо этого любой код, который выложен так, что он выполняется несколько раз подряд, является циклом в этих языках. Для случая Лабиринта простая линейная программа действует как цикл, потому что указатель инструкции будет подпрыгивать туда-сюда. Если программа abc(для некоторых команд a, bа c), то фактическое выполнение будет 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

Баш, 11 (граница неконкурентная)

exec $0 1$@

Этот скрипт рекурсивно выполняет сам себя, добавляя 1аргументы, передаваемые на каждой итерации. Я думаю, что это считается 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он потерпит неудачу, распечатав сообщение справки и установив ERRORLEVEL1.

Доказательство того, что цикл запущен хотя бы один раз: цвет вашей оболочки будет другим!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.