-1

You are given an array, for example:

arr = [['AB','KR','EH'],['EE','DD','PS'],['GH','LM','XK']]

array printed by rows

Then, through a function, you have to get this:

sorted array printed by rows

The array must be sorted ascending as a whole and not only by rows. You can not create new arrays for this. You have to do it in place.

I tried to find a way to do this with no new arrays but I could not. This is my code, it certainly sorts the array but creates a new array.

def sortArray(arr): #n : filas,columnas
    sorted_arr = []
    for j in arr:
        sorted_arr.extend(j)

    return sorted(sorted_arr)
Barmar
  • 741,623
  • 53
  • 500
  • 612

4 Answers4

1

You can perform a selection sort, using indexes from 0 to N * N - 1 where N is the length of the array (since it's square). The corresponding element in the actual array for each index can be calculated by dividing and taking the remainder.

def sortArray(arr):
    n = len(arr)
    for i in range(n * n):
        m = i
        for j in range(i + 1, n * n):
            if arr[j // n][j % n] < arr[m // n][m % n]:
                m = j
        arr[i // n][i % n], arr[m // n][m % n] = arr[m // n][m % n], arr[i // n][i % n]
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
0

Try:

from itertools import islice

arr = [["AB", "KR", "EH"], ["EE", "DD", "PS"], ["GH", "LM", "XK"]]

i = iter(sorted(v for l in arr for v in l))
for l in arr:
    l[:] = islice(i, 0, len(l))

print(arr)

Prints:

[
  ["AB", "DD", "EE"], 
  ["EH", "GH", "KR"], 
  ["LM", "PS", "XK"]
]
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
0

Well, if you can't create a new list and it has to be done in-place, you could always just do an exchange sort:

arr = [['AB','KR','EH'],['EE','DD','PS'],['GH','LM','XK']]

def sortedArray(arr):
    height = len(arr)
    width = len(arr[0])
    for left in range(height*width):
        for right in range(left+1, height*width):
            li, lj = left//height, left%width
            ri, rj = right//height, right%width
            if arr[li][lj] > arr[ri][rj]:
                arr[li][lj], arr[ri][rj] = arr[ri][rj], arr[li][lj]
    
    return arr

print(sortedArray(arr))

Output:

[
 ['AB', 'DD', 'EE'], 
 ['EH', 'GH', 'KR'], 
 ['LM', 'PS', 'XK']
]

Looks messy, feels dumb, but at least it does meet the requirements.

B Remmelzwaal
  • 1,581
  • 2
  • 4
  • 11
  • You can make it less messy if you use a translator like I did in my second solution now. – Kelly Bundy Mar 28 '23 at 23:15
  • While I do agree it's more elegant, I feel it's also getting into a grey area concerning the no allocations for new lists, since you are creating a whole class. Wonder if that would be allowed under the rules. – B Remmelzwaal Mar 28 '23 at 23:20
  • 1
    It's not storing anything, though. And takes O(1) space no matter how large the data is. Not much different than using a few variables and integer objects. – Kelly Bundy Mar 28 '23 at 23:24
0

(Result is based on their comments, i.e., not exactly as shown in the incorrect image. And using that they said it's always square.)

Solution 1: Odd insertion sort algorithm

a = [['AB','KR','EH'],['EE','DD','PS'],['GH','LM','XK']]

r = range(len(a))
for i in r:
  for j in r:
    for I in r:
      for J in r:
        if a[i][j] < a[I][J]:
          a[i][j], a[I][J] = a[I][J], a[i][j]

print(a)

Output (Attempt This Online!):

[['AB', 'DD', 'EE'], ['EH', 'GH', 'KR'], ['LM', 'PS', 'XK']]

Solution 2: Ordinary insertion sort

Really ordinary. Just one-dimensional insertion sort. But on an object that translates the indices and gets/sets the values in the two-dimensional original:

def insertionSort(A):
  for i, a in enumerate(A):
    while i and a < A[i-1]:
      A[i] = A[i-1]
      i -= 1
    A[i] = a

def sortArray(A):
  class B:
    def __getitem__(_, i):
      return A[i//n][i%n]
    def __setitem__(_, i, value):
      A[i//n][i%n] = value
  n = len(A)
  insertionSort(B())
  return A

arr = [['AB','KR','EH'],['EE','DD','PS'],['GH','LM','XK']]
print(sortArray(arr))

Try it online!

Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65