Найкоротший авторуйнівний цикл


61

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

Правила:

  1. Помилка повинна бути помилкою під час запуску, необробленим винятком або будь-чим, що змушує програму закінчуватися.
  2. Помилка повинна призвести до зупинки та виходу з програми, не викликаючи явно exit;(або еквівалент) в якийсь момент.
  3. Повідомлення типу Warning:, Notice:і т.д., які не викликають програму до кінця сам не є дійсними. Наприклад, у підрозділах PHP за нулем виробляється Warningповідомлення, але програма не зупинятиметься і продовжує працювати, це неправдива відповідь.
  4. Цикл повинен виконувати принаймні один повний цикл. Іншими словами, помилка може статися починаючи з другого циклу і далі. Це потрібно, щоб не викликати помилку при використанні неправильного синтаксису коду: код повинен бути синтаксично правильним.
  5. Цикл може бути навіть нескінченним (приклад for(;;);), якщо він дотримується вищезгаданих правил, але потрібно тривати не більше 2 хвилин, щоб закінчитися помилкою виконання.
  6. Рекурсія без оптимізації виклику хвоста недійсна ( 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

Табло:

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>

Дякуємо Мартіну Ендерові за фрагмент лідерів


Щоб було зрозуміло, рекурсію без ТСО можна використовувати до тих пір, поки помилка не має відношення до занадто великої рекурсії, правильно? (Наприклад, рекурсивна функція, яка помиляється під час другої рекурсії)
ETHproductions

@ETHproductions Це запропонував Денніс у чаті: "Можливо, буде важко вирішити, чи завершився повний цикл у цьому випадку [рекурсії]. Хвоста рекурсії начебто відповідає законопроекту, але тільки TCO фактично завершує цикл, якщо виконання виконано абонентно помилкою. [...] Я б сказав, що рекурсія без ТСО недійсна. "
Маріо

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

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

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

Відповіді:


33

MATL , 5 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

Пітон, 16 байт

Нецікавий підхід до поділу 0:

for x in 1,0:x/x

Перші ітераційні обчислення 1 / 1, які добре працюють. Друга ітерація намагається обчислити 0 / 0, в результаті чого ZeroDivisionErrorкидається.

17 байт (особистий фаворит)

i=1
while i:del i

Спочатку, i=1що є truthy, тому вводиться цикл.

При першому запуску циклу змінну 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засоби «рухатись праворуч».

У порожньому буфері (без вводу) це буде порушено під час першого проходу і не призведе до виводу. Якщо є вхід, він перерветься, як тільки ми перемістимо повідомлення останнього символу введення, і виведе весь вхід (зробивши це також програмою cat)


3
Зачекайте, lзначить «рухатися правильно»? Не "рухатись lефтом"?
Conor O'Brien

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 мод -1 , який виходить з ладу в Bash 4.2 та старіших версіях через відому помилку.


10

PHP, 22 21 20 18 байт

Це покладається на PHP, що дозволяє надати ім'я функції змінній та спробувати запустити її.

Це просто об'єднати назву piфункції двічі. Це вбиває PHP за допомогою a 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...().
    • π не є рядком, вбиваючи програму в цей момент за допомогою a Fatal Error.

Завдяки @Titus за те, що знайшов pi()функцію, врятував мені 1 байт!


Хороший, але я не думаю, що це дійсно. Він насправді не запускає цикл один раз. Ви збільшуєтесь $xдо abtзапуску корпусу циклу. Ви можете це виправити, зростаючи після циклу.
1616

Я подумав інший підхід
1616

@aross Duh, ти маєш рацію, це було не вірно. Приріст знаходиться в неправильному місці. Працює як слід зараз. Ви можете спробувати запустити for($x=abs;;++$x)echo$x,$x();тест. Це повинно показати abs0abt Fatal error[...]. Або подібне.
Ісмаїл Мігель

1
Ви можете використовувати piзамість abs. Це навіть не дає попередження, перш ніж воно кине фатальний.
Тит

@Titus Я повністю забув про цю функцію! Я знаю, що функція _визначена в деяких системах, але є ненадійною. Але дякую, що знайшли це!
Ісмаїл Мігель

10

GNU sed , 15 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))

Відповідь використовує вбудовану булеву змінну truthy, Tяка нескінченно зменшується у циклі, що повторюється. Функцією ls()називається кожна ітерація, в якій перераховані всі об'єкти в поточному середовищі. Однак перший аргумент nameвказує, з якого середовища, з якого потрібно перераховувати об'єкти. З R-документації ми знаходимо, що:

Аргумент імені може визначати середовище, з якого імена об'єктів взяті в одній з декількох форм: як ціле число (позиція у 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 мод 0, що виробляє поділ на нульову помилку на еталонному інтерпретаторі, і таким чином припиняє програму.

Є також більш нудна відповідь на 1 байт, хоча я не впевнений, чи вважається це дійсним.

"

Спробуйте в Інтернеті!

Ця "команда починає рядок, таким чином, кожен пробіл у решті рядка висувається на стек, поки лічильник програм не загортається і не стикається з "повторним закриттям рядка. Потім потрібно обернутись вдруге, щоб повторити процес, починаючи інший рядок і висуваючи ще 79 пробілів на стек. Врешті-решт це або втратить пам'ять (поведінка референтного перекладача), або створить переповнення стека.

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


Якщо ви вважаєте, що це рішення означає, що будь-який перекладач визначає мову (як багато тут), то ми можемо на даний момент припустити, що мова Befunge визначена цим перекладачем . І однією з "особливостей" цього інтерпретатора є те, що він виштовхує значення Невизначене на стек для кожного циклу ігрового поля при виконанні порожньої програми. Зважаючи на достатньо часу, з часом вичерпається пам'ять.

Наскільки швидко це відбудеться, буде залежати від швидкості роботи комп'ютера, наявної пам'яті та браузера, який використовується. На своїй машині я виявив, що Microsoft Edge працює найкраще, але навіть тоді це було "лише", використовуючи 500 Мб через дві хвилини. Лише приблизно через п'ятнадцять хвилин (з використанням декількох гігабайт) Edge вирішив вбити процес і оновити вкладку. Тож навряд чи вдасться це зробити за двохвилинний термін, але з правильними умовами, про які не обов'язково йтиметься.


8

ФАЙЗ, 8 байт

Мені дуже подобається ця мова.

1[$][.]#

Це натискає a 1, потім [$][.]#цикліть, коли $є true (дублює верхню частину стека) і ( .) виводить його. Цей інтерпретатор виходить з ладу після 1друку синглу (свідчення про те, що цикл працює хоча б один раз.) У цьому інтерпретаторі це здається помилкою. Наступна 9-байтна програма повинна працювати у всіх сумісних перекладачах:

1[$][..]#

Ви також повинні спробувати DUP, який в основному є набором FALSE. Це те, що я використовував для повернення.
Mama Fun Roll

@MamaFunRoll о так, я забув, що ти зробив ПОВЕРНЕННЯ! Я мушу спробувати це. : D
Conor O'Brien

@MamaFunRoll Я люблю DUP, я просто написав перекладача DUP, і я з ним граю.
МЛ

@ 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, ім'я, яке було використано для його виклику).
Райлі

Або реєстр аргументів все ще має значення, яке було там від головного виклику.
Райлі

@ Райлі Ах, остання теорія виглядає так, про що свідчить той факт, що кількість збільшується в міру додавання аргументів командного рядка. Дякуємо за розуміння!
Дверна ручка

Я не був впевнений, як ви називали це в моїй першій здогадці, але я повинен бути таким же, як перший аргумент функції, яка викликає 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)зазвичай даєте матрицю 2 на 2 з0+1i
Стюі Гріффін

Дякую! Це правда в 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 нулів. *

Отже, перший раз через цикл 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
Зазвичай ми оцінюємо збірку за розміром згенерованого байтового коду, а не для людей, що читаються.
Денніс

@ Асамблея, призначена Деннісом, є машинною мовою. але так, це можна стверджувати набагато коротше в машинній формі мови.
Ясен

Позбавтеся від f-label та 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 секунд.


Приємно! Ви можете зберегти 2 байти, використовуючи закінчення рядків Unix.
британіст

Ви можете використовувати% 0, яке є ім'ям файлу замість мітки та goto.
YourDeathIsComing

Я не був впевнений, чи порушив це правило хвостової рекурсії.
Something

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 Виконати? CreatePerIterationEn Environment (perIterationBindings).
2 Повторіть
3 Якщо це не [порожньо], то
4 Нехай testRef буде результатом оцінювання <test>.
5 Нехай testValue буде? GetValue (testRef).
6 Якщо параметр ToBoolean (testValue) невірний, поверніть NormalCompletion (V).
7 Нехай результат буде результатом оцінювання <statement>.
8 Якщо LoopContinues (результат, labelSet) помилковий, поверніть завершення (UpdateEmpty (результат, V)).
9 Якщо результат. [[Значення]] не порожній, нехай результат V. [[Значення]].
10 Виконати? CreatePerIterationEn Environment (perIterationBindings).
11 Якщо це не [порожньо], то
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

@Hurkyl Перша ітерація починається з ініціалізації, тому я думаю, що приріст повинен бути початком другої ітерації.
Хеді

4
Якщо ви прочитаєте специфікацію , то зможете побачити, що приріст операції є останньою частиною ітерації і як такий все ще належить до першої ітерації.
Нитка

3
@Hedi Я не бачу, наскільки це взагалі актуально. Приріст операції дуже чітко є частиною першого запуску циклу. Перефразовуючи, коли викликається операція збільшення, цикл не закінчив жодного повного запуску.
Ніт

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, який виходить з ладу для другої ітерації, коли код запускається з порожнім входом.

Якщо цикли, що використовують #(цикл до помилки), заборонені (я вважаю, що так), я думаю, що це найкоротший термін, який він може отримати.


3

Python 3, 29 байт

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

Дійсно просто. Під час другого дзвінка на x, я там не є, і Python скаржиться на це.


3

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

#(/

Спробуйте в Інтернеті!

Як і більшість двовимірних мов, у Лабіринті немає явних конструктивних циклів. Натомість будь-який код, який викладений таким чином, що він виконується кілька разів поспіль, є циклом для цих мов. Для випадку «Лабіринт» проста лінійна програма виконує функцію циклу, оскільки вказівник інструкції буде відскакувати по ній. Якщо програма 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не вдасться, надрукуючи довідкове повідомлення та встановивши ERRORLEVELзначення 1.

Доказ того, що цикл працює хоч раз: Колір вашої оболонки буде іншим!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.