คำตอบนี้เป็นส่วนหนึ่งของการทำงานร่วมกันระหว่างฉันกับ 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}.
ลองออนไลน์!
คำอธิบาย
คำตอบนี้เป็นแบบอย่างที่สมบูรณ์แบบของสิ่งที่ทำให้การเล่นกอล์ฟเป็นไปอย่างสนุกสนาน
คำตอบนี้ใช้ระบบที่มีประสิทธิภาพ Prologs สำหรับไวยากรณ์ประโยคที่ชัดเจน นี่คือหลักไวยากรณ์ของเรา
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)-->[].
สิ่งนี้จะบอก Prolog ว่าสตริงว่างสอดคล้องกับ 1
กฎการก่อสร้างข้อที่สองของเราซับซ้อนกว่าเล็กน้อย
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
สิ่งนี้บอกเราว่าสตริงที่ไม่ว่างใด ๆ มีวงเล็บอยู่รอบ clause ด้วยกฎเดียวกันนี้ทางด้านขวาของ clause ที่มีกฎเดียวกันเหล่านี้
นอกจากนี้ยังบอกเราว่ามูลค่าของข้อนี้ ( Q
) เป็นไปตามกฎ:
{prime(N,Y),Q is Y*B}
หมดสภาพนี้Q
เป็นผลิตภัณฑ์ของ 2 ตัวเลขและ Y
เป็นเพียงค่าของส่วนคำสั่งทางด้านซ้ายและเป็นส่วนที่สำคัญที่เป็นค่าของส่วนคำสั่งในวงเล็บB
B
Y
N
N
กฎนี้ครอบคลุมทั้งกฎการก่อตัวของทรีแฟคเตอร์
- การต่อข้อมูลแบบทวีคูณ
- สิ่งที่แนบมาใช้เวลาที่สำคัญที่
ตอนนี้สำหรับคำจำกัดความของคำกริยา ในเวอร์ชั่นที่ไม่ดีมีสองภาคที่เล่น (ในรหัสจริงของฉันฉันไปข้างหน้าล่ามโซ่ภาคไป) เพรดิเคตที่เกี่ยวข้องทั้งสองที่นี่คือisprime/1
ซึ่งตรงกับจำนวนเฉพาะและprime/2
ที่กำหนดN
และY
ตรงกับ iff Y
คือN
th ไพรม์ ก่อนอื่นเรามี
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
ผลงานของคำนิยามมาตรฐานสวยของ primality นี้เรายืนยันว่ามีจำนวนระหว่าง 2 และไม่I
รวมถึง 2 แต่ไม่ว่าแบ่งI
I
ภาคต่อไปนี้ก็ค่อนข้างง่าย
prime(N,Y):-
findnsols(N,I,(
between(2,inf,I),
isprime(I)
),L),
append(_,[Y],L),!.
เราใช้findnsols
เพื่อหาN
ตัวเลขแรกที่เป็นจำนวนเฉพาะเราจะคืนค่าตัวเลขสุดท้าย เคล็ดลับที่นี่คือในขณะที่findnsols
ไม่รับประกันว่าจะหาช่วงเวลาที่น้อยที่สุด N
เพราะวิธีการที่ SWI จัดการbetween
นั้นจะพบช่วงเวลาที่เล็กกว่าในไม่ช้า อย่างไรก็ตามนี่หมายความว่าเราต้องตัดเพื่อป้องกันไม่ให้หาช่วงเวลาที่มากขึ้น
นักกอล์ฟ
เราสามารถส่งต่อเหตุผลในรหัสของเราสองครั้ง ตั้งแต่ใช้เพียงครั้งเดียวหมายของมันสามารถเคลื่อนย้ายภายในของisprime
prime
สิ่งต่อไปคือการย้ายprime
โดยตรงภายใน DCG อย่างไรก็ตามเนื่องจากเราใช้การตัดprime
เพื่อป้องกันfindnsols
การผลิตช่วงเวลาที่มากเกินไปเราจึงมีปัญหาเล็กน้อย การตัดเป็นการลด DCG ทั้งหมดแทนที่จะเป็นบิตที่เราต้องการ หลังจากการขุดเอกสารเล็กน้อยเราพบว่าonce/1
สามารถใช้ตัดส่วนนี้ได้ แต่ไม่ใช่ DCG ทั้งหมด อย่างไรก็ตามการขุดเอกสารเพิ่มเติมพบว่า->
ผู้ปฏิบัติงานสามารถใช้เพื่อทำงานที่คล้ายกันได้ ->
ผู้ประกอบการคือประมาณเทียบเท่ากับ,!,
เพื่อให้เราย้ายไปตัดของเราไปยังด้านอื่น ๆ ของและแทนที่ด้วยappend/3
->
ใน SWI-Prolog predicates (และกฎ) สามารถให้โอเปอเรเตอร์เป็นชื่อซึ่งช่วยให้เราสามารถวางวงเล็บที่จำเป็นตามปกติ ดังนั้นเราสามารถบันทึก 6 \
ไบต์โดยการเรียกกฎ