Loop ohne 'Looping' [geschlossen]

85

Eine ähnliche Frage wurde vor ein paar Jahren gestellt , aber diese ist noch kniffliger.

Die Herausforderung ist einfach. Schreiben Sie ein Programm (in der Sprache Ihrer Wahl) , die wiederholt Code ausführt , ohne Wiederholung Strukturen unter Verwendung von wie while, for, do while, foreachoder goto( also für alle Sie Nitpicker, man kann nicht eine Schleife verwenden ). Eine Rekursion ist jedoch in der Funktion, die sich selbst aufruft , nicht zulässig (siehe Definition unten) . Das würde diese Herausforderung viel zu einfach machen.

Es gibt keine Einschränkung, was in der Schleife ausgeführt werden muss, aber geben Sie eine Erklärung mit Ihrer Antwort an, damit andere genau verstehen, was implementiert wird.

Für diejenigen, die an Definitionen aufgehängt werden können, lautet die Definition einer Schleife für diese Frage:

A programming language statement which allows code to be repeatedly executed.

Und die Definition der Rekursion für diese Frage ist Ihre Standarddefinition für rekursive Funktionen:

A function that calls itself.

Gewinner ist die Antwort, die am 16. Juli um 10.00 Uhr Ortszeit die meisten positiven Stimmen hat. Viel Glück!

AKTUALISIEREN:

Zur Beruhigung der noch bestehenden Verwirrung kann Folgendes hilfreich sein:

Regeln wie oben angegeben:

  • Benutze keine Schleifen oder gehe zu
  • Funktionen können sich nicht selbst aufrufen
  • Mach was du willst in der Schleife

Wenn Sie etwas implementieren möchten und die Regeln es nicht explizit verbieten, gehen Sie vor und tun Sie es. Viele Antworten haben die Regeln bereits verbogen.

CailinP
quelle
27
Für diejenigen, die einen einfachen Trick wollen, muss ich ihn unbedingt veröffentlichen: P Machen Sie einfach zwei Funktionen, function Arufen Sie auf function Bund function Brufen Sie auf, function Awährend eine der Funktionen etwas ausführt. Da sich die Funktion nicht selbst nennt, sollte sie nach den Kriterien ^. ^ Gültig sein
Teun Pronk
2
"Zum Beliebtheitswettbewerb gewechselt, um sich auf Kreativität zu konzentrieren" Die Frage zu ändern, ist Betrug!
CousinCocaine
4
Die Definition von "Rekursion" ist nicht sehr nützlich. Es wäre besser, rekursive Funktionen zu verbieten , die sich direkt oder indirekt auf sich selbst beziehen.
lrn
3
Unklar sind die "Definitionen" von Schleifenkonstruktor und Rekursion. Weder sind sehr präzise. Beispiel: rep(f){f();f();}- Dies ist eine Anweisung (eine Funktionsdeklaration ist eine Anweisung in einigen Sprachen), mit der Code wiederholt ausgeführt werden kann. Ist es nicht erlaubt? Sie fragen nach Code, um eine Schleife zu implementieren. Wenn dieser Code syntaktisch eine Anweisung ist, haben Sie ihn gerade nicht zugelassen. Ein weiteres Beispiel: f(b) { b(); g(b); }; g(b) { f(b); }. Ich würde sagen, es fist eine rekursive Funktion (indem man sich gegenseitig rekursiv behandelt g). Ist es nicht erlaubt?
lrn
3
@CailinP, woran ich " aufgehängt " bin, ist, dass Fragen auf der Site ein Thema für die Site sein sollten: Das bedeutet, eine klare, objektive Spezifikation zu haben, was bei dieser Frage nicht der Fall ist.
Peter Taylor

Antworten:

258

Rubin

def method_missing(meth,*args)
  puts 'Banana'
  send(meth.next)
end

def also
  puts "Orange you glad I didn't say banana?"
end

ahem

Demo

Räuspert sich, druckt 3070-mal "Banane" und schreibt auch "Orange, du bist froh, dass ich keine Banane gesagt habe?".

Dabei wird Rubys lächerliche Just-in-Time-Methodendefinitionsfunktion verwendet, um jede Methode zu definieren, die alphabetisch zwischen den Wörtern "ahem" und "also" ("ahem", "ahen", "aheo", "ahep", "aheq") liegt. "aher", "ahes", "ahet", "aheu", "ahev" ...), um zuerst die Banane zu drucken und dann die nächste in der Liste aufzurufen.

Histokrat
quelle
4
Es trifft schließlich "auch", was definiert ist und daher nicht fehlt.
Histokrat
77
Das ist hysterisch.
Michael B
4
@barrycarter: In Ruby, String#nextdas in method_missingFunktionen mehr oder weniger wie das Hinzufügen von 1 zu einer Zahl aufgerufen wird, funktioniert es jedoch mit allen alphanumerischen Zeichen (und Nicht-Alumni, wenn sie die einzigen Zeichen in der Zeichenfolge sind). Siehe ruby-doc.org/core-2.1.2/String.html#method-i-next
3Doubloons
2
@NickT kann in Klassen wie XML-Buildern verwendet werden, in denen Sie jedes Tag verwenden können, das nur von erstellt wurde b.my_tag. Es wird auch in ActiveRecord-Modellen oder verwendet OpenStruct. In "Wat Talk" sagt er, dass global method_missingschlecht ist, aber der Umfang ist fantastisch.
Hauleth
2
Ich erinnere mich an einen alten Kommentar zu einem anderen Ruby-Programm: "Ich mag es, weil es Meth hat"
Vidya Sagar
82

Python - 16

oder eine andere Sprache mit eval.

exec"print 1;"*9
Vektorisiert
quelle
Können Sie beschreiben, was Ihr Programm macht?
CailinP
10
Es nimmt einen String ( "print 1;"), dupliziert ihn 9 Mal ( *9) und führt dann den resultierenden String ( exec) aus. Wiederholen eines Codeblocks, ohne überhaupt eine Schleife auszuführen.
Scragar
12
Ja, für die String-Multiplikation!
Thane Brimhall
2
Funktioniert auch in Ruby, wenn Sie das execzu eval oder das printzu ändern echo.
Ajedi32
80

CSharp

Ich habe den Code auf eine lesbarere Art und Weise erweitert, da dies kein Code-Golf mehr ist, und habe einen Inkrement-Zähler hinzugefügt, damit die Leute tatsächlich sehen können, dass dieses Programm etwas tut.

class P{
    static int x=0;
    ~P(){
        System.Console.WriteLine(++x);
        new P();
    }
    static void Main(){
        new P();
    }
}

(Mach das bitte nie).

Beim Start erstellen wir eine neue Instanz der PKlasse, die beim Beenden des Programms den GC aufruft, der den Finalizer aufruft, der eine neue Instanz der PKlasse erstellt, und beim Aufräumen eine neue Instanz erstellt, Pdie den Finalizer aufruft. .

Das Programm stirbt schließlich.

Bearbeiten: Aus unerklärlichen Gründen läuft dies nur etwa 45.000 Mal vor dem Sterben. Ich weiß nicht genau, wie der GC meine knifflige Endlosschleife herausgefunden hat, aber es hat geklappt. Der Kurzschluss ist, dass es den Anschein hat, als hätte er es nicht herausgefunden, und der Thread wurde nur nach ungefähr 2 Sekunden Ausführung beendet: https://stackoverflow.com/questions/24662454/how-does-a-garbage-collector-avoid-an Endlosschleife hier

Edit2: Wenn Sie der Meinung sind, dass dies ein bisschen zu viel Rekursion ähnelt, ziehen Sie meine andere Lösung in Betracht: https://codegolf.stackexchange.com/a/33268/23300

Es verwendet die Reifizierung generischer Methoden, sodass zur Laufzeit ständig neue Methoden generiert werden und jede Methode im Ausdruck eine neu erstellte Methode aufruft. Ich vermeide auch die Verwendung von referenceTypparametern, da normalerweise die Laufzeitumgebung den Code für diese Methoden gemeinsam nutzen kann. Mit einem valueTypparameter wird die Laufzeit gezwungen, eine neue Methode anzulegen.

Michael B
quelle
20
Ich wusste nicht einmal, dass C # Destruktoren hat. +1 für mich zu lehren.
Siehe auch
4
@TheRare, aber sie sind nicht deterministisch und dürfen während der Ausführung eines Programms niemals aufgerufen werden. Sie werden als Überschreibung der virtuellen Methode implementiert, Finalizesodass sie manchmal aufgerufen werden finalizer. In echtem C # sollten Sie das IDisposableMuster verwenden.
Michael B
Es scheint, dass es irgendwann zu einem Timeout kommt. Ich denke nicht, dass der GC Ihren Zyklus stoppt, sondern dass das Betriebssystem entscheidet, dass Ihr Programm zu lange dauert, um zu enden.
LVBen
Ich denke, das ist wirklich die Laufzeit, die entscheidet, das Programm zu töten, nicht unbedingt das Betriebssystem. Der am Programmende aufgerufene Garbage-Collector-Thread hat eine feste Zeitgrenze von ~ 2 Sekunden, bevor er beendet wird.
Michael B
Mit einigen geringfügigen Änderungen (das Programm nicht enden lassen, das erste P-Objekt für den GC freigeben und GC.Collect wiederholt aufrufen) kann ich dafür sorgen, dass es auf unbestimmte Zeit ausgeführt wird.
LVBen
53

Befunge

.

Gute alte Befunge gibt 0 (von einem leeren Stapel) so ziemlich für immer aus, während Zeilen umlaufen.

Le Canard fou
quelle
1
Ha! Ich liebe Tricks wie diese
CailinP
47

JS

(f=function(){ console.log('hi!'); eval("("+f+")()") })()

Funktionsspaß!

Eine Funktion, die eine andere Funktion mit demselben Körper wie sich selbst erstellt und dann ausführt.

Am Ende wird hi angezeigt, wenn das Stack-Limit erreicht ist und das Ganze zusammenbricht.

Haftungsausschluss: Sie können in Ihrem Browser nichts tun, bis das Stack-Limit erreicht ist.


Und noch einer, böser :

function f(){ var tab = window.open(); tab.f = f; tab.f()}()

Es erstellt eine Funktion, die ein Fenster öffnet, erstellt dann eine Funktion in dem Fenster, das eine Kopie der Funktion ist, und führt sie dann aus.

Haftungsausschluss: Wenn Sie das Öffnen von Popups zulassen, können Sie dies nur beenden, indem Sie Ihren Computer neu starten

eithed
quelle
5
Das ist mit Sicherheit ziemlich böse;)
CailinP
28
@CailinP Ziemlich sicher eval.
Siehe auch
Ich denke, Sie vermissen eine fam Ende Ihrer zweiten Funktion. Es sollte }f()am Ende sein.
Chirag Bhatia - Chirag64
2
Leider ist es mir aufgefallen, weil ich es ausprobiert habe. : P
Chirag Bhatia - Chirag64
7
-1 - Dies ist nur eine Rekursion.
immibis
39

x86-Assembly / DOS

    org 100h

start:
    mov dx,data
    mov ah,9h
    int 21h
    push start
    ret

data:
    db "Hello World!",10,13,"$"

Habe ich gesagt, keine umgekehrte Schwanzrekursion ? Habe ich? madame mim lila drachen

Wie es funktioniert

Der retBefehl, der zur Rückkehr von einer Funktion verwendet wird, holt tatsächlich die Rücksprungadresse aus dem Stapel (der normalerweise von der entsprechenden Stelle dort abgelegt wird call) und springt dorthin . Hier geben wir bei jeder Iteration pushdie Eintrittspunktadresse auf dem Stapel an, bevor wir zurückkehren, wodurch eine Endlosschleife erzeugt wird.

Matteo Italia
quelle
Ich habe mich gefragt, ob das in der Montage möglich ist.
Ian D. Scott
2
Verwirren Sie sich auf eigene Gefahr mit dem Stapel . Hier Drachen sein ;-)
Digital Trauma
1
Ich wollte codegolf.stackexchange.com/a/34295/11259 als Dup von diesem aufrufen , aber ich sehe, dass das tatsächlich die frühere Antwort ist
Digital Trauma
@DigitalTrauma: Ja, ich habe es bemerkt, nachdem ich meinen Eintrag gepostet habe, aber ich habe es an das Bild von Madame Mim angehängt. :-) Zum Glück gibt es einige Unterschiede (sein ist etwas verschleierter und funktioniert unter 32-Bit-Linux, mein wird direkt unter DOS gespielt und hat keinen anderen Sprung), wenn niemand etwas dagegen hat, würde ich das hier sowieso lassen.
Matteo Italia
@ MatteoItalia Nicht verschleiert, nur beschissen;) (obwohl "add eax, 4" mich ebenfalls verwirrte, konnte ich keine Opcode-Größentabelle finden, also habe ich nur die wilde Größe erraten). Ich habe es im Online-Compiler gemacht, während mein Arbeitsprojekt kompiliert wurde, so dass es fürchterlich aussieht. Tolle Idee, "start:" zu verwenden.
PTwr
37

Java

Direkt von XKCD

Verbindung

Es ist ein nie endendes Fangspiel zwischen Eltern und Kind!

Das Ziel von CHILDist auf PARENTund das Ziel von PARENTist das CHILD. Wenn die PARENTAnrufe AIM, es die Instanz der wirft BALLKlasse und wird von der catch - Anweisung gefangen. Die catch-Anweisung ruft dann auf, PARENT.TARGET.AIMwo sich das Ziel befindet CHILD. Die CHILDInstanz macht dasselbe und "wirft den Ball zurück" zum Elternteil.

Kirk Backus
quelle
3
Ich mag diese Comics!
Derek 朕 朕 功夫
1
Wäre besser, wenn der Ball tatsächlich zwischen Eltern und Kind geworfen würde. Wie es ist, wird der Ball immer von derselben "Person" geworfen und gefangen.
Ajedi32
@ Ajedi32 Eigentlich scheint es, als würde es hin und her werfen. Eltern-ZIEL ist das Kind und das Ziel des Kindes ist das Elternteil. Aim wird auf Eltern gerufen, die den Ball werfen und das Kind zielen und den Ball werfen lassen, Cue-Loop
Alex Coleman
12
@AlexColeman Dieser Code ist analog zu dem Code, mit dem die Eltern den Ball in die Luft werfen, auffangen und dann an das Kind übergeben, das dasselbe tut, bevor sie den Ball an die Eltern zurückgeben, und so weiter.
Ajedi32
11
Der Befehl TARGET.AIM(B);in der Methode AIMist ein rekursiver Aufruf. Dies verstößt also gegen die Regel "Funktionen können sich nicht selbst nennen".
Theodore Norvell
31

Bash, 3 Zeichen

yes

yes gibt wiederholt "y" an die Konsole zurück

Bearbeiten: Jeder wird ermutigt, diese Zeile zu bearbeiten:

yes something | xargs someaction

(Danke an Olivier Dulac)

CousinCocaine
quelle
1
Warum läuft das weiter? Ich stelle es nicht in Frage, versuche nur herauszufinden, warum.
Teun Pronk
2
@TeunPronk yesist ein Bash-Befehl, der das Wort yes ausgibt, bis es beendet wird oder der Stream geschlossen wird. Wenn es auf den Bildschirm schreibt, hört es nie auf, bis Sie es töten. Es ist jedoch eine Art Betrug, da es sich um einen Befehl handelt, der im Grunde aus einer Schleife über printf besteht.
Scragar
1
Mehr Spaß wäre es yes, eine andere Schleife am Laufen zu halten.
Trlkly
3
@izkata: aber dann können Sie:: yes something | xargs someactionkeine Rekursion (Sie können sogar -n 1 zu xargs hinzufügen, um nur 1 "etwas" pro Zeile usw. zu haben). Die Verwendung von xargs eröffnet den Weg für komplexere Verhaltensweisen (selbst diejenigen, die überhaupt nichts mit der Ja-Ausgabe zu tun haben)
Olivier Dulac
4
@scragar Sie sollten gerade geantwortet haben yes.
Daviewales
28

C, 35 Zeichen

main(int a,char**v){execv(v[0],v);}

Das Programm führt sich selbst aus. Ich bin nicht sicher, ob dies als Rekursion angesehen wird oder nicht.

Kwokkie
quelle
4
@ Mniip Tail Rekursion, dann, wenn es auf der Prozessebene angewendet
Izkata
3
@Izkata Tail-Rekursion ist immer noch Rekursion, aber dies ist keine Rekursion. Rekursion bedeutet, dass eine Funktion (oder ein Prozess in diesem Fall) darauf wartet, dass eine weitere Iteration von sich selbst beendet wird. In diesem Fall wird execder ursprüngliche Prozess durch den neuen Prozess ersetzt, sodass es keinen Aufrufstapel gibt, der möglicherweise zurückkehrt oder überläuft.
Millinon
4
@millinon In einer Sprache, die die Optimierung unterstützt, ersetzt die Schwanzrekursion den vorherigen Aufruf in der Aufrufliste, ähnlich wie execbeim vorherigen Vorgang. Es wird auch nicht überlaufen.
Izkata
1
@millinon nur um Super pedantisch und diese Diskussion mehr in die Länge ziehen, in der Programmiersprache Scheme, diese Optimierung ist eine Sprache - Funktion. Es ist in der Spezifikation , dass , wenn Sie einen Schwanz-rekursive Aufruf, die Interpreter / Compiler hat den letzten Stapelrahmen wieder zu verwenden. Dies liegt daran, dass Scheme keine eingebauten Schleifenstrukturen hat. Die einzige Möglichkeit, eine Schleife in Scheme zu implementieren, ist die Schwanzrekursion. Wenn Sie versuchen, zu viele Schleifen zu durchlaufen, ist dies eine Art Scheiße :)
Ord
2
Wenn Sie Pedanterie wünschen, verfügt Schema nicht über "Tail-Call-Optimierung", sondern über "richtige Tail-Calls". Es ist keine Optimierung, es ist eine Grundvoraussetzung des Sprachstandards, und die Nichtbereitstellung ist nicht zulässig. "Optimierung" (oder der Vorschlag, dass es sich um eine Rekursion handelt) ist daher ein äußerst entmutigender Begriff.
Leushenko
28

C (mit GCC Builtins - scheint auch mit Clang zu funktionieren)

  • Keine expliziten Schleifen
  • Keine expliziten gotos
  • Keine Rekursion
  • Nur gutes altmodisches Durcheinander mit dem Stapel (Kinder, versuchen Sie dies nicht zu Hause ohne Aufsicht):
#include <stdio.h>

void *frameloop (void *ret_addr) {
    void **fp;
    void *my_ra = __builtin_return_address(0);

    if (ret_addr) {
        fp = __builtin_frame_address(0);
        if (*fp == my_ra) return (*fp = ret_addr);
        else fp++;
        if (*fp == my_ra) return (*fp = ret_addr);
        else fp++;
        if (*fp == my_ra) return (*fp = ret_addr);
        else fp++;
        if (*fp == my_ra) return (*fp = ret_addr);
        return NULL;
    } else {
        return (my_ra);
    }
}

int main (int argc, char **argv) {
    void *ret_addr;
    int i = 0;

    ret_addr = frameloop(NULL);
    printf("Hello World %d\n", i++);
    if (i < 10) {
        frameloop(ret_addr);
    }
}

Erläuterung:

  • main()erste Anrufe frameloop(NULL). In diesem Fall verwenden Sie das __builtin_return_address()Built-In, um die Rücksprungadresse (in main()) abzurufen, zu der zurückgekehrt frameloop()wird. Wir senden diese Adresse zurück.
  • printf() um zu zeigen, wir schleifen
  • jetzt rufen wir frameloop()mit der rücksprungadresse für den vorigen anruf an. Wir durchsuchen den Stapel nach der aktuellen Absenderadresse und ersetzen die vorherige Absenderadresse, wenn wir sie finden.
  • Wir kehren dann vom 2. frameloop()Anruf zurück. Da die Absenderadresse oben gehackt wurde, kehren wir zu dem Punkt zurück, main()an den der erste Anruf zurückkehren soll. So geraten wir in eine Schleife.

Die Suche nach der Absenderadresse im Stapel wäre natürlich sauberer als eine Schleife, aber ich habe ein paar Iterationen abgewickelt, um überhaupt keine Schleife zu haben.

Ausgabe:

$ CFLAGS=-g make frameloop
cc -g    frameloop.c   -o frameloop
$ ./frameloop 
Hello World 0
Hello World 1
Hello World 2
Hello World 3
Hello World 4
Hello World 5
Hello World 6
Hello World 7
Hello World 8
Hello World 9
$ 
Digitales Trauma
quelle
2
nett! Ich frage mich, warum diese Funktionen nicht Teil der C-Spezifikation sind. ;-D
Brian Minton
4
@BrianMinton Eigentlich sollte mit setjmp()/ eine ähnliche Sache erreichbar sein longjmp(). Diese befinden sich nicht im c-Standard, sondern in der Standardbibliothek . Ich wollte den Stapel heute allerdings manuell mischen ;-)
Digitales Trauma
@ BrianMinton Ich vermute, weil es in CPU-Spezifikationen, die es (Hardware) plattformabhängig macht. Und es ist ziemlich gefährlich zu verwenden, wenn Stackframe automatisch generiert wird. Ich wäre nicht überrascht, wenn AV über solchen Code weinen würde. Überprüfen Sie dies oder dies für x86-ASM-Versionen.
PTwr
27

Haskell

Der folgende Code enthält keine rekursive Funktion (auch nicht indirekt), kein Schleifenprimitiv und ruft keine eingebaute rekursive Funktion auf (verwendet nur IOdie Ausgabe und die Bindung von), wiederholt jedoch eine gegebene Aktion endlos:

data Strange a = C (Strange a -> a)

-- Extract a value out of 'Strange'
extract :: Strange a -> a
extract (x@(C x')) = x' x

-- The Y combinator, which allows to express arbitrary recursion
yc :: (a -> a) -> a
yc f =  let fxx = C (\x -> f (extract x))
        in extract fxx

main = yc (putStrLn "Hello world" >>)

Funktion extractruft nichts auf, ycruft nur extractund mainruft nur ycund putStrLnund auf >>, was nicht rekursiv ist.

Erläuterung: Der Trick liegt im rekursiven Datentyp vor Strange. Es ist ein rekursiver Datentyp, der sich selbst verbraucht, was, wie im Beispiel gezeigt, eine willkürliche Wiederholung ermöglicht. Zunächst können wir konstruieren extract x, was im Wesentlichen die Selbstanwendung x xim untypisierten Lambda-Kalkül ausdrückt . Und dies erlaubt es, den als definierten Y-Kombinator zu konstruieren λf.(λx.f(xx))(λx.f(xx)).


Update: Wie vorgeschlagen, veröffentliche ich eine Variante, die der Definition von Y im untypisierten Lambda-Kalkül näher kommt :

data Strange a = C (Strange a -> a)

-- | Apply one term to another, removing the constructor.
(#) :: Strange a -> Strange a -> a
(C f) # x = f x
infixl 3 #

-- The Y combinator, which allows to express arbitrary recursion
yc :: (a -> a) -> a
yc f =  C (\x -> f (x # x)) # C (\x -> f (x # x))

main = yc (putStrLn "Hello world" >>)
Petr Pudlák
quelle
3
Rekursive Datenstrukturen statt rekursiver Funktionen ... schön.
ApproachingDarknessFish
6
Dieser liegt mir am Herzen, als jemand, der sich für funktionale Programmierung interessiert. Sie haben gerade gezeigt, wie der Y-Kombinator mit einem negativ wiederkehrenden Datentyp erstellt wird. Dies ist der Grund, warum für Gesamtsprachen wiederkehrende Typen rechts vom Pfeil erforderlich sind und warum Rosenbäume nicht zugelassen sind. Schön! Ich habe hier einen Account erstellt, um dies zu unterstützen!
Jake
Sie könnten die letBindung entfernen und definieren yc f = extract $ C $ f.extract, da die letBindung möglicherweise eine Sprachfunktion ist, die eine Rekursion ermöglicht (die klassische let x = x in x). Dies reduziert auch einige Zeichen :)
Earth Engine
oder sogaryc = extract . C . (.extract)
Earth Engine
@EarthEngine Stimmt, ich wollte nur die Struktur näher an der ursprünglichen Definition von halten Y.
Petr Pudlák
26

C ++

Das Folgende gibt einen Countdown von 10 bis "Blast off!" mit Vorlage Metaprogrammierung.

#include <iostream>

template<int N>
void countdown() {
    std::cout << "T minus " << N << std::endl;
    countdown<N-1>();
}

template<>
void countdown<0>() {
    std::cout << "Blast off!" << std::endl;
}

int main()
{
    countdown<10>();
    return 0;
}

Es mag wie ein klassisches Beispiel für Rekursion aussehen, ist aber, zumindest technisch, nicht von Ihrer Definition abhängig. Der Compiler generiert zehn verschiedene Funktionen. countdown<10>gibt "T minus 10" aus und ruft dann countdown<9>und so weiter auf countdown<0>, was "Blast off!" und kehrt dann zurück. Die Rekursion tritt auf, wenn Sie den Code kompilieren, die ausführbare Datei enthält jedoch keine Schleifenstrukturen.

In C ++ 11 können mit dem constexprSchlüsselwort ähnliche Effekte erzielt werden, z. B. diese Fakultätsfunktion. (Es ist nicht möglich, das Countdown-Beispiel auf diese Weise zu implementieren, da constexprFunktionen keine Nebenwirkungen haben können, aber ich denke, dass dies im kommenden C ++ 14 möglich sein könnte.)

constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n-1));
}

Auch hier sieht wirklich wie Rekursion, aber der Compiler erweitert heraus factorial(10)in 10*9*8*7*6*5*4*3*2*1, und dann wahrscheinlich mit einem konstanten Wert von ersetzen 3628800, so dass die ausführbaren Datei wird jedes Looping oder rekursive Code nicht enthalten.

Nathaniel
quelle
4
Die zweite davon ist eine reine und einfache Rekursion, keine Metaprogrammierung. Erstens, weil der Compiler (im Allgemeinen) einen regulären Funktionsrumpf ausgibt, den Sie mit nicht konstanten Argumenten verwenden können. und zweitens, weil es, wenn es eine Kompilierungsoperation ausführt, keine dieser "Erweiterungs" -Stücke im Template-Stil ausführt, sondern eine Standard-In-Place-Evaluierung ausführt - genau wie die Laufzeit-Evaluierung -, um 3628800direkt ohne eine zu produzieren Zwischenform.
Leushenko
@Leushenko ja ich weiß. Andererseits macht das Beispiel für eine Vorlage dasselbe - verwendet eine rekursive Funktion in einer Turing-vollständigen Sprache zur Kompilierungszeit - der einzige Unterschied ist, dass der Constexpr eine Sprache verwendet, die viel mehr wie C ++ aussieht. Wie bei allen Antworten verstößt dieser gegen die Regeln, und ich bin nur ehrlich. constexprwurde speziell entwickelt, um (einige Aspekte von) Template-Metaprogrammierung überflüssig zu machen, daher scheint es definitiv erwähnenswert, in einem Beitrag zu diesem Thema erwähnt zu werden.
Nathaniel
1
+1: &countdown<N-1> != &countdown<N>.
Thomas Eding
21

Java

Spielen wir mit dem Java-Klassenladeprogramm und legen es als eigenes übergeordnetes Element fest:

import java.lang.reflect.Field;

public class Loop {
    public static void main(String[] args) throws Exception {
        System.out.println("Let's loop");
        Field field = ClassLoader.class.getDeclaredField("parent");
        field.setAccessible(true);
        field.set(Loop.class.getClassLoader(), Loop.class.getClassLoader());

    }
}

Diese Schleife ist tatsächlich so stark, dass man sie mit einem kill -9stoppen muss :-)

Es nutzt 100,1% der CPU meines Mac.

100,1% der CPU

Sie können versuchen, die Taste System.outam Ende der Hauptfunktion zu bewegen , um ein anderes lustiges Verhalten zu testen.

Arnaud
quelle
lol. Immer Java in sich selbst stecken :)
MasterX244
Ich liebe den rekursiven JVM-Lade-Hack.
Isiah Meadows
20

CSharp

Eine weitere und ebenso böse:

public class P{

    class A<B>{
        public static int C<T>(){
            System.Console.WriteLine(typeof(T));
            return C<A<T>>();
        }
    }
    public static void Main(){
        A<P>.C<int>();
    }
}

Dies ist keine Rekursion ... dies ist die Reifizierung von Codevorlagen. Während es so aussieht, als ob wir dieselbe Methode aufrufen, erstellt die Laufzeit ständig neue Methoden. Wir verwenden den Typparameter von int, da dies tatsächlich dazu zwingt, einen völlig neuen Typ zu erstellen, und jede Instanz der Methode eine neue Methode erzeugen muss. Es kann hier keine Codefreigabe erfolgen. Schließlich beenden wir den Aufrufstapel, da er unendlich lange auf die Rückkehr von int wartet, die wir versprochen, aber nie geliefert haben. In ähnlicher Weise schreiben wir den Typ, den wir erstellt haben, um ihn interessant zu halten. Grundsätzlich ist jedes C, das wir aufrufen, eine völlig neue Methode, die nur den gleichen Körper hat. Dies ist in einer Sprache wie C ++ oder D, die ihre Vorlagen zur Kompilierungszeit erstellt, nicht wirklich möglich. Da C # JIT sehr faul ist, erstellt es dieses Zeug nur im letztmöglichen Moment. Somit,

Michael B
quelle
14

Redcode 94 (Kernkrieg)

MOV 0, 1

Kopiert die Anweisung an der Adresse Null in die Adresse Eins. Da in Core War alle Adressen relativ zur aktuellen PC-Adresse sind und die Größe des Kerns modulieren, handelt es sich um eine Endlosschleife in einem Befehl, der kein Sprung ist.

Dieses Programm (Krieger) heißt " Imp " und wurde zuerst von AK Dewdney veröffentlicht.

wberry
quelle
3
Die Imps marschieren, bereiten Ihre Tore vor, bereiten sie vor, oder Sie werden niedergeschlagen.
Siehe auch
Bereiten Sie in der SPL 0, 0; MOV 1, -2Tat vor.
Wberry
Schön, ich hatte gehofft, dass dies noch nicht gepostet wurde. +1
mbomb007
14

Pfeil

Ich denke, dies wäre die klassische Art, eine Rekursion ohne tatsächliche rekursive Funktion durchzuführen. Keine der folgenden Funktionen bezieht sich direkt oder indirekt auf sich selbst.

(Versuchen Sie es unter dartpad.dartlang.org )

// Strict fixpoint operator.
fix(f) => ((x)=>f(x(x))) ((x)=>(v)=>f(x(x))(v));
// Repeat action while it returns true.
void repeat(action) { fix((rep1) => (b) { if (b()) rep1(b); })(action); }

main() {
  int x = 0;
  repeat(() {  
    print(++x);
    return x < 10;
  });
}
lrn
quelle
6
Der Y-Kombinator?
Aditsu
5
Technisch gesehen ist es der Z-Kombinator, weil er für eine strenge Sprache ist. Der Y-Kombinator benötigt eine faule Sprache, um eine unendliche Entfaltung zu vermeiden. Der einzige Unterschied ist, dass der letzte Teil davon eta-expandiert ist.
lrn
12

JS

Nicht sehr originell, aber klein. 20 Zeichen.

setInterval(alert,1)
xem
quelle
Sie können tatsächlich entfernen ,1und es wird immer noch funktionieren,
Derek 朕 朕 會
@Derek 朕 會 功夫 wenn ich das tue, bekomme ich nur eine Warnung bei Firefox
xem
1
In Chrom funktioniert es ohne den letzten Parameter. Der Code sollte als gültig gezählt werden, wenn er in mindestens einer Umgebung funktioniert.
Derek 朕 朕 功夫
3
@Derek 朕 會 功夫setIntervalist jedoch keine Aussage; Es ist nur eine Funktion. Es wird in einer expression-Anweisung verwendet, und wenn wir expression-Anweisungen nicht verwenden können, weiß ich es einfach nicht einmal mehr.
Keen
1
@Cory - Nun, ich denke, das ist dann gültig!
Derek 朕 朕 功夫
12

Signale in C

#include <stdio.h>
#include <signal.h>

int main(void) {
    signal(SIGSEGV, main);
    *(int*)printf("Hello, world!\n") = 0;
    return 0;
}

Das Verhalten dieses Programms ist offensichtlich sehr undefiniert, aber heute druckt es auf meinem Computer immer noch "Hallo Welt!".

Thomas Padron-McCarthy
quelle
11

Emacs Lisp

Dies ist eine großartige Gelegenheit, um Lisps leistungsstarkes Design zu demonstrieren, bei dem "Code Daten und Daten Code sind". Zugegeben, diese Beispiele sind sehr ineffizient und sollten niemals in einem realen Kontext verwendet werden.

Die Makros generieren Code, der eine nicht gerollte Version der angenommenen Schleife ist, und dieser generierte Code wird zur Laufzeit ausgewertet.

repeat-it: Hiermit können Sie N-mal eine Schleife ausführen

(defmacro repeat-it (n &rest body)
  "Evaluate BODY N number of times.
Returns the result of the last evaluation of the last expression in BODY."
  (declare (indent defun))
  (cons 'progn (make-list n (cons 'progn body))))

Wiederholungstest:

;; repeat-it test
(progn
  (setq foobar 1)

  (repeat-it 10
    (setq foobar (1+ foobar)))

  ;; assert that we incremented foobar n times
  (assert (= foobar 11)))

Wiederholung mit Index:

Dieses Makro ähnelt repeat-it, funktioniert jedoch genauso wie das allgemeine Schleifenmakro do-times, mit dem Sie ein Symbol angeben können, das an den Schleifenindex gebunden wird. Mithilfe eines Erweiterungszeitsymbols wird sichergestellt, dass die Indexvariable am Anfang jeder Schleife korrekt festgelegt ist, unabhängig davon, ob Sie den Wert während des Schleifenkörpers ändern oder nicht.

(defmacro repeat-it-with-index (var-and-n &rest body)
  "Evaluate BODY N number of times with VAR bound to successive integers from 0 inclusive to n exclusive..
VAR-AND-N should be in the form (VAR N).
Returns the result of the last evaluation of the last expression in BODY."
  (declare (indent defun))
  (let ((fallback-sym (make-symbol "fallback")))
    `(let ((,(first var-and-n) 0)
           (,fallback-sym 0))
       ,(cons 'progn
              (make-list (second var-and-n)
                         `(progn
                            (setq ,(first var-and-n) ,fallback-sym)
                            ,@body
                            (incf ,fallback-sym)))))))

Wiederholungstest mit Index:

Dieser Test zeigt, dass:

  1. Der Körper wertet N-mal aus

  2. Die Indexvariable wird zu Beginn jeder Iteration immer korrekt gesetzt

  3. Das Ändern des Werts eines Symbols mit dem Namen "Fallback" wirkt sich nicht auf den Index aus

;; repeat-it-with-index test
(progn
  ;; first expected index is 0
  (setq expected-index 0)

  ;; start repeating
  (repeat-it-with-index (index 50)
    ;; change the value of a  'fallback' symbol
    (setq fallback (random 10000))
    ;; assert that index is set correctly, and that the changes to
    ;; fallback has no affect on its value
    (assert (= index expected-index))
    ;; change the value of index
    (setq index (+ 100 (random 1000)))
    ;; assert that it has changed
    (assert (not (= index expected-index)))
    ;; increment the expected value
    (incf expected-index))

  ;; assert that the final expected value is n
  (assert (= expected-index 50)))
Jordon Biondo
quelle
11

Untypisierter Lambda-Kalkül

λf.(λx.f (x x)) (λx.f (x x))
Arthur B
quelle
3
Ich bin mir nicht sicher, ob dies als Rekursion zählt oder nicht, was die grundlegende theoretische Grundlage dafür ist ... +1 sowieso.
flauschige
@fluffy Es ist selbst nicht rekursiv, keine der Funktionen ruft sich selbst auf (insbesondere, weil Funktionen nicht benannt sind).
stolzer Haskeller
IMHO, Lambda-Kalkül ist ein Rechenmodell und keine Programmiersprache (dh ohne ein konkretes Maschinenmodell können wir Lambda-Kalkül nicht als PL betrachten).
Ta Thanh Dinh
Sie können absolut eine Maschine bauen, die Lambda-Kalkül interpretiert. Und die Syntax kann als Programmiersprache verwendet werden. Siehe zum Beispiel github.com/MaiaVictor/caramel
Arthur B
10

Haskell, 24 Zeichen

sequence_ (repeat (print "abc"))

oder in komprimierter Form mit 24 Zeichen

sequence_$repeat$print"" 

(Obwohl der Text geändert wird, wird die Schleife fortgesetzt - dies gibt zwei Anführungszeichen und eine neue Zeile unendlich aus.)

Erklärung: print "abc" ist im Grunde eine I / O-Aktion, die nur "abc" ausgibt.
repeat ist eine Funktion, die den Wert x annimmt und eine unendliche Liste mit nur x zurückgibt.
sequence_ ist eine Funktion, die eine Liste von E / A-Aktionen aufnimmt und eine E / A-Aktion zurückgibt, die alle Aktionen nacheinander ausführt.

Im Grunde genommen erstellt dieses Programm eine unendliche Liste von Druckbefehlen "abc" und führt sie wiederholt aus. ohne Schleifen oder Rekursion.

stolzer haskeller
quelle
4
Ich würde im Grunde die gleiche Antwort in Clojure posten, aber ich dachte, es repeatwäre so a programming language statement which allows code to be repeatedly executed.
Siehe auch
3
fix(print"">>)Dies beinhaltet auch keine explizit genannten Wiederholungsfunktionen.
Mittwoch,
1
@TheRare Ich weiß nicht, wie es zu Ende geht, aber in Haskell ist repeat keine "Programmiersprachenanweisung, mit der Code wiederholt ausgeführt werden kann" - es ist eine Funktion, die unendliche Listen generiert. Es ist eine Schleife wie "int [] arr = {x, x, x};" ist eine Schleife.
stolzer Haskeller
1
ja, aber irgendetwas muss
rekursiv
3
Tatsächlich wird jede Funktion, die in diesem Code enthalten ist, mithilfe des
rekursiven
10

ASM (x86 + I / O für Linux)

Es spielt keine Rolle, wie schwer Ihre mickrigen Hochsprachen werden, es wird immer noch nur eine versteckte Manipulation des Befehlszeigers sein. Am Ende wird es eine Art "goto" (jmp) sein, es sei denn, Sie sind gelangweilt genug, um die Schleife in der Laufzeit abzurollen.

Sie können Code auf Ideone testen

Sie können auch eine verfeinerte Version dieser Idee im Matteo Italia-DOS-Code nachlesen .

Es beginnt mit der Zeichenfolge 0..9 und ersetzt sie durch A..J, es werden keine direkten Sprünge verwendet (also sagen wir, es ist kein "goto" aufgetreten), auch keine Wiederholung.

Der Code könnte wahrscheinlich kleiner sein, wenn die Adressberechnung missbraucht wird, aber die Arbeit am Online-Compiler ist lästig, und ich werde ihn so lassen, wie er ist.

Kernteil:

mov dl, 'A' ; I refuse to explain this line!
mov ebx, msg ; output array (string)

call rawr   ; lets put address of "rawr" line on stack
rawr: pop eax ; and to variable with it! In same time we are breaking "ret"

add eax, 4 ; pop eax takes 4 bytes of memory, so for sake of stack lets skip it
mov [ebx], dl ; write letter
inc dl ; and proceed to next 
inc ebx
cmp dl, 'J' ; if we are done, simulate return/break by leaving this dangerous area
jg print

push eax ; and now lets abuse "ret" by making "call" by hand
ret

Ganzer Code

section     .text
global      _start                              

_start:

;<core>
mov dl, 'A'
mov ebx, msg

call rawr
rawr: pop eax

add eax, 4
mov [ebx], dl
inc dl
inc ebx
cmp dl, 'J'
jg print

push eax
ret
;</core>

; just some Console.Write()
print:
    mov     edx,len
    mov     ecx,msg
    mov     ebx,1
    mov     eax,4
    int     0x80

    mov     eax,1
    xor     ebx, ebx
    int     0x80

section     .data

msg     db  '0123456789',0xa
len     equ $ - msg
PTwr
quelle
Ich wollte dies als Dup von codegolf.stackexchange.com/a/34298/11259 bezeichnen , aber ich sehe, dass dies die frühere Antwort ist. +1
Digitales Trauma
@DigitalTrauma oh, ich sehe, dass jemand eine raffinierte Version meiner Idee gemacht hat - ein alter Trick, aber in Zeiten von verwaltetem Code vergessen die Leute oft, wie die Dinge wirklich funktionieren. (Ich mag Golfen nicht, viel zu oft wird es auf "Schau, Mama! Ich kann Sachen passieren, indem ich eine Taste
drücke
9

C Präprozessor

Eine kleine "Technik", die ich mir bei einer Obfuscation Challenge ausgedacht habe. Es gibt keine Funktionsrekursion, aber es gibt ... Dateirekursion?

noloop.c:

#if __INCLUDE_LEVEL__ == 0
int main() 
{
    puts("There is no loop...");
#endif
#if __INCLUDE_LEVEL__ <= 16
    puts(".. but Im in ur loop!");
    #include "noloop.c"
#else
    return 0;
}
#endif

Ich habe das mit gcc geschrieben / getestet. Offensichtlich muss Ihr Compiler das __INCLUDE_LEVEL__Makro (oder alternativ das __COUNTER__Makro mit einigen Optimierungen) unterstützen, damit dies kompiliert werden kann. Es sollte ziemlich offensichtlich sein, wie dies funktioniert, aber zum Spaß sollten Sie den Präprozessor ausführen, ohne den Code zu kompilieren (verwenden Sie das -EFlag mit gcc).

ApproachingDarknessFish
quelle
8

PHP

Hier ist eine mit PHP. Führt eine Schleife durch, indem dieselbe Datei eingeschlossen wird, bis der Zähler $ max erreicht:

<?php
if (!isset($i))
    $i = 0;        // Initialize $i with 0
$max = 10;         // Target value

// Loop body here
echo "Iteration $i <br>\n";

$i++;               // Increase $i by one on every iteration

if ($i == $max)
    die('done');    // When $i reaches $max, end the script
include(__FILE__);  // Proceed with the loop
?>

Das gleiche wie eine for-Schleife:

<?php
for ($i = 0; $i < 10; $i++) {
    echo "Iteration $i <br>\n";
}
die('done');
?>
Pichan
quelle
Verdammt, das zählt auch als Rekursion, nicht wahr?
Pichan
Denken Sie nicht, dass dies der Fall ist - die Ähnlichkeit wird durch das Beispiel von @ Nathaniel deutlich: Der Präprozessor nimmt diese Dateien auf, die dann gleichzeitig ausgewertet werden.
10.
@Pichan Ich würde sagen, es handelt sich eher um das Entfalten einer Schleife, da Sie mit Kopien des Codes im Speicher enden.
PTwr
Ich habe die Frage heute gesehen und fast identischen Code gefunden. Zu spät für mich!
TecBrat
Wird header("Location: .?x=".$_GET['x']+1);als Rekursion gezählt?
Charlie
8

Python

Der folgende Code enthält keine rekursive Funktion (direkt oder indirekt), kein Schleifenprimitiv und ruft keine eingebaute Funktion auf (außer print):

def z(f):
    g = lambda x: lambda w: f(lambda v: (x(x))(v), w)
    return g(g)

if __name__ == "__main__":
    def msg(rec, n):
        if (n > 0):
            print "Hello world!"
            rec(n - 1)
    z(msg)(7)

Druckt "Hallo Welt!" eine bestimmte Anzahl von Malen.

Erläuterung: Die Funktion zimplementiert den strengen Z- Festkomma-Kombinator , mit dem (obwohl nicht rekursiv definiert) ein beliebiger rekursiver Algorithmus ausgedrückt werden kann.

Petr Pudlák
quelle
Ich würde gsehr indirekt rekursiv nennen.
Siehe auch
@TheRare Warum? Was ist dein Argument? Wie nennt gman das gnochmal? Natürlich ist der Trick die Selbstanwendung g(g), aber es gibt keine Rekursion. Würden Sie in der Tat gindirekt rekursiv nennen, wenn Sie nicht gesehen haben g(g)? Dies ist die Standardmethode für Sprachen, die keine rekursiven Definitionen zulassen, z. B. die Lambda-Rechnung.
Petr Pudlák
Sie geben gals Argument xund rufen dann an x(x).
Siehe auch
2
@TheRare Eine Funktion (oder eine Reihe von Funktionen) ist nicht rekursiv oder nicht rekursiv, je nachdem, wie sie verwendet wird. Dies wird nur durch ihre Definition bestimmt.
Petr Pudlák
1
Alle Antworten schummeln auf die eine oder andere Weise: Es gibt immer irgendwo eine Rekursion oder eine Schleife , wenn nicht in der Antwort, dann wird die Antwort im Code aufgerufen. Ich mag die Art und Weise, wie dieser betrügt.
Wayne Conrad
8

z80 Maschinencode

In einer Umgebung, in der Sie an jedem Adress- und Zuordnungs-ROM überall ausführen können, ordnen Sie dem gesamten Adressraum 64 KB ROM mit Nullen zu.

Was es macht: nichts. Wiederholt.

So funktioniert es: Der Prozessor beginnt mit der Ausführung, das Byte 00ist eine nopAnweisung, daher fährt er einfach fort, erreicht die Adresse $ffff, wechselt zu $0000und führt nops weiter aus, bis Sie es zurücksetzen.

Um es etwas interessanter zu machen, füllen Sie den Speicher mit einem anderen Wert (achten Sie darauf, Steuerflussanweisungen zu vermeiden).

Harold
quelle
Sie könnten den Speicher mit Nullen füllen und irgendwo ein echtes Programm einfügen.
Siehe auch
Sie könnten also ein 64-KB-Programm ohne Verzweigung einfügen, das nur wiederholt ausgeführt wird.
Bill Woodger
@ BillWoodger Sie könnten, vor allem, wenn Sie keine Interrupts auf der Plattform haben (oder keine aktiviert)
Harold
Ein bisschen Spaß :-)
Bill Woodger
8

Perl-Regex

(q x x x 10) =~ /(?{ print "hello\n" })(?!)/;

Demo

oder versuchen Sie es als:

perl -e '(q x x x 10) =~ /(?{ print "hello\n" })(?!)/;'

Das (?!)passt nie zusammen. Daher versucht die Regex-Engine, alle Positionen mit der Breite Null in der übereinstimmenden Zeichenfolge abzugleichen.

Das (q x x x 10)ist das Gleiche wie (" " x 10)- Wiederholen Sie die spacezehn Mal.

Bearbeiten: Die "Zeichen" wurden zur besseren Verständlichkeit in Positionen mit der Breite Null geändert . Hier finden Sie Antworten auf diese Stapelüberlauf-Frage .

jm666
quelle
6

T-SQL -12

print 1
GO 9

Eigentlich eher eine Eigenheit von SQL Server Management Studio. GO ist ein Skripttrennzeichen und nicht Teil der T-SQL-Sprache. Wenn Sie GO gefolgt von einer Zahl angeben, wird der Block so oft ausgeführt.

Michael B
quelle
1
Ich benutze T-SQL fast jeden Tag und hatte keine Ahnung, dass Sie dies mit GO tun können. +1
CailinP
Technisch gesehen ist das nicht T-SQL. GOist eigentlich eine SSMS-Direktive, weshalb Sie sie nicht in T-SQL-Skriptobjekte einfügen können, wie beispielsweise eine gespeicherte Prozedur.
RBarryYoung
Ja, das habe ich in meinem Spoiler-Kommentar hinzugefügt. Ich würde mir vorstellen, dass die Verwendung von sqlcmd zu viel Betrug bedeuten würde.
Michael B
6

C #

Gibt alle Ganzzahlen von uint.MaxValue bis 0 aus.

   class Program
   {
      public static void Main()
      {
          uint max = uint.MaxValue;
          SuperWriteLine(ref max);
          Console.WriteLine(0);
      }

      static void SuperWriteLine(ref uint num)
      {
          if ((num & (1 << 31)) > 0) { WriteLine32(ref num); }
          if ((num & (1 << 30)) > 0) { WriteLine31(ref num); }
          if ((num & (1 << 29)) > 0) { WriteLine30(ref num); }
          if ((num & (1 << 28)) > 0) { WriteLine29(ref num); }
          if ((num & (1 << 27)) > 0) { WriteLine28(ref num); }
          if ((num & (1 << 26)) > 0) { WriteLine27(ref num); }
          if ((num & (1 << 25)) > 0) { WriteLine26(ref num); }
          if ((num & (1 << 24)) > 0) { WriteLine25(ref num); }
          if ((num & (1 << 23)) > 0) { WriteLine24(ref num); }
          if ((num & (1 << 22)) > 0) { WriteLine23(ref num); }
          if ((num & (1 << 21)) > 0) { WriteLine22(ref num); }
          if ((num & (1 << 20)) > 0) { WriteLine21(ref num); }
          if ((num & (1 << 19)) > 0) { WriteLine20(ref num); }
          if ((num & (1 << 18)) > 0) { WriteLine19(ref num); }
          if ((num & (1 << 17)) > 0) { WriteLine18(ref num); }
          if ((num & (1 << 16)) > 0) { WriteLine17(ref num); }
          if ((num & (1 << 15)) > 0) { WriteLine16(ref num); }
          if ((num & (1 << 14)) > 0) { WriteLine15(ref num); }
          if ((num & (1 << 13)) > 0) { WriteLine14(ref num); }
          if ((num & (1 << 12)) > 0) { WriteLine13(ref num); }
          if ((num & (1 << 11)) > 0) { WriteLine12(ref num); }
          if ((num & (1 << 10)) > 0) { WriteLine11(ref num); }
          if ((num & (1 << 9)) > 0) { WriteLine10(ref num); }
          if ((num & (1 << 8)) > 0) { WriteLine09(ref num); }
          if ((num & (1 << 7)) > 0) { WriteLine08(ref num); }
          if ((num & (1 << 6)) > 0) { WriteLine07(ref num); }
          if ((num & (1 << 5)) > 0) { WriteLine06(ref num); }
          if ((num & (1 << 4)) > 0) { WriteLine05(ref num); }
          if ((num & (1 << 3)) > 0) { WriteLine04(ref num); }
          if ((num & (1 << 2)) > 0) { WriteLine03(ref num); }
          if ((num & (1 <<  1)) > 0) { WriteLine02(ref num); }
          if ((num & (1 <<  0)) > 0) { WriteLine01(ref num); }
      }

      private static void WriteLine32(ref uint num) { WriteLine31(ref num); WriteLine31(ref num); }
      private static void WriteLine31(ref uint num) { WriteLine30(ref num); WriteLine30(ref num); }
      private static void WriteLine30(ref uint num) { WriteLine29(ref num); WriteLine29(ref num); }
      private static void WriteLine29(ref uint num) { WriteLine28(ref num); WriteLine28(ref num); }
      private static void WriteLine28(ref uint num) { WriteLine27(ref num); WriteLine27(ref num); }
      private static void WriteLine27(ref uint num) { WriteLine26(ref num); WriteLine26(ref num); }
      private static void WriteLine26(ref uint num) { WriteLine25(ref num); WriteLine25(ref num); }
      private static void WriteLine25(ref uint num) { WriteLine24(ref num); WriteLine24(ref num); }
      private static void WriteLine24(ref uint num) { WriteLine23(ref num); WriteLine23(ref num); }
      private static void WriteLine23(ref uint num) { WriteLine22(ref num); WriteLine22(ref num); }
      private static void WriteLine22(ref uint num) { WriteLine21(ref num); WriteLine21(ref num); }
      private static void WriteLine21(ref uint num) { WriteLine20(ref num); WriteLine20(ref num); }
      private static void WriteLine20(ref uint num) { WriteLine19(ref num); WriteLine19(ref num); }
      private static void WriteLine19(ref uint num) { WriteLine18(ref num); WriteLine18(ref num); }
      private static void WriteLine18(ref uint num) { WriteLine17(ref num); WriteLine17(ref num); }
      private static void WriteLine17(ref uint num) { WriteLine16(ref num); WriteLine16(ref num); }
      private static void WriteLine16(ref uint num) { WriteLine15(ref num); WriteLine15(ref num); }
      private static void WriteLine15(ref uint num) { WriteLine14(ref num); WriteLine14(ref num); }
      private static void WriteLine14(ref uint num) { WriteLine13(ref num); WriteLine13(ref num); }
      private static void WriteLine13(ref uint num) { WriteLine12(ref num); WriteLine12(ref num); }
      private static void WriteLine12(ref uint num) { WriteLine11(ref num); WriteLine11(ref num); }
      private static void WriteLine11(ref uint num) { WriteLine10(ref num); WriteLine10(ref num); }
      private static void WriteLine10(ref uint num) { WriteLine09(ref num); WriteLine09(ref num); }
      private static void WriteLine09(ref uint num) { WriteLine08(ref num); WriteLine08(ref num); }
      private static void WriteLine08(ref uint num) { WriteLine07(ref num); WriteLine07(ref num); }
      private static void WriteLine07(ref uint num) { WriteLine06(ref num); WriteLine06(ref num); }
      private static void WriteLine06(ref uint num) { WriteLine05(ref num); WriteLine05(ref num); }
      private static void WriteLine05(ref uint num) { WriteLine04(ref num); WriteLine04(ref num); }
      private static void WriteLine04(ref uint num) { WriteLine03(ref num); WriteLine03(ref num); }
      private static void WriteLine03(ref uint num) { WriteLine02(ref num); WriteLine02(ref num); }
      private static void WriteLine02(ref uint num) { WriteLine01(ref num); WriteLine01(ref num); }
      private static void WriteLine01(ref uint num) { Console.WriteLine(num--); }
   }
LVBen
quelle
1
Ich weiß nicht wirklich, ob das zählt. Sie rufen explizit die WriteLine01 Int.MaxValue-Zeiten auf. Es explodierte gerade hinter einer massiven Menge von Callstack.
Michael B
Wie zählt es nicht? Es gibt keine Schleife und keine Rekursion.
LVBen
1
Außerdem ist der Call-Stack nicht annähernd massiv, es sei denn, Sie halten 32 Calls für massiv.
LVBen
1
Warum nur 32 mal statt 4294967296 mal?
LVBen
4
@ ja72 Wenn ich jemals an einem Open-Source-Projekt arbeite, in dem ich keine Schleifen oder Rekursionen verwenden kann, dann werde ich einen solchen Code voll und ganz beisteuern!
LVBen
6

JS (im Browser)

Wie wäre es damit?

document.write(new Date());
location = location;

Druckt die aktuelle Uhrzeit und lädt die Seite neu.

Pichan
quelle
Oh, schieß. Ich habe gerade eine Antwort mit dem gleichen Grundkonzept gepostet. Ich habe die Seite nach "JavaScript" oder etwas anderem durchsucht, das HTML-Tags enthält. Ich nehme an, ich lasse meine Antwort offen, nur weil sie den Eckfall behandelt, in dem der Ort ein "#" enthält. Wie auch immer, +1.
Keen
In Firefox 30:[Exception... "The operation is insecure." code: "18" nsresult: "0x80530012 (SecurityError)" location: "<unknown>"]
Alex Reynolds
@ AlexReynolds Huh, komisch. Meins funktioniert gut für FF 30.
Pichan
Ich habe Ihren Code nur so kopiert und eingefügt, wie er geschrieben wurde. Es funktioniert nicht Vielleicht haben Sie einige spezielle Sicherheitseinstellungen aktiviert, damit dies funktioniert?
Alex Reynolds
@AlexReynolds Nein, hat nie Sicherheitseinstellungen geändert. Und es funktioniert auch auf Chrome.
Pichan