

from random import shuffle

import tensorflow as tf
from numpy import array




def 			UpperCAmelCase__				(			_A      : Optional[int]	,      _A      : Dict							):





  '''simple docstring'''







  a__  =int(_A							)
  assert noofclusters < len(_A							)

  # Find out the dimensionality
  a__  =len(vectors[0]							)

  # Will help select random centroids from among the available vectors
  a__  =list(range(len(_A							)							)							)
  shuffle(_A							)

  # GRAPH OF COMPUTATION
  # We initialize a new graph and set it as the default during each run
  # of this algorithm. This ensures that as this function is called
  # multiple times, the default graph doesn't keep getting crowded with
  # unused ops and Variables from previous function calls.

  a__  =tf.Graph()

  with graph.as_default():
    # SESSION OF COMPUTATION

    a__  =tf.Session()

    ##CONSTRUCTING THE ELEMENTS OF COMPUTATION

    ##First lets ensure we have a Variable vector for each centroid,
    ##initialized to one of the vectors from the available data points
    a__  =[
        tf.Variable(vectors[vector_indices[i]]							) for i in range(_A							)
    ]
    ##These nodes will assign the centroid Variables the appropriate
    ##values
    a__  =tf.placeholder('''float64'''	,      [dim]							)
    a__  =[]
    for centroid in centroids:
      cent_assigns.append(tf.assign(_A	,      _A							)							)

    ##Variables for cluster assignments of individual vectors(initialized
    ##to 0 at first)
    a__  =[tf.Variable(0							) for i in range(len(_A							)							)]
    ##These nodes will assign an assignment Variable the appropriate
    ##value
    a__  =tf.placeholder('''int32'''							)
    a__  =[]
    for assignment in assignments:
      cluster_assigns.append(tf.assign(_A	,      _A							)							)

    ##Now lets construct the node that will compute the mean
    # The placeholder for the input
    a__  =tf.placeholder('''float'''	,      [None, dim]							)
    # The Node/op takes the input and computes a mean along the 0th
    # dimension, i.e. the list of input vectors
    a__  =tf.reduce_mean(_A	,      0							)

    ##Node for computing Euclidean distances
    # Placeholders for input
    a__  =tf.placeholder('''float'''	,      [dim]							)
    a__  =tf.placeholder('''float'''	,      [dim]							)
    a__  =tf.sqrt(tf.reduce_sum(tf.pow(tf.sub(_A	,      _A							)	,      2							)							)							)

    ##This node will figure out which cluster to assign a vector to,
    ##based on Euclidean distances of the vector from the centroids.
    # Placeholder for input
    a__  =tf.placeholder('''float'''	,      [noofclusters]							)
    a__  =tf.argmin(_A	,      0							)

    ##INITIALIZING STATE VARIABLES

    ##This will help initialization of all Variables defined with respect
    ##to the graph. The Variable-initializer should be defined after
    ##all the Variables have been constructed, so that each of them
    ##will be included in the initialization.
    a__  =tf.initialize_all_variables()

    # Initialize all variables
    sess.run(_A							)

    ##CLUSTERING ITERATIONS

    # Now perform the Expectation-Maximization steps of K-Means clustering
    # iterations. To keep things simple, we will only do a set number of
    # iterations, instead of using a Stopping Criterion.
    a__  =1_00
    for _ in range(_A							):
      ##EXPECTATION STEP
      ##Based on the centroid locations till last iteration, compute
      ##the _expected_ centroid assignments.
      # Iterate over each vector
      for vector_n in range(len(_A							)							):
        a__  =vectors[vector_n]
        # Compute Euclidean distance between this vector and each
        # centroid. Remember that this list cannot be named
        #'centroid_distances', since that is the input to the
        # cluster assignment node.
        a__  =[
            sess.run(_A	,      feed_dict={va: vect, va: sess.run(_A							)}							)
            for centroid in centroids
        ]
        # Now use the cluster assignment node, with the distances
        # as the input
        a__  =sess.run(
            _A	,      feed_dict={centroid_distances: distances}							)
        # Now assign the value to the appropriate state variable
        sess.run(
            cluster_assigns[vector_n]	,      feed_dict={assignment_value: assignment}							)

      ##MAXIMIZATION STEP
      # Based on the expected state computed from the Expectation Step,
      # compute the locations of the centroids so as to maximize the
      # overall objective of minimizing within-cluster Sum-of-Squares
      for cluster_n in range(_A							):
        # Collect all the vectors assigned to this cluster
        a__  =[
            vectors[i]
            for i in range(len(_A							)							)
            if sess.run(assignments[i]							) == cluster_n
        ]
        # Compute new centroid location
        a__  =sess.run(
            _A	,      feed_dict={mean_input: array(_A							)}							)
        # Assign value to appropriate variable
        sess.run(
            cent_assigns[cluster_n]	,      feed_dict={centroid_value: new_location}							)

        # Return centroids and assignments
    a__  =sess.run(_A							)
    a__  =sess.run(_A							)
    return centroids, assignments



import os




def 			UpperCAmelCase__				(			_A      : Any							):





  '''simple docstring'''







  a__  =len(grid[0]							)
  a__  =len(_A							)

  a__  =0
  a__  =0
  a__  =0

  # Check vertically, horizontally, diagonally at the same time (only works
  # for nxn grid)
  for i in range(_A							):
    for j in range(n_rows - 3							):
      a__  =grid[j][i] * grid[j + 1][i] * grid[j + 2][i] * grid[j + 3][i]
      a__  =grid[i][j] * grid[i][j + 1] * grid[i][j + 2] * grid[i][j + 3]

      # Left-to-right diagonal (\) product
      if i < n_columns - 3:
        a__  =(
            grid[i][j]
            * grid[i + 1][j + 1]
            * grid[i + 2][j + 2]
            * grid[i + 3][j + 3]
        )

      # Right-to-left diagonal(/) product
      if i > 2:
        a__  =(
            grid[i][j]
            * grid[i - 1][j + 1]
            * grid[i - 2][j + 2]
            * grid[i - 3][j + 3]
        )

      a__  =max(
          _A	,      _A	,      _A	,      _A							)
      if max_product > largest:
        a__  =max_product

  return largest




def 			UpperCAmelCase__				(			):





  '''simple docstring'''







  a__  =[]
  with open(os.path.dirname(_A							) + '''/grid.txt'''							) as file:
    for line in file:
      grid.append(line.strip('''\n'''							).split(''' '''							)							)

  a__  =[[int(_A							) for i in grid[j]] for j in range(len(_A							)							)]

  return largest_product(_A							)


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