यह उत्तर मेरे और 0 के बीच एक सहयोग का हिस्सा है। हम दोनों ने इस पर एक साथ काम किया, इसका एकमात्र कारण मैं इसे पोस्ट कर रहा हूं क्योंकि मैंने रॉक, पेपर, कैंची जीती है।
\Q-->{Q=1};"(",\N,")",\B,{findnsols(N,I,(between(2,inf,I),\+ (between(3,I,U),0=:=I mod(U-1))),L)->append(_,[Y],L),Q is Y*B}.
इसे ऑनलाइन आज़माएं!
व्याख्या
यह जवाब प्रोलॉग फन में गोल्फ बनाने के लिए एक उत्तम उदाहरण है।
यह उत्तर निश्चित खंडों के व्याकरण के लिए प्रोलॉग्स शक्तिशाली प्रणाली का उपयोग करता है। यहाँ हमारा व्याकरण थोड़ा असंगठित है।
head(1)-->[].
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
पहला निर्माण नियम है:
head(1)-->[].
यह प्रोलॉग को बताता है कि खाली स्ट्रिंग 1 से मेल खाती है।
हमारे निर्माण का दूसरा नियम एक छोटे से अधिक जटिल है।
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
यह हमें बताता है कि किसी भी गैर रिक्त स्ट्रिंग में इन समान नियमों के साथ खंड के चारों ओर कोष्ठक होते हैं, इन समान नियमों के साथ खंड के दाईं ओर।
यह हमें यह भी बताता है कि इस खंड का मूल्य ( Q) नियम का अनुसरण करता है:
{prime(N,Y),Q is Y*B}
इसे तोड़कर, Q2 नंबर Yऔर का उत्पाद है B। Bबाईं ओर दिए गए खंड का मूल्य है और Yवह Nमुख्य है जहां Nकोष्ठक के अंदर खंड का मूल्य है।
यह नियम फैक्टर ट्री के गठन के नियमों को शामिल करता है
- संघटन गुणन
- संलग्नक nth प्राइम लेता है
अब विधेय परिभाषाओं के लिए। अनगुल्ड वर्जन में प्ले पर दो डेडिकेटेड होते हैं (अपने वास्तविक कोड में मैंने आगे की ओर प्रेडिकेट को जंजीर से बांध दिया है)। यहाँ दो प्रासंगिक विधेय हैं isprime/1, जो एक अभाज्य संख्या से मेल खाते हैं, और prime/2, जो, दिए गए Nऔर Y, यदि तत्कालीन अभाज्य Yहै , से मेल खाता है N। पहले हमारे पास है
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
यह एक बहुत ही मानक परिभाषा का काम करता है, हम जोर देकर कहते हैं कि 2 के बीच कोई संख्या नहीं है और I2 सहित, लेकिन ऐसा नहीं है Iजो विभाजित हो I।
अगले विधेय भी बहुत सरल है
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
हम findnsolsपहले Nनंबरों को खोजने के लिए उपयोग करते हैं जो प्राइम हैं, हम फिर अंतिम एक को वापस करते हैं। यहाँ ट्रिक यह है कि सबसे छोटे प्राइम findnsolsको खोजने की गारंटी नहीं है , क्योंकि SWI को जिस तरह से हैंडल किया जाता है, वह हमेशा छोटे प्राइमर को जल्द ही खोज लेगा। हालांकि इसका मतलब है कि हमें इसे और अधिक खोज करने से रोकने के लिए काटना होगा। Nbetween
गोल्फ
हम अपने कोड में दो बार कारण बता सकते हैं। चूंकि isprimeकेवल एक बार उपयोग किया जाता है, इसलिए इसकी परिभाषा को अंदर ले जाया जा सकता है prime। अगले एक को primeसीधे डीसीजी के अंदर ले जाना है , हालांकि जब से हम बहुत सारे अपराधों को पैदा primeकरने से रोकने के लिए कटौती का उपयोग findnsolsकरते हैं, तो हमारे पास एक मुद्दा है। कटौती, केवल उस बिट के बजाय पूरे डीसीजी को काटती है जो हम चाहते हैं। दस्तावेज के थोड़ा खुदाई के बाद हमने पाया कि once/1इस हिस्से को काटने के लिए इस्तेमाल किया जा सकता है लेकिन पूरे डीसीजी में नहीं। हालाँकि अधिक दस्तावेज खुदाई से पता चला है कि ->ऑपरेटर का उपयोग एक समान कार्य करने के लिए भी किया जा सकता है। ->ऑपरेटर मोटे तौर पर के बराबर है ,!,तो हम के दूसरी तरफ हमारे कटौती ले जाया गया append/3और साथ बदल दिया ->।
SWI- प्रोलॉग में भविष्यवाणी (और नियम) ऑपरेटर को नाम के रूप में दे सकते हैं जो हमें आवश्यक रूप से आवश्यक कोष्ठकों को छोड़ने की अनुमति देता है। जिससे हम नियम को कॉल करके 6 बाइट बचा सकते हैं \।