سؤال

لقد رأيت الكثير من الحلول المستندة إلى C/C++ لهذه المشكلة حيث يتعين علينا كتابة برنامج يقوم عند التنفيذ بطباعة مصدره الخاص.

بعض الحلول--

http://www.cprogramming.com/challenges/solutions/self_print.html

حل Quine Page بعدة لغات

وهناك العديد من الحلول على الشبكة، كل منها يختلف عن الآخر.وأتساءل كيف نتعامل مع مثل هذه المشكلة، وما الذي يدور في ذهن من يحلها.أعطني بعض الأفكار حول هذه المشكلة ...في حين أن الحلول باللغات المترجمة مثل Perl وphp وRuby وما إلى ذلك قد تكون سهلة...أود أن أعرف كيف يمكن للمرء تصميمه باللغات المجمعة ...

هل كانت مفيدة؟

المحلول

وبصرف النظر عن الغش¹، لا يوجد فرق بين اللغات المترجمة والمترجمة.

النهج العام للكوينز سهل للغاية.أولاً، مهما كان شكل البرنامج، فإنه في مرحلة ما يجب عليه طباعة شيء ما:

print ...

ومع ذلك، ما الذي يجب طباعته؟بحد ذاتها.لذلك يحتاج إلى طباعة أمر "الطباعة":

print "print ..."

ما الذي يجب طباعته بعد ذلك؟حسنًا، في غضون ذلك، نما البرنامج، لذلك يحتاج إلى طباعة السلسلة التي تبدأ بـ "print" أيضًا:

print "print \"print ...\""

الآن نما البرنامج مرة أخرى، لذلك هناك المزيد لطباعته مرة أخرى:

print "print \"print \\\"...\\\"\""

وما إلى ذلك وهلم جرا.مع كل رمز مضاف هناك المزيد من التعليمات البرمجية للطباعة.هذا النهج لا يحصل على أي مكان ، لكنه يكشف عن نمط مثير للاهتمام:يتم تكرار السلسلة "print \"" مرارًا وتكرارًا.سيكون من الجيد وضع الجزء المتكرر في متغير:

a = "print \""
print a

ومع ذلك ، تغير البرنامج للتو ، لذلك نحن بحاجة إلى ضبط أ:

a = "a = ...\nprint a"
print a

عندما نحاول الآن ملء "..." ، نواجه نفس المشكلات كما كان من قبل.في النهاية، نريد أن نكتب شيئًا كهذا:

a = "a = " + (quoted contents of a) + "\nprint a"
print a

لكن هذا غير ممكن ، لأنه حتى لو كان لدينا مثل هذه الوظيفة quoted() للاقتباس ، لا تزال هناك المشكلة التي نحددها a من حيث نفسه:

a = "a = " + quoted(a) + "\nprint a"
print a

لذا فإن الشيء الوحيد الذي يمكننا فعله هو وضع حامل المكان فيه a:

a = "a = @\nprint a"
print a

وهذه هي الحيلة كلها!وأي شيء آخر أصبح واضحا الآن.ببساطة استبدال حامل المكان بمحتويات مقتبسة a:

a = "a = @\nprint a"
print a.replace("@", quoted(a))

نظرًا لأننا قمنا بتغيير الكود ، نحتاج إلى ضبط السلسلة:

a = "a = @\nprint a.replace(\"@\", quoted(a))"
print a.replace("@", quoted(a))

وهذا كل شيء!جميع Quines بجميع اللغات تعمل بهذه الطريقة (باستثناء اللغات الغش).

حسنًا ، يجب عليك التأكد من استبدالك فقط أول حدوث صاحب المكان.وإذا كنت تستخدم حامل المركز الثاني ، فيمكنك تجنب الحاجة إلى اقتباس السلسلة.

ولكن هذه قضايا بسيطة وسهلة حلها.إذا كان الأمر واقعا، فإن تحقيق quoted() و replace()هي التفاصيل الوحيدة التي تختلف فيها الأنواع المختلفة حقًا.


¹ بجعل البرنامج يقرأ الملف المصدر الخاص به

نصائح أخرى

هناك استراتيجيتان مختلفتان لكتابة القصائد.الأمر الواضح هو كتابة الكود الذي يفتح الكود ويطبعه.لكن الميزات الأكثر إثارة للاهتمام تتضمن ميزات اللغة التي تسمح بالتضمين الذاتي، مثل ميزة printf بنمط %s في العديد من اللغات.يجب عليك معرفة كيفية تضمين شيء ما بحيث ينتهي به الأمر إلى تلبية طلب تضمينه.أظن أن هناك الكثير من التجارب والخطأ، مثل المتناظرات.

يمكنك أيضًا دراسة كيفية عمل لعبة Core Wars.أعتقد أنه سيكون مثالاً جيدًا.

الطريقة المعتادة (عندما لا تستطيع الغش*) هي كتابة شيء يشفر مصدره في ثابت سلسلة، ثم طباعة هذا الثابت مرتين:مرة واحدة كسلسلة حرفية، ومرة ​​واحدة كرمز.هذا يدور حول "في كل مرة أكتب فيها سطرًا من التعليمات البرمجية ، يجب أن أكتب آخر لطباعته!" مشكلة.

"الغش" يشمل:- استخدام لغة تفسير و ببساطة تحميل المصدر وطباعته - ملفات طويلة 0 بايت ، وهي صالحة في بعض اللغات ، مثل C.

من أجل المتعة، توصلت إلى واحدة في Scheme، والتي كنت فخورة بها لمدة 5 دقائق تقريبًا حتى اكتشفت أنه تم اكتشافها من قبل.على أي حال، هناك تعديل طفيف على "قواعد" اللعبة من أجل حساب أفضل لازدواجية البيانات والتعليمات البرمجية في Lisp:بدلاً من طباعة مصدر البرنامج، فهو عبارة عن تعبير S يُرجع نفسه:

((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))

ال واحد على ويكيبيديا له نفس المفهوم، ولكن مع آلية مختلفة قليلاً (أكثر تفصيلاً) للاقتباس.أنا أحب بلدي أفضل بالرغم من ذلك.

إحدى الأفكار التي يجب التفكير فيها هي التشفير وكيفية إعطاء شيء ما معنى مزدوجًا بحيث يمكن استخدامه لإخراج شيء ما في عدة أشكال.هناك أيضًا تحذير بأن هذا النوع من المشكلات يأتي مع قيود لجعل الأمر أكثر صعوبة، حيث أنه بدون أي قواعد بخلاف مخرجات البرنامج نفسه، فإن البرنامج الفارغ هو الحل.

يمكنك العثور على عدد غير قليل من الحلول لهذا هنا: http://forums.thedailywtf.com/forums/p/5232/147528.aspx

ماذا عن قراءة وطباعة كود المصدر الخاص بك فعليًا؟الأمر ليس صعباً على الإطلاق!!هنا واحد في PHP:

<?php
{
header("Content-Type: text/plain");
    $f=fopen("5.php","r");
    while(!feof($f))
    {
        echo fgetc($f);
    } 
    fclose($f);
}
?>

في بايثون يمكنك الكتابة:

s='c=chr(39);print"s="+c+s+c+";"+s';c=chr(39);print"s="+c+s+c+";"+s

مستوحاة من هذا الكود الزائف الذي يطبع ذاتيًا:

Print the following line twice, the second time with quotes.
"Print the following line twice, the second time with quotes."

لقد قمت بعمل مثال AS3 للمهتمين بهذا

var program = "var program = @; function main(){trace(program.replace('@', 

String.fromCharCode(34) + program + String.fromCharCode(34)))} main()"; 
function main(){
   trace(program.replace('@', String.fromCharCode(34) + program + String.fromCharCode(34)))
}
main()

في روبي:

يضع File.read(_ _ FILE _ _)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top