Search code examples
pythonfunctioncode-duplication

Python: Possible to exchange math operators so as to avoid code duplication?


I have this function (see below) that looks like it repeats itself four times. The four code snippets are very similar, they are just differing on some of the math operators. Is it possible to make this code shorter? I cannot find a way, but I would like to be able to just call a function (whitin the function) that exchanges the "-", "+" and "<"/">" signs in the code snippets so that I do not have to repeat them?

CODE

def diag_grannar(storlek,troll_position): #funktion som kollar efter diagonala grannar
    ny_rad = troll_position[0]
    ny_kol = troll_position[1]
    diag_grannar = []

    # while-loopen letar efter diagonala grannar snett vänster ovanifrån troll_position
    while True:
        ny_rad -= 1
        ny_kol -= 1
        if ny_rad >= 1 and ny_kol >= 1:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    # while-loopen letar efter diagonala grannar snett vänster nedanifrån troll_position
    while True:
        ny_rad += 1
        ny_kol -= 1
        if ny_rad <= storlek and ny_kol >= 1:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    # while-loopen letar efter diagonala grannar snett höger nedanifrån troll_position
    while True:
        ny_rad += 1
        ny_kol += 1
        if ny_rad <= storlek and ny_kol <= storlek:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    # while-loopen letar efter diagonala grannar snett höger ovanifrån troll_position
    while True:
        ny_rad -= 1
        ny_kol += 1
        if ny_rad >= 1 and ny_kol <= storlek:
            diag_grannar.append([ny_rad,ny_kol])
        else:
            ny_rad = troll_position[0]
            ny_kol = troll_position[1]
            break

    return diag_grannar

Just to be clear, the code snippets I am refering to are these:

while True:
    ny_rad -= 1
    ny_kol += 1
    if ny_rad >= 1 and ny_kol <= storlek:
        diag_grannar.append([ny_rad,ny_kol])
    else:
        ny_rad = troll_position[0]
        ny_kol = troll_position[1]
        break

Best regards;


Solution

  • we can loop over various parameterizations of the same thing... the thing to notice is that instead of exchanging math operators we can always use addition and just add either 1 or -1 (easier than exchanging match operators)

    def diag_grannar1(storlek,troll_position): #funktion som kollar efter diagonala grannar
        ny_rad = troll_position[0]
        ny_kol = troll_position[1]
        diag_grannar = []
        def diag_compare(v1, leq):
            if leq:
                return v1 <= storlek
            else:
                return v1 >= 1
        params = [((-1, -1, False, False)),
                  ((1, -1, True, False)),
                  ((1, 1, True, True)), 
                  ((-1, 1, False, True))]
    
        for v1, v2, leq1, leq2 in params:
            while True:
                ny_rad += v1
                ny_kol += v2
                if diag_compare(ny_rad, leq1) and diag_compare(ny_kol, leq2):
                    diag_grannar.append([ny_rad,ny_kol])
                else:
                    ny_rad = troll_position[0]
                    ny_kol = troll_position[1]
                    break
    
        return diag_grannar