example = """../.# => ##./#../...
.#./..#/### => #..#/..../..../#..#"""
data = open("input.txt").read()

def match(square, rule):
    return square == rule

def func(data, iter):
    start = """.#.
..#
###"""
    rules = {}
    for line in data.splitlines():
        parts = line.split(" => ")

        a = parts[0]
        for rot in range(4):
            a = "/".join(["".join(i) for i in zip(*reversed(a.split("/")))])
            b = "/".join(p[::-1] for p in a.split("/"))

            if a not in rules:
                rules[a] = parts[1]
            if b not in rules:
                rules[b] = parts[1]

    image = start.splitlines()
    for round in range(iter):
        no_lines = len(image)
        new_image = []
        if no_lines % 2 == 0:
            for i in range(0, no_lines, 2):
                new_line1 = []
                new_line2 = []
                new_line3 = []
                line1 = image[i]
                line2 = image[i+1]
                for j in range(0, no_lines, 2):
                    square = line1[j:j+2] + "/" + line2[j:j+2]
                    res = rules[square]
                    p = res.split("/")
                    new_line1.append(p[0])
                    new_line2.append(p[1])
                    new_line3.append(p[2])
                new_image.append("".join(new_line1))
                new_image.append("".join(new_line2))
                new_image.append("".join(new_line3))
            image = new_image

        elif no_lines % 3 == 0:
            for i in range(0, no_lines, 3):
                new_line1 = []
                new_line2 = []
                new_line3 = []
                new_line4 = []
                line1 = image[i]
                line2 = image[i+1]
                line3 = image[i+2]
                for j in range(0, no_lines, 3):
                    square = line1[j:j+3] + "/" + line2[j:j+3] + "/" + line3[j:j+3]
                    res = rules[square]
                    p = res.split("/")
                    new_line1.append(p[0])
                    new_line2.append(p[1])
                    new_line3.append(p[2])
                    new_line4.append(p[3])
                new_image.append("".join(new_line1))
                new_image.append("".join(new_line2))
                new_image.append("".join(new_line3))
                new_image.append("".join(new_line4))
            image = new_image

    return "\n".join(image).count("#")

print("Test", func(example,2))
print("Part 1",func(data,5))
print("Part 2",func(data,18))

@@ -165,27 +165,33 @@
 c(data, iter
+ations
 ):%0A
-
     start = 
@@ -671,16 +671,22 @@
 nge(iter
+ations
 ):%0A     
@@ -745,71 +745,25 @@
     
-if no_lines %25 2 == 0:%0A            for i in range(0, no_lines, 2
+for size in (2, 3
 ):%0A 
@@ -777,156 +777,32 @@
     
-  
-  new_line1 = %5B%5D%0A                new_line2 = %5B%5D%0A                new_line3 = %5B%5D%0A                line1 = image%5Bi%5D%0A                line2 = image%5Bi+1%5D
+if no_lines %25 size == 0:
 %0A   
@@ -810,33 +810,33 @@
             for 
-j
+i
  in range(0, no_
@@ -842,17 +842,20 @@
 _lines, 
-2
+size
 ):%0A     
@@ -873,481 +873,125 @@
     
-square = line1%5Bj:j+2%5D + %22/%22 + line2%5Bj:j+2%5D%0A                    res = rules%5Bsquare%5D%0A                    p = res.split(%22/%22)%0A                    new_line1.append(p%5B0%5D)%0A                    new_line2.append(p%5B1%5D)%0A                    new_line3.append(p%5B2%5D)%0A                new_image.append(%22%22.join(new_line1))%0A                new_image.append(%22%22.join(new_line2))%0A                new_image.append(%22%22.join(new_line3))%0A            image = new_image%0A%0A        elif no_lines %25 3 == 0:%0A
+new_lines = %5B%5B%5D for k in range(size+1)%5D%0A                    old_lines = %5Bimage%5Bk%5D for k in range(i, i+size)%5D%0A        
     
@@ -994,33 +994,33 @@
             for 
-i
+j
  in range(0, no_
@@ -1018,33 +1018,36 @@
 ge(0, no_lines, 
-3
+size
 ):%0A             
@@ -1053,219 +1053,134 @@
     
-new_line1 = %5B%5D%0A                new_line2 = %5B%5D%0A                new_line3 = %5B%5D%0A                new_line4 = %5B%5D%0A                line1 = image%5Bi%5D%0A                line2 = image%5Bi+1%5D%0A                line3 = image%5Bi+2%5D%0A
+        square = %22/%22.join(old_line%5Bj:j+size%5D for old_line in old_lines)%0A                        res = rules%5Bsquare%5D%0A          
     
@@ -1193,189 +1193,44 @@
     
-  
 for 
-j in range(0, no
+new
 _line
-s
 , 
-3):%0A                    square = line1%5Bj:j+3%5D + %22/%22 + line2%5Bj:j+3%5D + %22/%22 + line3%5Bj:j+3%5D%0A                    res = rules%5Bsquare%5D%0A                    p =
+part in zip(new_lines,
  res
@@ -1240,16 +1240,18 @@
 lit(%22/%22)
+):
 %0A       
@@ -1255,43 +1255,8 @@
     
-            new_line1.append(p%5B0%5D)%0A
     
@@ -1279,17 +1279,16 @@
 new_line
-2
 .append(
@@ -1288,19 +1288,19 @@
 append(p
-%5B1%5D
+art
 )%0A      
@@ -1313,24 +1313,28 @@
         
+for 
 new_line
 3.append
@@ -1329,119 +1329,33 @@
 line
-3.append(p%5B2%5D)%0A                    new_line4.append(p%5B3%5D)%0A                new_image.append(%22%22.join(new_line1))%0A
+ in new_lines:%0A          
     
@@ -1356,34 +1356,32 @@
                 
-  
 new_image.append
@@ -1397,17 +1397,16 @@
 new_line
-2
 ))%0A     
@@ -1420,127 +1420,47 @@
     
-new_
 image
-.append(%22%22.join(new_line3))%0A                new_image.append(%22%22.join(new_line4))%0A            image = new_image
+ = new_image%0A                break
 %0A%0A  

Simplify code for day 21 of 2017