यह उत्तर मेरे और 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}
इसे तोड़कर, Q
2 नंबर 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 के बीच कोई संख्या नहीं है और I
2 सहित, लेकिन ऐसा नहीं है I
जो विभाजित हो I
।
अगले विधेय भी बहुत सरल है
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
हम findnsols
पहले N
नंबरों को खोजने के लिए उपयोग करते हैं जो प्राइम हैं, हम फिर अंतिम एक को वापस करते हैं। यहाँ ट्रिक यह है कि सबसे छोटे प्राइम findnsols
को खोजने की गारंटी नहीं है , क्योंकि SWI को जिस तरह से हैंडल किया जाता है, वह हमेशा छोटे प्राइमर को जल्द ही खोज लेगा। हालांकि इसका मतलब है कि हमें इसे और अधिक खोज करने से रोकने के लिए काटना होगा। N
between
गोल्फ
हम अपने कोड में दो बार कारण बता सकते हैं। चूंकि isprime
केवल एक बार उपयोग किया जाता है, इसलिए इसकी परिभाषा को अंदर ले जाया जा सकता है prime
। अगले एक को prime
सीधे डीसीजी के अंदर ले जाना है , हालांकि जब से हम बहुत सारे अपराधों को पैदा prime
करने से रोकने के लिए कटौती का उपयोग findnsols
करते हैं, तो हमारे पास एक मुद्दा है। कटौती, केवल उस बिट के बजाय पूरे डीसीजी को काटती है जो हम चाहते हैं। दस्तावेज के थोड़ा खुदाई के बाद हमने पाया कि once/1
इस हिस्से को काटने के लिए इस्तेमाल किया जा सकता है लेकिन पूरे डीसीजी में नहीं। हालाँकि अधिक दस्तावेज खुदाई से पता चला है कि ->
ऑपरेटर का उपयोग एक समान कार्य करने के लिए भी किया जा सकता है। ->
ऑपरेटर मोटे तौर पर के बराबर है ,!,
तो हम के दूसरी तरफ हमारे कटौती ले जाया गया append/3
और साथ बदल दिया ->
।
SWI- प्रोलॉग में भविष्यवाणी (और नियम) ऑपरेटर को नाम के रूप में दे सकते हैं जो हमें आवश्यक रूप से आवश्यक कोष्ठकों को छोड़ने की अनुमति देता है। जिससे हम नियम को कॉल करके 6 बाइट बचा सकते हैं \
।