Rubik-sorting matrix (aka ปริศนาพรู)


16

แนวคิดสำหรับนี้ง่าย: ให้เมทริกซ์ของจำนวนเต็มลองเรียงลำดับโดยใช้การเคลื่อนไหวสไตล์ Rubik ซึ่งหมายความว่าคุณสามารถเลือกแถวหรือคอลัมน์เดียวและหมุนองค์ประกอบในทิศทางใดก็ได้:

[1, 3, 2, 4]  => [3, 2, 4, 1] (rotate left for rows/up for columns)
[1, 3, 2, 4]  => [4, 1, 3, 2] (rotate right for rows/down for columns)

ดังนั้นด้วยเมทริกซ์ของจำนวนเต็มของมิติใด ๆ ให้เรียงลำดับองค์ประกอบโดยใช้การแปลงสไตล์รูบิคเหล่านี้เท่านั้น เมทริกซ์

[a11a12a13a14a21a22a23a24a31a32a33a34]

จะได้รับการพิจารณาให้เรียงลำดับหากองค์ประกอบขององค์ประกอบสอดคล้องกับข้อ จำกัด ต่อไปนี้:

a11a12a13a14a21a22a23a24a31a32a33a34

I / O

  • อินพุตจะเป็นเมทริกซ์ของจำนวนเต็มบวกที่ไม่มีค่าซ้ำ
  • ผลลัพธ์จะเป็นการเคลื่อนไหวที่จำเป็นในการจัดเรียง เช่นนี้ไม่ได้เป็นความท้าทายรหัสกอล์ฟและคุณไม่จำเป็นต้องกังวลเกี่ยวกับความยาวของรูปแบบที่นำเสนอสำหรับทุกการเคลื่อนไหวเป็น#[UDLR]ที่#เป็นจำนวนของแถวหรือคอลัมน์ที่จะย้าย (0 จัดทำดัชนี) และ[UDLR]เป็นตัวเดียวในการที่ ช่วงที่ระบุว่าการเคลื่อนไหวขึ้น / ลง (สำหรับคอลัมน์) หรือซ้าย / ขวา (สำหรับแถว) ดังนั้น1Uจะหมายถึง "ย้ายคอลัมน์ที่ 1 ขึ้นไป" แต่1Rจะเป็น "เลื่อนแถวที่ 1 ไปทางขวา" 1R,1U,0L,2Dการเคลื่อนไหวจะคั่นด้วยเครื่องหมายจุลภาคเพื่อแก้ปัญหาจะได้รับการแสดงเช่นนี้

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

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

ตัวอย่าง: หากผู้ใช้ A ค้นหาโซลูชันสำหรับ N = 5 และ B ค้นหาโซลูชันสำหรับ N = 6 B จะชนะโดยไม่คำนึงถึงความยาวของทั้งสองเส้นทาง หากทั้งคู่หาวิธีแก้ปัญหาสำหรับ N = 6 แต่โซลูชันที่พบโดย A มี 50 ขั้นตอนและโซลูชันของ B มี 60 ขั้นตอน A จะชนะ

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

กรณีทดสอบ

เมทริกต่อไปนี้ ( ลิงก์ Pastebinสำหรับเวอร์ชันที่คัดลอกได้มากขึ้น) ได้ถูกสร้างขึ้นเริ่มต้นจากเมทริกซ์ที่เรียงลำดับแล้วโดย scrambling พวกมันด้วยการเคลื่อนไหว 10K แบบสุ่ม, Rubik-style:

[8561110131513]
[211012161762214851926132431]
[11381659402126221124143928321937310301736734]
[34214022354118333130124319113924282344136538451417916132683476254]
[20361711550187267341032355424396306139284154272357048132512465863523784533146859655673606422]
[85565275894441682715879132373973676419997846164221631004172131197309328403365070258058960845496172943342335776182482943866]
[567990617112211031551144284851306188443386611324962010275685888098351007713216410810601144023472731068232120263653936910454191111176217278873349155811695112571189151426545]

Plaintext Test Cases:

[[8, 5, 6], [11, 10, 1], [3, 15, 13]]

[[21, 10, 12, 16], [17, 6, 22, 14], [8, 5, 19, 26], [13, 24, 3, 1]]

[[1, 13, 8, 16, 5], [9, 40, 21, 26, 22], [11, 24, 14, 39, 28], [32, 19, 37, 3, 10], [30, 17, 36, 7, 34]]

[[34, 21, 40, 22, 35, 41], [18, 33, 31, 30, 12, 43], [19, 11, 39, 24, 28, 23], [44, 1, 36, 5, 38, 45], [14, 17, 9, 16, 13, 26], [8, 3, 47, 6, 25, 4]]

[[20, 36, 17, 1, 15, 50, 18], [72, 67, 34, 10, 32, 3, 55], [42, 43, 9, 6, 30, 61, 39], [28, 41, 54, 27, 23, 5, 70], [48, 13, 25, 12, 46, 58, 63], [52, 37, 8, 45, 33, 14, 68], [59, 65, 56, 73, 60, 64, 22]]

[[85, 56, 52, 75, 89, 44, 41, 68], [27, 15, 87, 91, 32, 37, 39, 73], [6, 7, 64, 19, 99, 78, 46, 16], [42, 21, 63, 100, 4, 1, 72, 13], [11, 97, 30, 93, 28, 40, 3, 36], [50, 70, 25, 80, 58, 9, 60, 84], [54, 96, 17, 29, 43, 34, 23, 35], [77, 61, 82, 48, 2, 94, 38, 66]]

[[56, 79, 90, 61, 71, 122, 110, 31, 55], [11, 44, 28, 4, 85, 1, 30, 6, 18], [84, 43, 38, 66, 113, 24, 96, 20, 102], [75, 68, 5, 88, 80, 98, 35, 100, 77], [13, 21, 64, 108, 10, 60, 114, 40, 23], [47, 2, 73, 106, 82, 32, 120, 26, 36], [53, 93, 69, 104, 54, 19, 111, 117, 62], [17, 27, 8, 87, 33, 49, 15, 58, 116], [95, 112, 57, 118, 91, 51, 42, 65, 45]]

Please ask for more if you solve them all. :-) And many thanks to the people who helped me refine this challenge while in the sandbox.


1 A reasonable amount of time: any amount of time that doesn't undermine our patience while testing your solution. Note that TIO only runs code for 60 seconds, any amount of time over that limit will make us test the code in our machines. Example: my rather inefficient algorithm takes a few milliseconds to solve matrices of order 3x3 and 4x4, but I have just tested it with a 5x5 matrix and it took 317 seconds to solve it (in over 5 million movements, very funny if we consider that the matrix to solve was scrambled only 10K times). I tried to reduce the number of movements to less than 10K but I surrendered after 30 minutes executing the code.


1
Nice challenge! However, I have a few requests/questions: 1) Could you provide the test cases in a more copy-paste friendly format? (such as pastebin) 2) Could you provide a more precise definition of the time limit order? 3) Is the matrix guaranteed to be square? (The test cases suggest so, but the definition does not.)
Arnauld

@Arnauld 1) I'm on it. 2) I didn't want to establish a time limit, and nobody suggested any limit while the challenge was in the sandbox. If you need one, would you consider 30 minutes a reasonable limit? 3) Yes, the test matrices are the ones shown, and they will all be square if more are needed.
Charlie

There exists an (relatively easy to implement) O(input size) algorithm to this challenge, so it's not as interesting as it may look at first.
user202729

@user202729 What would the input-size be in your O(input size) then? For a 5x5 matrix it would O(25)? That seems to be extremely fast, so I would be very interested to see that algorithm or implementation of yours. EDIT: You do realize we input the 'scrambled' matrix and output the movements, right? Not the other way around.
Kevin Cruijssen

4
I think, it's something like this algorithm
Kirill L.

คำตอบ:


8

Nim

import algorithm, math, sequtils, strutils

let l = split(stdin.readLine())
var m = map(l, parseInt)
let n = int(sqrt(float(len(m))))
let o = sorted(m, system.cmp[int])

proc rotations(P, Q: int): tuple[D, L, R, U: string, P, Q: int]=
  result = (D: "D", L: "L", R: "R", U: "U", P: P, Q: Q)
  if P > n - P:
    result.D = "U"
    result.U = "D"
    result.P = n - P
  if Q > n - Q:
    result.L = "R"
    result.R = "L"
    result.Q = n - Q

proc triangle(r: int): string=
  let p = r div n
  let q = r mod n
  let i = find(m, o[r])
  let s = i div n
  let t = i mod n
  var u = s
  var v = q
  if s == p and t == q:
    return ""
  var patt = 0
  if p == s: 
    u = s + 1
    patt = 4
  elif q == t:
    if q == n - 1:
      v = t - 1
      patt = 8
    else:
      u = p
      v = t + 1
      patt = 3
  elif t > q:
    patt = 2
  else:
    patt = 7
  var Q = abs(max([q, t, v]) - min([q, t, v]))
  var P = abs(max([p, s, u]) - min([p, s, u]))
  let x = p*n + q
  let y = s*n + t
  let z = u*n + v
  let w = m[x]
  m[x] = m[y]
  m[y] = m[z]
  m[z] = w
  let R = rotations(P, Q)

  result = case patt:
    of 2:
      repeat("$#$#," % [$v, R.D], R.P) & 
        repeat("$#$#," % [$u, R.L], R.Q) &
        repeat("$#$#," % [$v, R.U], R.P) & 
        repeat("$#$#," % [$u, R.R], R.Q)
    of 3:
      repeat("$#$#," % [$q, R.U], R.P) & 
        repeat("$#$#," % [$p, R.L], R.Q) &
        repeat("$#$#," % [$q, R.D], R.P) & 
        repeat("$#$#," % [$p, R.R], R.Q)
    of 4:
      repeat("$#$#," % [$p, R.L], R.Q) & 
        repeat("$#$#," % [$q, R.U], R.P) &
        repeat("$#$#," % [$p, R.R], R.Q) & 
        repeat("$#$#," % [$q, R.D], R.P)
    of 7:
      repeat("$#$#," % [$v, R.D], R.P) & 
        repeat("$#$#," % [$u, R.R], R.Q) &
        repeat("$#$#," % [$v, R.U], R.P) & 
        repeat("$#$#," % [$u, R.L], R.Q)
    of 8:
      repeat("$#$#," % [$s, R.R], R.Q) & 
        repeat("$#$#," % [$t, R.D], R.P) &
        repeat("$#$#," % [$s, R.L], R.Q) & 
        repeat("$#$#," % [$t, R.U], R.P)
    else: ""

proc Tw(p, t, P, Q: int): string =
  let S = P + Q
  result = "$#D,$#$#U,$#$#D,$#$#U," % [
    $t, if P > n - P: repeat("$#L," % $p, n - P) else: repeat("$#R," % $p, P),
    $t, if S > n - S: repeat("$#R," % $p, n - S) else: repeat("$#L," % $p, S), 
    $t, if Q > n - Q: repeat("$#L," % $p, n - Q) else: repeat("$#R," % $p, Q), 
    $t]

proc line(r: int): string=
  let p = n - 1
  let q = r mod n
  let i = find(m, o[r])
  var t = i mod n
  if t == q: 
    return ""
  let j = t == n - 1
  var P = t - q
  let x = p*n + q
  let y = x + P
  let z = y + (if j: -1 else: 1)
  let w = m[x]
  m[x] = m[y]
  m[y] = m[z]
  m[z] = w
  if j:
    let R = rotations(1, P)
    result = "$#D,$#$#U,$#$#R,$#D,$#L,$#U," % [
      $t, repeat("$#$#," % [$p, R.R], R.Q), 
      $t, repeat("$#$#," % [$p, R.L], R.Q), 
      $p, $t, $p, $t]
  else:
    result = Tw(p, t, P, 1)  
  
proc swap: string=
  result = ""
  if m[^1] != o[^1]:
    m = o
    for i in 0..(n div 2-1):
      result &= Tw(n - 1, n - 2*i - 1, 1, 1)
    result &= "$#R," % $(n - 1)
  
var moves = ""
for r in 0..(n^2 - n - 1):
  moves &= triangle(r)
if n == 2 and m[^1] != o[^1]:
  m = o
  moves &= "1R"
else:
  for r in (n^2 - n)..(n^2 - 3):
    moves &= line(r)
  if n mod 2 == 0:
    moves &= swap()
  if len(moves) > 0:
    moves = moves[0..^2]
  
echo moves

Try it online!

A quick attempt to implement the Torus puzzle solution algorithm from an article published in Algorithms 2012, 5, 18-29 that I mentioned in comments.

Accepts the input matrix in flattened form, as a line of space-delimited numbers.

Here also is a validator in Python 2. It takes two lines as input: the original scrambled matrix in the same form as the main code, and the proposed sequence of moves. The output of the validator is the matrix resulting from applying these moves.

Explanation

In the first part of the algorithm, we order all rows except the last one.

We do this by performing series of "triangle rotations" (proc triangle) - the sequences of moves that result in only three cells swapping places, and all the rest staying unchanged. We take each consecutive "working" cell with coordinates [p,q], then find the cell [s,t] that currently contains the number that should go to [p,q], and complete the right triangle by selecting a third point [u,v] according to some pattern, as shown in Fig. 4 of the linked article.

In Fig. 2, the authors present 8 possible patterns and the corresponding sequences of moves, but in my code all cases have actually been covered by only 5 patterns, so that no. 1, 5, and 6 are not used.

In the second part, the last row except the two last elements is ordered by performing "three elements rotations" on a line (proc line), which consist of two triangle rotations each (see Fig. 3 of the article).

We select our current working cell [p,q] as the left point, cell containing the target value [s,t] as the central point, and [s,t+1] as the right point. This westbound movement is named TW in the article, and so is my string forming proc for this. If t is already the last column, so that t+1 does not exist, we take [s,t1] as the third point, and modify the action accordingly: two triangle rotations are performed by patterns 7 and 8 (instead of 7 and 1 in the original TW sequence).

Finally, if n is odd, the remaining two elements must be already in place, as we are guaranteed that a solution exists. If n is even, and the two remaining elements are not in place, then according to Lemma 1 (page 22), they can be swapped by a series of TW moves, followed by one shift east (=R). Since the provided example swaps the first two entries, and we need to swap the last two, our proc swap performs TW moves in reverse order.

In the edge case of n=2 we don't need all these complex procedures at all - if the last row elements are not in place after part 1, a single 1R move is sufficient to make the matrix fully ordered.

Update: Added new proc rotations that reverses the direction of moves if that would result in less steps.


Impressive! I'll create some more test cases then. Meanwhile, I'm sure this solution can be optimized, as there are chunks like 7L,7L,7L,7L,7D,7D,7D,7D than can be reduced and 8R,8R,8R,8R,8R,8R,8R than can be converted to 8L,8L for a 9x9 matrix.
Charlie

I've tried your algorithm with a 100x100 matrix and it solves it in less than 4 seconds. I really didn't expect this problem to have a linear-time solution. I'll try to write better challenges in the future!
Charlie

Maybe it would have been better to pose this challenge with a single, fixed matrix as the only test case, and set the winning criterion to be just the size of the found path to solve it, had I known before that this problem had a O(n^2) solution. Would you consider porting this answer to a new question with such winning criterion?
Charlie

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

5

Python 2ขนาด 100 ใน <30 วินาทีบน TIO

import random
def f(a):
 d = len(a)
 r = []
 def V(j, b = -1):
  b %= d
  if d - b < b:
   for k in range(d - b):
    if r and r[-1] == "U%d" % j:r.pop()
    else:r.append("D%d" % j)
    b = a[-1][j]
    for i in range(len(a) - 1):
     a[-1 - i][j] = a[-2 - i][j]
    a[0][j] = b
  else:
   for k in range(b):
    if r and r[-1] == "D%d" % j:r.pop()
    else:r.append("U%d" % j)
    b = a[0][j]
    for i in range(len(a) - 1):
     a[i][j] = a[i + 1][j]
    a[-1][j] = b
 def H(i, b = -1):
  b %= d
  if d - b < b:
   for k in range(d - b):
    if r and r[-1] == "L%d" % i:r.pop()
    else:r.append("R%d" % i)
    a[i] = a[i][-1:] + a[i][:-1]
  else:
   for k in range(b):
    if r and r[-1] == "R%d" % i:r.pop()
    else:r.append("L%d" % i)
    a[i] = a[i][1:] + a[i][:1]
 b = sorted(sum(a, []))
 for i in range(d - 1):
  for j in range(d):
   c = b.pop(0)
   e = sum(a, []).index(c)
   if e / d == i:
    if j == 0:H(i, e - j)
    elif j < e % d:
     if i:
      V(e % d, 1)
      H(i, j - e)
      V(e % d)
      H(i, e - j)
     else:
      V(e)
      H(1, e - j)
      V(j, 1)
   else:
    if j == e % d:
     H(e / d)
     e += 1
     if e % d == 0:e -= d
    if i:
     V(j, i - e / d)
    H(e / d, e - j)
    V(j, e / d - i)
 c = [b.index(e) for e in a[-1]]
 c = [sum(c[(i + j) % d] < c[(i + k) % d] for j in range(d) for k in range(j)) % 2 and d * d or sum(abs(c[(i + j) % d] - j) for j in range(d)) for i in range(d)]
 e = min(~c[::-1].index(min(c)), c.index(min(c)), key = abs)
 H(d - 1, e)
 for j in range(d - 2):
  e = a[-1].index(b[j])
  if e > j:
   c = b.index(a[-1][j])
   if c == e:
    if e - j == 1:c = j + 2
    else:c = j + 1
   V(e)
   H(d - 1, j - e)
   V(e, 1)
   H(d - 1, c - j)
   V(e)
   H(d - 1, e - c)
   V(e, 1)
 return r

ลองออนไลน์! ลิงก์มีกรณีทดสอบขนาดเล็กสามกรณีพร้อมเอาท์พุทเต็มรูปแบบรวมถึงการทดสอบแบบเงียบ 100x100 เพื่อแสดงให้เห็นว่ารหัสทำงานได้ (เอาต์พุตการย้ายจะเกินขีด จำกัด ของ TIO) คำอธิบาย: รหัสพยายามทำการเรียงลำดับการแทรกบนอาร์เรย์สร้างขึ้นในลำดับจากน้อยไปมาก สำหรับแถวทั้งหมดยกเว้นแถวสุดท้ายมีหลายกรณี:

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

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

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

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


ขอบคุณมากสำหรับคำตอบของคุณนีล! แต่จำไว้ว่านี่ไม่ใช่กอล์ฟรหัส แทนที่จะเป็นความยาวของรหัสคุณควรระบุขนาด N ที่สุดของเมทริกซ์ NxN ที่คุณแก้ไขและความยาวของรายการการเคลื่อนไหวเพื่อแก้เมทริกซ์นั้น
Charlie

@ Charlie ที่ดีนั่นคือ 6 แต่เพียงเพราะฉันขี้เกียจเกินไปที่จะวางในเมทริกซ์ที่ใหญ่กว่า แม้ว่ามันจะดุร้าย แต่มันก็ทำการสเกลพื้นที่กับเส้นตรงดังนั้นมันควรจะมีเมทริกซ์ขนาดใหญ่
Neil

ที่จริงกรณีที่เลวร้ายที่สุดอาจเป็นกำลังสองกับพื้นที่
Neil

1
@Charlie TIO ลิงค์แก้เมทริกซ์ 100x100 แบบสุ่ม
Neil

1
@ Charlie ตอนนี้ฉันได้พบกับการเพิ่มประสิทธิภาพที่สำคัญสำหรับแถวล่าง แต่ฉันคิดว่านั่นคือการเปลี่ยนแปลงครั้งสุดท้ายที่ฉันจะทำกับคำตอบนี้
Neil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.