Najkrótsza pętla autodestrukcyjna

61

Twoim zadaniem jest napisanie pełny program lub funkcję, która pobiera żadnych wejściowe i uruchamia dowolny rodzaj pętli ( while, for, foreach, do, do-while, do-loop, goto, rekursji, etc), które zakończą się w powodując błąd, co oznacza, że program musi zatrzymać się z systemem i wyjście.

Zasady:

  1. Błąd musi być błędem w czasie wykonywania, nieobsługiwanym wyjątkiem lub czymkolwiek, co powoduje, że program sam się kończy.
  2. Błąd musi powodować zatrzymanie i wyjście z programu bez wywoływania jawnego exit;(lub równoważnego) w pewnym momencie.
  3. Komunikaty takie jak Warning:, Notice:itp, które nie powodują program do końca sama nie obowiązują. Na przykład w działach PHP przez zero generuje Warningkomunikat, ale program się nie zatrzyma i nadal będzie działał, to nie jest poprawna odpowiedź.
  4. Pętla musi przebiegać co najmniej jeden pełny cykl. Innymi słowy, błąd może się zdarzyć począwszy od drugiego cyklu i dalej. Ma to na celu uniknięcie spowodowania błędu przy użyciu niepoprawnej składni kodu: kod musi być poprawny pod względem składniowym.
  5. Pętla może być nawet nieskończona (przykład for(;;);), jeśli przestrzega powyższych zasad, ale nie może zająć więcej niż 2 minuty, aby zakończyć się błędem w czasie wykonywania.
  6. Rekurencja bez optymalizacji wezwania ogona jest nieprawidłowa ( 1 , 2 ).
  7. To jest więc wygrywa najkrótszy kod.
  8. Standardowe luki są zabronione.

Przykład C # ( test online ):

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

Tabela liderów:

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>

Podziękowania dla Martina Endera za fragment tabeli wyników

Mario
źródło
Żeby było jasne, rekurencja bez całkowitego kosztu posiadania może być używana, o ile błąd nie ma związku z zbyt dużą rekurencją, prawda? (Na przykład funkcja rekurencyjna, która powoduje błąd przy drugiej rekurencji)
ETHproductions
@ETHproductions Dennis zasugerował na czacie: „Może być trudno zdecydować, czy pełny cykl został zakończony w tym przypadku [rekursji]. Rekurencja ogona w pewnym sensie pasuje do rachunku, ale tylko TCO faktycznie kończy cykl, jeśli wykonanie zostanie przerwane przez błąd. [...] Powiedziałbym, że rekurencja bez całkowitego kosztu posiadania jest nieprawidłowa. ”
Mario,
W for(a;b;c)d;, po którym stwierdzeniu kończy się pierwszy cykl? Czy ważne jest złamanie przy pierwszej ocenie coświadczenia?
Hedi
1
@Hedi Oto moja skromna opinia (nie OP): Wszystkie wpisy muszą ukończyć jeden pełny cykl, co oznacza, że ​​muszą przejść drugi cykl; oznacza to, że uruchamiana jest co najmniej jedna instrukcja po raz drugi . Ponieważ kolejność wykonywania w twoim przykładzie jest a, b, d, c, b, d, c, ..., bjest początkiem cyklu i musi zostać uruchomiona co najmniej drugi raz.
ETHprodukcje
2
Nie chcę zaczynać żadnych problemów, ale ponieważ program (funkcji w tym przypadku) nie powinien pobierać żadnych danych wejściowych, wszystkie rozwiązania rekurencyjne, które mają parametr, są nieprawidłowe, ponieważ parametr jest wprowadzany.
BrainStone

Odpowiedzi:

33

MATL , 5 1 bajt

Pomysł zaczerpnięty z odpowiedzi CJam @ MartinEnder

`

Wypróbuj online!

`    % 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

Stara wersja

2:t"x

Wypróbuj online!

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
Luis Mendo
źródło
3
Działa również offline. Brak danych wejściowych oznacza, że ​​możesz założyć puste dane wejściowe.
Dennis,
@Dennis Hm program offline będzie czekał na dane wejściowe użytkownika. Wejście jest interaktywne, tzn. Wymagane w wersji offline. Tak więc program będzie czekać w nieskończoność. Nie jesteś pewien, czy to się liczy?
Luis Mendo,
Nie do końca wiem, jak działa MATL, ale jeśli wykonasz go w środowisku niezdolnym do żądania danych wejściowych (takim jak backend TIO), nie będzie w stanie uzyskać żadnych danych wejściowych. Również naciśnięcie Ctrl-D lub odpowiednika zależnego od systemu operacyjnego powinno pozwolić na wysyłanie pustych danych wejściowych.
Dennis,
35

Python, 16 bajtów

Nieciekawe podejście z podziałem 0:

for x in 1,0:x/x

Pierwsza iteracja jest obliczana 1 / 1, co działa dobrze. Druga iteracja próbuje obliczyć 0 / 0, powodując ZeroDivisionErrorwyrzucenie.

17 bajtów (osobisty ulubiony)

i=1
while i:del i

Początkowo, i=1co jest prawdą, więc pętla jest wprowadzana.

Przy pierwszym uruchomieniu pętli zmienna ijest usuwana.

Oznacza to, że po raz drugi inie jest już zmienną i dlatego jego ocena kończy się niepowodzeniemNameError: name 'i' is not defined.


Innym 15-bajtowym rozwiązaniem byłoby def _():_()(nowa linia) _(), ponieważ Python nie optymalizuje rekurencji ogona. To jednak narusza zasadę nr 6.

FlipTack
źródło
Rozwiązanie działa również 17 bajtów, jeśli zastąpi while isię while 1, ponieważ próbuje usunąć iponownie;
user6245072,
2
@ user6245072 tak, oba fragmenty można trywialnie zmodyfikować dla wielu działających rozwiązań
FlipTack,
Można użyć delsztuczki z wbudowanym ogolił trochę więcej: while 1:del id.
DSM
@DSM: del idnie działa. W ten sposób nie można usunąć wbudowanych plików .
user2357112
18

Galaretka , 3 2 bajty

Ṿß

Zabija się przez brak pamięci. Lokalnie robi to po ~ 100 sekundach.

Wypróbuj online! (akt zgonu w szufladzie debugowania )

Jak to działa

Ṿß  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.

Pierwsze kilka iteracji daje:

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

Potem robi się naprawdę brzydko, naprawdę szybko.

Dennis
źródło
Jakie są limity pamięci galaretki?
tuskiomi
Galaretka nie ma wyraźnego limitu pamięci, więc cokolwiek Python może rozwiązać. Zużycie pamięci podwaja się jednak z każdą iteracją, więc powinno to dość szybko wyczerpać całą dostępną pamięć.
Dennis
28
Co dwa lata będziemy mogli wykonać kolejną iterację
tuskiomi
Czy więc nie powiedzie się warunek nr 5 na powolnym komputerze z dużą ilością pamięci RAM?
Szalony fizyk,
@MadPhysicist To prawda. Jest to jednak nieodłączny problem związany z ograniczeniami czasowymi. Zgodność zależy bardzo od tego, na której maszynie jest uruchomiony program.
Dennis,
13

V , 2 bajty

òl

Wypróbuj online!

To idealne wyzwanie dla V, ponieważ już to robię przez cały czas! W rzeczywistości V nie ma nawet żadnych warunków, ma tylko funkcje, które psują się po błędzie. W tym przypadku òoznacza „powtarzaj na zawsze” i l„ruszaj się w prawo”.

W pustym buforze (bez danych wejściowych) spowoduje to przerwanie pierwszego przejścia i nie spowoduje wyjścia. Jeśli jest wejście, to pęknie, gdy przejdziemy po ostatnim znaku wejścia i wyprowadzimy wszystkie dane wejściowe (co czyni go również programem cat)

DJMcMayhem
źródło
3
Czekaj, lznaczy „ruszaj się w prawo”? Nie „przenieść left”?
Conor O'Brien
1
@ ConorO'Brien tak. Jest tak naprawdę z kilku dobrych historycznych powodów .
DJMcMayhem
3
Wyzwanie wymaga odpowiedzi na awarię przy drugiej lub późniejszej iteracji, a nie przy pierwszej iteracji.
Martin Ender,
11

JavaScript (ES6), 13 bajtów

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

Jest to funkcja rekurencyjna, która raz działa poprawnie, a następnie rzuca ReferenceError: a is not defined i wychodzi.

Oto 15-bajtowa wersja spoza ES6:

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

Działa to dobrze raz, a następnie rzuca TypeError: i is undefinedi wychodzi.

ETHprodukcje
źródło
10

Bash 4.2, 22 bajty

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

Nie działa w TIO, ponieważ ma Bash 4.3, a błąd, na którym polegam, został w końcu naprawiony.

Weryfikacja

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

Występuje awaria, gdy program próbuje obliczyć 2 63 mod -1 , co ulega awarii w Bash 4.2 i starszych wersjach z powodu znanego błędu.

Dennis
źródło
10

PHP, 22 21 20 18 bajtów

Zależy to od PHP, który pozwala nadać nazwę funkcji zmiennej i spróbować ją uruchomić.

To po prostu konkatenuje nazwę pifunkcji dwukrotnie. To zabija PHP za pomocą Fatal Error: Uncaught Error: Call to undefined function pipi() in [...][...].

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

Działa to podobnie do mojej starej odpowiedzi.


Stara odpowiedź, 20 bajtów

PHP pozwala inkrementować znaki za pomocą operatora inkrementacji. Działa tylko w a-zzakresie, ale wystarczy.

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

Uważam, że spełnia to wszystkie wymagane punkty, a pętla działa raz.

Możesz sprawdzić, czy ponieważ otrzymasz błąd Fatal error: Function name must be a string.


Jak to działa, krok po kroku:

  • Przypisz pido $x.
    Ponieważ pijest używany jako stała, PHP sprawdzi, czy istnieje.
    Ponieważ tak nie jest, PHP wyświetla ostrzeżenieUse of undefined constant pi - assumed 'pi' (Zasadniczo: ponieważ stała nie istnieje, zakłada się, że jest to ciąg znaków)
  • Pętla za pierwszym razem
    • Uruchom funkcję $x().
      Ponieważ $xma wartość pi, uruchomi funkcję pi().
  • Zapisz wartość w $x.
    $xteraz ma π zamiastpi
  • Pętla po raz drugi
    • Uruchom funkcję $x().
      Ponieważ $xma π, uruchomi funkcję 3.14159...().
    • π nie jest łańcuchem, zabijając program w tym momencie za pomocą Fatal Error.

Dzięki @Titus za znalezienie pi()funkcji, oszczędzając mi 1 bajt!

Ismael Miguel
źródło
Fajny, ale nie sądzę, żeby był ważny. Tak naprawdę nie uruchamia raz pętli. Ci zwiększyć $xsię abtzanim skończy ciało pętli. Możesz to naprawić, zwiększając wartość po pętli.
aross
Pomyślałem o innym podejściu
aross
@aross Duh, masz rację, to nie było ważne. Przyrost znajduje się w niewłaściwym miejscu. Działa jak teraz. Możesz spróbować uruchomić, for($x=abs;;++$x)echo$x,$x();aby przetestować. Powinien pokazać abs0abt Fatal error[...]. Lub podobne.
Ismael Miguel
1
Możesz użyć pizamiast abs. To nawet nie daje ostrzeżenia, zanim doprowadzi to do zgonu.
Tytus
@Titus Całkowicie zapomniałem o tej funkcji! Wiem, że funkcja _jest zdefiniowana w niektórych systemach, ale jest zawodna. Ale dziękuję za znalezienie tego!
Ismael Miguel
10

GNU sed , 15 13 5 bajtów

-2 Dzięki seshoumara
-8 Dzięki Zeppelin

H;G;D
  1. Dołącza znak nowej linii i przestrzeń wstrzymania do obszaru wzoru.
  2. Dołącza nową linię i przestrzeń wzoru do przestrzeni wstrzymania.
  3. Usuwa do pierwszej nowej linii i zaczyna od nowa.

Szybko kończy się pamięć:

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

real    0m1.580s
user    0m0.545s
sys     0m1.012s
Riley
źródło
Cześć, a może s:a\?:&a:g? Jest to 1 bajt mniej i podwaja rozmiar wzoru na iterację.
seshoumara
@seshoumara Nie sądzę, żeby to pasowało do niczego, gdy przestrzeń wzorców jest pusta, więc nigdy nie dokona pierwszego zastąpienia.
Riley
@seshoumara echo -n | sed 's:a\?:&a:g'i nie otrzymałem danych wyjściowych. Byłoby to to samo, sed 's::a:'co nie pasowałoby do niczego.
Riley
Z echo -nabsolutnie nic nie przechodzi do sed, ale sed nie może zacząć bez wkładu z założenia. Sprawdź ten meta link, aby zobaczyć, że echo|sedjest to akceptowany sposób na rozpoczęcie sedna dla wyzwań wywołujących regułę braku danych wejściowych.
seshoumara
@seshoumara Myślałem, że nadal da mu pusty ciąg. To wydaje się wtedy działać. Dzięki!
Riley
9

R, 22 25 22 20 18 bajtów

Edycja: Podziękowania dla @Mego za zwrócenie uwagi, że R nie obsługuje optymalizacji wezwania ogona.

Edit4: Znaleziono jeszcze krótsze rozwiązanie, które jest proste, ale dość skomplikowane.

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

Odpowiedź korzysta z wbudowanej zmiennej boolean truey, Tktóra jest zmniejszana w nieskończoność w powtarzającej się pętli. Funkcja ls()nazywana jest każdą iteracją, która wyświetla listę wszystkich obiektów w bieżącym środowisku. Jednak pierwszy argument nameokreśla, z którego środowiska mają być wyświetlane obiekty. Z dokumentacji R wynika, że:

Argument name może określać środowisko, z którego pobierane są nazwy obiektów w jednej z kilku form: jako liczba całkowita (pozycja na searchliście); jako nazwa ciągu znaków elementu na liście wyszukiwania; lub jawnie environment(w tym za pomocą sys.framedostępu do aktualnie aktywnych wywołań funkcji).

Zasadniczo oznacza to, że w pierwszej iteracji uruchamiamy, ls(-1)która zwróci character(0)(standard przy próbie uzyskania dostępu do nieistniejącego everything-except-the-firstelementu dowolnego obiektu typu znakowego). Podczas drugiej iteracji Tzmniejsza się o dwa, a następnie wywołujemy, ls(-3)co z kolei zwraca błąd:

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

Jest tak, ponieważ próbujemy wyświetlić everything-except-the-thirdelement, ale środowisko lokalne zawiera tylko zmienną Tw tym momencie (jako takie, zwróciłoby ls()listę długości 1w tej iteracji) i zwrócony został błąd.

Billywob
źródło
1
Nie brzmi to tak, jakby rekurencja była wykonywana z optymalizacją wywołania ogona, jeśli istnieje limit rekurencji.
Mego
@Mego Po krótkich poszukiwaniach dowiedziałem się, że R rzeczywiście nie obsługuje optymalizacji połączeń ogonowych, więc ta odpowiedź jest nieprawidłowa (nigdy wcześniej nie słyszałem o tej koncepcji). Za chwilę zmieni się na prawidłową odpowiedź.
Billywob,
9

Befunge-93, 3 bajty (ewentualnie 1 lub 0)

!%!

Wypróbuj online!

Podczas pierwszej iteracji pętli stos jest pusty, co odpowiada ekwiwalentowi zer. Operacja !(nie) konwertuje zatem stos na górę na 1, a %operacja (modulo) oblicza 0 mod 1, pozostawiając 0. Następny! operacja konwertuje to 0 na 1, zanim licznik programu zawinie się i ponownie rozpocznie pętlę.

W drugiej iteracji pierwsze !operacje konwertują 1, który jest teraz na górze stosu, na 0. The% Operacja następnie oblicza 0 mod 0, co powoduje błąd dzielenia przez zero na interpreter referencyjny, a tym samym kończy działanie programu.

Jest też nudniejsza odpowiedź 1-bajtowa, chociaż nie jestem pewien, czy jest to poprawne.

"

Wypróbuj online!

To "polecenie rozpoczyna ciąg, dlatego każde miejsce w pozostałej części wiersza jest wypychane na stos, dopóki licznik programu nie zawinie się i nie napotka "ponownie zamknięcia łańcucha. Będzie musiał wtedy zawinąć się po raz drugi, aby powtórzyć proces rozpoczynając kolejny ciąg i wypychając kolejne 79 spacji na stos. W końcu zabraknie pamięci (zachowanie interpretera odniesienia) lub spowoduje przepełnienie stosu.

Teraz, jeśli chcesz naprawdę przeforsować reguły, istnieje również technicznie zerowe rozwiązanie.


Jeśli przyjmiesz to orzeczenie w ten sposób, że dowolny tłumacz ustnie określa język (jak wielu tutaj), wówczas możemy założyć, że język Befunge jest zdefiniowany przez tego tłumacza . Jedną z „cech” tego interpretera jest to, że wypycha on niezdefiniowaną wartość na stos dla każdej pętli pola gry podczas wykonywania pustego programu. Przy wystarczającej ilości czasu zabraknie mu pamięci.

To, jak szybko to się stanie, będzie zależeć od szybkości komputera, dostępnej pamięci i używanej przeglądarki. Na moim komputerze stwierdziłem, że Microsoft Edge działał najlepiej, ale nawet wtedy „tylko” używał 500 MB po dwóch minutach. Dopiero około piętnastu minut (przy użyciu kilku gigabajtów) Edge zdecydował się zabić proces i odświeżyć kartę. Jest więc mało prawdopodobne, aby udało się to zrobić w terminie dwóch minut, ale przy odpowiednich warunkach, które niekoniecznie byłyby wykluczone.

James Holderness
źródło
8

FAŁSZ, 8 bajtów

Naprawdę podoba mi się ten język.

1[$][.]#

Powoduje to wypchnięcie a 1, a następnie [$][.]#zapętla się, gdy $jest prawdą (duplikat góry stosu) i ( .) wyprowadza go. Ten interpreter ulega awarii po 1wydrukowaniu singla (dowód na to, że pętla działa co najmniej raz). Wygląda na to, że w tym tłumaczu jest błąd. Poniższy 9-bajtowy program powinien działać we wszystkich zgodnych tłumaczach:

1[$][..]#
Conor O'Brien
źródło
Powinieneś także wypróbować DUP, który jest w zasadzie nadzbiorem FAŁSZ. Właśnie tego użyłem do ZWROTU.
Mama Fun Roll
@MamaFunRoll o tak, zapomniałem, że dokonałeś POWRÓT! Muszę spróbować tego. : D
Conor O'Brien
@MamaFunRoll Uwielbiam DUP, właśnie napisałem tłumacza DUP i bawię się nim.
ML
@ ConnorO'Brien: Powiedziałbym, że twoje pierwsze rozwiązanie powinno spowodować awarię każdego tłumacza. Właśnie uruchomiłem debugowanie przy użyciu własnego interpretera i oczywiste jest, że pierwszy .opróżnia stos danych, podczas gdy w drugiej pętli $próbuje zduplikować górny element pustego stosu, co powinno prowadzić do błędu (cóż, mój interpreter robi ). Druga wersja nie powinna być poprawna, ponieważ nawet nie kończy pierwszej pętli, ponieważ już próbuje przedwcześnie uzyskać dostęp do pustego stosu.
ML
Dla twojego drugiego przykładu, oto kolorowy zrzut debugowania mojego interpretera DUP. jest to oczywiste, gdy zobaczysz, jak działa stos danych (ds) i stos powrotny (rs), przy czym ten ostatni nie jest przezroczysty w FAŁSZ.
ML
8

C, 21 bajtów

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

Tutaj na ipewno zaczniesz jako 0.

Można potwierdzić, że działa to raz tak:

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

Co na moim komputerze powoduje:

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

Najkrótsze rekurencyjne rozwiązanie, jakie mogę znaleźć, to 22 bajty :

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

gcceliminuje tylko wywołanie ogonowe na poziomie -O2wyższym lub wyższym, w którym to momencie musimy wywołać funkcję taką, putsaby zapobiec optymalizacji całej rzeczy. Potwierdzenie, że to działa:

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

Oto pełny program, który zakłada, że ​​jest wywoływany bez argumentów wiersza poleceń, o wielkości 22 bajtów :

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

co jest równoważne funkcji o tej samej długości:

f(i){for(i=1;1/i--;);}
Klamka
źródło
Czy taka funkcja jest traktowana jak główna? Jeśli tak, pierwszym argumentem jest długość listy argumentów (która jest 1, nazwa, która została użyta do jej wywołania).
Riley
Lub rejestr argumentów nadal ma wartość, która istniała od wywołania głównego.
Riley
@ Riley Ahh, ta druga teoria wydaje się być przypadkiem, o czym świadczy fakt, że liczba ta rośnie wraz z dodawaniem argumentów wiersza poleceń. Dzięki za wgląd!
Klamka
Nie byłam pewna, jak wywołujesz to przy pierwszym podejściu, ale powinienem być taki sam jak pierwszy argument funkcji wywołującej f.
Riley
Tak, tio
Riley
6

MATLAB, 18 bajtów

Można to uruchomić jako skrypt:

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

Pierwsza iteracja jest w porządku, ponieważ j(1)jest słuszna1 . Druga iteracja ulega awarii z błędem tablicy poza zakresem, ponieważ j(2)przekracza ona wymiary j, czyli tablicę 1x1.

Można to również uruchomić jako skrypt, ale działa tylko przy pierwszym uruchomieniu. Mimo to jest wystarczająco zabawne nadużywanie predefiniowanych stałych MATLAB-a, że ​​myślałem, że je uwzględnię. Ma również 18 bajtów.

while i/i;i={};end

Przy uruchomieniu w obszarze roboczym, w którym zmienna inie została jeszcze zdefiniowana, zakłada się, że ijest to jednostka urojona, więc i/i = 1. W pierwszej pętli przypisanie i={}tworzy pustą tablicę komórek o nazwie i. W drugiej iteracji pętla kończy się na „Niezdefiniowany operator” / „dla argumentów wejściowych typu„ komórka ”.

MattWH
źródło
Oba są niesamowite! Prawdopodobnie wiesz o tym, ale j(2)normalnie dałbyś macierz 2 na 2 z0+1i
Stewie Griffin
Dzięki! Tak jest w Octave, ale chyba nie w
MATLABie
6

Perl 6 , 13 bajtów

loop {5[$++]}

Indeksuje literał całkowity w nieskończonej pętli.
Opiera się na fakcie, że w przypadku wartości skalarnych można używać składni indeksowania tablicy z indeksem 0(zwracając samą wartość), ale generuje Index out of rangebłąd dla dowolnego innego indeksu.

smls
źródło
6

QBasic, 17 bajtów

Ten kod jest bardzo dziwny.

DO
i=11+a(i)
LOOP

Jak to działa

W QBasic zmienne są wstępnie inicjowane. Zmienna regularna bez żadnego przyrostka typu, jak itutaj, jest wstępnie inicjowana na zero.

Z wyjątkiem sytuacji, gdy spróbujesz zapisać się do tej zmiennej jak tablica ... w takim przypadku jest to tablica 11 zer. *

Dlatego po raz pierwszy w pętli ijest 0i ajest tablicą. a(i)daje zerowy element tablicy (który jest 0). Wszystko dobrze i dobrze. Ustawiamy ina 11i zapętlamy. Ale teraz 11nie jest prawidłowym indeksem dla tablicy a, a program zatrzymuje się na Subscript out of range.

19-bajtowa wersja, która lepiej pokazuje, co się dzieje:

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

Zostanie wydrukowany 0jedenaście razy, zanim popełni błąd.


* Koncepcyjnie jest to 10-elementowa tablica. Większość rzeczy w QBasic ma indeks 1, ale tablice nie są, prawdopodobnie z powodów implementacyjnych. Aby wszystko działało zgodnie z oczekiwaniami dla programistów, QBasic dodaje dodatkowy wpis, dzięki czemu można używać indeksów od 1 do 10. Indeks 0 jest jednak nadal doskonale dostępny. Domyśl.

DLosc
źródło
QBasic i tablice, gdzie kończy się zabawa!
steenbergh
Ponieważ błąd nie musi występować w drugiej pętli, nie możesz tego zrobić i=1+a(i)?
Quelklef
@Quelklef Nie, musiałbyś to zrobić i=i+1+a(i). W przeciwnym razie indeks nigdy nie wzrośnie powyżej 1, co nie jest błędem.
DLosc
@DLosc Och, masz rację.
Quelklef
5

Haskell, 15 bajtów

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

f"a"uruchamia rekurencyjnie ciąg „a”, upuszczając pierwszy znak i ostatecznie kończy się niepowodzeniem na końcu z Non-exhaustive patterns in function fwyjątkiem, ponieważ fjest zdefiniowany tylko dla niepustych ciągów.

nimi
źródło
5

C #, 71 38 bajtów

Ponieważ podałeś przykład w C # tutaj inna gra w golfa

I dzięki pinkfloydx33

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

Niższy niż Parse.ToString()nawet Parse($"{c--}") mentalnie porzuconychecked ponieważ jest on zbyt długi dla słowa kluczowego. Trudne to z pewnością jest krótsze niżParse(c.ToString())

Oryginalna odpowiedź

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

Spowoduje to uruchomienie c=0następnie zmniejszyć je, gdy spowoduje an:c=-1uint.Parse

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

Wersja bez golfa i sprawdzanie, czy pętla działa co najmniej raz

class p {
    static void Main() {
        for(int c=0;;c--) {
            System.Console.Write(c);
            uint.Parse(c.ToString());
        }
    }
}
MrPaulch
źródło
for(int c=0;;)uint.Parse($"{c--}");
pinkfloydx33
1
checked{for(uint c=1;;)c--;}
pinkfloydx33
Ok, wow! Nie wiedziałem o skrócie „$”!
MrPaulch,
4

CJam , 4 bajty

1{}g

Wypróbuj online!

Pierwsza iteracja pustej {}gpętli wyskakuje 1, co każe jej kontynuować. Druga iteracja próbuje wyskoczyć z innego warunkowego, ale stos jest pusty, więc program ulega awarii.

Martin Ender
źródło
4

Zestaw x86 (składnia AT&T), 40 bajtów

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

Deklaruje funkcję f, która dzieli pierwszą przez 1 iterację, a następnie próbuje podzielić 0 przez 0 i błędy.

poi830
źródło
Możesz zaoszczędzić 4 bajty, przełączając się na składnię Intela :)
mriklojn
6
Zazwyczaj oceniamy zestaw według rozmiaru wygenerowanego kodu bajtowego, a nie instrukcji czytelnych dla człowieka.
Dennis
@Dennis assmebled assembly jest językiem maszynowym. ale tak, można powiedzieć, że jest to znacznie krótsze w formie języka maszynowego.
Jasen
Pozbądź się etykiety f i mov. Zamień dec i div, a możesz pozbyć się jeszcze więcej.
Jaśniejsze
4

CJam, 4 bajty

P`:~

P`generuje ciąg 3.141592653589793. :~ocenia każdą postać. 3jest poprawnym kodem w CJam, który po prostu zwraca 3. W następnej iteracji .powoduje błąd, ponieważ wymaga cyfry lub następującego po nim operatora.

jimmy23013
źródło
4

Ruby, 14 bajtów

loop{$./=~$.}

Wyjścia z powodu ZeroDivisionError: divided by 0

$. The current input line number of the last file that was read

Ruby Docs

Jatin Dhankhar
źródło
4

> <> , 3 bajty

!]!

Wypróbuj tutaj!

Wyjaśnienie

!    skip next instruction
 ]   close stack (crash)
  !  skip next instruction (jumping to close stack)
redstarcoder
źródło
4

Partia, 22 20 bajtów

:a
set i=%i%1
goto a

Wyjaśnienie

Jest to nieskończona pętla, która dołącza 1do początkowo pustego łańcucha. W końcu minie maksymalna długość ciągu 8192 i nastąpi awaria. Na moim komputerze zajmuje to około 30 sekund.

Coś Ciemno
źródło
Miły! Możesz zapisać 2 bajty, używając zakończeń linii uniksowych.
briantist
Możesz użyć% 0, który jest nazwą pliku zamiast etykiety i goto.
YourDeathIsComing
Nie byłem pewien, czy to złamało zasadę rekurencji ogona.
SomethingDark
4

JavaScript, 9 bajtów

for(;;i);

Działa to raz, a następnie wyrzuca, ReferenceError: i is not definedco zatrzymuje pętlę.

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


Biorąc za przykład następujące, <increment>czy koniec pierwszego cyklu czy początek drugiego cyklu?

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

1 / Widzę to

Po przejściu z linii 0 do linii 3, a następnie z powrotem do linii 0, wydaje się, że pełny cykl został zakończony.
To byłby <increment>początek drugiego cyklu.
- Pierwszy cykl: <init>-> <test>-> <statement>
- Drugi cykl: <increment>-><test> -><statement>

2 / Whileekwiwalent

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

W tym równoważnej whileThe <increment>koniec pierwszego cyklu i wydaje się, jakby to samo z for.
To byłby <increment>koniec pierwszego cyklu.
- Pierwszy cykl: <test>-> <statement>-> <increment>
- Drugi cykl: <test>-> <statement>-><increment>

3 / Instrukcja pojawia się dwa razy

Pełny cykl kończy się, gdy instrukcja zostanie napotkana dwukrotnie.
Pierwsza napotkana instrukcja dwukrotnie <test>.
To byłby <increment>koniec pierwszego cyklu.
- Pierwszy cykl: <test>-> <statement>-> <increment>
- Drugi cykl: <test>-><statement> -><increment>

4 / To konfiguracja

Po <init>prostu ustawia wszystko, co jest potrzebne do pierwszego cyklu.
Po <increment>prostu ustawia wszystko, co jest potrzebne do drugiego cyklu.
To byłby <increment>początek drugiego cyklu.
- Pierwszy cykl: <init as a setup>-> <test>-> <statement>
- Drugi cykl: <increment as a setup>-> <test>-><statement>


Specyfikacja języka ECMAScript® 2016

Czas działania for(<init>;<test>;<increment>)<statement>;

Niech varDcl będzie wynikiem oceny <init>.
ReturnIfAbrupt (varDcl).
Powrót ? ForBodyEvaluation ( <test>, <increment>, <statement>, «», labelSet).

Istnieją trzy formy, więc wybrałem tutaj najkrótszą, nie ma różnicy:
- Cokolwiek <init>to nie jest częścią pierwszej iteracji.
- To, co jest istotne, znajduje się w ForBodyEvaluation.

Szczegóły ForBodyEvaluation ( <test>, <increment>, <statement>, «», labelSet)

0 Niech V będzie niezdefiniowane.
1 Wykonaj? CreatePerIterationEnvironment (perIterationBindings).
2 Powtórz
3 Jeśli nie jest [pusty], to
4 Niech testRef będzie wynikiem oceny <test>.
5 Niech testValue będzie? GetValue (testRef).
6 Jeśli ToBoolean (testValue) ma wartość false, zwróć wartość NormalCompletion (V).
7 Niech wynik będzie wynikiem oceny <statement>.
8 Jeśli LoopContinues (result, labelSet) ma wartość false, zwróć Completion (UpdateEmpty (wynik, V)).
9 Jeśli wynik. [[Wartość]] nie jest pusty, niech V będzie wynikiem. [[Wartość]].
10 Wykonaj? CreatePerIterationEnvironment (perIterationBindings).
11 Jeśli nie jest [pusty], to
12 Niech incRef będzie wynikiem oceny <increment>.
13 Wykonaj? GetValue (incRef).

6 / Widzę to

Pełny cykl pełny cykl powtarzania części.
To byłby <increment>koniec pierwszego cyklu.
- Pierwszy cykl: <test>-> <statement>-> <increment>/ Innymi słowy od linii 3 do linii 13
- Drugi cykl: <test>-> <statement>-> <increment>/ Innymi słowy od linii 3 do linii 13

7 / Cykl jest iteracją

Cykl zaczyna się od CreatePerIterationEnvironment.
Kiedy więc się pojawia CreatePerIterationEnvironment, rozpoczyna się nowy cykl, kończąc w ten sposób poprzedni.
To byłby <increment>początek drugiego cyklu.
- Pierwszy cykl: <test>-> <statement>/ Innymi słowy od linii 1 do linii 9
- Drugi cykl: <increment>-> <test>-> <statement>/ Innymi słowy od linii 10 pętli do linii 9


Czy <increment>koniec pierwszego cyklu czy początek drugiego cyklu?

Prawidłowe wyjaśnienie to 6 lub 7.

Hedi
źródło
8
Myślę, że jestem bardziej skłonny przypisywać przyrost do końca pierwszej iteracji, niż do początku drugiej iteracji lub żadnej iteracji. Przypuszczam, że jest to dwuznaczność pytania.
1
Ponieważ for(a;b;c)d;jest to mniej więcej odpowiednik a;while(b){d;c;}, jestem skłonny powiedzieć, że błąd jest nadal zgłaszany w pierwszej iteracji (przed sprawdzeniem warunku pętli po raz drugi).
ETHproductions
@Hurkyl Pierwsza iteracja zaczyna się od inicjalizacji, więc myślę, że przyrost powinien być początkiem drugiej iteracji.
Hedi
4
Jeśli przeczytasz specyfikację , zobaczysz, że operacja przyrostowa jest ostatnią częścią iteracji i jako taka nadal należy do pierwszej iteracji.
Nit,
3
@Hedi Nie rozumiem, jak to w ogóle jest istotne. Operacja przyrostowa jest bardzo wyraźnie częścią pierwszego przebiegu pętli. Aby sformułować inaczej, gdy wywoływana jest operacja przyrostowa, pętla nie zakończyła ani jednego pełnego uruchomienia.
Nit
4

INTERCAL , 12 bajtów

(1)DO(1)NEXT

Wypróbuj online!

NEXTjest głównym poleceniem przepływu sterowania INTERCAL-72. (Wprowadzono późniejsze wersje COME FROM, które stały się bardziej znane, ale nie było ich w oryginalnej wersji języka; i wszystkie zakończone implementacje INTERCAL Jestem świadomy wsparcia NEXTdla kompatybilności wstecznej, a wszystkie oprócz jednej domyślnie ją obsługują. Więc Nie czuję potrzeby, aby w tytule wymieniać INTERCAL-72).

Podczas NEXTtworzenia pętli należy użyć RESUMElub FORGETw celu zwolnienia miejsca, które wykorzystuje do zapamiętania, gdzie był program; RESUMEz mocą wsteczną NEXTzamienia to w coś podobnego do wywołania funkcji (chociaż możesz powrócić z funkcji innych niż ta, w której się znajdujesz), podczas FORGETgdy zamienia to w coś bardziej podobnego do instrukcji GOTO. Jeśli tego nie zrobisz (a ten program nie), program ulegnie awarii po 80 iteracjach (takie zachowanie jest faktycznie określone w specyfikacji INTERCAL).

Niejednoznaczne jest, czy liczy się to jako nieograniczona rekurencja (niedozwolone w pytaniu); z pewnością możesz użyć tego rodzaju NEXTdo zaimplementowania wywołania funkcji, w którym to przypadku byłaby to funkcja rekurencyjna, ale nie ma tu wystarczających informacji, aby ustalić, czy wykonujemy wywołanie funkcji, czy nie. Przynajmniej i tak to publikuję, ponieważ nie narusza to jednoznacznie reguł, a implementacja INTERCAL, która zoptymalizowała „wywołanie ogonowe”, nie tylko naruszyłaby specyfikację, ale także spowodowałaby awarię większości istniejących programów, ponieważ powrót z „zła funkcja” jest głównym sposobem wykonania odpowiednika instrukcji JEŻELI.

Oto wynikowy komunikat o błędzie wygenerowany przez C-INTERCAL:

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

(Zauważ, że druga linia jest wcięta tabulatorem, a trzecia ośmioma spacjami. Wygląda to poprawnie w terminalu lub w prawie każdym programie, który ma tabulatory w wielokrotnościach 8. Jednak Markdown ma tabulatory w wielokrotnościach cztery, co narusza założenia większości starszych programów dotyczące kart, więc komunikat o błędzie jest tutaj nieco zniekształcony).


źródło
Czy błąd naprawdę mówi CORRECT SOURCE AND RESUBNIT? Jak w literówce w oryginalnym komunikacie o błędzie C-INTERCAL?
Andrakis,
1
@Andrakis: Tak, to prawda. Ta literówka została starannie zachowana przez lata.
3

Pyth, 3 bajty

W1w

Wypróbuj online.

W1jest tylko while 1:w Pythonie. Ciało pętli drukuje wiersz odczytany ze STDIN, który ulega awarii dla drugiej iteracji, gdy kod jest uruchamiany z pustym wejściem.

Jeśli pętle używające #(loop-till-error) są zbanowane (zakładam, że tak), myślę, że jest to najkrótszy możliwy.

PurkkaKoodari
źródło
3

Python 3, 29 bajtów

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

Naprawdę proste. Przy drugim wywołaniu do x nie ma mnie i Python narzeka na to.

python-b5
źródło
3

Labirynt , 3 bajty

#(/

Wypróbuj online!

Podobnie jak większość języków 2D, Labirynt nie ma żadnych wyraźnych konstrukcji pętli. Zamiast tego każdy kod, który jest tak ułożony, że jest wykonywany wiele razy z rzędu, jest pętlą w tych językach. W przypadku Labiryntu prosty program liniowy działa jak pętla, ponieważ wskaźnik instrukcji będzie się na nim podskakiwał. Jeśli program jest abc(dla niektórych poleceń a, ba c), wówczas rzeczywista realizacja będzieabcbabcbabcb... tak, że działa abcbw nieskończonej pętli.

Jeśli chodzi o to, dlaczego ten konkretny program ulega awarii podczas drugiej iteracji tej pętli, oto, co robią poszczególne polecenia. Zauważ, że stos Labiryntu zawiera ukrytą nieskończoną liczbę zer na dole:

#   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.
Martin Ender
źródło
3

Bash, 11 (Granica niekonkurująca)

exec $0 1$@

Ten skrypt rekurencyjnie wykonuje się, dołączając 1do argumentów przekazywanych przy każdej iteracji. Myślę, że liczy się to jako całkowity koszt posiadania, ponieważ exec ponownie wykorzystuje przestrzeń procesu, ale nie zużywa stosu. Jest to granica niekonkurencyjna, ponieważ zabicie na mojej maszynie - YMMV, trwało około 10 minut.

Cyfrowa trauma
źródło
1
exec $0 1$@$@ kończy się znacznie szybciej, ale ma dwa znaki dłużej.
Jasen
3

cmd, 34 bajty

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

Będzie to cyklicznie %iod 0 do 10. Polecenie (starożytne) colorz radością przyjmie każdy argument, który ma 2 (szesnastkowo) cyfry dziesiętne. Z argumentem 100nie powiedzie się, drukując komunikat pomocy i ustawiając ERRORLEVELna 1.

Dowód, że pętla działa co najmniej raz: Kolor twojej powłoki będzie inny!

MrPaulch
źródło