Advertisement
Woobinda

Search The Treasure

Oct 9th, 2019
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.15 KB | None | 0 0
  1. from typing import Tuple, List, Any
  2. from marshmallow import Schema, fields, validates, ValidationError
  3.  
  4. MATRIX_ROW_LENGTH = 5
  5. MATRIX_COL_LENGTH = 5
  6. MATRIX_LENGTH = MATRIX_COL_LENGTH * MATRIX_ROW_LENGTH
  7.  
  8. MATRIX_MIN_VALUE = 11
  9. MATRIX_MAX_VALUE = 55
  10.  
  11. MATRIX_START_CELL = (1, 1)
  12.  
  13.  
  14. ####################### Functionality implementation ##################
  15.  
  16. def validate_matrix_data(data: Tuple[int]) -> Tuple[int]:
  17.     """Validate given data before create matrix."""
  18.     if len(data) != MATRIX_LENGTH:
  19.         raise Exception(f"Length of matrix must be equal to {MATRIX_LENGTH}")
  20.  
  21.     for value in data:
  22.         if not isinstance(value, int):
  23.             raise Exception(
  24.                 f"Values in given data must be of type Integer, not {type(value).__name__}")
  25.  
  26.         if value not in range(MATRIX_MIN_VALUE, MATRIX_MAX_VALUE + 1):
  27.             raise Exception(
  28.                 f"Values in given data must be in range {MATRIX_MIN_VALUE} - {MATRIX_MAX_VALUE}")
  29.  
  30.     return data
  31.  
  32.  
  33. def create_matrix(validated_data: Tuple[int]) -> List[List[int]]:
  34.     """Create matrix from validated data."""
  35.     matrix = []
  36.     while validated_data:
  37.         matrix.append(validated_data[:MATRIX_ROW_LENGTH])
  38.         validated_data = validated_data[MATRIX_ROW_LENGTH:]
  39.  
  40.     return matrix
  41.  
  42.  
  43. def do_next_step(matrix: List[List[int]],
  44.                  row_index: int,
  45.                  col_index: int,
  46.                  steps_taken: Any = None
  47.                  ) -> List[int]:
  48.     """
  49.    Take the next step to find the treasure.
  50.    If the treasure was found - returns an array of steps taken.
  51.    """
  52.     found_value = matrix[row_index - 1][col_index - 1]
  53.  
  54.     if not steps_taken:
  55.         steps_taken = []
  56.     else:
  57.         if found_value == steps_taken[-1]:
  58.             return steps_taken
  59.  
  60.     steps_taken.append(found_value)
  61.     next_row_index, next_col_index = int(str(found_value)[0]), int(str(found_value)[1])
  62.  
  63.     return do_next_step(matrix, next_row_index, next_col_index, steps_taken)
  64.  
  65.  
  66. def search_treasure(*data: Tuple[int]) -> List[int]:
  67.     """Preparing matrix and processing steps for find a treasure."""
  68.     validated_data = validate_matrix_data(data)
  69.     matrix = create_matrix(validated_data)
  70.     steps_to_treasure = do_next_step(matrix, MATRIX_START_CELL[0], MATRIX_START_CELL[1])
  71.  
  72.     return steps_to_treasure
  73.  
  74.  
  75. #################### OOP Implementation ##################
  76.  
  77. class TreasureMap:
  78.  
  79.     def __init__(self,
  80.                  MATRIX_ROW_LENGTH: int, MATRIX_COL_LENGTH: int,
  81.                  MATRIX_MIN_VALUE: int, MATRIX_MAX_VALUE: int,
  82.                  MATRIX_LENGTH: int,
  83.                  ValidateSchema: Schema,
  84.                  data: List[int]
  85.                  ) -> None:
  86.  
  87.         self.MATRIX_ROW_LENGTH = MATRIX_ROW_LENGTH
  88.         self.MATRIX_COL_LENGTH = MATRIX_COL_LENGTH
  89.         self.MATRIX_MIN_VALUE = MATRIX_MIN_VALUE
  90.         self.MATRIX_MAX_VALUE = MATRIX_MAX_VALUE
  91.  
  92.         self.set_validator(ValidateSchema)
  93.         self.create_matrix(data)
  94.  
  95.     def set_validator(self, ValidateSchema: Schema) -> None:
  96.         if not issubclass(ValidateSchema, Schema):
  97.             raise ValidationError("ValidateSchema must be type of marshmallow.Schema")
  98.         self._validator = ValidateSchema
  99.  
  100.     def create_matrix(self, data: List[int]) -> None:
  101.         validated_data = self._validator().load({"data": data})
  102.         validated_data = validated_data["data"]
  103.  
  104.         matrix = []
  105.         while validated_data:
  106.             matrix.append(validated_data[:self.MATRIX_ROW_LENGTH])
  107.             validated_data = validated_data[self.MATRIX_ROW_LENGTH:]
  108.  
  109.         self._matrix = matrix
  110.  
  111.     def get_matrix_number(self, row_index: int, col_index: int) -> int:
  112.         return self._matrix[row_index - 1][col_index - 1]
  113.  
  114.  
  115. class MatrixValidateSchema(Schema):
  116.     data = fields.List(fields.Integer(), required=True)
  117.  
  118.     @validates("data")
  119.     def validate_data(self, data: List[int]) -> List[int]:
  120.         if len(data) != MATRIX_LENGTH:
  121.             raise ValidationError(f"Length of matrix must be equal to {MATRIX_LENGTH}")
  122.  
  123.         for value in data:
  124.             if value not in range(MATRIX_MIN_VALUE, MATRIX_MAX_VALUE + 1):
  125.                 raise Exception(
  126.                     f"Values in given data must be in range {MATRIX_MIN_VALUE} - {MATRIX_MAX_VALUE}")
  127.  
  128.         return data
  129.  
  130.  
  131. class TreasureSearcher:
  132.  
  133.     def __init__(self,
  134.                  matrix: TreasureMap,
  135.                  MATRIX_START_CELL: Tuple[int, int]
  136.                  ) -> None:
  137.  
  138.         self.matrix = matrix
  139.         self.row_index = MATRIX_START_CELL[0]
  140.         self.col_index = MATRIX_START_CELL[1]
  141.         self.steps_taken = []
  142.         self.search_is_completed = False
  143.  
  144.     def __call__(self) -> None:
  145.         self.search_treasure()
  146.  
  147.     def search_treasure(self) -> List[int]:
  148.         while not self.search_is_completed:
  149.             self.do_next_step()
  150.  
  151.         return self.steps_taken
  152.  
  153.     def do_next_step(self) -> None:
  154.         next_matrix_number = self.matrix.get_matrix_number(self.row_index, self.col_index)
  155.  
  156.         if self.steps_taken and next_matrix_number == self.steps_taken[-1]:
  157.             self.search_is_completed = True
  158.         else:
  159.             self.steps_taken.append(next_matrix_number)
  160.             self.row_index = int(str(next_matrix_number)[0])
  161.             self.col_index = int(str(next_matrix_number)[1])
  162.  
  163.  
  164.  
  165. if __name__ == '__main__':
  166.     # In Functionality
  167.  
  168.     print(search_treasure(
  169.         55, 14, 25, 52, 21,
  170.         44, 31, 11, 53, 43,
  171.         24, 13, 45, 12, 34,
  172.         42, 22, 43, 32, 41,
  173.         51, 23, 33, 54, 15)
  174.     )
  175.  
  176.     # In OOP
  177.     data = [55, 14, 25, 52, 21,
  178.             44, 31, 11, 53, 43,
  179.             24, 13, 45, 12, 34,
  180.             42, 22, 43, 32, 41,
  181.             51, 23, 33, 54, 15]
  182.  
  183.     matrix = TreasureMap(
  184.         MATRIX_ROW_LENGTH=MATRIX_ROW_LENGTH, MATRIX_COL_LENGTH=MATRIX_COL_LENGTH,
  185.         MATRIX_MIN_VALUE=MATRIX_MIN_VALUE, MATRIX_MAX_VALUE=MATRIX_MAX_VALUE,
  186.         MATRIX_LENGTH=MATRIX_LENGTH,
  187.         ValidateSchema=MatrixValidateSchema,
  188.         data=data
  189.     )
  190.  
  191.     treasure_searcher = TreasureSearcher(matrix, MATRIX_START_CELL)
  192.  
  193.     print(treasure_searcher.search_treasure())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement