Home > front end >  How can I make my code simpler and still get the same output?
How can I make my code simpler and still get the same output?

Time:11-07

So I had to write a code to find all the diagonal strings in a grid mystery

mystery = [["r","a","w","b","i","t"],
           ["x","a","y","z","c","h"],
           ["p","q","b","e","i","e"],
           ["t","r","s","b","o","g"],
           ["u","w","x","v","i","t"],
           ["n","m","r","w","o","t"]]

And here is what I have so far, with the help of a few experts because I'm new to this. The expert who helped me is https://stackoverflow.com/users/5237560/alain-t

def diagsDownRight(M):
    diags,pad = [],[]
    while any(M):
        edge = [*next(zip(*reversed(M))),*M[0][1:]]
        M    = [r[1:] for r in M[1:]]
        diags.append(pad edge pad)
        pad.append("")
    return [*map("".join,zip(*diags))]

While this does work, I myself find it hard to grasp and I do not want to just write down a code that I do not understand. So, can anyone please help make the code as basic as possible?

When I mean basic as possible, I mean like picture yourself as a person who has just learnt coding for a couple of months, and please try to simplify my code as much as possible.

CodePudding user response:

The easiest I could think of: pad rows so that diagonals become columns. The code:

def diagsDownRight(M): 
    n = len(M)
    m = [[''] * (n-i-1)   row   [''] * i for i, row in enumerate(M)]  # pad rows 
    return [''.join(col) for col in zip(*m)] 

The result is the same, and IMO the approach is more intuitive

CodePudding user response:

consider a square matrix

[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

the indexes into the diagonals are as follows

d1 = [[0,0],[1,1],[2,2]]
d2 = [[0,1],[1,2]]
d3 = [[1,0],[2,1]]
d4 = [[2,0]]
d5 = [[0,2]]

to get the middle diagonal you can simply start with the indexes

for i in range(3):
    index = [i,i]

for the next diagonal we simply do the same... but offset x by 1, until we go out of bounds

for i in range(3):
   if i   1 > 2:
      break
   index = [i, i 1]

for the next diagonal its the same ... except we do it on the other axis

for i in range(3):
   if i   1 > 2:
      break
   index = [i   1, i]

for the toprightmost (in this case ...) its the same but we add 2

 for i in range(3):
   if i   2 > 2:
      break
   index = [i, i 2]

same for the bottom most but using the other index

 for i in range(3):
   if i   2 > 2:
      break
   index = [i   2, i]

I will leave it to you to extrapolate this into a working solution

CodePudding user response:

here's a simpler version:

def diagsDownRight(M):
    rows = len(M)      # number of rows
    cols = len(M[0])   # number of columns
    result   = []      # result will be a list of strings
    leftSide = [(r,0) for r in range(rows)]   # first column
    topSide  = [(0,c) for c in range(1,cols)] # first row
    for r,c in leftSide[::-1]   topSide:      # all start positions
        s = "" # string on the diagonal
        while r < rows and c < cols:
            s  = M[r][c]  # accumulate characters
            r  = 1        # move down
            c  = 1        # and to the right
        result.append(s)  # add diagonal string to result
    return result

print(diagsDownRight(mystery))
['n', 'um', 'twr', 'prxw', 'xqsvo', 
 'rabbit', 'ayeot', 'wzig', 'bce', 'ih', 't']

The way it works is by starting at the coordinate of the left and top positions, accumulate characters going one place to the right and down until going out of the matrix.

I would suggest you go with Marat's solution though. It is simple and elegant. If you print the m matrix I'm sure, you'll understand what's going on

  • Related