Ένα πρόγραμμα Quine ή Quine είναι ένα πρόγραμμα που εξάγει τον δικό του πηγαίο κώδικα όταν εκτελείται. Ένα Quine δεν μπορεί να "βγαίνει έξω από τον εαυτό του", για παράδειγμα, εκτυπώνοντας τα περιεχόμενα του αρχείου που το περιέχει ή χρησιμοποιώντας ενδοσκοπικές ικανότητες για να εκτυπώσει τη δική του αναπαράσταση. Αντίθετα, πρέπει να υπολογίσει τον δικό του πηγαίο κώδικα.
Ο κλασικός τρόπος δημιουργίας ενός τέτοιου προγράμματος γίνεται σε δύο βήματα:
- Αρχικοποιήστε μια μεταβλητή συμβολοσειράς με ένα σύμβολο κράτησης θέσης για παρεμβολή.
- Εκτυπώστε τη συμβολοσειρά και παρεμβάλετε την στον εαυτό της .
Το κόλπο είναι να βγάλεις σωστά τη χορδή. Ο τρόπος με τον οποίο γίνεται αυτό διαφέρει από γλώσσα σε γλώσσα και εξαρτάται από τον τρόπο δήλωσης της μεταβλητής, την ανάγκη για ερωτηματικά και νέες γραμμές, τα απαιτούμενα εισαγωγικά κ.λπ. Η χρήση εισαγωγικών είναι ενδιαφέρουσα. Κάποιος πρέπει να βρει έναν τρόπο να υποδείξει ότι ένα εισαγωγικό πρέπει να τυπωθεί χωρίς στην πραγματικότητα να χρησιμοποιηθεί εισαγωγικό.
Βίαιο χτύπημα
Όπως τα περισσότερα πράγματα στο Bash, αυτό το πρόγραμμα χρησιμοποιεί μια ενδιαφέρουσα ιδιορρυθμία. Αν και τα μεμονωμένα εισαγωγικά είναι ισχυρά εισαγωγικά και δεν επεκτείνουν τίποτα, ερμηνευμένα printf
οκταδικοί χαρακτήρες διαφυγής ως χαρακτήρες με το καθορισμένο σημείο κώδικα:
s='s=%s;printf "$s" "$s"';printf "$s" "$s"
Πύθων
Στην Python, ο προσδιοριστής μορφής επιστρέφει %r
αυτόματα μεμονωμένα εισαγωγικά. Είναι πιο εύκολο αν ο κώδικας τελειώνει με χαρακτήρα νέας γραμμής:
s='s=%r;print(s%%s)';print(s%s)
Αν θέλετε τον κώδικα χωρίς αλλαγές γραμμής, πρέπει να γράψετε τα εξής:
s='s=%r;print(s%%s,sep="")';print(s%s,sep="")
JavaScript
Τα ακόλουθα quines JavaScript τρέχουν στο node.js. χρησιμοποιείτε console.log
, που πάντα προσθέτει μια νέα γραμμή, επομένως χρειάζεται μια νέα γραμμή στο τέλος κάθε σεναρίου:
s="s=%j;console.log(s,s)";console.log(s,s)
Το παρακάτω πρόγραμμα είναι επίσης ενδιαφέρον: δεν εκτυπώνει ολόκληρη την αναπαράστασή του, αλλά βασίζεται στο γεγονός ότι οι συναρτήσεις έχουν μια συγκεκριμένη αναπαράσταση:
(function a(){console.log('('+a+')()')})()
Το επόμενο παράδειγμα είναι κοντά στην εξαπάτηση γιατί eval
μεταχειρισμένος:
code='var q=unescape("%27");console.log("code="+q+code+q+";eval(code)")';eval(code)
Σκωρία
Το Rust παρέχει έναν τρόπο να περικλείει ένα όρισμα σε εισαγωγικά στη μορφοποιημένη μακροεντολή εκτύπωσης. Ωστόσο, αυτή η μακροεντολή απαιτεί το πρώτο όρισμα της μακροεντολής εκτύπωσης να είναι κυριολεκτική συμβολοσειρά! Επομένως, είναι καλύτερο να χρησιμοποιήσετε το αναγνωριστικό όρισμα θέσης:
fn main(){print!("fn main(){{print!({0:?},{0:?})}}","fn main(){{print!({0:?},{0:?})}}")}
PHP
Αυτό το πρόγραμμα PHP λειτουργεί αποθηκεύοντας τον πηγαίο κώδικα σε μια συμβολοσειρά και στη συνέχεια χρησιμοποιώντας αυτήν τη συμβολοσειρά printf
εξόδους. Ο 39
αντιπροσωπεύει τον χαρακτήρα ASCII '
, για να χειριστεί σωστά τα εισαγωγικά στη συμβολοσειρά:
<?php
$code = '<?php
$code = %c%s%c;
printf($code, 39, $code, 39);
';
printf($code, 39, $code, 39);
HQ9+
Τελευταίο αλλά εξίσου σημαντικό είναι το HQ9+, που αναπτύχθηκε από τον Cliff Biffle:
Q