ปัญหา“ เติมกริด”


36

ความท้าทายด้วยกฎง่ายๆ แต่อัลกอริธึมที่ไม่สำคัญ :-)

งาน

รับอินพุตในรูปแบบของจำนวนเต็มคั่นด้วยช่องว่าง:

N A B S

โดยที่ N คือความยาวด้านของเมทริกซ์จตุรัส 2D ที่เต็มไปด้วยตัวเลขเฉพาะ (จำนวนเต็ม) ระหว่าง A และ B สำหรับแต่ละแถวและคอลัมน์ในเมทริกซ์นี้ผลรวมจะเท่ากันเสมอ: S. (กล่าวอีกนัยหนึ่งเมทริกซ์คือจตุรัสกึ่งเวทมนต์)

บันทึก:

ตัวเลขทั้งหมดเป็นค่าบวก ข้อยกเว้นคือ A ซึ่งสามารถเป็น 0

ตัวอย่าง

สำหรับ

3 1 10000 2015

ทางออกที่ถูกต้องจะเป็น

ป้อนคำอธิบายรูปภาพที่นี่

สำหรับ

8 1 300 500

ทางออกที่ถูกต้องจะเป็น

ป้อนคำอธิบายรูปภาพที่นี่

เอาท์พุต

ผลลัพธ์ของคุณควรเป็นตาราง ASCII ตัวอย่างสำหรับตัวอย่างแรกด้านบน:

 384  159 1472
1174  499  342
 457 1357  201

จำนวนเต็มจัดชิดขวาด้วยการเว้นวรรค ความกว้างของแต่ละคอลัมน์คือความกว้างของจำนวนเต็มที่มากที่สุดในคอลัมน์นั้น

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

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


1
เราได้รับอนุญาตให้สร้างตัวเลขสุ่มระหว่าง A และ B จนกว่าพวกเขาจะรวมกันอย่างถูกต้องและไม่ซ้ำกัน?
lirtosiast

เพียงแค่การตรวจสอบA, BและNสามารถเป็นเชิงลบได้อย่างไร
xnor

2
minxomat ฉันไม่ได้บอกว่ามันเป็นทางออกที่ดีที่สุดที่ฉันสามารถหาได้ฉันพูดว่ามันอาจจะสั้นที่สุด
lirtosiast

3
@LuisMendo คุณต้องสร้างตัวอย่างผลลัพธ์ตามภารกิจ หากคุณสามารถจัดการสิ่งนี้ในชีวิตของคุณด้วยวิธีการที่ดุร้ายฉันก็จะต้องประทับใจ :-) ฉันสามารถแยกแยะออกได้ แต่มันจะคลุมเครือเกินไปเนื่องจากวิธีแก้ปัญหายอดนิยม (ซึ่งก็คือ GA) ยังคงเกี่ยวข้องกับการสุ่ม นอกจากนี้ฉันไม่ต้องการเปลี่ยนกฎเมื่อใครบางคนอาจใช้งานโซลูชันได้อยู่แล้ว
mınxomaτ

1
@minxomat ข้อโต้แย้งทั้งสามข้อของคุณนั้นเป็นคะแนนที่ดีมาก :-)
Luis Mendo

คำตอบ:


19

CJam, 119 91 ไบต์

q~:M;),>:R;(:L{{R{ML)d/-Y#)mr}$L/L<2{{M1$:+-+}%z}*:U:+__O|=R*-}gU{:s_:,:e>f{Se[}}%zSf*N*}M?

นี่เป็นวิธีที่พิสูจน์ได้อย่างถูกต้องและไม่สามารถกำหนดได้

บนเดสก์ท็อปของฉันกรณีทดสอบที่สองโดยทั่วไปจะเสร็จสิ้นในเวลาน้อยกว่า 10 นาที

กรณีแรกเสร็จสิ้นทันที ลองใช้ออนไลน์ในล่าม CJam

วิ่งตัวอย่าง

$ cjam grid.cjam <<< '8 1 300 500'
77  66  37 47  56  46 86  85
63 102  70 72  49  54 81   9
62  69  58 57  71  17 48 118
64  65  67 87  53  44 80  40
73  60  55 89  51  76 84  12
68  59  28 78  74  38 50 105
61  75  52 43 125  83 42  19
32   4 133 27  21 142 29 112

ความคิด

โดยไม่มีการ จำกัด เวลาเราสามารถสุ่มสร้างสี่เหลี่ยมจัตุรัสจนกระทั่งหาตารางที่ถูกต้อง วิธีนี้สร้างจากแนวคิดนั้นโดยเพิ่มการเพิ่มประสิทธิภาพสองอย่าง:

  • แทนที่จะหลอกสุ่มสร้างตารางของความยาวด้านNเราสร้างสี่เหลี่ยมของความยาวด้านN-1เพิ่มคอลัมน์หนึ่งในรูปแบบN ร (N-1)รูปสี่เหลี่ยมผืนผ้าที่มีแถวมียอดรวมSแล้วหนึ่งแถวในรูปแบบตารางของ ความยาวด้านNซึ่งมียอดรวมคอลัมน์S

    เนื่องจากผลรวมขององค์ประกอบของคอลัมน์ทั้งหมดจะNSและผลรวมขององค์ประกอบแรกที่N-1แถวเป็น(N-1) S , แถวสุดท้ายจะยังมีผลรวมS

    อย่างไรก็ตามกระบวนการนี้อาจสร้างเมทริกซ์ที่ไม่ถูกต้องเนื่องจากมีการรับประกันว่าทุกองค์ประกอบของแถวสุดท้ายและคอลัมน์จะไม่ซ้ำกันหรือตกอยู่ในช่วงที่ไม่มี[A ... B]

  • การเลือกจำนวนเต็มจำนวนสี่เหลี่ยมจัตุรัสที่ไม่ซ้ำกันใน[A ... B]และความยาวด้านN-1สม่ำเสมอโดยการสุ่มจะใช้เวลานานเกินไป เราต้องจัดลำดับความสำคัญของสี่เหลี่ยมที่มีโอกาสสูงกว่าที่จะทำให้เกิดสี่เหลี่ยมจัตุรัสที่มีความยาวด้านN ที่ถูกต้องหลังจากใช้กระบวนการที่มีรายละเอียดในสัญลักษณ์แสดงหัวข้อก่อนหน้า

    ระบุว่าในแต่ละแถวและคอลัมน์จะต้องมีผลรวมของS , องค์ประกอบของมีค่าเฉลี่ยของS / N ดังนั้นการเลือกองค์ประกอบเพิ่มเติมที่ใกล้เคียงกับค่าเฉลี่ยควรเพิ่มโอกาสของเรา

    สำหรับแต่ละฉันใน[A ... B]เราหลอกสุ่มเลือกลอยระหว่าง0และ(I - S / N) 2 + 1และจัดเรียงองค์ประกอบของ[A ... B]โดยลอยเลือก เราเก็บตัวเลขN 2ตัวแรกและวางไว้ในลำดับการอ่านในตาราง

    สมมติว่ามีการแจกแจงที่เหมือนกันอย่างสมบูรณ์ของจำนวนจริงทั้งหมดระหว่าง0และ(I - S / N) 2 + 1ในแต่ละขั้นตอนสี่เหลี่ยมทั้งหมดมีความน่าจะเป็นที่ไม่เป็นศูนย์ของการเลือกซึ่งหมายความว่ากระบวนการจะเสร็จสิ้นในที่สุด

รหัส

q~          e# Read all input from STDIN and evaluate it.
:M;         e# Save "S" in M and discard it from the stack.
),>:R;      e# Transform "A B" into [A ... B], save in R and discard.
(:L         e# Save "N - 1" in L and keep it on the stack.
{           e# If L is non-zero:
  {         e#   Do:
    R{      e#     For each I in R:
      ML)d/ e#       Compute M/Double(L+1).
      -Y#   e#       Subtract the result from I and square the difference.
      )mr   e#       Add 1 and pick a non-negative Double below the result.
    }$      e#     Sort the values of I according to the picks.
    L/      e#     Split the shuffled R into chunks of length L.
    L<      e#     Keep only the first L chunks.
    2{      e#     Do twice:
      {     e#       For each row of the  L x L array.
        M1$ e#       Push M and a copy of the row.
        :+- e#       Add the integers of the row and subtract their sum from M.
        +   e#       Append the difference to the row.
      }%    e#
      z     e#       Transpose rows and columns.
    }*      e#
    :U:+    e#     Save the result in U and concatenate its rows.
    __O|    e#     Push two copies. Deduplicate the second copy.
    =R*     e#     Push R if all elements are unique, an empty array otherwise.
    -       e#     Remove the result's elements from U's elements.
  }g        e#   If the resulting array is non-empty, repeat the loop.
  U{        e#   For each row in U:
    :s      e#     Convert its integers into strings.
    _:,     e#     Copy and replace each string with its length.
    :e>     e#     Compute the maximum length.
    f{      e#     For each integer, push the maximum length; then
      Se[   e#       Left-pad the integer with spaces to that length.
    }       e#
  }%        e#
  z         e#   Transpose rows with columns.
  Sf*N*     e#   Join columns by spaces, rows by linefeeds.
}M?         e# Else, push M.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.