Saturday, July 25, 2015

Python : Breadth-First Search (4) floodfile in a map


Abstract: make colors with a given point in a map

There is a map with some islands circulating by sea. calculate the area of all islands in this map.

The result:
The area is 19
The area is 7
The area is 81
The area is 42
Total number of lands= 4
ok


The script:
# -*- coding: utf-8 -*-
"""
Created on Fri Jul 24 09:44:46 2015

@author: yuan
"""

import numpy as np
# search areas of islands in a map

#record a queue using circling list
class queue:
   
    def __init__(self,arr, q_len=1):
        self.size=len(arr)
        if q_len==1 or q_len<self.size:       
            self.q=[None]*self.size
            self.q_len=self.size
        else:
            self.q=[None]*q_len
            self.q_len=q_len
        self.q[0]=0
        self.q[1:self.size]=arr
        self.head=1       #skip the index 0
        self.tail=len(arr)+1 #the index of next element of arr
        #print 'Initiate queue:', self.q
       
    def q_size(self):
        #print 'Size of the queue:', self.size
        return self.size
       
    def isFull(self):
        return self.tail==(self.q_len+1)
       
    def export_arr(self):
        if self.tail>self.head:
            arr=self.q[self.head:self.tail]
        elif self.tail==self.head:
            arr=[]
        else:
            arr=self.q[self.head:(self.q_len+1)] + self.q[1:self.tail]
        return arr
   
    def enqueue(self, value):
        if self.size<self.q_len:
            #increase size
            self.size +=1
            #increase tail
            if self.tail==(self.q_len+1):
                self.tail=1
            #add value
            self.q[self.tail]=value
            self.tail += 1
        else:
            print "queue is full, fail to adding", value
        #print '##', self.q, self.head,self.tail
        #return self.export_arr()
       
    def dequeue(self):
        #increase head
        value='NA'
        #print self.head, self.tail
        if self.size>0:
            value=self.q[self.head]
            if self.head==self.q_len:
                self.head=1
            else:
                self.head +=1
                #decrease size
            self.size -= 1
            #print 'remove', value, self.export_arr()
        return value

##################
class breadth_first_search(queue):
   
    def __init__(self, pool):
        self.pool=pool
        self.nrow=len(pool)
        self.ncol=len(pool[1])
        self.book=list(pool)
        self.next=[[1,0],[-1,0], [0,1],[0,-1]]
        self.area={}
        #print self.pool
    def possible_points(self):
        points=[]
        for row_index,row in enumerate(self.book):
            for col_index,element in enumerate(row):
                #print row_index, col_index, element
                if element>0:
                    points.append((row_index,col_index))
        return points
    def export_land(self):
        if not self.area=={}:
            for point in self.area.keys():
                points_num=len(self.area[point])
                print 'The area is', points_num
            print 'Total number of lands=', len(self.area)
   
    def largest_area(self):
        #get all land points
        points=self.possible_points()
        #print self.pool[25][16]

        #
        for candidate_point in points:
            q=queue([candidate_point], self.nrow*self.ncol)
            land_points=[candidate_point]
            while q.q_size()>0:
                start_point=q.dequeue()
                for i in range(4):
                    next_move=self.next[i]
                    x=start_point[0]+next_move[0]
                    y=start_point[1]+next_move[1]
                    #out of bound or sea point

                    if 0<x<self.nrow and 0<y<self.ncol:
                        #print candidate_point, x, y, self.nrow, self.ncol
                        if self.pool[x][y]==1 and self.book[x][y]==1:
                            new_point=(x, y)
                            land_points.append(new_point)
                            self.book[x][y]=3
                            q.enqueue(new_point)
                            points.remove(new_point)
            self.area[candidate_point]=land_points
        #
        self.export_land()
       
#main
if __name__ == "__main__":
    #0 is sea point, 1 is land point, 3 is visited land point
    pool=[
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
        [1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0],
        [0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
        [0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
        [0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0],
        [0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0],   
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0],
        [0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],   
        [0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
        [0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0] ]
   
    #coordinate of the end point
    s=breadth_first_search(pool)
    s.largest_area()
    print 'ok'

No comments:

Post a Comment