python challenge qn for loop
<p>EDIT: I SOLVED THE QUESTION BUT I WOULD APPRECIATE IF SOMEONE COULD JUST HELP ME MAKE MY CODE AS SHORT AS POSSIBLE (THE CHALLENGE WAS TO CODE IT WITH THE LEAST POSSIBLE CHARACTERS).</p>

<p>I was going through some python challenges online and I came across this question.</p>

<p><a href="https://i.stack.imgur.com/wGw4F.png" rel="nofollow">Click here to view the challenge question</a></p>

<p>I have been trying to solve it for quite a while but I am stuck in one place (heres my code):</p>

<pre><code>c = ['H','H','H','H','H','H','H','I','H','H','H','H','F','H','H','H','H','H','H','H','H','H','H','H','H',]
c_copy = list(c)

def prt():
    print("\n"+c[0]+"\t"+c[1]+"\t"+c[2]+"\t"+c[3]+"\t"+c[4]+"\n"+
          c[5]+"\t"+c[6]+"\t"+c[7]+"\t"+c[8]+"\t"+c[9]+"\n"+
          c[10]+"\t"+c[11]+"\t"+c[12]+"\t"+c[13]+"\t"+c[14]+"\n"+
          c[15]+"\t"+c[16]+"\t"+c[17]+"\t"+c[18]+"\t"+c[19]+"\n"+
          c[20]+"\t"+c[21]+"\t"+c[22]+"\t"+c[23]+"\t"+c[24])

generations = 3

while generations &gt; 0:
    for x, y in enumerate(c):

        if(y == 'F'):
            c_copy[x] = 'H'

        if(y == 'I'):
            c_copy[x] = 'F'

            try:
                if(c[x+1] == 'H'):
                    c_copy[x+1] = 'I'
                if(c[x-1] == 'H'):
                    c_copy[x-1] = 'I'
                if(c[x+5] == 'H'):
                    c_copy[x+5] = 'I'
                if(c[x-5] == 'H'):
                    c_copy[x-5] = 'I'
            except IndexError:
                pass

    c = list(c_copy)         
    generations = generations - 1

    prt()
</code></pre>

<p>I know where my problem is but I cant seem to get around it. In the for loop, when i[7] == I, I change the value to its east to 'I', but when the for loop goes to i[8], it will change the value to its east again. That keeps happening until the value is not 'I'. how do I get around that? And also if someone can do the challenge in a simpler and better way, please put up your code.
Thanks</p>

<p>A Numpy based solution (in the 2D numpy arrays <code>curr</code> and <code>next</code> in function <code>update</code>, 0, 1 and 2 correspond to "healthy", "infected" and "faded" respectively):</p>

<pre><code>import numpy as np
def update(curr, next):
    next[curr==1] = 2 # infected flowers become faded
    next[curr==2] = 0 # faded flowers become healthy 

    iw0 = np.argwhere(curr==0) # indices of elements of `curr` that are 0 (healthy)
    next[tuple(iw0.T)] = 0

    def fix_bad_indices(ia, shape):
        """ ia : an array of array-indices, some of which may be bad (exceed array dimensions)
            shape: an array's shape based on which any bad index in `ia` will be fixed 

            (Note that the data in `ia` may get modified in this function)
        """
        assert ia.ndim == 2 and len(shape) == ia.shape[1]
        for axis, size in enumerate(shape):
            for bad, new in [(-1, 0), (size, size-1)]:
                kk = ia[:, axis]
                kk[bad == kk] = new
        return ia

    senw = [(1, 0), (0, 1), (-1, 0), (0, -1)] # south, east, north, west

    # an array of neighbour indices of all healthy flowers
    nb_idxs = np.stack([fix_bad_indices(iw0 + shift, curr.shape) for shift in senw], axis=1)

    # elements of `curr` at neighbour-indices
    nb_elems = curr[tuple(nb_idxs.reshape(-1, 2).T)]
    nb_elems = nb_elems.reshape(*nb_idxs.shape[:-1])

    nb_elems[nb_elems==2] = 0
    next[tuple(iw0.T)] = np.any(nb_elems, axis=1)


def run(grid):
    curr = grid
    next = curr.copy()
    while 1:
        update(curr, next)
        yield next
        next, curr = curr, next


def main(grid, ngens):
    dct = {'H':0, 'I':1, 'F':2}
    rdct = dict(zip(dct.values(), dct.keys())) 

    def to_string(array):
        return '\n'.join(''.join(rdct[x] for x in row) for row in array)

    def to_array(string):
        return np.array([[dct[x] for x in row] for row in string.splitlines()])

    # grid = np.mod(np.arange(20).reshape(5, 4), 3)
    grid = to_array(grid)

    print(to_string(grid))
    print()
    for i, grid in zip(range(ngens), run(grid)): 
        print(to_string(grid))
        print()
    return to_string(grid)

if __name__ == '__main__':
    grid="""HHHHH 
            HHIHH 
            HHFHH 
            HHHHH 
            HHHHH""".replace(' ','')
    main(grid, 3)
</code></pre>

python for-loop