"""simple docstring"""



import numpy as np
import torch
from torch.utils.data import Dataset, IterableDataset

from ..utils.generic import ModelOutput






class 				snake_case__     (   snake_case_   ):


 def __init__(				self  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase		):
        __a     				=  dataset
        __a     				=  process
        __a     				=  params


 def __len__(				self		):
        return len(self.dataset		)






 def __getitem__(				self  ,						lowerCamelCase		):
        __a     				=  self.dataset[i]
        __a     				=  self.process(lowerCamelCase  ,						**self.params		)
        return processed






class 				snake_case__     (   snake_case_   ):


 def __init__(				self  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase=None		):
        __a     				=  loader
        __a     				=  infer
        __a     				=  params
        if loader_batch_size == 1:
               # Let's spare some time by deactivating altogether
               __a     				=  None
        __a     				=  loader_batch_size

        # Internal bookkeeping
        __a     				=  None
        __a     				=  None


 def __len__(				self		):
        return len(self.loader		)


 def __iter__(				self		):
        __a     				=  iter(self.loader		)
        return self


 def 		a__ (				self		):
        if isinstance(self._loader_batch_data  ,						torch.Tensor		):
               # Batch data is simple tensor, just fetch the slice
               __a     				=  self._loader_batch_data[self._loader_batch_index]
        else:
               # Batch data is assumed to be BaseModelOutput (or dict)
               __a     				=  {}
               for k, element in self._loader_batch_data.items():
                      if isinstance(lowerCamelCase  ,						lowerCamelCase		):
                             # Convert ModelOutput to tuple first
                             __a     				=  element.to_tuple()
                             if isinstance(element[0]  ,						torch.Tensor		):
                                    __a     				=  tuple(el[self._loader_batch_index].unsqueeze(0		) for el in element		)
                             elif isinstance(element[0]  ,						np.ndarray		):
                                    __a     				=  tuple(np.expand_dims(el[self._loader_batch_index]  ,						0		) for el in element		)
                             continue
                      if k in {"hidden_states", "past_key_values", "attentions"} and isinstance(lowerCamelCase  ,						lowerCamelCase		):
                             # Those are stored as lists of tensors so need specific unbatching.
                             if isinstance(element[0]  ,						torch.Tensor		):
                                    __a     				=  tuple(el[self._loader_batch_index].unsqueeze(0		) for el in element		)
                             elif isinstance(element[0]  ,						np.ndarray		):
                                    __a     				=  tuple(np.expand_dims(el[self._loader_batch_index]  ,						0		) for el in element		)
                             continue
                      if element is None:
                             # This can happen for optional data that get passed around
                             __a     				=  None
                      elif isinstance(element[self._loader_batch_index]  ,						torch.Tensor		):
                             # Take correct batch data, but make it looked like batch_size=1
                             # For compatibility with other methods within transformers

                             __a     				=  element[self._loader_batch_index].unsqueeze(0		)
                      elif isinstance(element[self._loader_batch_index]  ,						np.ndarray		):
                             # Take correct batch data, but make it looked like batch_size=1
                             # For compatibility with other methods within transformers
                             __a     				=  np.expand_dims(element[self._loader_batch_index]  ,						0		)
                      else:
                             # This is typically a list, so no need to `unsqueeze`.
                             __a     				=  element[self._loader_batch_index]
            # Recreate the element by reusing the original class to make it look
            # batch_size=1
               __a     				=  self._loader_batch_data.__class__(lowerCamelCase		)
        self._loader_batch_index += 1
        return result






 def 		a__ (				self		):
        if self._loader_batch_index is not None and self._loader_batch_index < self.loader_batch_size:
               # We are currently unrolling a batch so we just need to return
               # the current item within a batch
               return self.loader_batch_item()

        # We're out of items within a batch
        __a     				=  next(self.iterator		)
        __a     				=  self.infer(lowerCamelCase  ,						**self.params		)
        # We now have a batch of "inferred things".
        if self.loader_batch_size is not None:
               # Try to infer the size of the batch
               if isinstance(lowerCamelCase  ,						torch.Tensor		):
                      __a     				=  processed
               else:
                      __a     				=  list(processed.keys()		)[0]
                      __a     				=  processed[key]
               if isinstance(lowerCamelCase  ,						lowerCamelCase		):
                      __a     				=  len(lowerCamelCase		)
               else:
                      __a     				=  first_tensor.shape[0]
               if 0 < observed_batch_size < self.loader_batch_size:
                      # could be last batch so we can't unroll as many
                      # elements.
                      __a     				=  observed_batch_size
               # Setting internal index to unwrap the batch
               __a     				=  processed
               __a     				=  0
               return self.loader_batch_item()
        else:
               # We're not unrolling batches
               return processed






class 				snake_case__     (   snake_case_   ):


 def __init__(				self  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase=None		):
        super().__init__(lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase		)


 def __iter__(				self		):
        __a     				=  iter(self.loader		)
        __a     				=  None
        return self






 def 		a__ (				self		):
        if self.subiterator is None:
               __a     				=  self.infer(next(self.iterator		)  ,						**self.params		)
        try:
               # Try to return next item
               __a     				=  next(self.subiterator		)
        except StopIteration:
               # When a preprocess iterator ends, we can start lookig at the next item
               # ChunkIterator will keep feeding until ALL elements of iterator
               # all have created their subiterator and have been iterating against.
               #
               # Another way to look at it, is we're basically flattening lists of lists
               # into a single list, but with generators
               __a     				=  self.infer(next(self.iterator		)  ,						**self.params		)
               __a     				=  next(self.subiterator		)
        return processed






class 				snake_case__     (   snake_case_   ):


 def __iter__(				self		):
        __a     				=  iter(self.loader		)
        return self






 def 		a__ (				self		):
        # Extremely similar to PipelineIterator in its unpacking mechanism
        # BUT, we have an extra required item which is the presence of `is_last`
        # That is because everything is flattened by `PipelineChunkIterator` we
        # need to keep track of how to regroup here in the original `process`
        # boundaries so that `process` and `postprocess` see the same data.

        # This iterator accumulates items (possibly while unbatching) until it
        # its a `is_last` and then just passes it on to the caller.
        __a     				=  False
        __a     				=  []
        if self._loader_batch_index is not None and self._loader_batch_index < self.loader_batch_size:
               while self._loader_batch_index < self.loader_batch_size:
                      __a     				=  self.loader_batch_item()
                      __a     				=  item.pop("is_last"		)
                      accumulator.append(lowerCamelCase		)
                      if is_last:
                             return accumulator

        while not is_last:
               __a     				=  self.infer(next(self.iterator		)  ,						**self.params		)
               if self.loader_batch_size is not None:
                      if isinstance(lowerCamelCase  ,						torch.Tensor		):
                             __a     				=  processed
                      else:
                             __a     				=  list(processed.keys()		)[0]
                             __a     				=  processed[key]
                      if isinstance(lowerCamelCase  ,						lowerCamelCase		):
                             __a     				=  len(lowerCamelCase		)
                      else:
                             __a     				=  first_tensor.shape[0]
                      if 0 < observed_batch_size < self.loader_batch_size:
                             # could be last batch so we can't unroll as many
                             # elements.
                             __a     				=  observed_batch_size
                      __a     				=  processed
                      __a     				=  0
                      while self._loader_batch_index < self.loader_batch_size:
                             __a     				=  self.loader_batch_item()
                             __a     				=  item.pop("is_last"		)
                             accumulator.append(lowerCamelCase		)
                             if is_last:
                                    return accumulator
               else:
                      __a     				=  processed
                      __a     				=  item.pop("is_last"		)
                      accumulator.append(lowerCamelCase		)
        return accumulator






class 				snake_case__     (   snake_case_   ):


 def __init__(				self  ,						lowerCamelCase  ,						lowerCamelCase		):
        __a     				=  dataset
        __a     				=  key


 def __len__(				self		):
        return len(self.dataset		)






 def __getitem__(				self  ,						lowerCamelCase		):
        return self.dataset[i][self.key]






class 				snake_case__     (   snake_case_   ):


 def __init__(				self  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase		):
        __a     				=  dataset
        __a     				=  keya
        __a     				=  keya


 def __len__(				self		):
        return len(self.dataset		)






 def __getitem__(				self  ,						lowerCamelCase		):
        return {"text": self.dataset[i][self.keya], "text_pair": self.dataset[i][self.keya]}

"""simple docstring"""



import os



def 					_lowerCamelCase(					):
       with open(os.path.dirname(a							) + "/grid.txt"							) as f:
              __a     				=  []  # noqa: E741
              for _ in range(2_0							):
                     l.append([int(a							) for x in f.readline().split()]							)

              __a     				=  0

              # right
              for i in range(2_0							):
                     for j in range(1_7							):
                            __a     				=  l[i][j] * l[i][j + 1] * l[i][j + 2] * l[i][j + 3]
                            if temp > maximum:
                                   __a     				=  temp

        # down
              for i in range(1_7							):
                     for j in range(2_0							):
                            __a     				=  l[i][j] * l[i + 1][j] * l[i + 2][j] * l[i + 3][j]
                            if temp > maximum:
                                   __a     				=  temp

        # diagonal 1
              for i in range(1_7							):
                     for j in range(1_7							):
                            __a     				=  l[i][j] * l[i + 1][j + 1] * l[i + 2][j + 2] * l[i + 3][j + 3]
                            if temp > maximum:
                                   __a     				=  temp

        # diagonal 2
              for i in range(1_7							):
                     for j in range(3 ,  2_0							):
                            __a     				=  l[i][j] * l[i + 1][j - 1] * l[i + 2][j - 2] * l[i + 3][j - 3]
                            if temp > maximum:
                                   __a     				=  temp
              return maximum


if __name__ == "__main__":
   print(solution())
