เติมแถวคอลัมน์และเส้นทแยงมุมของตาราง NxN ด้วย 1 ถึง N


26

งาน

รับอินพุต N สร้างและส่งออกตาราง NxN โดยที่แต่ละแถวคอลัมน์และเส้นทแยงมุมทั้งสองมีตัวเลข 1 ถึงN(หรือ 0 ถึงN−1 ถ้าง่ายกว่า)

อินพุต

Nการป้อนข้อมูลที่เป็นจำนวนเต็มบวก เพราะมันหมายถึงจำนวนคอลัมน์และแถวในตาราง สำหรับปัญหานี้คุณสามารถสันนิษฐานNได้ว่ามีขนาดที่เหมาะสม4 ≤ N ≤ 8หรือ ( 1 ≤ N ≤ 8หากคุณไปเพื่อรับโบนัสด้านล่าง)

เอาท์พุต

ผลลัพธ์จะเป็นกริดN× Nในตารางแต่ละแถวมีเพียงตัวเลข 1 ถึงNแต่ละคอลัมน์มีเพียงหมายเลข 1 ไปNและทั้งสองเส้นทแยงมุมของความยาวN(หนึ่งจาก(0,0)ไป(N-1,N-1)และจาก(0,N-1)ไป(N-1, 0)) เพียง แต่มีตัวเลข 1 Nถึง คุณสามารถใช้หมายเลข 0 N−1ไป สำหรับแต่ละวิธีNมีวิธีแก้ปัญหาที่เป็นไปได้มากมายคุณจะต้องพิมพ์วิธีแรกที่คุณพบ คุณไม่จำเป็นต้องพิมพ์ช่องว่างระหว่างตัวเลข

ข้อ จำกัด

รหัสของคุณควรจะให้ผลลัพธ์ซ้ำN >= 7ๆ นั่นคือถ้าคุณสามารถเรียกใช้และได้รับการแก้ไขN = 7จากรหัสของคุณในแต่ละครั้งคุณก็ดี ในแง่ของการ จำกัด แน่นอนรหัสของคุณควรจะสามารถแก้ไขได้N = 7ภายใน 10 นาทีในแต่ละครั้งที่คุณเรียกใช้ (เช่นถ้าคุณขึ้นอยู่กับตัวเลขสุ่มสำหรับกรณีที่เลวร้ายที่สุดรหัสของคุณควรจะเสร็จภายใน 10 นาทีN = 7) .

ตัวอย่าง

  • การป้อนข้อมูล: 4

    หนึ่งเอาต์พุตที่เป็นไปได้:

    1 2 3 4
    3 4 1 2
    4 3 2 1
    2 1 4 3
    
  • การป้อนข้อมูล: 5

    หนึ่งเอาต์พุตที่เป็นไปได้:

    1 2 3 4 5
    5 3 1 2 4
    2 5 4 3 1
    4 1 2 5 3
    3 4 5 1 2
    
  • การป้อนข้อมูล: 8

    หนึ่งเอาต์พุตที่เป็นไปได้:

    1 2 3 4 5 6 7 8
    2 3 1 5 4 8 6 7
    4 1 2 3 7 5 8 6
    6 4 7 8 1 2 3 5
    7 5 8 2 6 3 4 1
    5 8 4 6 2 7 1 3
    8 7 6 1 3 4 5 2
    3 6 5 7 8 1 2 4
    

เกณฑ์การให้คะแนน

นี่คือดังนั้นรหัสที่สั้นที่สุดในหน่วยไบต์ชนะด้วยข้อยกเว้นหนึ่งข้อ สำหรับอินพุตN = 2, 3ไม่มีโซลูชันที่ถูกต้อง หากรหัสของคุณสามารถจัดการกับสิ่งนี้ได้ (เรียกใช้ให้เสร็จสิ้นโดยไม่ต้องแสดงผลลัพธ์ใด ๆ สำหรับกรณีเหล่านี้หรือส่งออกสตริงว่างเปล่า) และยังคงจัดการN = 1(เอาท์พุท1ของมัน) ให้ลดจำนวนไบต์ลง 20%


1
ที่เกี่ยวข้องแต่กริดดังกล่าวจะไม่ทำงานที่นี่เพราะข้อกำหนดของเส้นทแยงมุม
xnor

ฉันชอบความท้าทายนี้ แต่ฉันไม่สามารถหาอัลกอริทึมสำหรับค่าที่Nเท่ากันได้ รหัส JavaScript นี้ใช้งานได้N = 1, 5 or 7แม้ว่าจะช่วยให้ทุกคน:for(o="",y=N;y--;o+="\n")for(x=N;x--;)o+=(((N-y)*2+x)%N)+1
user81655

ซ้ำกันมากที่เกี่ยวข้องและเป็นไปได้: codegolf.stackexchange.com/q/47846/15599
เลเวลริเวอร์เซนต์

@ สตีฟเวอร์ริลล์นั่นไม่ได้เป็นรหัสกอล์ฟ
Randomra

1
บางทีคุณควรจะมีความชัดเจนมากขึ้นเกี่ยวกับN = 1กรณีนี้: คำตอบที่เป้าหมายสำหรับโบนัสควรกลับมา1ไม่ใช่สตริงว่าง
ลินน์

คำตอบ:


3

Python 3, 275 260 Bytes * 0.8 = 220 208 Bytes

แนวทางแบบเรียกซ้ำ / ย้อนรอย Rเป็นฟังก์ชั่นวนซ้ำlคือ coLumn wคือ roW Kเป็นรายการถัดไป

ฉันเลือกที่จะใส่ไว้ในอาร์เรย์ที่ 1d และพิมพ์สวยในตอนท้ายเพื่อทำให้ดัชนีง่ายขึ้น

r=range
n=(int)(input())
def R(A,I):
 l=I%n;w=I//n
 if I==n*n:[print(A[i*n:i*n+n])for i in r(n)];exit()
 for K in r(n):
  if all([all([A[i*n+l]!=K,w!=l or A[i+n*i]!=K,w!=n-1-l or A[n*i+n-i-1]!=K])for i in r(w)]+[A[w*n+i]!=K for i in r(l)]):R(A+[K],I+1)
R([],0)

เวอร์ชันที่ไม่ถูกปรับแต่ง:

def Recurse(A,I,n):
 column=I%n
 row=I//n
 if I==n*n:
     [print(*A[i*n:i*n+n])for i in range(n)] # output
     exit() #end recursion
 for K in range(n):
    # try every possibility. Test if they satisfy the constraints:
    # if so, move the index on. If none of them do, we'll return None.
    # if a child returns None, we'll move onto the next potential child:
    # if all of them fail it will backtrack to the next level.
    if all([
        all([
            A[i*n+column]!=K, # column constraint
            row!=column or A[i+n*i]!=K, # diagonal constraint
            row!=n-1-column or A[n*i+n-i-1]!=K # antidiagonal constraint
            ]) for i in range(row)
        ]+[
            A[row*n+i]!=K for i in range(column) # row constraint
            ]):
        Recurse(A+[K],I+1,n)

Recurse([],0,(int)(input()))

22

Funcitonไม่ใช่การแข่งขัน

UPDATE! การปรับปรุงประสิทธิภาพครั้งใหญ่! n = 7 เสร็จสมบูรณ์ในเวลาไม่ถึง 10 นาที! ดูคำอธิบายที่ด้านล่าง!

มันสนุกดีที่จะเขียน นี่คือตัวแก้ปัญหาแบบ brute-force สำหรับปัญหานี้ที่เขียนใน Funciton บาง factoids:

  • ยอมรับจำนวนเต็มใน STDIN ช่องว่างภายนอกใด ๆ จะทำลายมันรวมถึงการขึ้นบรรทัดใหม่หลังจากจำนวนเต็ม
  • มันใช้ตัวเลข 0 ถึงn - 1 (ไม่ใช่ 1 ถึงn )
  • มันเติมตาราง“ย้อนกลับ” เพื่อให้คุณได้รับการแก้ปัญหาที่แถวด้านล่างอ่านมากกว่าที่แถวบนสุดอ่าน3 2 1 00 1 2 3
  • มันส่งออกอย่างถูกต้อง0(ทางออกเดียว) สำหรับn = 1
  • เอาท์พุทที่ว่างเปล่าสำหรับn = 2 และn = 3
  • เมื่อคอมไพล์เป็น exe จะใช้เวลาประมาณ8¼นาทีสำหรับn = 7 (ประมาณหนึ่งชั่วโมงก่อนการปรับปรุงประสิทธิภาพ) หากไม่มีการรวบรวม (ใช้ล่าม) จะใช้เวลาประมาณ 1.5 เท่าดังนั้นการใช้คอมไพเลอร์จึงคุ้มค่า
  • นี่เป็นครั้งแรกที่ฉันเขียนโปรแกรม Funciton ทั้งหมดโดยไม่ต้องเขียนโปรแกรมด้วยภาษาหลอกก่อน ฉันเขียนเป็น C # จริงก่อน
  • (อย่างไรก็ตามนี่ไม่ใช่ครั้งแรกที่ฉันทำการเปลี่ยนแปลงเพื่อปรับปรุงประสิทธิภาพของบางสิ่งบางอย่างใน Funciton ครั้งแรกที่ฉันทำนั่นคือในฟังก์ชันแฟคทอเรียลการสลับลำดับตัวถูกดำเนินการของการคูณทำให้แตกต่างกันอย่างมากเนื่องจากอัลกอริทึมการคูณทำงานอย่างไรในกรณีที่คุณอยากรู้)

โดยไม่ต้องกังวลใจเพิ่มเติม:

            ┌────────────────────────────────────┐           ┌─────────────────┐
            │                                  ┌─┴─╖ ╓───╖ ┌─┴─╖   ┌──────┐    │
            │                    ┌─────────────┤ · ╟─╢ Ӂ ╟─┤ · ╟───┤      │    │
            │                    │             ╘═╤═╝ ╙─┬─╜ ╘═╤═╝ ┌─┴─╖    │    │
            │                    │               └─────┴─────┘   │ ♯ ║    │    │
            │                  ┌─┴─╖                             ╘═╤═╝    │    │
            │     ┌────────────┤ · ╟───────────────────────────────┴───┐  │    │
          ┌─┴─╖ ┌─┴─╖   ┌────╖ ╘═╤═╝ ┌──────────┐         ┌────────┐ ┌─┴─╖│    │
          │ ♭ ║ │ × ╟───┤ >> ╟───┴───┘        ┌─┴─╖       │ ┌────╖ └─┤ · ╟┴┐   │
          ╘═╤═╝ ╘═╤═╝   ╘══╤═╝          ┌─────┤ · ╟───────┴─┤ << ╟─┐ ╘═╤═╝ │   │
    ┌───────┴─────┘ ┌────╖ │            │     ╘═╤═╝         ╘══╤═╝ │   │   │   │
    │     ┌─────────┤ >> ╟─┘            │       └───────┐      │   │   │   │   │
    │     │         ╘══╤═╝            ┌─┴─╖   ╔═══╗   ┌─┴─╖ ┌┐ │   │ ┌─┴─╖ │   │
    │     │           ┌┴┐     ┌───────┤ ♫ ║ ┌─╢ 0 ║ ┌─┤ · ╟─┤├─┤   ├─┤ Ӝ ║ │   │
    │     │   ╔═══╗   └┬┘     │       ╘═╤═╝ │ ╚═╤═╝ │ ╘═╤═╝ └┘ │   │ ╘═╤═╝ │   │
    │     │   ║ 1 ╟───┬┘    ┌─┴─╖       └───┘ ┌─┴─╖ │   │      │   │   │ ┌─┴─╖ │
    │     │   ╚═══╝ ┌─┴─╖   │ ɓ ╟─────────────┤ ? ╟─┘   │    ┌─┴─╖ │   ├─┤ · ╟─┴─┐
    │     ├─────────┤ · ╟─┐ ╘═╤═╝             ╘═╤═╝   ┌─┴────┤ + ╟─┘   │ ╘═╤═╝   │
  ┌─┴─╖ ┌─┴─╖       ╘═╤═╝ │ ╔═╧═╕ ╔═══╗ ┌───╖ ┌─┴─╖ ┌─┴─╖    ╘═══╝     │   │     │
┌─┤ · ╟─┤ · ╟───┐     └┐  └─╢   ├─╢ 0 ╟─┤ ⌑ ╟─┤ ? ╟─┤ · ╟──────────────┘   │     │
│ ╘═╤═╝ ╘═╤═╝   └───┐ ┌┴┐   ╚═╤═╛ ╚═╤═╝ ╘═══╝ ╘═╤═╝ ╘═╤═╝                  │     │
│   │   ┌─┴─╖ ┌───╖ │ └┬┘   ┌─┴─╖ ┌─┘           │     │                    │     │
│ ┌─┴───┤ · ╟─┤ Җ ╟─┘  └────┤ ? ╟─┴─┐   ┌─────────────┘                    │     │
│ │     ╘═╤═╝ ╘═╤═╝         ╘═╤═╝   │   │╔════╗╔════╗                      │     │
│ │       │  ┌──┴─╖ ┌┐   ┌┐ ┌─┴─╖ ┌─┴─╖ │║ 10 ║║ 32 ║    ┌─────────────────┘     │
│ │       │  │ << ╟─┤├─┬─┤├─┤ · ╟─┤ · ╟─┘╚══╤═╝╚╤═══╝ ┌──┴──┐                    │
│ │       │  ╘══╤═╝ └┘ │ └┘ ╘═╤═╝ ╘═╤═╝     │ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖                  │
│ │     ┌─┴─╖ ┌─┴─╖  ┌─┴─╖  ┌─┴─╖ ╔═╧═╕     └─┤ ? ╟─┤ · ╟─┤ % ║                  │
│ └─────┤ · ╟─┤ · ╟──┤ Ӂ ╟──┤ ɱ ╟─╢   ├───┐   ╘═╤═╝ ╘═╤═╝ ╘═╤═╝                  │
│       ╘═╤═╝ ╘═╤═╝  ╘═╤═╝  ╘═══╝ ╚═╤═╛ ┌─┴─╖ ┌─┴─╖   │     └────────────────────┘
│         └─────┤      │            └───┤ ‼ ╟─┤ ‼ ║   │        ┌──────┐
│               │      │                ╘═══╝ ╘═╤═╝   │        │ ┌────┴────╖
│               │      │                      ┌─┴─╖   │        │ │ str→int ║
│               │      └──────────────────────┤ · ╟───┴─┐      │ ╘════╤════╝
│               │          ┌─────────╖        ╘═╤═╝     │    ╔═╧═╗ ┌──┴──┐
│               └──────────┤ int→str ╟──────────┘       │    ║   ║ │ ┌───┴───┐
│                          ╘═════════╝                  │    ╚═══╝ │ │ ┌───╖ │
└───────────────────────────────────────────────────────┘          │ └─┤ × ╟─┘
           ┌──────────────┐                                  ╔═══╗ │   ╘═╤═╝
╔════╗     │ ╓───╖ ┌───╖  │                              ┌───╢ 0 ║ │   ┌─┴─╖ ╔═══╗
║ −1 ║     └─╢ Ӝ ╟─┤ × ╟──┴──────┐                       │   ╚═╤═╝ └───┤ Ӂ ╟─╢ 0 ║
╚═╤══╝       ╙───╜ ╘═╤═╝         │                       │   ┌─┴─╖     ╘═╤═╝ ╚═══╝
┌─┴──╖ ┌┐ ┌───╖ ┌┐ ┌─┴──╖ ╔════╗ │                       │ ┌─┤   ╟───────┴───────┐
│ << ╟─┤├─┤ ÷ ╟─┤├─┤ << ║ ║ −1 ║ │                       │ │ └─┬─╜ ┌─┐ ┌─────┐   │
╘═╤══╝ └┘ ╘═╤═╝ └┘ ╘═╤══╝ ╚═╤══╝ │                       │ │   └───┴─┘ │   ┌─┴─╖ │
  │         └─┘      └──────┘    │                       │ └───────────┘ ┌─┤ ? ╟─┘
  └──────────────────────────────┘         ╓───╖         └───────────────┘ ╘═╤═╝
                               ┌───────────╢ Җ ╟────────────┐                │
      ┌────────────────────────┴───┐       ╙───╜            │
      │                          ┌─┴────────────────────┐ ┌─┴─╖
    ┌─┴─╖                      ┌─┴─╖                  ┌─┴─┤ · ╟──────────────────┐
    │ ♯ ║ ┌────────────────────┤ · ╟───────┐          │   ╘═╤═╝                  │
    ╘═╤═╝ │                    ╘═╤═╝       │          │     │              ┌───╖ │
┌─────┴───┘    ┌─────────────────┴─┐   ┌───┴───┐    ┌─┴─╖ ┌─┴─╖          ┌─┤ × ╟─┴─┐
│              │                 ┌─┴─╖ │   ┌───┴────┤ · ╟─┤ · ╟──────────┤ ╘═╤═╝   │
│              │ ┌───╖ ┌───╖  ┌──┤ · ╟─┘ ┌─┴─┐      ╘═╤═╝ ╘═╤═╝        ┌─┴─╖ │     │
│         ┌────┴─┤ ♭ ╟─┤ × ╟──┘  ╘═╤═╝   │ ┌─┴─╖ ┌───╖└┐ ┌──┴─╖      ┌─┤ · ╟─┘     │
│         │      ╘═══╝ ╘═╤═╝ ┌───╖ │     │ │ × ╟─┤ Ӝ ╟─┴─┤ ÷% ╟─┐    │ ╘═╤═╝ ┌───╖ │
│   ┌─────┴───┐     ┌────┴───┤ Ӝ ╟─┴─┐   │ ╘═╤═╝ ╘═╤═╝   ╘══╤═╝ │    │   └───┤ Ӝ ╟─┘
│ ┌─┴─╖ ┌───╖ │     │ ┌────╖ ╘═╤═╝   │   └───┘   ┌─┴─╖      │   │    └────┐  ╘═╤═╝
│ │ × ╟─┤ Ӝ ╟─┘     └─┤ << ╟───┘   ┌─┴─╖ ┌───────┤ · ╟───┐  │ ┌─┴─╖ ┌───╖ │    │
│ ╘═╤═╝ ╘═╤═╝         ╘══╤═╝   ┌───┤ + ║ │       ╘═╤═╝   ├──┴─┤ · ╟─┤ × ╟─┘    │
└───┤     └────┐ ╔═══╗ ┌─┴─╖ ┌─┴─╖ ╘═╤═╝ │ ╔═══╗ ┌─┴─╖ ┌─┴─╖  ╘═╤═╝ ╘═╤═╝      │
  ┌─┴─╖ ┌────╖ │ ║ 0 ╟─┤ ? ╟─┤ = ║  ┌┴┐  │ ║ 0 ╟─┤ ? ╟─┤ = ║    │     │ ┌────╖ │
  │ × ╟─┤ << ╟─┘ ╚═══╝ ╘═╤═╝ ╘═╤═╝  └┬┘  │ ╚═══╝ ╘═╤═╝ ╘═╤═╝    │     └─┤ << ╟─┘
  ╘═╤═╝ ╘═╤══╝ ┌┐     ┌┐ │     │     └───┘       ┌─┴─╖   ├──────┘       ╘═╤══╝
    │     └────┤├──┬──┤├─┘     ├─────────────────┤ · ╟───┘                │
    │          └┘┌─┴─╖└┘       │     ┌┐   ┌┐     ╘═╤═╝ ┌┐   ┌┐            │
    └────────────┤ · ╟─────────┘   ┌─┤├─┬─┤├─┐     └───┤├─┬─┤├────────────┘
                 ╘═╤═╝             │ └┘ │ └┘ │         └┘ │ └┘
                   └───────────────┘    │    └────────────┘

คำอธิบายของรุ่นแรก

รุ่นแรกใช้เวลาประมาณหนึ่งชั่วโมงในการแก้ปัญหาn = 7 ต่อไปนี้อธิบายส่วนใหญ่ว่ารุ่นที่ทำงานช้านี้ ที่ด้านล่างฉันจะอธิบายสิ่งที่เปลี่ยนแปลงฉันทำเพื่อให้ได้ภายใน 10 นาที

การเที่ยวชมเป็นบิต

โปรแกรมนี้ต้องการบิต มันต้องการบิตจำนวนมากและมันต้องการในตำแหน่งที่ถูกต้องทั้งหมด โปรแกรมเมอร์ Funciton ที่มีประสบการณ์รู้อยู่แล้วว่าหากคุณต้องการบิตnคุณสามารถใช้สูตรได้

2 ^ n-1

ซึ่งใน Funciton สามารถแสดงเป็น

(1 << n) - 1

เมื่อทำการปรับประสิทธิภาพให้เหมาะสมฉันพบว่าฉันสามารถคำนวณค่าเดียวกันได้เร็วขึ้นโดยใช้สูตรนี้:

¬ (−1 << n)

ฉันหวังว่าคุณจะยกโทษให้ฉันว่าฉันไม่ได้อัปเดตกราฟิกสมการทั้งหมดในโพสต์นี้ตามลำดับ

ตอนนี้สมมติว่าคุณไม่ต้องการบล็อกบิตต่อเนื่องกัน ในความเป็นจริงคุณต้องการnบิตในช่วงปกติทุก ๆk -th เช่น:

                                 LSB
                                  ↓
00000010000001000000100000010000001
                            └──┬──┘
                               k

สูตรนี้ค่อนข้างตรงไปตรงมาเมื่อคุณรู้:

((1 << nk) - 1) / ((1 << k) - 1)

ในโค้ดฟังก์ชันӜใช้ค่าnและkและคำนวณสูตรนี้

การติดตามหมายเลขที่ใช้

มีn ²ตัวเลขในตารางสุดท้ายและตัวเลขแต่ละตัวสามารถใด ๆ ของnที่เป็นไปได้ค่า ในการติดตามว่าอนุญาตให้ใช้หมายเลขใดในแต่ละเซลล์เราจะรักษาหมายเลขที่ประกอบด้วยn ³บิตโดยมีการตั้งค่าบิตเพื่อระบุว่ามีการใช้ค่าเฉพาะ เริ่มแรกตัวเลขนี้คือ 0 อย่างชัดเจน

อัลกอริทึมเริ่มต้นที่มุมล่างขวา หลังจาก“ เดา” หมายเลขแรกคือ 0 เราต้องติดตามความจริงที่ว่า 0 ไม่ได้รับอนุญาตในเซลล์ใด ๆ ในแถวคอลัมน์และเส้นทแยงมุมเดียวกัน:

LSB                               (example n=5)
 ↓
 10000 00000 00000 00000 10000
 00000 10000 00000 00000 10000
 00000 00000 10000 00000 10000
 00000 00000 00000 10000 10000
 10000 10000 10000 10000 10000
                             ↑
                            MSB

ด้วยเหตุนี้เราคำนวณค่าสี่ค่าต่อไปนี้:

  • แถวปัจจุบัน:เราต้องการn bits ทุกบิตn -th (หนึ่งต่อเซลล์) แล้วเปลี่ยนเป็นแถวปัจจุบันrโดยจำได้ว่าทุกแถวมีn ²บิต:

    ((1 << n²) −1) / ((1 << n²) −1) << n²r

  • คอลัมน์ปัจจุบัน:เราต้องการn bits ทุก ๆn ²-th บิต (หนึ่งต่อแถว) แล้วเปลี่ยนเป็นคอลัมน์cปัจจุบันโดยจำได้ว่าทุกคอลัมน์มีn bits:

    ((1 << n³) −1) / ((1 << n²) −1) << n²r

  • เส้นทแยงมุมไปข้างหน้า:เราต้องการบิตnทุก ๆ ... (คุณให้ความสนใจหรือไม่ด่วนคิดออก!) ... n ( n +1) - บิตที่ (ทำได้ดีมาก!) แต่ถ้าเราอยู่บน เส้นทแยงมุมไปข้างหน้า:

    ((1 << n² (n + 1)) - 1) / ((1 << n² (n + 1)) - 1) ถ้า c = r

  • เส้นทแยงมุมถอยหลัง:สองสิ่งที่นี่ ก่อนอื่นเราจะรู้ได้อย่างไรว่าเราอยู่ในแนวทแยงย้อนหลัง? ในทางคณิตศาสตร์เงื่อนไขคือc = ( n - 1) - rซึ่งเหมือนกับc = n + (- r - 1) เฮ้นั่นทำให้คุณนึกถึงบางสิ่ง? ถูกต้องมันเป็นส่วนประกอบสองอย่างดังนั้นเราจึงสามารถใช้การปฏิเสธบิต (มีประสิทธิภาพมากใน Funciton) แทนการลดลง ประการที่สองสูตรด้านบนสมมติว่าเราต้องการบิตที่สำคัญน้อยที่สุดที่จะตั้งค่า แต่ในแนวทแยงหลังเราไม่ได้ดังนั้นเราต้องเลื่อนขึ้นโดย ... คุณรู้หรือไม่? ... ถูกต้องn ( n - 1)

    ((1 << n² (n-1)) - 1) / ((1 << n (n-1)) - 1) << n (n-1) ถ้า c = n + ¬r

    นี่ก็เป็นสิ่งเดียวที่เราอาจหารด้วย 0 ถ้าn = 1 อย่างไรก็ตาม Funciton ไม่สนใจ 0 ÷ 0 เป็นเพียง 0 คุณไม่รู้หรอ

ในโค้ดฟังก์ชันҖ(อันล่างสุด) รับnและดัชนี (ซึ่งคำนวณจากrและcตามการหารและส่วนที่เหลือ) คำนวณค่าสี่ค่าเหล่านี้และorรวมเข้าด้วยกัน

อัลกอริทึมแรงเดรัจฉาน

อัลกอริทึมแรงเดรัจฉานจะดำเนินการโดยӁ(ฟังก์ชั่นที่ด้านบน) ใช้n (ขนาดกริด), ดรรชนี (ซึ่งในกริดที่เรากำลังวางตัวเลขอยู่) และใช้ (จำนวนที่มีn ³บิตบอกเราว่าเราสามารถวางตัวเลขใดในแต่ละเซลล์)

ฟังก์ชันนี้คืนค่าลำดับของสตริง แต่ละสตริงเป็นวิธีแก้ปัญหาแบบเต็มของกริด มันเป็นตัวแก้ปัญหาที่สมบูรณ์ มันจะส่งคืนการแก้ปัญหาทั้งหมดถ้าคุณปล่อยให้มัน แต่มันกลับมาเป็นลำดับที่ขี้เกียจประเมิน

  • หากดัชนีมีค่าถึง 0 เราได้เติมกริดทั้งหมดสำเร็จแล้วดังนั้นเราจึงส่งคืนลำดับที่มีสตริงว่าง (โซลูชันเดียวที่ไม่ครอบคลุมเซลล์ใด ๆ ) สตริงว่างคือ0และเราใช้ฟังก์ชั่นห้องสมุดเพื่อเปลี่ยนให้เป็นลำดับองค์ประกอบเดียว

  • เช็คที่อธิบายไว้ในการปรับปรุงประสิทธิภาพด้านล่างเกิดขึ้นที่นี่

  • หากดัชนียังไม่ถึง 0 เราจะลดมันลง 1 เพื่อให้ได้ดัชนีที่ตอนนี้เราต้องวางตัวเลข (เรียกว่าix )

    เราใช้เพื่อสร้างลำดับขี้เกียจที่มีค่าจาก 0 ถึงn - 1

    จากนั้นเราใช้ɓ(monadic bind) กับแลมบ์ดาที่ทำสิ่งต่อไปนี้ตามลำดับ:

    • ดูครั้งแรกที่บิตที่เกี่ยวข้องในการดำเนินการที่จะตัดสินใจว่าจำนวนที่ถูกต้องที่นี่หรือไม่ เราสามารถวางหมายเลขi ได้หากถูกยึด & (1 << ( n × ix ) << i ) ยังไม่ได้ตั้งค่า หากตั้งไว้ให้ส่งคืน0(ลำดับที่ว่างเปล่า)
    • ใช้Җในการคำนวณบิตที่สอดคล้องกับแถวคอลัมน์และแนวทแยงปัจจุบัน เปลี่ยนได้โดยผมและจากนั้นorก็เข้าสู่การดำเนินการ
    • ซ้ำเรียกӁเพื่อดึงการแก้ปัญหาทั้งหมดสำหรับเซลล์ที่เหลือผ่านมันใหม่นำและ decremented ix ส่งคืนลำดับของสตริงที่ไม่สมบูรณ์ แต่ละสตริงมีอักขระix (กริดเติมได้ถึงดัชนีix )
    • ใช้ɱ(แผนที่) เพื่อค้นหาคำตอบที่พบและใช้เพื่อเชื่อมiเข้ากับท้ายแต่ละรายการ ต่อท้าย newline ถ้าindexมีหลายตัวเป็นnหรือเว้นวรรค

สร้างผลลัพธ์

โปรแกรมหลักเรียกӁ(ตัวค้นหาสัตว์เดรัจฉาน) ด้วยn , index = n ² (จำไว้ว่าเราเติมกริดกลับไปด้านหลัง) และนำมา = 0 (ตอนแรกไม่มีอะไรทำ) หากผลลัพธ์นี้เป็นลำดับว่างเปล่า (ไม่พบวิธีแก้ไข) ให้ส่งออกสตริงว่าง มิฉะนั้นเอาท์พุทสตริงแรกในลำดับ โปรดทราบว่านี่หมายความว่ามันจะประเมินเฉพาะองค์ประกอบแรกของลำดับซึ่งเป็นสาเหตุที่นักแก้ปัญหาไม่ดำเนินการต่อจนกว่าจะพบโซลูชันทั้งหมด

การปรับปรุงประสิทธิภาพ

(สำหรับผู้ที่อ่านคำอธิบายเวอร์ชันเก่าอยู่แล้ว: โปรแกรมไม่สร้างลำดับของลำดับที่ต้องแยกเป็นสตริงสำหรับเอาท์พุตอีกต่อไปมันเพิ่งสร้างลำดับของสตริงโดยตรงฉันได้แก้ไขคำอธิบายตามนั้น แต่นั่นไม่ใช่การปรับปรุงที่สำคัญมันมาที่นี่)

บนเครื่องของฉันคอมไพล์ exe ของรุ่นแรกใช้เวลา 1 ชั่วโมงในการแก้ปัญหาอย่างมากn = 7 นี่ไม่ใช่ภายในระยะเวลาที่กำหนด 10 นาทีดังนั้นฉันจึงไม่ได้พัก (อันที่จริงเหตุผลที่ฉันไม่ได้พักเพราะฉันมีความคิดนี้เกี่ยวกับวิธีเร่งความเร็วให้ใหญ่ขึ้น)

ขั้นตอนวิธีการดังกล่าวข้างต้นจะหยุดการค้นหาและ backtracks ของมันทุกครั้งที่พบเซลล์ที่บิตทั้งหมดในการดำเนินการจำนวนจะถูกตั้งค่าแสดงให้เห็นว่าไม่มีอะไรที่สามารถใส่ลงในมือถือนี้

อย่างไรก็ตามขั้นตอนวิธีการจะยังคงลมๆแล้งๆกรอกตารางขึ้นไปเซลล์ที่บิตทุกคนเป็นชุด มันจะได้เร็วขึ้นมากถ้ามันสามารถที่จะหยุดเร็วที่สุดเท่าที่ใดๆ เพื่อที่จะเต็มไปด้วยในมือถือแล้วได้ทุกบิตชุดที่แล้วแสดงให้เห็นว่าเราไม่เคยสามารถแก้ส่วนที่เหลือของตารางไม่ว่าสิ่งที่หมายเลขเราใส่ใน มัน. แต่อย่างไรคุณได้อย่างมีประสิทธิภาพตรวจสอบว่าใด ๆเซลล์มีของnบิตตั้งโดยไม่ต้องผ่านทั้งหมดของพวกเขา?

เคล็ดลับเริ่มต้นด้วยการเพิ่มบิตเดียวต่อเซลล์ไปยังหมายเลขที่ถ่าย แทนที่จะเป็นสิ่งที่แสดงไว้ด้านบนตอนนี้จะเป็นดังนี้:

LSB                               (example n=5)
 ↓
 10000 0 00000 0 00000 0 00000 0 10000 0
 00000 0 10000 0 00000 0 00000 0 10000 0
 00000 0 00000 0 10000 0 00000 0 10000 0
 00000 0 00000 0 00000 0 10000 0 10000 0
 10000 0 10000 0 10000 0 10000 0 10000 0
                                       ↑
                                      MSB

แทนที่จะเป็นn ³ตอนนี้มีบิตn ² ( n + 1) ในจำนวนนี้ ฟังก์ชั่นที่เติมแถว / คอลัมน์ / แนวทแยงปัจจุบันมีการเปลี่ยนแปลงตามจริง (จริง ๆ แล้วเขียนใหม่ทั้งหมดเพื่อความซื่อสัตย์) ฟังก์ชั่นที่จะยังคงเติมเพียงn0บิตต่อเซลล์แม้ว่าดังนั้นบิตพิเศษที่เราเพิ่งเพิ่มจะเป็น

ทีนี้สมมติว่าเราผ่านการคำนวณไปครึ่งทางแล้วเราเพิ่งวางไว้1ในเซลล์ตรงกลางและจำนวนที่นำมามีลักษณะดังนี้:

                 current
LSB              column           (example n=5)
 ↓                 ↓
 11111 0 10010 0 01101 0 11100 0 11101 0
 00011 0 11110 0 01101 0 11101 0 11100 0
 11111 0 11110 0[11101 0]11100 0 11100 0    ← current row
 11111 0 11111 0 11111 0 11111 0 11111 0
 11111 0 11111 0 11111 0 11111 0 11111 0
                                       ↑
                                      MSB

อย่างที่คุณเห็นเซลล์บนซ้าย (ดัชนี 0) และเซลล์กลางซ้าย (ดัชนี 10) ตอนนี้เป็นไปไม่ได้ เราจะตรวจสอบเรื่องนี้ได้อย่างมีประสิทธิภาพมากที่สุดได้อย่างไร?

พิจารณาตัวเลขที่บิตที่ 0 ของแต่ละเซลล์ถูกตั้งค่า แต่ขึ้นอยู่กับดัชนีปัจจุบันเท่านั้น ตัวเลขดังกล่าวนั้นง่ายต่อการคำนวณโดยใช้สูตรที่คุ้นเคย:

((1 << (n + 1) i) - 1) / ((1 << (n + 1)) - 1)

เราจะได้อะไรถ้าเราเพิ่มตัวเลขทั้งสองเข้าด้วยกัน

LSB                                               LSB
 ↓                                                 ↓
 11111 0 10010 0 01101 0 11100 0 11101 0           10000 0 10000 0 10000 0 10000 0 10000 0        ╓───╖
 00011 0 11110 0 01101 0 11101 0 11100 0     ║     10000 0 10000 0 10000 0 10000 0 10000 0            ║
 11111 0 11110 0 11101 0 11100 0 11100 0  ═══╬═══  10000 0 10000 0 00000 0 00000 0 00000 0  ═════   ╓─╜
 11111 0 11111 0 11111 0 11111 0 11111 0     ║     00000 0 00000 0 00000 0 00000 0 00000 0  ═════   ╨
 11111 0 11111 0 11111 0 11111 0 11111 0           00000 0 00000 0 00000 0 00000 0 00000 0          o
                                       ↑                                                 ↑
                                      MSB                                               MSB

ผลลัพธ์คือ:

             OMG
              ↓
        00000[1]01010 0 11101 0 00010 0 00011 0
        10011 0 00001 0 11101 0 00011 0 00010 0
═════   00000[1]00001 0 00011 0 11100 0 11100 0
═════   11111 0 11111 0 11111 0 11111 0 11111 0
        11111 0 11111 0 11111 0 11111 0 11111 0

อย่างที่คุณเห็นการเพิ่มล้นเข้าไปในบิตพิเศษที่เราเพิ่ม แต่เฉพาะถ้าบิตทั้งหมดสำหรับเซลล์นั้นถูกตั้งค่า! ดังนั้นสิ่งที่เหลืออยู่ที่ต้องทำคือการปิดบังบิตเหล่านั้น (สูตรเดียวกันกับด้านบน แต่ << n ) และตรวจสอบว่าผลลัพธ์เป็น 0:

00000[1]01010 0 11101 0 00010 0 00011 0    ╓╖    00000 1 00000 1 00000 1 00000 1 00000 1         ╓─╖ ╓───╖
10011 0 00001 0 11101 0 00011 0 00010 0   ╓╜╙╖   00000 1 00000 1 00000 1 00000 1 00000 1        ╓╜ ╙╖    ║
00000[1]00001 0 00011 0 11100 0 11100 0   ╙╥╥╜   00000 1 00000 1 00000 0 00000 0 00000 0  ═════ ║   ║  ╓─╜
11111 0 11111 0 11111 0 11111 0 11111 0   ╓╜╙╥╜  00000 0 00000 0 00000 0 00000 0 00000 0  ═════ ╙╖ ╓╜  ╨
11111 0 11111 0 11111 0 11111 0 11111 0   ╙──╨─  00000 0 00000 0 00000 0 00000 0 00000 0         ╙─╜   o

ถ้ามันไม่เป็นศูนย์กริดเป็นไปไม่ได้และเราสามารถหยุดได้

  • สกรีนช็อตแสดงวิธีแก้ปัญหาและเวลาทำงานสำหรับ n = 4 ถึง 7

3
ศักดิ์สิทธิ์ FUCK เพื่อนมันน่าประทับใจ
Deusovi

1
ฉันสองความเห็น @ Deusovi ขอขอบคุณสำหรับความพยายามอย่างมากในการนี้
hargasinski

7

Haskell, 790 * 0.80 = 632 ไบต์

import Data.List
import Control.Monad
import Data.Array
s r=let{h as bs=[(a,b)|a<-as,b<-bs];(&)m k=(\(Just x)->x)$lookup k m;j=Just;n=Nothing;c=[1..r];q=delete;u=h[1..r]c;o=[(s,[u |u<-[h[1..r][c]|c<-c]++[h[r]c|r<-[1..r]]++[zip[1..r][1..r],zip[1..r][r,r-1..1]],s`elem`u])|s<-u];k=foldr(>=>)j;a p d g0=k[t p d2|d2<-q d(g0!p)]g0;t p d g0|not(d`elem`(g0!p))=j g0|[]<-v=n|[d2]<-v=k[t s2 d2|s2<-[(s,delete s$nub(concat(o&s)))|s<-u]&p]g1|True=k[l[s|s<-u,not(d`elem`v)]|u<-o&p]g1 where{v=q d(g0!p);g1=g0//[(p,v)];l[]_=n;l[d3]g=a d3 d g;l _ r=j r};w g0|and[case g0!s of{[_]->True;_->False}|s<-u]=j g0|True=msum[a s' d g0>>=w|d<-g0!s']where(_,s')=minimumBy(\(a,_)(b,_)->compare a b)[(l,s)|s<-u,let v=g0!s;l=length v,l>1]}in fmap(fmap(\[x]->x))$w$array((1,1),(r,r))[((i,j),[1..r])|i<-[1..r],j<-[1..r]]

ฉันสังเกตเห็นว่าปัญหานี้คล้ายกับซูโดกุมาก ฉันจำตัวแก้ซูโดกุตัวเก่าที่ฉันเขียนใน Haskell จากอันอื่นใน Python นี่คือรหัสโพสต์กอล์ฟครั้งแรกของฉันหรือความพยายาม

นี้ตอบสนองโบนัสเพราะมันส่งกลับNothingสำหรับn=2,3และJust <result>สำหรับn>=4ที่<result>เป็นอาร์เรย์ 2 มิติของค่าหนึ่ง

ดูที่นี่สำหรับล่ามออนไลน์ โค้ดนั้นยาวกว่าโค้ดในการโพสต์เพราะล่ามออนไลน์นั้นมีข้อกำหนดที่เข้มงวดมากขึ้นเกี่ยวกับรูปแบบของโปรแกรมที่สมบูรณ์ (กฎบอกว่าการส่งสามารถเป็นฟังก์ชันได้) การส่งนี้รับอินพุตเป็นอาร์กิวเมนต์ของฟังก์ชัน


1
เคล็ดลับที่รวดเร็วไม่กี่ a) คุณกำหนดc=[1..r]เพื่อให้คุณสามารถใช้งานได้ภายในและo wข) คือminimumBy(\(a,_)(b,_)->compare a b)[...] head$sortOn fst[...]c) vในใช้เพียงครั้งเดียวจึงไม่กำหนดมันที่ทั้งหมด:v=g0!s l=length$g0!sd) คุณยังมีชื่อพารามิเตอร์ตัวอักษรสองตัว จ) แทนที่Trueด้วย1<2และมีFalse 2<1ฉ) เป็นand[case g0!s of{[_]->True;_->False}|s<-u] all((==1).length.(g0!))u
nimi

เคล็ดลับอย่างรวดเร็วส่วนที่สอง: g) สามารถกำหนดมัด:(&)m k= m&k=เอช) not(delem คือ(g0!p)) notElem d$g0!pi) คือconcat(...) id=<<(...)เจ) ใช้ประกอบการมัดสำหรับเช่นh as%bs=
nimi

3
เคล็ดลับเมตาด่วน: คุณสามารถกำหนดรหัสที่มี backticks อย่างถูกต้องโดยใช้ backticks สองครั้ง​``like`this``​!
ลินน์

4

Pyth, 41 ไบต์

#Km.SQQI.AmqQl{d+.TK.Tm,@@Kdd@@Kt-QddQB;K
#                                      ;   # while(True)
 Km.SQQ                                    # K = random QxQ 2d list
       I                               ;   # if ...
        .A                                 # all of...
          m                          Q     # map(range(Q))...
                +                          # concat
                 .TK                       # transpose K
                    .Tm,@@Kdd@@Kt-Qdd      # diagonals of K
                      m             d      # map(range(d))
                       ,                   # 2-elem list of...
                        @@Kdd              # K[n][n]
                             @@Kt-Qd       # and K[len(K)-n-1][n]
                    .T                     # transpose
           qQl{d                           # subarrays have no dups...
                                      B;   # ... then, break
                                        K  # output final result

กำลังโง่เขลา ftw!

เนื่องจากสิ่งนี้โดยทั่วไปจะพยายามสับสุ่มจนกระทั่งมันได้ผล (มันก็พยายามต่อไปn * [shuffle(range(n))]) มันใช้เวลานานมากจริงๆ นี่คือการทดสอบบางส่วนเพื่อให้คุณเข้าใจว่าต้องใช้เวลานานเท่าใด

llama@llama:~$ time echo 4 | pyth <(echo '#Km.SQQI.AmqQl{d+.TK.Tm,@@Kdd@@Kt-QddQB;K')               
[[2, 1, 0, 3], [0, 3, 2, 1], [3, 0, 1, 2], [1, 2, 3, 0]]
echo 4  0.00s user 0.00s system 0% cpu 0.001 total
pyth <(echo '#Km.SQQI.AmqQl{d+.TK.Tm,@@Kdd@@Kt-QddQB;K')  0.38s user 0.00s system 96% cpu 0.397 total

นั่นเป็นเพียง 4x4 และมันทำงานได้ในเวลาไม่ถึงครึ่งวินาที ฉันโกงจริง ๆ เพราะนี่เป็นการทดลองที่ดีที่สุดสองสามครั้งส่วนใหญ่ใช้เวลาสองหรือสองวินาที

ฉันยังไม่ได้กำหนดเวลาในวันที่ 5x5 (มันจะเสร็จสมบูรณ์หนึ่งครั้ง แต่นั่นก็เป็น REPL และฉันไม่ได้จับเวลา)

โปรดทราบว่ากฎสำหรับการ จำกัด เวลาถูกแก้ไขในคำถามเท่านั้นหลังจากคำตอบนี้ถูกโพสต์


ฉันคิดว่าสิ่งนี้ไม่สามารถทำได้ 7x7 ภายในสิบนาที? ^^
ลินน์

@Mauris ดีบางครั้งก็สามารถ ... ;) นั่นคือข้อกำหนดที่ฉันพลาดหรือไม่? ฉันไม่เห็นอะไรเลยที่พูดถึงการ จำกัด เวลาในคำถาม
Doorknob

ฉันเห็นมันในความคิดเห็น (ไม่ใช่ความคิดเห็นใหม่ 12 ชั่วโมงก่อน)
edc65

ขอโทษด้วยเกี่ยวกับเรื่องนั้นฉันไม่ได้คิดจนกว่าจะมีใครพูดถึงฉันจะแก้ไขข้อท้าทายในตอนนี้
hargasinski

1
+1 สำหรับนามธรรม ASCII art ในเวอร์ชันที่คุณแสดงความคิดเห็น :)
Ilmari Karonen

3

SWI-Prolog, 326 * 0.80 = 260.8 ไบต์

:-use_module(library(clpfd)).
a(N):-l(N,R),m(l(N),R),append(R,V),V ins 1..N,transpose(R,C),d(0,R,D),maplist(reverse,R,S),d(0,S,E),m(m(all_distinct),[R,C,[D,E]]),m(label,R),m(p,R).
l(L,M):-length(M,L).
d(X,[H|R],[A|Z]):-nth0(X,H,A),Y is X+1,(R=[],Z=R;d(Y,R,Z)).
p([H|T]):-write(H),T=[],nl;write(' '),p(T).
m(A,B):-maplist(A,B).

แก้ไข: บันทึก 16 ไบต์ด้วย @Mat

การใช้

โทรในล่ามของคุณสำหรับa(5). N=5ผลตอบแทนนี้falseสำหรับหรือN=2N=3

เนื่องจากใช้ไลบรารี CLPFD จึงไม่ใช่ bruteforce ที่แท้จริง โปรแกรมนี้สามารถค้นหาวิธีแก้ไขN=20ในประมาณ 15 วินาทีบนคอมพิวเตอร์ของฉัน

คำอธิบาย Ungolfed +:

วิธีนี้ใช้งานได้เหมือนนักแก้ปัญหา Sudoku ยกเว้นว่าข้อ จำกัด ของบล็อกจะถูกแทนที่ด้วยข้อ จำกัด diagonals

:-use_module(library(clpfd)).      % Import Constraints library

a(N):-
    l(N,R),                        % R is a list of length N
    maplist(l(N),R),               % R contains sublists, each of length N
    append(R,V),                   
    V ins 1..N,                    % Each value in the matrix is between 1 and N
    maplist(all_distinct,R),       % Values must be different on each row
    transpose(R,C),
    maplist(all_distinct,C),       % Values must be different on each column
    d(0,R,D),
    maplist(reverse,R,S),          
    d(0,S,E),
    all_distinct(D),               % Values must be different on the diagonal
    all_distinct(E),               % Values must be different on the "anti"-diagonal
    maplist(label,R),              % Affects actual values to each element
    maplist(p,R).                  % Prints each row

l(L,M):-length(M,L).               % True if L is the length of M

d(X,[H|R],[A|Z]):-nth0(X,H,A),Y is X+1,(R=[],Z=R;d(Y,R,Z)). % True if the third argument is the diagonal of the second argument

p([H|T]):-write(H),T=[],nl;write(' '),p(T).  % Prints a row separated by spaces and followed by a new line

ดีมาก! คุณสามารถบันทึกไบต์ด้วย:maplist(maplist(all_distinct), [R,C,D,E])
เสื่อ

1
@mat ขอบคุณสำหรับคำแนะนำบันทึก 16 ไบต์ ฉันต้องใช้[R,C,[D,E]]เพราะEและDเป็นรายการง่าย ๆ
ลดขนาด

ใช่วิธีแก้ปัญหาที่ดีมาก!
เสื่อ

2
@ ทำให้เพียงแค่ให้คุณรู้ว่าวิธีการแก้ปัญหาของคุณเป็นที่น่าประทับใจที่สุดเพราะมันเป็นทางเดียวที่จะแก้ปัญหาN=20
hargasinski

1
@ ขอบคุณครับ! แต่นั่นเป็นส่วนใหญ่เนื่องจากห้องสมุดที่น่าตื่นตาตื่นใจของ CLPFD เปิดฉากซึ่งไม่ยกของหนักในปัญหาเช่น :) เหล่านี้
Fatalize

2

CJam, 87 ไบต์ - โบนัส 20% = 69.6 ไบต์

qi__"@I/l
ŤˏūȻ
܀ᅀ൹৽჈͚
㑢鴑慚菥洠㬝᚜
"N/=:i0+\,m!f=`1LL](4e<=

Hardcodes คำตอบ มีบาง unprintables ผลงานผ่านN = 1N = 8

โดยพื้นฐานแล้วแต่ละบรรทัดในสตริงลึกลับนั้นมีดัชนีอยู่ในรายการการเรียงสับเปลี่ยนของrange(N)ซึ่งเข้ารหัสเป็นอักขระ Unicode

=:i0+\,m!f=ดัชนีลงในรายการของพีชคณิตเพิ่ม 0 0 1 2 ... N-1ถึงจุดสิ้นสุดของรายการของดัชนีแรกคิดเป็นแถวด้านล่าง สำหรับN < 4อาร์เรย์ 2D ที่ได้นั้นเป็นเรื่องไร้สาระ

`1LL][N, pretty output, 1, "", ""]สร้างรายการ จากนั้น(4e<=ป็อปอิลิเมนต์แรกจากรายการนี้Nและดึงmin(N, 4) % 4อิลิเมนต์ th จากส่วนที่เหลือของมัน สำหรับN >= 4นั่นคือผลลัพธ์และมิฉะนั้นจะเป็นกรณีพิเศษสำหรับสามกรณีแรก

ลองได้ที่นี่


0

C ++, 672 * 0.80 645 * 0.80 = 516 ไบต์

#include <iostream>
int **b,**x,**y,*d,*a,n;
#define R(i) for(i=0;i<n;i++){
#define E(e) e=new int[n];
int f(int c,int r) {int i=0,p=c-1;if(r>=n)return 1;if(c == n + 1)return f(1,r+1);R(i)int m=r==i,s=r+i==n-1;if(!b[r][i]&&!x[r][p]&&!(m&&d[p])&&!(s&&a[p])&&!y[i][p]){b[r][i]=c;x[r][p]=1;y[i][p]=1;if(m)d[p]=1;if(s)a[p]=1;if(f(c+1,r))return 1;b[r][i]=0;x[r][p]=0;y[i][p]=0;if(m)d[p]=0;if(s)a[p]=0;}}return 0;}
int main(){std::cin>>n;int i=0,j=0;b=new int*[n];x=new int*[n];y=new int*[n];E(d);E(a);R(i)E(b[i]);E(x[i]);E(y[i]); d[i]=0;a[i]=0;R(j)b[i][j]=0;x[i][j]=0;y[i][j]=0;}}if(f(1,0)){R(i)R(j)std::cout<<b[i][j];}std::cout<<std::endl;}}}

ลองออนไลน์ได้ที่นี่

เนื่องจากคำตอบสองสามข้อถูกโพสต์แล้วฉันคิดว่าฉันจะโพสต์รหัส golfed รุ่นที่ฉันใช้ในการสร้างผลลัพธ์สำหรับตัวอย่าง นี่เป็นครั้งแรกที่ฉันตอบดังนั้นจึงยินดีรับข้อเสนอแนะทั้งหมด :)

คำอธิบาย Ungolfed +:

โดยพื้นฐานแล้วโค้ดนั้นใช้วิธีการเดรัจฉานบังคับ มันเริ่มต้นในแถวแรกด้วย 0 มันเริ่มต้นในจุดแรกถ้าจุดนั้นผ่านการตรวจสอบทั้งหมดมันจะย้ายไปยังหมายเลขถัดไป ถ้ามันเติมแถวมันจะย้ายไปยังแถวถัดไป หากดำเนินการครบทุกแถวหมายความว่าหาวิธีแก้ไขแล้ว หากจุดไม่ผ่านการตรวจสอบทั้งหมดก็จะย้ายไปยังจุดต่อไป หากทำแถวเสร็จแล้วมันจะย้อนรอยเนื่องจากตัวเลขในหนึ่งในแถวก่อนหน้านี้ช่วยป้องกันไม่ให้มีวิธีแก้ปัญหา

#include <iostream>

// global variables to save bytes on passing these are function arguments
int **b, // this will store the state of the board
    **x, // if x[i][j] is true, row i of b contains the number j
    **y, // if y[i][j] is true, column i of b contains the number j
    *d,  // if d[i] the main diagonal of b contains i
    *a,  // if a[i] the antidiagonal of a contains i
    n;

// preprocessor to save bytes on repeated statements
#define R(i) for(i=0;i<n;i++){
#define E(e) e=new int[n];

// Recursively looks for a solution 
// c - the current number to insert in row r
// r - the current row to fill
int f (int c, int r) {
        int i=0,p=c-1;
        if (r >= n) return 1;             // we are done
        if (c == n + 1) return f(1,r+1);  // this row is full, move to the next row
        R(i)                              // go through the positions in this row,
                                                                            // trying to fill them with c
                int m=r==i, s=r+i==n-1;   // check if this position (r,i) is on ones
                                                                            // of the diagonals
                // if this spot isn't filled, and the row (r), column (i) and diagonals
                // (if it's on the diagonal) doesn't contain the number, fill the spot
                if (!b[r][i] && !x[r][p] && !(m&&d[p]) && !(s&&a[p]) && !y[i][p]) {
                        // fill the spot, and indicate that this row, column and diagonals 
                        // contain this number, c
                        b[r][i]=c; x[r][p]=1; y[i][p]=1;
                        if (m) d[p]=1; if (s)a[p]=1;

                        // move onto to the next number, if you find a solution, stop
                        if (f(c+1,r)) return 1;

                        // with this number in this spot, a solution is impossible, clear
                        // its, and clear the checks
                        b[r][i]=0; x[r][p]=0; y[i][p]=0;
                        if (m) d[p]=0; if (s) a[p]=0;
                }
        }

        return 0; // a solution wasn't found
}

int main() {
        std::cin >> n; // get n from STDIN

        // initialization 
        int i=0,j=0;
        b=new int*[n]; x=new int*[n]; y=new int*[n];
        E(d); E(a);
        R(i)
                E(b[i]); E(x[i]); E(y[i]); // initialization the inner arrays of b, x, y
                d[i]=0; a[i]=0;

                R(j)
                        b[i][j]=0; x[i][j]=0; y[i][j]=0; // ensure each point is initialized as 0
                }
        }

        // find a solution starting at the top-left corner and print it if it finds one
        if (f(1,0)) {
                R(i)
                        R(j)
                                std::cout<<b[i][j];
                        }
                        std::cout<<std::endl;
                }
        }
}

หลังจาก rereading if (x[r][p]) return f(c+1,r);รหัสฉันตระหนักบางส่วนของการตรวจสอบอาจไม่จำเป็นเช่น ฉันกำลังทำให้สั้นลง
hargasinski

0

Clojure, (215 + 258) * 0.8 = 378.4 (174 + 255) * 0.8 = 343.2

แบ่งออกเป็นสองส่วน: การนับข้อผิดพลาด Sและฟังก์ชั่นที่ไม่ระบุชื่อซึ่งจะเพิ่มประสิทธิภาพที่เกิดขึ้นจริงผ่านการค้นหาห้าม

อัปเดต: สั้นกว่า S (นับค่าที่แตกต่างภายในกลุ่ม), สถานะเริ่มต้นที่ดีที่สุดน้อยกว่า (ไม่สลับ)

(defn S[I n](count(mapcat set(vals(apply merge-with concat(flatten(for[R[(range n)]i R j R v[[(I(+(* n i)j))]]][{[1 i]v}{[2 j]v}(if(= i j){3 v})(if(=(- n 1 i)j){4 v})])))))))
#(if-let[s({1[0]2()3()}%)]s(loop[I(vec(for[R[(range %)]i R j R]i))P #{}](let[[s I](last(sort-by first(for[R[(range(count I))]i R j R I[(assoc(assoc I i(I j))j(I i))]:when(not(P I))][(S I %)I])))](if(=(*(+(* % 2)2)%)s)(partition % I)(recur I(conj P I))))))

มาตรฐานแกนเดี่ยว (เป็นมิลลิวินาที) สำหรับ 4, 5, 6 และ 7 ทำงาน 3 ครั้ง:

[[  131.855337   132.96267    138.745981]
 [ 1069.187325  1071.189488  1077.339372]
 [ 9114.736987  9206.65368   9322.656693]
 [36546.309408 36836.567267 36928.346312]]

เดิม:

(defn S[I n](apply +(flatten(for[p(concat(partition n I)(for[p(apply map vector(partition n(range(count I))))](map I p))[(take-nth(inc n)I)][(rest(butlast(take-nth(dec n)I)))])](remove #{1}(vals(frequencies p)))))))
#(if-let[s({1[0]2()3()}%)]s(loop[I(vec(flatten(map shuffle(repeat %(range %)))))P #{}](let[[s I](first(sort-by first(for[R[(range(count I))]i R j R I[(assoc(assoc I i(I j))j(I i))]:when(not(P I))][(S I %)I])))](if(= s 0)(partition % I)(recur I(conj P I))))))

ฉันหวังว่า Sสั้น แต่เพราะมันนับเฉพาะการเกิดขึ้นของมากกว่าหนึ่งพาร์ทิชัน / (= s 0)เกณฑ์การหยุดเป็นเรื่องง่าย

รอบ CPU จำนวนมากสูญเปล่าเนื่องจากการแลกเปลี่ยนที่ไม่มีประโยชน์ตัวอย่างเช่นมันจะไม่ปรับปรุงคะแนนถ้าคุณสลับ 2ไป2มาและคุณไม่จำเป็นต้องสลับตัวเลขระหว่างแถว

การวัดประสิทธิภาพด้วย Intel 6700K (หน่วยเป็นมิลลิวินาที):

(defn S[I n]( ... )
(def F #( ... ))

(defmacro mytime[expr]
  `(let [start# (. System (nanoTime)) ret# ~expr]
     (/ (double (- (. System (nanoTime)) start#)) 1000000.0)))

(pprint(vec(for[n[4 5 6 7]](vec(sort(repeatedly 5 #(mytime (F n)))))))

[[  43.445902   45.895107   47.277399   57.681634    62.594037]
 [ 222.964582  225.467034  240.532683  330.237721   593.686911]
 [2285.417473 2531.331068 3002.597908 6361.591714  8331.809410]
 [3569.62372  4779.062486 5725.905756 7444.941763 14120.796615]]

มัลติเธรดด้วยpmap:

[[   8.881905  16.343714   18.87262  18.9717890   22.194430]
 [  90.963870 109.719332  163.00299  245.824443  385.365561]
 [ 355.872233 356.439256 1534.31059 2593.482767 3664.221550]
 [1307.727115 1554.00260 2068.35932 3626.878526 4029.543011]]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.