"""
igraph library.
"""

__license__ = """
Copyright (C) 2006- The igraph development team

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
"""

from igraph._igraph import (
    ADJ_DIRECTED,
    ADJ_LOWER,
    ADJ_MAX,
    ADJ_MIN,
    ADJ_PLUS,
    ADJ_UNDIRECTED,
    ADJ_UPPER,
    ALL,
    ARPACKOptions,
    BFSIter,
    BLISS_F,
    BLISS_FL,
    BLISS_FLM,
    BLISS_FM,
    BLISS_FS,
    BLISS_FSM,
    DFSIter,
    Edge,
    GET_ADJACENCY_BOTH,
    GET_ADJACENCY_LOWER,
    GET_ADJACENCY_UPPER,
    GraphBase,
    IN,
    InternalError,
    OUT,
    REWIRING_SIMPLE,
    REWIRING_SIMPLE_LOOPS,
    STAR_IN,
    STAR_MUTUAL,
    STAR_OUT,
    STAR_UNDIRECTED,
    STRONG,
    TRANSITIVITY_NAN,
    TRANSITIVITY_ZERO,
    TREE_IN,
    TREE_OUT,
    TREE_UNDIRECTED,
    Vertex,
    WEAK,
    arpack_options as default_arpack_options,
    community_to_membership,
    convex_hull,
    is_bigraphical,
    is_degree_sequence,
    is_graphical,
    is_graphical_degree_sequence,
    set_progress_handler,
    set_random_number_generator,
    set_status_handler,
    umap_compute_weights,
    __igraph_version__,
)
from igraph.adjacency import (
    _get_adjacency,
    _get_adjacency_sparse,
    _get_adjlist,
    _get_biadjacency,
    _get_inclist,
)
from igraph.automorphisms import (
    _count_automorphisms_vf2,
    _get_automorphisms_vf2,
)
from igraph.basic import (
    _add_edge,
    _add_edges,
    _add_vertex,
    _add_vertices,
    _delete_edges,
    _clear,
    _as_directed,
    _as_undirected,
)
from igraph.bipartite import (
    _maximum_bipartite_matching,
    _bipartite_projection,
    _bipartite_projection_size,
)
from igraph.community import (
    _community_fastgreedy,
    _community_infomap,
    _community_leading_eigenvector,
    _community_label_propagation,
    _community_multilevel,
    _community_optimal_modularity,
    _community_edge_betweenness,
    _community_spinglass,
    _community_walktrap,
    _k_core,
    _community_leiden,
    _modularity,
)
from igraph.clustering import (
    Clustering,
    VertexClustering,
    Dendrogram,
    VertexDendrogram,
    Cover,
    VertexCover,
    CohesiveBlocks,
    compare_communities,
    split_join_distance,
    _biconnected_components,
    _cohesive_blocks,
    _connected_components,
    _clusters,
)
from igraph.cut import (
    Cut,
    Flow,
    _all_st_cuts,
    _all_st_mincuts,
    _gomory_hu_tree,
    _maxflow,
    _mincut,
    _st_mincut,
)
from igraph.configuration import Configuration, init as init_configuration
from igraph.drawing import (
    BoundingBox,
    CairoGraphDrawer,
    DefaultGraphDrawer,
    MatplotlibGraphDrawer,
    Plot,
    Point,
    Rectangle,
    plot,
)
from igraph.drawing.colors import (
    Palette,
    GradientPalette,
    AdvancedGradientPalette,
    RainbowPalette,
    PrecalculatedPalette,
    ClusterColoringPalette,
    color_name_to_rgb,
    color_name_to_rgba,
    hsv_to_rgb,
    hsva_to_rgba,
    hsl_to_rgb,
    hsla_to_rgba,
    rgb_to_hsv,
    rgba_to_hsva,
    rgb_to_hsl,
    rgba_to_hsla,
    palettes,
    known_colors,
)
from igraph.drawing.graph import __plot__ as _graph_plot
from igraph.drawing.utils import autocurve
from igraph.datatypes import Matrix, DyadCensus, TriadCensus, UniqueIdGenerator
from igraph.formula import construct_graph_from_formula
from igraph.io import _format_mapping
from igraph.io.files import (
    _construct_graph_from_graphmlz_file,
    _construct_graph_from_dimacs_file,
    _construct_graph_from_pickle_file,
    _construct_graph_from_picklez_file,
    _construct_graph_from_adjacency_file,
    _construct_graph_from_file,
    _write_graph_to_adjacency_file,
    _write_graph_to_dimacs_file,
    _write_graph_to_graphmlz_file,
    _write_graph_to_pickle_file,
    _write_graph_to_picklez_file,
    _write_graph_to_file,
)
from igraph.io.objects import (
    _construct_graph_from_dict_list,
    _export_graph_to_dict_list,
    _construct_graph_from_tuple_list,
    _export_graph_to_tuple_list,
    _construct_graph_from_list_dict,
    _export_graph_to_list_dict,
    _construct_graph_from_dict_dict,
    _export_graph_to_dict_dict,
    _construct_graph_from_dataframe,
    _export_vertex_dataframe,
    _export_edge_dataframe,
)
from igraph.io.adjacency import (
    _construct_graph_from_adjacency,
    _construct_graph_from_weighted_adjacency,
)
from igraph.io.libraries import (
    _construct_graph_from_networkx,
    _export_graph_to_networkx,
    _construct_graph_from_graph_tool,
    _export_graph_to_graph_tool,
)
from igraph.io.random import (
    _construct_random_geometric_graph,
)
from igraph.io.bipartite import (
    _construct_bipartite_graph,
    _construct_bipartite_graph_from_adjacency,
    _construct_full_bipartite_graph,
    _construct_random_bipartite_graph,
)
from igraph.io.images import _write_graph_to_svg
from igraph.layout import (
    Layout,
    _layout,
    _layout_auto,
    _layout_sugiyama,
    _layout_method_wrapper,
    _3d_version_for,
    _layout_mapping,
)
from igraph.matching import Matching
from igraph.operators import (
    disjoint_union,
    union,
    intersection,
    operator_method_registry as _operator_method_registry,
)
from igraph.seq import EdgeSeq, VertexSeq, _add_proxy_methods
from igraph.statistics import (
    FittedPowerLaw,
    Histogram,
    RunningMean,
    mean,
    median,
    percentile,
    quantile,
    power_law_fit,
)
from igraph.structural import (
    _indegree,
    _outdegree,
    _degree_distribution,
    _pagerank,
    _shortest_paths,
)
from igraph.summary import GraphSummary, summary
from igraph.utils import (
    deprecated,
    numpy_to_contiguous_memoryview,
    rescale,
)
from igraph.version import __version__, __version_info__

import os
import sys

class Graph(GraphBase):
    """Generic graph.

    This class is built on top of L{GraphBase}, so the order of the
    methods in the generated API documentation is a little bit obscure:
    inherited methods come after the ones implemented directly in the
    subclass. L{Graph} provides many functions that L{GraphBase} does not,
    mostly because these functions are not speed critical and they were
    easier to implement in Python than in pure C. An example is the
    attribute handling in the constructor: the constructor of L{Graph}
    accepts three dictionaries corresponding to the graph, vertex and edge
    attributes while the constructor of L{GraphBase} does not. This extension
    was needed to make L{Graph} serializable through the C{pickle} module.
    L{Graph} also overrides some functions from L{GraphBase} to provide a
    more convenient interface; e.g., layout functions return a L{Layout}
    instance from L{Graph} instead of a list of coordinate pairs.

    Graphs can also be indexed by strings or pairs of vertex indices or vertex
    names.  When a graph is indexed by a string, the operation translates to
    the retrieval, creation, modification or deletion of a graph attribute:

      >>> g = Graph.Full(3)
      >>> g["name"] = "Triangle graph"
      >>> g["name"]
      'Triangle graph'
      >>> del g["name"]

    When a graph is indexed by a pair of vertex indices or names, the graph
    itself is treated as an adjacency matrix and the corresponding cell of
    the matrix is returned:

      >>> g = Graph.Full(3)
      >>> g.vs["name"] = ["A", "B", "C"]
      >>> g[1, 2]
      1
      >>> g["A", "B"]
      1
      >>> g["A", "B"] = 0
      >>> g.ecount()
      2

    Assigning values different from zero or one to the adjacency matrix will
    be translated to one, unless the graph is weighted, in which case the
    numbers will be treated as weights:

      >>> g.is_weighted()
      False
      >>> g["A", "B"] = 2
      >>> g["A", "B"]
      1
      >>> g.es["weight"] = 1.0
      >>> g.is_weighted()
      True
      >>> g["A", "B"] = 2
      >>> g["A", "B"]
      2
      >>> g.es["weight"]
      [1.0, 1.0, 2]
    """

    # Some useful aliases
    omega = GraphBase.clique_number
    alpha = GraphBase.independence_number
    shell_index = GraphBase.coreness
    cut_vertices = GraphBase.articulation_points
    blocks = GraphBase.biconnected_components
    evcent = GraphBase.eigenvector_centrality
    vertex_disjoint_paths = GraphBase.vertex_connectivity
    edge_disjoint_paths = GraphBase.edge_connectivity
    cohesion = GraphBase.vertex_connectivity
    adhesion = GraphBase.edge_connectivity

    # Compatibility aliases
    shortest_paths = _shortest_paths
    shortest_paths_dijkstra = shortest_paths
    subgraph = GraphBase.induced_subgraph

    def __init__(self, *args, **kwds):
        """__init__(n=0, edges=None, directed=False, graph_attrs=None,
        vertex_attrs=None, edge_attrs=None)

        Constructs a graph from scratch.

        @keyword n: the number of vertices. Can be omitted, the default is
          zero. Note that if the edge list contains vertices with indexes
          larger than or equal to M{n}, then the number of vertices will
          be adjusted accordingly.
        @keyword edges: the edge list where every list item is a pair of
          integers. If any of the integers is larger than M{n-1}, the number
          of vertices is adjusted accordingly. C{None} means no edges.
        @keyword directed: whether the graph should be directed
        @keyword graph_attrs: the attributes of the graph as a dictionary.
        @keyword vertex_attrs: the attributes of the vertices as a dictionary.
          The keys of the dictionary must be the names of the attributes; the
          values must be iterables with exactly M{n} items where M{n} is the
          number of vertices.
        @keyword edge_attrs: the attributes of the edges as a dictionary. The
          keys of the dictionary must be the names of the attributes; the values
          must be iterables with exactly M{m} items where M{m} is the number of
          edges.
        """
        # Pop the special __ptr keyword argument
        ptr = kwds.pop("__ptr", None)

        # Set up default values for the parameters. This should match the order
        # in *args
        kwd_order = (
            "n",
            "edges",
            "directed",
            "graph_attrs",
            "vertex_attrs",
            "edge_attrs",
        )
        params = [0, [], False, {}, {}, {}]

        # Is there any keyword argument in kwds that we don't know? If so,
        # freak out.
        unknown_kwds = set(kwds.keys())
        unknown_kwds.difference_update(kwd_order)
        if unknown_kwds:
            raise TypeError(
                "{0}.__init__ got an unexpected keyword argument {1!r}".format(
                    self.__class__.__name__, unknown_kwds.pop()
                )
            )

        # If the first argument is a list or any other iterable, assume that
        # the number of vertices were omitted
        args = list(args)
        if len(args) > 0 and hasattr(args[0], "__iter__"):
            args.insert(0, params[0])

        # Override default parameters from args
        params[: len(args)] = args

        # Override default parameters from keywords
        for idx, k in enumerate(kwd_order):
            if k in kwds:
                params[idx] = kwds[k]

        # Now, translate the params list to argument names
        nverts, edges, directed, graph_attrs, vertex_attrs, edge_attrs = params

        # When the number of vertices is None, assume that the user meant zero
        if nverts is None:
            nverts = 0

        # When 'edges' is None, assume that the user meant an empty list
        if edges is None:
            edges = []

        # When 'edges' is a NumPy array or matrix, convert it into a memoryview
        # as the lower-level C API works with memoryviews only
        try:
            from numpy import ndarray, matrix

            if isinstance(edges, (ndarray, matrix)):
                edges = numpy_to_contiguous_memoryview(edges)
        except ImportError:
            pass

        # Initialize the graph
        if ptr:
            super().__init__(__ptr=ptr)
        else:
            super().__init__(nverts, edges, directed)

        # Set the graph attributes
        for key, value in graph_attrs.items():
            if isinstance(key, int):
                key = str(key)
            self[key] = value
        # Set the vertex attributes
        for key, value in vertex_attrs.items():
            if isinstance(key, int):
                key = str(key)
            self.vs[key] = value
        # Set the edge attributes
        for key, value in edge_attrs.items():
            if isinstance(key, int):
                key = str(key)
            self.es[key] = value

    #############################################
    # Auxiliary I/O functions
    # Graph libraries
    from_networkx = classmethod(_construct_graph_from_networkx)
    to_networkx = _export_graph_to_networkx

    from_graph_tool = classmethod(_construct_graph_from_graph_tool)
    to_graph_tool = _export_graph_to_graph_tool

    # Files
    Read_DIMACS = classmethod(_construct_graph_from_dimacs_file)
    write_dimacs = _write_graph_to_dimacs_file

    Read_GraphMLz = classmethod(_construct_graph_from_graphmlz_file)
    write_graphmlz = _write_graph_to_graphmlz_file

    Read_Pickle = classmethod(_construct_graph_from_pickle_file)
    write_pickle = _write_graph_to_pickle_file

    Read_Picklez = classmethod(_construct_graph_from_picklez_file)
    write_picklez = _write_graph_to_picklez_file

    Read_Adjacency = classmethod(_construct_graph_from_adjacency_file)
    write_adjacency = _write_graph_to_adjacency_file

    write_svg = _write_graph_to_svg

    Read = classmethod(_construct_graph_from_file)
    Load = Read
    write = _write_graph_to_file
    save = write

    # Various objects
    # list of dict representation of graphs
    DictList = classmethod(_construct_graph_from_dict_list)
    to_dict_list = _export_graph_to_dict_list

    # tuple-like representation of graphs
    TupleList = classmethod(_construct_graph_from_tuple_list)
    to_tuple_list = _export_graph_to_tuple_list

    # dict of sequence representation of graphs
    ListDict = classmethod(_construct_graph_from_list_dict)
    to_list_dict = _export_graph_to_list_dict

    # dict of dicts representation of graphs
    DictDict = classmethod(_construct_graph_from_dict_dict)
    to_dict_dict = _export_graph_to_dict_dict

    # adjacency matrix
    Adjacency = classmethod(_construct_graph_from_adjacency)
    Weighted_Adjacency = classmethod(_construct_graph_from_weighted_adjacency)

    # pandas dataframe(s)
    DataFrame = classmethod(_construct_graph_from_dataframe)
    get_vertex_dataframe = _export_vertex_dataframe
    get_edge_dataframe = _export_edge_dataframe

    # Bipartite graphs
    Bipartite = classmethod(_construct_bipartite_graph)
    Biadjacency = classmethod(_construct_bipartite_graph_from_adjacency)
    Full_Bipartite = classmethod(_construct_full_bipartite_graph)
    Random_Bipartite = classmethod(_construct_random_bipartite_graph)

    # Other constructors
    GRG = classmethod(_construct_random_geometric_graph)

    # Graph formulae
    Formula = classmethod(construct_graph_from_formula)

    #############################################
    # Summary/string representation
    def __str__(self):
        """Returns a string representation of the graph.

        Behind the scenes, this method constructs a L{GraphSummary}
        instance and invokes its C{__str__} method with a verbosity of 1
        and attribute printing turned off.

        See the documentation of L{GraphSummary} for more details about the
        output.
        """
        params = {
            "verbosity": 1,
            "width": 78,
            "print_graph_attributes": False,
            "print_vertex_attributes": False,
            "print_edge_attributes": False,
        }
        return self.summary(**params)

    def summary(self, verbosity=0, width=None, *args, **kwds):
        """Returns the summary of the graph.

        The output of this method is similar to the output of the
        C{__str__} method. If I{verbosity} is zero, only the header line
        is returned (see C{__str__} for more details), otherwise the
        header line and the edge list is printed.

        Behind the scenes, this method constructs a L{GraphSummary}
        object and invokes its C{__str__} method.

        @param verbosity: if zero, only the header line is returned
          (see C{__str__} for more details), otherwise the header line
          and the full edge list is printed.
        @param width: the number of characters to use in one line.
          If C{None}, no limit will be enforced on the line lengths.
        @return: the summary of the graph.
        """
        return str(GraphSummary(self, verbosity, width, *args, **kwds))

    #############################################
    # Commonly used attributes
    def is_named(self):
        """Returns whether the graph is named.

        A graph is named if and only if it has a C{"name"} vertex attribute.
        """
        return "name" in self.vertex_attributes()

    def is_weighted(self):
        """Returns whether the graph is weighted.

        A graph is weighted if and only if it has a C{"weight"} edge attribute.
        """
        return "weight" in self.edge_attributes()

    #############################################
    # Vertex and edge sequence
    @property
    def vs(self):
        """The vertex sequence of the graph"""
        return VertexSeq(self)

    @property
    def es(self):
        """The edge sequence of the graph"""
        return EdgeSeq(self)

    #############################################
    # Basic operations
    add_edge = _add_edge
    add_edges = _add_edges
    add_vertex = _add_vertex
    add_vertices = _add_vertices
    delete_edges = _delete_edges
    clear = _clear
    as_directed = _as_directed
    as_undirected = _as_undirected

    ###################
    # Graph operators
    __iadd__ = _operator_method_registry["__iadd__"]
    __add__ = _operator_method_registry["__add__"]
    __and__ = _operator_method_registry["__and__"]
    __isub__ = _operator_method_registry["__isub__"]
    __sub__ = _operator_method_registry["__sub__"]
    __mul__ = _operator_method_registry["__mul__"]
    __or__ = _operator_method_registry["__or__"]
    disjoint_union = _operator_method_registry["disjoint_union"]
    union = _operator_method_registry["union"]
    intersection = _operator_method_registry["intersection"]

    #############################################
    # Adjacency/incidence
    get_adjacency = _get_adjacency
    get_adjacency_sparse = _get_adjacency_sparse
    get_adjlist = _get_adjlist
    get_biadjacency = _get_biadjacency
    get_inclist = _get_inclist

    #############################################
    # Structural properties
    indegree = _indegree
    outdegree = _outdegree
    degree_distribution = _degree_distribution
    pagerank = _pagerank

    #############################################
    # Flow
    all_st_cuts = _all_st_cuts
    all_st_mincuts = _all_st_mincuts
    gomory_hu_tree = _gomory_hu_tree
    maxflow = _maxflow
    mincut = _mincut
    st_mincut = _st_mincut

    #############################################
    # Connected components
    biconnected_components = _biconnected_components
    clusters = _clusters
    cohesive_blocks = _cohesive_blocks
    connected_components = _connected_components
    blocks = _biconnected_components
    components = _connected_components

    #############################################
    # Community detection/clustering
    community_fastgreedy = _community_fastgreedy
    community_infomap = _community_infomap
    community_leading_eigenvector = _community_leading_eigenvector
    community_label_propagation = _community_label_propagation
    community_multilevel = _community_multilevel
    community_optimal_modularity = _community_optimal_modularity
    community_edge_betweenness = _community_edge_betweenness
    community_spinglass = _community_spinglass
    community_walktrap = _community_walktrap
    k_core = _k_core
    community_leiden = _community_leiden
    modularity = _modularity

    #############################################
    # Layout
    layout = _layout
    layout_auto = _layout_auto
    layout_sugiyama = _layout_sugiyama

    #############################################
    # Plotting
    __plot__ = _graph_plot

    #############################################
    # Bipartite
    maximum_bipartite_matching = _maximum_bipartite_matching
    bipartite_projection = _bipartite_projection
    bipartite_projection_size = _bipartite_projection_size

    #############################################
    # Automorphisms
    count_automorphisms_vf2 = _count_automorphisms_vf2
    get_automorphisms_vf2 = _get_automorphisms_vf2

    ###########################
    # Paths/traversals
    def get_all_simple_paths(self, v, to=None, cutoff=-1, mode="out"):
        """Calculates all the simple paths from a given node to some other nodes
        (or all of them) in a graph.

        A path is simple if its vertices are unique, i.e. no vertex is visited
        more than once.

        Note that potentially there are exponentially many paths between two
        vertices of a graph, especially if your graph is lattice-like. In this
        case, you may run out of memory when using this function.

        @param v: the source for the calculated paths
        @param to: a vertex selector describing the destination for the calculated
          paths. This can be a single vertex ID, a list of vertex IDs, a single
          vertex name, a list of vertex names or a L{VertexSeq} object. C{None}
          means all the vertices.
        @param cutoff: maximum length of path that is considered. If negative,
          paths of all lengths are considered.
        @param mode: the directionality of the paths. C{\"in\"} means to calculate
          incoming paths, C{\"out\"} means to calculate outgoing paths, C{\"all\"} means
          to calculate both ones.
        @return: all of the simple paths from the given node to every other
          reachable node in the graph in a list. Note that in case of mode=C{\"in\"},
          the vertices in a path are returned in reversed order!
        """
        paths = self._get_all_simple_paths(v, to, cutoff, mode)
        prev = 0
        result = []
        for index, item in enumerate(paths):
            if item < 0:
                result.append(paths[prev:index])
                prev = index + 1
        return result

    def path_length_hist(self, directed=True):
        """Returns the path length histogram of the graph

        @param directed: whether to consider directed paths. Ignored for
          undirected graphs.
        @return: a L{Histogram} object. The object will also have an
          C{unconnected} attribute that stores the number of unconnected
          vertex pairs (where the second vertex can not be reached from
          the first one). The latter one will be of type long (and not
          a simple integer), since this can be I{very} large.
        """
        data, unconn = GraphBase.path_length_hist(self, directed)
        hist = Histogram(bin_width=1)
        for i, length in enumerate(data):
            hist.add(i + 1, length)
        hist.unconnected = int(unconn)
        return hist

    # DFS (C version will come soon)
    def dfs(self, vid, mode=OUT):
        """Conducts a depth first search (DFS) on the graph.

        @param vid: the root vertex ID
        @param mode: either C{\"in\"} or C{\"out\"} or C{\"all\"}, ignored
          for undirected graphs.
        @return: a tuple with the following items:
           - The vertex IDs visited (in order)
           - The parent of every vertex in the DFS
        """
        nv = self.vcount()
        added = [False for v in range(nv)]
        stack = []

        # prepare output
        vids = []
        parents = []

        # ok start from vid
        stack.append((vid, self.neighbors(vid, mode=mode)))
        vids.append(vid)
        parents.append(-1)
        added[vid] = True

        # go down the rabbit hole
        while stack:
            vid, neighbors = stack[-1]
            if neighbors:
                # Get next neighbor to visit
                neighbor = neighbors.pop()
                if not added[neighbor]:
                    # Add hanging subtree neighbor
                    stack.append((neighbor, self.neighbors(neighbor, mode=mode)))
                    vids.append(neighbor)
                    parents.append(vid)
                    added[neighbor] = True
            else:
                # No neighbor found, end of subtree
                stack.pop()

        return (vids, parents)

    def spanning_tree(self, weights=None, return_tree=True):
        """Calculates a minimum spanning tree for a graph.

        B{Reference}: Prim, R.C. Shortest connection networks and some
        generalizations. I{Bell System Technical Journal} 36:1389-1401, 1957.

        @param weights: a vector containing weights for every edge in
          the graph. C{None} means that the graph is unweighted.
        @param return_tree: whether to return the minimum spanning tree (when
          C{return_tree} is C{True}) or to return the IDs of the edges in
          the minimum spanning tree instead (when C{return_tree} is C{False}).
          The default is C{True} for historical reasons as this argument was
          introduced in igraph 0.6.
        @return: the spanning tree as a L{Graph} object if C{return_tree}
          is C{True} or the IDs of the edges that constitute the spanning
          tree if C{return_tree} is C{False}.
        """
        result = GraphBase._spanning_tree(self, weights)
        if return_tree:
            return self.subgraph_edges(result, delete_vertices=False)
        return result

    ###########################
    # Dyad/triad census
    def dyad_census(self, *args, **kwds):
        """Calculates the dyad census of the graph.

        Dyad census means classifying each pair of vertices of a directed
        graph into three categories: mutual (there is an edge from I{a} to
        I{b} and also from I{b} to I{a}), asymmetric (there is an edge
        from I{a} to I{b} or from I{b} to I{a} but not the other way round)
        and null (there is no connection between I{a} and I{b}).

        B{Reference}: Holland, P.W. and Leinhardt, S. A Method for Detecting
        Structure in Sociometric Data. I{American Journal of Sociology}, 70,
        492-513, 1970.

        @return: a L{DyadCensus} object.
        """
        return DyadCensus(GraphBase.dyad_census(self, *args, **kwds))

    def triad_census(self, *args, **kwds):
        """Calculates the triad census of the graph.

        B{Reference}: Davis, J.A. and Leinhardt, S. The Structure of
        Positive Interpersonal Relations in Small Groups. In:
        J. Berger (Ed.), Sociological Theories in Progress, Volume 2,
        218-251. Boston: Houghton Mifflin (1972).

        @return: a L{TriadCensus} object.
        """
        return TriadCensus(GraphBase.triad_census(self, *args, **kwds))

    ###########################
    # Other functions
    def transitivity_avglocal_undirected(self, mode="nan", weights=None):
        """Calculates the average of the vertex transitivities of the graph.

        In the unweighted case, the transitivity measures the probability that
        two neighbors of a vertex are connected. In case of the average local
        transitivity, this probability is calculated for each vertex and then
        the average is taken. Vertices with less than two neighbors require
        special treatment, they will either be left out from the calculation
        or they will be considered as having zero transitivity, depending on
        the I{mode} parameter. The calculation is slightly more involved for
        weighted graphs; in this case, weights are taken into account according
        to the formula of Barrat et al (see the references).

        Note that this measure is different from the global transitivity
        measure (see L{transitivity_undirected()}) as it simply takes the
        average local transitivity across the whole network.

        B{References}

          - Watts DJ and Strogatz S: Collective dynamics of small-world
            networks. I{Nature} 393(6884):440-442, 1998.
          - Barrat A, Barthelemy M, Pastor-Satorras R and Vespignani A:
            The architecture of complex weighted networks. I{PNAS} 101, 3747
            (2004). U{http://arxiv.org/abs/cond-mat/0311416}.

        @param mode: defines how to treat vertices with degree less than two.
          If C{TRANSITIVITY_ZERO} or C{"zero"}, these vertices will have zero
          transitivity. If C{TRANSITIVITY_NAN} or C{"nan"}, these vertices
          will be excluded from the average.
        @param weights: edge weights to be used. Can be a sequence or iterable
          or even an edge attribute name.

        @see: L{transitivity_undirected()}, L{transitivity_local_undirected()}
        """
        if weights is None:
            return GraphBase.transitivity_avglocal_undirected(self, mode)

        xs = self.transitivity_local_undirected(mode=mode, weights=weights)
        return sum(xs) / float(len(xs))

    ###########################
    # ctypes support
    @property
    def _as_parameter_(self):
        return self._raw_pointer()

    # Other type functions
    def __bool__(self):
        """Returns True if the graph has at least one vertex, False otherwise."""
        return self.vcount() > 0

    def __coerce__(self, other):
        """Coercion rules.

        This method is needed to allow the graph to react to additions
        with lists, tuples, integers, strings, vertices, edges and so on.
        """
        if isinstance(other, (int, tuple, list, str)):
            return self, other
        if isinstance(other, Vertex):
            return self, other
        if isinstance(other, VertexSeq):
            return self, other
        if isinstance(other, Edge):
            return self, other
        if isinstance(other, EdgeSeq):
            return self, other
        return NotImplemented

    @classmethod
    def _reconstruct(cls, attrs, *args, **kwds):
        """Reconstructs a Graph object from Python's pickled format.

        This method is for internal use only, it should not be called
        directly."""
        result = cls(*args, **kwds)
        result.__dict__.update(attrs)
        return result

    def __reduce__(self):
        """Support for pickling."""
        constructor = self.__class__
        gattrs, vattrs, eattrs = {}, {}, {}
        for attr in self.attributes():
            gattrs[attr] = self[attr]
        for attr in self.vs.attribute_names():
            vattrs[attr] = self.vs[attr]
        for attr in self.es.attribute_names():
            eattrs[attr] = self.es[attr]
        parameters = (
            self.vcount(),
            self.get_edgelist(),
            self.is_directed(),
            gattrs,
            vattrs,
            eattrs,
        )
        return (constructor, parameters, self.__dict__)

    __iter__ = None  # needed for PyPy
    __hash__ = None  # needed for PyPy

    ###########################
    # Deprecated functions

    @classmethod
    def Incidence(cls, *args, **kwds):
        """Deprecated alias to L{Graph.Biadjacency()}."""
        deprecated("Graph.Incidence() is deprecated; use Graph.Biadjacency() instead")
        return cls.Biadjacency(*args, **kwds)

    def get_incidence(self, *args, **kwds):
        """Deprecated alias to L{Graph.get_biadjacency()}."""
        deprecated(
            "Graph.get_incidence() is deprecated; use Graph.get_biadjacency() "
            "instead"
        )
        return self.get_biadjacency(*args, **kwds)

##############################################################
# I/O format mapping
Graph._format_mapping = _format_mapping

##############################################################
# Additional methods of VertexSeq and EdgeSeq that call Graph methods
_add_proxy_methods()

##############################################################
# Layout mapping
Graph._layout_mapping = _layout_mapping

##############################################################
# Making sure that layout methods always return a Layout
for name in dir(Graph):
    if not name.startswith("layout_"):
        continue
    if name in ("layout_auto", "layout_sugiyama"):
        continue
    setattr(Graph, name, _layout_method_wrapper(getattr(Graph, name)))

##############################################################
# Adding aliases for the 3D versions of the layout methods
Graph.layout_fruchterman_reingold_3d = _3d_version_for(
    Graph.layout_fruchterman_reingold
)
Graph.layout_kamada_kawai_3d = _3d_version_for(Graph.layout_kamada_kawai)
Graph.layout_random_3d = _3d_version_for(Graph.layout_random)
Graph.layout_grid_3d = _3d_version_for(Graph.layout_grid)
Graph.layout_sphere = _3d_version_for(Graph.layout_circle)

##############################################################
# Auxiliary global functions
def get_include():
    """Returns the folder that contains the C API headers of the Python
    interface of igraph."""
    import igraph

    paths = [
        # The following path works if igraph is installed already
        os.path.join(
            sys.prefix,
            "include",
            "python{0}.{1}".format(*sys.version_info),
            "igraph",
        ),
        # Fallback for cases when igraph is not installed but
        # imported directly from the source tree
        os.path.join(os.path.dirname(igraph.__file__), "..", "src", "_igraph"),
    ]
    for path in paths:
        if os.path.exists(os.path.join(path, "igraphmodule_api.h")):
            return os.path.abspath(path)
    raise ValueError("cannot find the header files of the Python interface of igraph")

def read(filename, *args, **kwds):
    """Loads a graph from the given filename.

    This is just a convenience function, calls L{Graph.Read} directly.
    All arguments are passed unchanged to L{Graph.Read}

    @param filename: the name of the file to be loaded
    """
    return Graph.Read(filename, *args, **kwds)

load = read

def write(graph, filename, *args, **kwds):
    """Saves a graph to the given file.

    This is just a convenience function, calls L{Graph.write} directly.
    All arguments are passed unchanged to L{Graph.write}

    @param graph: the graph to be saved
    @param filename: the name of the file to be written
    """
    return graph.write(filename, *args, **kwds)

save = write

##############################################################
# Configuration singleton instance
config = init_configuration()
"""The main configuration object of igraph. Use this object to modify igraph's
behaviour, typically when used in interactive mode.
"""

##############################################################
# Remove modular methods from namespace
del (
    construct_graph_from_formula,
    _construct_graph_from_graphmlz_file,
    _construct_graph_from_dimacs_file,
    _construct_graph_from_pickle_file,
    _construct_graph_from_picklez_file,
    _construct_graph_from_adjacency_file,
    _construct_graph_from_file,
    _format_mapping,
    _construct_graph_from_dict_list,
    _construct_graph_from_tuple_list,
    _construct_graph_from_list_dict,
    _construct_graph_from_dict_dict,
    _construct_graph_from_adjacency,
    _construct_graph_from_weighted_adjacency,
    _construct_graph_from_dataframe,
    _construct_random_geometric_graph,
    _construct_bipartite_graph,
    _construct_bipartite_graph_from_adjacency,
    _construct_full_bipartite_graph,
    _construct_random_bipartite_graph,
    _construct_graph_from_networkx,
    _export_graph_to_networkx,
    _construct_graph_from_graph_tool,
    _export_graph_to_graph_tool,
    _export_graph_to_list_dict,
    _export_graph_to_dict_dict,
    _export_graph_to_dict_list,
    _export_graph_to_tuple_list,
    _community_fastgreedy,
    _community_infomap,
    _community_leading_eigenvector,
    _community_label_propagation,
    _community_multilevel,
    _community_optimal_modularity,
    _community_edge_betweenness,
    _community_spinglass,
    _community_walktrap,
    _k_core,
    _community_leiden,
    _modularity,
    _graph_plot,
    _operator_method_registry,
    _add_edge,
    _add_edges,
    _add_vertex,
    _add_vertices,
    _delete_edges,
    _as_directed,
    _as_undirected,
    _layout,
    _layout_auto,
    _layout_sugiyama,
    _layout_method_wrapper,
    _3d_version_for,
    _layout_mapping,
    _count_automorphisms_vf2,
    _get_automorphisms_vf2,
    _get_adjacency,
    _get_adjacency_sparse,
    _get_adjlist,
    _maximum_bipartite_matching,
    _bipartite_projection,
    _bipartite_projection_size,
    _biconnected_components,
    _cohesive_blocks,
    _connected_components,
    _add_proxy_methods,
)

# Re-export from _igraph for API docs
# Because _igraph starts with an underscore, pydoctor skips the whole docs
# except for the objects mentioned down here.
__all__ = (
    "config",
    "AdvancedGradientPalette",
    "BoundingBox",
    "CairoGraphDrawer",
    "ClusterColoringPalette",
    "Clustering",
    "CohesiveBlocks",
    "Configuration",
    "Cover",
    "Cut",
    "DefaultGraphDrawer",
    "Dendrogram",
    "DyadCensus",
    "Edge",
    "EdgeSeq",
    "FittedPowerLaw",
    "Flow",
    "GradientPalette",
    "Graph",
    "GraphBase",
    "GraphSummary",
    "Histogram",
    "InternalError",
    "Layout",
    "Matching",
    "MatplotlibGraphDrawer",
    "Matrix",
    "Palette",
    "Plot",
    "Point",
    "PrecalculatedPalette",
    "RainbowPalette",
    "Rectangle",
    "RunningMean",
    "TriadCensus",
    "UniqueIdGenerator",
    "Vertex",
    "VertexClustering",
    "VertexCover",
    "VertexDendrogram",
    "VertexSeq",
    "autocurve",
    "color_name_to_rgb",
    "color_name_to_rgba",
    "community_to_membership",
    "compare_communities",
    "convex_hull",
    "default_arpack_options",
    "disjoint_union",
    "get_include",
    "hsla_to_rgba",
    "hsl_to_rgb",
    "hsva_to_rgba",
    "hsv_to_rgb",
    "is_bigraphical",
    "is_degree_sequence",
    "is_graphical",
    "is_graphical_degree_sequence",
    "intersection",
    "known_colors",
    "load",
    "mean",
    "median",
    "palettes",
    "percentile",
    "plot",
    "power_law_fit",
    "quantile",
    "read",
    "rescale",
    "rgba_to_hsla",
    "rgb_to_hsl",
    "rgba_to_hsva",
    "rgb_to_hsv",
    "save",
    "set_progress_handler",
    "set_random_number_generator",
    "set_status_handler",
    "split_join_distance",
    "summary",
    "umap_compute_weights",
    "union",
    "write",
    "__igraph_version__",
    "__version__",
    "__version_info__",
    # enums and stuff
    "ADJ_DIRECTED",
    "ADJ_LOWER",
    "ADJ_MAX",
    "ADJ_MIN",
    "ADJ_PLUS",
    "ADJ_UNDIRECTED",
    "ADJ_UPPER",
    "ALL",
    "ARPACKOptions",
    "BFSIter",
    "BLISS_F",
    "BLISS_FL",
    "BLISS_FLM",
    "BLISS_FM",
    "BLISS_FS",
    "BLISS_FSM",
    "DFSIter",
    "GET_ADJACENCY_BOTH",
    "GET_ADJACENCY_LOWER",
    "GET_ADJACENCY_UPPER",
    "IN",
    "OUT",
    "REWIRING_SIMPLE",
    "REWIRING_SIMPLE_LOOPS",
    "STAR_IN",
    "STAR_MUTUAL",
    "STAR_OUT",
    "STAR_UNDIRECTED",
    "STRONG",
    "TRANSITIVITY_NAN",
    "TRANSITIVITY_ZERO",
    "TREE_IN",
    "TREE_OUT",
    "TREE_UNDIRECTED",
    "WEAK",
)


# -*- coding:utf-8 -*-
"""
@project = 0606-1
@file = decision tree_CART_1
@author = Liangjisheng
@create_time = 2018/6/10 0010 上午 10:22
@https://blog.csdn.net/herosofearth/article/details/52425952
"""
import operator
import copy

# Ck是D中属于第k类的样本子集，K是类的个数
def calcGini(dataSet):
    """
    计算基尼指数
    :param dataSet:数据集
    :return: 计算结果
    """
    numEntries = len(dataSet)
    labelCounts = {}
    for featVec in dataSet:     # 遍历每个实例，统计标签的频数
        currentLabel = featVec[-1]
        if currentLabel not in labelCounts.keys():
            labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1
    Gini = 1.0
    for key in labelCounts:
        prob = float(labelCounts[key]) / numEntries
        Gini -= prob * prob
    return Gini

# 基尼指数Gini(D)表示集合D的不确定性，基尼指数Gini(D,A)表示经A=a分割后集合D的不确定性
# 基尼指数值越大，样本集合的不确定性也就越大，这一点与熵相似
def calcGiniWithFeat(dataSet, feature, value):
    """
    计算给定特征下的基尼指数
    :param dataSet:数据集
    :param feature:特征维度
    :param value:该特征变量所取的值
    :return: 计算结果
    """
    D0 = []
    D1 = []
    # 根据特征划分数据
    for featVec in dataSet:
        if featVec[feature] == value:
            D0.append(featVec)
        else:
            D1.append(featVec)
    Gini = len(D0) / len(dataSet) * calcGini(D0) + len(D1) / len(dataSet) * calcGini(D1)
    return Gini

def chooseBestSplit(dataSet):
    numFeatures = len(dataSet[0]) - 1
    bestGini = 1000000
    bestFeat = 0
    bestValue = 0
    newGini = 0
    for i in range(numFeatures):
        featList = [example[i] for example in dataSet]
        uniqueVals = set(featList)
        for splitVal in uniqueVals:
            newGini = calcGiniWithFeat(dataSet, i, splitVal)
            if newGini < bestGini:
                bestFeat = i
                bestGini = newGini
    return bestFeat

def majorityCnt(classList):
    """
    采用多数表决的方法决定叶结点的分类
    :param: 所有的类标签列表
    :return: 出现次数最多的类
    """
    classCount={}
    for vote in classList:                  # 统计所有类标签的频数
        if vote not in classCount.keys():
            classCount[vote] = 0
        classCount[vote] += 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)     # 排序
    return sortedClassCount[0][0]

def splitDataSet(dataSet, axis, value):
    """
    按照给定特征划分数据集
    :param dataSet:待划分的数据集
    :param axis:划分数据集的特征
    :param value:需要返回的特征的值
    :return:划分结果列表
    """
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            reduceFeatVec = featVec[:axis]      # chop out axis used for splitting
            reduceFeatVec.extend(featVec[axis + 1:])
            retDataSet.append(reduceFeatVec)

    return retDataSet

def createTree(dataSet,labels):
    """
    创建决策树
    :param: dataSet:训练数据集
    :return: labels:所有的类标签
    """
    classList = [example[-1] for example in dataSet]
    if classList.count(classList[0]) == len(classList):
        return classList[0]             # 第一个递归结束条件：所有的类标签完全相同
    if len(dataSet[0]) == 1:
        return majorityCnt(classList)   # 第二个递归结束条件：用完了所有特征

    bestFeat = chooseBestSplit(dataSet)   # 最优划分特征
    bestFeatLabel = labels[bestFeat]
    myTree = {bestFeatLabel: {}}         # 使用字典类型储存树的信息
    del(labels[bestFeat])
    featValues = [example[bestFeat] for example in dataSet]
    uniqueVals = set(featValues)
    for value in uniqueVals:
        subLabels = labels[:]       # 复制所有类标签，保证每次递归调用时不改变原始列表的内容
        myTree[bestFeatLabel][value] = \
            createTree(splitDataSet(dataSet, bestFeat, value), subLabels)
    return myTree

def createDataSet():
    dataSet = [['youth', 'no', 'no', 1, 'refuse'],
               ['youth', 'no', 'no', '2', 'refuse'],
               ['youth', 'yes', 'no', '2', 'agree'],
               ['youth', 'yes', 'yes', 1, 'agree'],
               ['youth', 'no', 'no', 1, 'refuse'],
               ['mid', 'no', 'no', 1, 'refuse'],
               ['mid', 'no', 'no', '2', 'refuse'],
               ['mid', 'yes', 'yes', '2', 'agree'],
               ['mid', 'no', 'yes', '3', 'agree'],
               ['mid', 'no', 'yes', '3', 'agree'],
               ['elder', 'no', 'yes', '3', 'agree'],
               ['elder', 'no', 'yes', '2', 'agree'],
               ['elder', 'yes', 'no', '2', 'agree'],
               ['elder', 'yes', 'no', '3', 'agree'],
               ['elder', 'no', 'no', 1, 'refuse'],
               ]
    labels = ['age', 'working?', 'house?', 'credit_situation']
    return dataSet, labels

def classify(inputTree, featLabels, testVec):
    """
    利用决策树进行分类
    :param: inputTree:构造好的决策树模型
    :param: featLabels:所有的类标签
    :param: testVec:测试数据
    :return: 分类决策结果
    """
    firstStr = list(inputTree.keys())[0]
    secondDict = inputTree[firstStr]
    featIndex = featLabels.index(firstStr)
    key = testVec[featIndex]
    valueOfFeat = secondDict[key]
    if isinstance(valueOfFeat, dict):
        classLabel = classify(valueOfFeat, featLabels, testVec)
    else:
        classLabel = valueOfFeat
    return classLabel

# 在决策树学习中将已生成的树进行简化的过程称为剪枝。决策树的剪枝往往通过极小化决策树的损失函数
# 或代价函数来实现。实际上剪枝的过程就是一个动态规划的过程：从叶结点开始，自底向上地对内部结点
# 计算预测误差以及剪枝后的预测误差，如果两者的预测误差是相等或者剪枝后预测误差更小，当然是剪掉
# 的好。但是如果剪枝后的预测误差更大，那就不要剪了。剪枝后，原内部结点会变成新的叶结点，其决策
# 类别由多数表决法决定。不断重复这个过程往上剪枝，直到预测误差最小为止

# 计算预测误差
def calcTestErr(myTree,testData,labels):
    errorCount = 0.0
    for i in range(len(testData)):
        if classify(myTree, labels, testData[i]) != testData[i][-1]:
            errorCount += 1
    return float(errorCount)

# 计算剪枝后的预测误差
def TestMajor(major,testData):
    errorCount = 0.0
    for i in range(len(testData)):
        if major != testData[i][-1]:
            errorCount += 1
    return float(errorCount)

def isTree(param):
    if type(param) is dict:
        return True
    else:
        return False

def pruningTree(inputTree,dataSet,testData,labels):
    firstStr = list(inputTree.keys())[0]
    secondDict = inputTree[firstStr]        # 获取子树
    classList = [example[-1] for example in dataSet]
    featKey = copy.deepcopy(firstStr)
    labelIndex = labels.index(featKey)
    subLabels = copy.deepcopy(labels)
    del(labels[labelIndex])
    for key in list(secondDict.keys()):
        if isTree(secondDict[key]):
            # 深度优先搜索,递归剪枝
            subDataSet = splitDataSet(dataSet, labelIndex, key)
            subTestSet = splitDataSet(testData, labelIndex, key)
            if len(subDataSet) > 0 and len(subTestSet) > 0:
                inputTree[firstStr][key] = pruningTree(secondDict[key], subDataSet, subTestSet, copy.deepcopy(labels))
    if calcTestErr(inputTree, testData, subLabels) < TestMajor(majorityCnt(classList), testData):
        # 剪枝后的误差反而变大，不作处理，直接返回
        return inputTree
    else:
        # 剪枝，原父结点变成子结点，其类别由多数表决法决定
        return majorityCnt(classList)

if __name__ == '__main__':
    dataSet, labels = createDataSet()
    subLabels = labels[:]
    myTree = createTree(dataSet, labels)
    print(myTree)


def merge_sort(arr):
    global cnt
    # 분할
    if len(arr) == 1:
        return arr
    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])

    # 병합
    merged = []
    l = r = 0
    while l < len(left) and r < len(right):
        if left[l] <= right[r]:
            merged.append(left[l])
            l += 1
        else:
            merged.append(right[r])
            r += 1

    # 오른쪽이 먼저 모두 복사되었을 때 (왼쪽 list가 남아있을 때)
    if left[l:]:
        cnt += 1
    merged.extend(left[l:])
    merged.extend(right[r:])
    return merged

# -------------------------------------------
T = int(input())
for tc in range(1, 1+T):
    N = int(input())
    arr = list(map(int, input().split()))
    cnt = 0
    merged = merge_sort(arr)
    print(f'#{tc} {merged[N//2]} {cnt}')


Import('env')

#dependencies = ['voxel']
dependencies = ['applayer', 'renderer', 'input', 'kinect']

src_files = env.Glob("src/*.cpp")
prog = env.KProgram("kinevox", src_files, dependencies)
finalProduct = env.Install(env.Dir("$INSTALL_DIR"), prog)

Default(finalProduct)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 11 11:337:50 2019

@author: pevifol
"""
import time as t
import os
def data():
    '''Retorna uma string com a data atual no formato dia_mês_ano'''
    a=list(t.localtime())
    return str(a[2])+'_'+str(a[1])+'_'+str(a[0])
def logging(mensagem=''):
    '''Faz/adiciona ao log diário alguma coisa.'''
    mensagem=' - '+str(mensagem)
    try:
        os.stat("log")
    except OSError:
        print('Criando diretório de log')
        os.mkdir("log")
    with open("./log/"+data()+'.txt','a+') as w:
        w.write(t.strftime("%H:%M:%S", t.gmtime())+mensagem+'\n')
    return
logging(69)
logging('Nice')


from __future__ import print_function
# In[1]:
import pickle
import numpy as np
import time
import sys
sys.path.append('./models')
import matplotlib.pyplot as plt

import keras
from keras import backend as K
#from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
from keras.datasets import cifar10
from keras.utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint
import keras
import numpy as np
from keras.models import load_model
from kerassurgeon.operations import delete_layer, insert_layer, delete_channels
from heapq import nsmallest
from keras.models import Sequential,Model
import time

def normalize(X_train,X_test):
	#this function normalize inputs for zero mean and unit variance
	# it is used when training a model.
	# Input: training set and test set
	# Output: normalized training set and test set according to the trianing set statistics.
	mean = np.mean(X_train,axis=(0,1,2,3))
	std = np.std(X_train, axis=(0, 1, 2, 3))
	X_train = (X_train-mean)/(std+1e-7)
	X_test = (X_test-mean)/(std+1e-7)
	return X_train, X_test

def load_data():
	t0 = time.time()

	(X_train, Y_train), (X_test, Y_test) = cifar10.load_data()  # 32×32
	X_train = X_train.astype('float32')  # uint8-->float32
	X_test = X_test.astype('float32')
	X_train,X_test = normalize(X_train,X_test)
	print('训练样例:', X_train.shape, Y_train.shape,
	      ', 测试样例:', X_test.shape, Y_test.shape)

	nb_classes = 10  # label为0~9共10个类别
	# Convert class vectors to binary class matrices
	Y_train = to_categorical(Y_train, nb_classes)
	Y_test = to_categorical(Y_test, nb_classes)
	print("取数据耗时: %.2f seconds ..." % (time.time() - t0))

	# define generators for training and validation data
    #data augmentation
	train_datagen = ImageDataGenerator(
	    featurewise_center=False,  # set input mean to 0 over the dataset
	    samplewise_center=False,  # set each sample mean to 0
	    featurewise_std_normalization=False,  # divide inputs by std of the dataset
	    samplewise_std_normalization=False,  # divide each input by its std
	    zca_whitening=False,  # apply ZCA whitening
	    rotation_range=15,  # randomly rotate images in the range (degrees, 0 to 180)
	    width_shift_range=0.1,  # randomly shift images horizontally (fraction of total width)
	    height_shift_range=0.1,  # randomly shift images vertically (fraction of total height)
	    horizontal_flip=True,  # randomly flip images
	    vertical_flip=False)  # randomly flip images

	val_datagen = ImageDataGenerator(
	    featurewise_center=True,
	    featurewise_std_normalization=True)

	# compute quantities required for featurewise normalization
	# (std, mean, and principal components if ZCA whitening is applied)
	train_datagen.fit(X_train)
	val_datagen.fit(X_test)
	return X_train,Y_train,X_test,Y_test,train_datagen,val_datagen

def train(model,X_train,Y_train,X_test,Y_test,train_datagen,val_datagen):
	learning_rate = 0.001
	lr_decay = 1e-6
	lr_drop = 20
	def lr_scheduler(epoch):
		return learning_rate * (0.5 ** (epoch // lr_drop))
	reduce_lr = keras.callbacks.LearningRateScheduler(lr_scheduler)

	sgd = keras.optimizers.SGD(lr=learning_rate, decay=lr_decay, momentum=0.9, nesterov=True)
	model.compile(
	    optimizer=sgd,
	    loss='categorical_crossentropy', metrics=['accuracy']
	)

	callbacks = [
	    EarlyStopping(monitor='val_acc', patience=7, min_delta=0.01,verbose=1),
	    reduce_lr
	            ]

	batch_size = 256
	model.fit_generator(train_datagen.flow(X_train, Y_train, batch_size=batch_size),
	                steps_per_epoch=len(X_train)//batch_size, epochs=10,
	                validation_data=val_datagen.flow(X_test, Y_test, batch_size=batch_size),
	                validation_steps=len(X_test)//batch_size,
	                callbacks=callbacks, initial_epoch=0, shuffle=True, verbose=2)
	return model

def test(model,X_train,Y_train,X_test,Y_test,train_datagen,val_datagen):
	batch_size = 256
	model.compile(
	    optimizer=keras.optimizers.Adam(lr=1e-4),
	    loss='categorical_crossentropy', metrics=['accuracy']
	)
	score = model.evaluate_generator(val_datagen.flow(X_test, Y_test), steps=len(X_test)/batch_size, use_multiprocessing=False, verbose=2)
	loss = score[0]
	acc = score[1]
	print('loss:',loss)
	print('acc:',acc)
	return model,loss,acc


# Given an integer numRows, return the first numRows of Pascal's triangle.
# In Pascal's triangle, each number is the sum of the two numbers directly above it as shown:

from typing import List

class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        res = [[1]]
        for i in range(1, numRows):
            res.append(newRow(res[i-1]))
        return res
def newRow(old):
    new = [1]
    for i in range(0, len(old)-1):
        new.append(old[i]+old[i+1])
    new.append(1)
    return new

s = Solution()
print(s.generate(3))
print(s.generate(4))
print(s.generate(5))
print(s.generate(6))


#! /usr/bin/env python
# coding=utf-8
"""
Author: Deean
Date: 2022-06-09 23:41
LastEditTime: 2022-06-09 23:41
Description:
FilePath: LCP 40. 心算挑战.py
"""

from typing import List

class Solution:
    def maxmiumScore(self, cards: List[int], cnt: int) -> int:
        if cnt > len(cards):
            return 0

        odd, even, score = [0], [0], 0
        cards.sort(reverse=True)
        for card in cards:
            if card % 2:
                odd.append(card + odd[-1])
            else:
                even.append(card + even[-1])

        for i in range(0, min(len(odd) - 1, cnt) + 1, 2):
            if len(even) - 1 >= cnt - i:
                score = max(score, odd[i] + even[cnt - i])

        return score

if __name__ == '__main__':
    solution = Solution()
    ans = solution.maxmiumScore(cards=[1, 2, 8, 9], cnt=3)
    print(ans)


from typing import Any
from pprint import pformat
from datetime import timedelta
import uuid
import logging

# for redis
from pottery import Redlock
from redis import Redis
import orjson

# for dynamodb
import boto3
from python_dynamodb_lock.python_dynamodb_lock import DynamoDBLockClient, DynamoDBLock

import settings

class KVData:
    """
    A key-value storage interface
    """

    logger = logging.getLogger("attendence.db")

    def __init__(self) -> None:
        self.data: dict[str, Any] = {}

    def get(self, key: str, default: Any | None = None) -> Any:
        """Get Data by key"""
        value = self.data.get(key, default)
        self.logger.debug(f"Get {key}={value}")
        return value

    def set(self, key: str, value: Any) -> None:
        """Set data by key"""
        self.logger.debug(f"Set {key}={pformat(value)}")
        self.data[key] = value

    def gets(self, keys: list[str]) -> list[Any]:
        """Get Data by keys"""
        return [self.get(key) for key in keys]

    def sets(self, key_values: list[tuple[str, Any]]) -> None:
        """Set data by keys and values"""
        for key, value in key_values:
            self.set(key, value)

    def delete(self, key: str) -> None:
        """Delete key"""
        self.logger.debug(f"Delete {key}")
        del self.data[key]

    def create(self, prefix: str) -> str:
        """Find a random and unused key"""
        while True:
            key = prefix + str(uuid.uuid4())
            if not self.get(key):
                break
        return key

    def clear(self) -> None:
        """Remove all data"""
        self.data = {}

    def lock(self, key: str) -> None:
        """Not implement"""

    @classmethod
    def isLock(cls, lock: Any) -> bool:
        """Lock status"""
        return False

    @classmethod
    def release(cls, lock: Any) -> None:
        """Release lock"""

class RedisDB:
    """
    A key-value storage interface
    """

    logger = logging.getLogger("attendence.db")

    def __init__(self) -> None:
        """Connect to redis instance"""
        self.redis = Redis.from_url(settings.redis_url, decode_responses=True)

    def clear(self) -> None:
        """Remove all data"""
        self.redis.flushall()

    def lock(self, key: str) -> Redlock:
        """Block the execution depended on the key"""
        lock = Redlock(key=key, masters={self.redis}, auto_release_time=0.5)
        lock.acquire()
        return lock

    @classmethod
    def isLock(cls, lock: Redlock) -> bool:
        """Lock status"""
        return bool(lock.locked())

    @classmethod
    def release(cls, lock: Redlock) -> None:
        """Release lock"""
        lock.release()

    def get(self, key: str, default: Any | None = None) -> Any:
        """Get Data by key"""
        raw_value = self.redis.get(key)
        if not raw_value:
            return default
        value = orjson.loads(raw_value)
        self.logger.debug(f"Get {key}={value}")
        return value

    def set(self, key: str, value: Any) -> None:
        """Set data by key"""
        self.redis.set(key, orjson.dumps(value))
        self.logger.debug(f"Set {key}=\n{pformat(value)}")

    def gets(self, keys: list[str]) -> list[Any]:
        """Get Data by keys"""
        pipe = self.redis.pipeline()
        [pipe.get(key) for key in keys]
        return [orjson.loads(raw_value) for raw_value in pipe.execute()]

    def sets(self, key_values: list[tuple[str, Any]]) -> None:
        """Set data by keys and values"""
        pipe = self.redis.pipeline()
        [pipe.set(key, orjson.dumps(value)) for key, value in key_values]
        pipe.execute()

    def delete(self, key: str) -> None:
        """Delete key"""
        self.redis.delete(key)
        self.logger.debug(f"Delete {key}")

    def create(self, prefix: str) -> str:
        """Find a random and unused key"""
        while True:
            key = prefix + str(uuid.uuid4())
            if not self.redis.exists(key):
                break
        return key

class DynamoDB:
    """
    A KV storage of AWS
    """

    logger = logging.getLogger("attendence.db")

    def __init__(self) -> None:
        """Connect to redis instance"""
        self.dynamo_client = boto3.client("dynamodb")
        self.dynamo_resource = boto3.resource("dynamodb")
        self.createTable()
        self.createLockTable()

    def createLockTable(self) -> None:
        """
        Create Lock table
        However, there is not official implemented package.
        I use outdated https://github.com/mohankishore/python_dynamodb_lock.
        Maybe I'll change it
        """
        self.lock_client = DynamoDBLockClient(
            self.dynamo_resource,
            table_name=settings.dynamodb_table + "-lock",
            expiry_period=timedelta(seconds=30),
        )
        try:
            self.logger.info(f"Creating {self.lock_client._table_name}")
            db_lock = self.dynamo_resource.create_table(
                TableName=self.lock_client._table_name,
                KeySchema=[
                    {
                        "AttributeName": self.lock_client._partition_key_name,
                        "KeyType": "HASH",
                    },
                    {
                        "AttributeName": self.lock_client._sort_key_name,
                        "KeyType": "RANGE",
                    },
                ],
                AttributeDefinitions=[
                    {
                        "AttributeName": self.lock_client._partition_key_name,
                        "AttributeType": "S",
                    },
                    {
                        "AttributeName": self.lock_client._sort_key_name,
                        "AttributeType": "S",
                    },
                ],
                **settings.dynamodb_other,
            )
            db_lock.wait_until_exists()
            self.dynamo_client.update_time_to_live(
                TableName=self.lock_client._table_name,
                TimeToLiveSpecification={
                    "Enabled": True,
                    "AttributeName": self.lock_client._ttl_attribute_name,
                },
            )
            db_lock.wait_until_exists()

        except boto3.exceptions.botocore.exceptions.ClientError:
            self.logger.info(f"{self.lock_client._table_name} has created")
            pass

    def createTable(self) -> None:
        """Create or use the table"""
        try:
            self.db = self.dynamo_resource.create_table(
                TableName=settings.dynamodb_table,
                KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
                AttributeDefinitions=[
                    {"AttributeName": "id", "AttributeType": "S"},
                ],
                **settings.dynamodb_other,
            )
            self.db.wait_until_exists()
            self.logger.info(f"Create {self.db}")
        except boto3.exceptions.botocore.exceptions.ClientError:
            self.db = self.dynamo_resource.Table(settings.dynamodb_table)
            self.logger.info(f"Use existed {self.db}")

    def clear(self) -> None:
        """Remove all data"""
        self.logger.info(f"Delete {self.db}")
        self.db.delete()
        db_lock = self.dynamo_resource.Table(self.lock_client._table_name)
        self.logger.info(f"Delete {db_lock}")
        db_lock.delete()
        self.db.wait_until_not_exists()
        db_lock.wait_until_not_exists()
        self.createTable()
        self.createLockTable()

    @classmethod
    def isLock(cls, lock: DynamoDBLock) -> bool:
        """Lock status"""
        return lock.status == "LOCKED"  # type: ignore

    @classmethod
    def release(cls, lock: DynamoDBLock) -> None:
        """Release lock"""
        lock.release()

    def lock(self, key: str) -> DynamoDBLock:
        """Block the execution depended on the key"""
        return self.lock_client.acquire_lock(key)

    def get(self, key: str, default: Any | None = None) -> Any:
        """Get Data by key"""
        raw_value = self.db.get_item(Key={"id": key}).get("Item")
        if not raw_value:
            return default
        value = orjson.loads(raw_value["data"].value)
        self.logger.debug(f"Get {key}={value}")
        return value
        # directly save dict into db
        # return raw_value

    def set(self, key: str, value: Any) -> None:
        """Set data by key"""
        # why dynamodb not support time
        # directly save dict into db
        # value['id'] = key
        # self.db.put_item(Item=value)
        self.db.put_item(Item={"id": key, "data": orjson.dumps(value)})
        self.logger.debug(f"Set {key}=\n{pformat(value)}")

    def gets(self, keys: list[str]) -> list[Any]:
        """Get Data by keys"""
        raise NotImplementedError

    def sets(self, key_values: list[tuple[str, Any]]) -> None:
        """Set data by keys and values"""
        raise NotImplementedError
        # with self.db.batch_writer() as writer:
        #     for key, value in key_values:
        #         value['id'] = key
        #         writer.put_item(Item=value)

    def delete(self, key: str) -> None:
        """Delete key"""
        self.db.delete_item(Key={"id": key})
        self.logger.debug(f"Delete {key}")

    def create(self, prefix: str) -> str:
        """Find a random and unused key"""
        while True:
            key = prefix + str(uuid.uuid4())
            if not self.get(key):
                break
        return key

if settings.db == "object":
    db_instance = KVData()
elif settings.db == "redis":
    db_instance = RedisDB()
elif settings.db == "dynamodb":
    db_instance = DynamoDB()
else:
    raise ValueError(f"DB type {settings.db} not found")
if settings.mode == "test":
    db_instance.clear()


from db.async_requests import RequestToDjango
from bot.suport_fl.mess import get_lst_spots_from_txt
from suport_fl.set_up import *
import asyncio
import json

def add_spots_to_json():
    total = []
    with open('spot_list.txt') as file:
        for line in file:
            d = {
                "url_forecast": "",
                "url_map": "",
                "city_name": "Kazan",
                "city": 1
            }

            gen = ['description',
                   "url_forecast",
                   "wind_max",
                   'wind_min',
                   "wind_degree_r",
                   "wind_degree_l",
                   "lon",
                   "lat",
                   "name",
                   ]
            try:
                line = get_lst_spots_from_txt(line.rstrip())
                for i in line:
                    name = gen.pop()
                    d[name] = i

                total.append(d)

            except IndexError:
                break

    with open('./spots.json', 'w') as j_file:
        json.dump(total, j_file, indent=6, ensure_ascii=False)

async def push_spots():
    req = RequestToDjango(LOCAL_HOST, OPEN_API_HOST)
    with open('./spots.json', 'r') as file:
        spots = json.load(file)

    for spot in spots:
        spot['city'] = 1

    total = spots

    with open('./spots.json', 'w') as j_file:
        json.dump(total, j_file, indent=6, ensure_ascii=True)

    with open('./spots.json', 'r') as file:
        spots = json.load(file)
        for spot in spots:
            print(await req.post_spots(spot))

if __name__ == '__main__':
    asyncio.run(push_spots())


import numpy as np
import cvxpy
import matplotlib.pyplot as plt
#from DrawingUtils import plot_extreme_points,graph_plane,PlotPolytope
import random as rnd
import time

# Van Der Pol Oscillator
#
# x_{t+1} = y_t \Delta_t + x_t
# y_{t+1} = -[u_t(1-x_t^2)y_t - x_t] \Delta_t + y_t

T = 5
del_t = 0.1

u_min = -1.0
u_max = 1.0

x_up_b = 0.01 + 1
x_lw_b = -0.01 + 1
y_up_b = 0.01
y_lw_b = -0.01

def forwardEulerVP(x0,y0,T,plot=True):

    xs, ys = [x0], [y0]
    x,y = x0, y0
    for t in range(T):
        x, y = y*del_t + x, (-0.5*(u_min+u_max)*(1-x**2)*y - x)*del_t + y
        xs.append(x)
        ys.append(y)

    if plot:
        plt.plot(xs, ys, "*")
    return xs, ys

def McCormick(w,x,y,x_bounds,y_bounds):
    xL,xU = x_bounds
    yL,yU = y_bounds

    c = []
    c.append(w >= xL*y + x*yL - xL*yL)
    c.append(w >= xU*y + x*yU - xU*yU)
    c.append(w <= xU*y + x*yL - xU*yL)
    c.append(w <= x*yU + xL*y - xL*yU)
    return c

Npast = 0
def bounds(x,constraints,Npast=0):

    objective_max = cvxpy.Maximize(x)
    problem_maximum = cvxpy.Problem(objective_max,constraints[-Npast:])
    value_max = problem_maximum.solve(solver=cvxpy.GUROBI)

    objective_min = cvxpy.Minimize(x)
    problem_minimum = cvxpy.Problem(objective_min,constraints[-Npast:])
    value_min = problem_minimum.solve(solver=cvxpy.GUROBI)

    return (value_min,value_max)

def VanDerPolConstraints(T=1,variables=[],constraints=[],control_bounds=[]):

    times = []
    for t in range(T):
        tt = time.time()

        x = variables[t]["x"]
        x_bounds = bounds(x,constraints,Npast=Npast)
        y = variables[t]["y"]
        y_bounds = bounds(y,constraints,Npast=Npast)

        ######### lil plot
        xL,xU = x_bounds
        yL,yU = y_bounds
        plt.figure(1)
        if t>0:
            #plt.clf()
            plt.plot([x_lw_b,x_lw_b,x_up_b,x_up_b,x_lw_b],[y_lw_b,y_up_b,y_up_b,y_lw_b,y_lw_b],'b')
            plt.plot([xL,xL,xU,xU,xL],[yL,yU,yU,yL,yL],'k')
            # print("x_b: ",x_bounds)
            # print("y_b: ",y_bounds)
        plt.pause(1.01)
        ########

        u = variables[t]["u"]
        u_bounds = control_bounds[t]
        constraints.append(u <= u_bounds[1])
        constraints.append(u >= u_bounds[0])

        n = variables[t]["n"]
        constraints.extend(McCormick(n,x,x,x_bounds,x_bounds))

        v = variables[t]["v"]
        constraints.append(v == 1 - n)
        v_bounds = bounds(v,constraints,Npast=Npast)

        w = variables[t]["w"]
        constraints.extend(McCormick(w,y,v,y_bounds,v_bounds))
        w_bounds = bounds(w,constraints,Npast=Npast)

        z = variables[t]["z"]
        constraints.extend(McCormick(z,u,w,u_bounds,w_bounds))

        y_new = variables[t+1]["y"]
        constraints.append(y_new == z*del_t - x*del_t + y)

        x_new = variables[t+1]["x"]
        constraints.append(x_new == y*del_t + x)

        tt = time.time() - tt
        times.append(tt)
        print("Time for ",t,"-th loop: ",tt)

    # plt.figure(2)
    # plt.plot(times,'r*')
    return variables,constraints

variables = [{"u":cvxpy.Variable(),"x":cvxpy.Variable(),"y":cvxpy.Variable(),"z":cvxpy.Variable(),"w":cvxpy.Variable(),"v":cvxpy.Variable(),"n":cvxpy.Variable()} for t in range(T+1)]

plt.figure(1)
plt.plot([x_lw_b,x_lw_b,x_up_b,x_up_b,x_lw_b],[y_lw_b,y_up_b,y_up_b,y_lw_b,y_lw_b],'b')

x = variables[0]["x"]
y = variables[0]["y"]

constraints = []
constraints.append(x >= x_lw_b)
constraints.append(x <= x_up_b)
constraints.append(y >= y_lw_b)
constraints.append(y <= y_up_b)

control_bounds = [(0.2,1.0) for t in range(T)]
#control_bounds = [(2.0,2.5),(2.0,2.5),(2.0,2.5),(2.0,2.5)]

variables,constraints = VanDerPolConstraints(T,variables,constraints,control_bounds)
xL,xU = bounds(variables[-1]["x"],constraints)
yL,yU = bounds(variables[-1]["y"],constraints)

plt.plot([xL,xL,xU,xU,xL],[yL,yU,yU,yL,yL],'r')
forwardEulerVP(1,0,T,True)
plt.pause(1000.0)


def sieve(n):
	lf, pr = [0] * (n + 1), []
	for i in range(2, n + 1):
		if lf[i] == 0:
			lf[i] = i
			pr.append(i)
		j = 0
		while j < len(pr) and pr[j] <= lf[i] and i * pr[j] <= n:
			lf[i * pr[j]] = pr[j]
			j += 1
	return (lf, pr)

lf, pr = sieve(1000000)
ub = max(pr)

ans, prm = 0, -1
for l in range(len(pr)):
	s = 0
	for r in range(l, len(pr)):
		s += pr[r]
		if s > ub:
			break
		if lf[s] == s and r - l + 1 > ans:
			ans, prm = r - l + 1, s
with open('answer.txt', 'w+') as af:
	print(prm, file = af)
	af.close()


# encoding=utf8
import json
import time
from flask import Flask, make_response, request, jsonify, render_template
from flask_cors import CORS
from urllib3 import disable_warnings

from utils import *

disable_warnings()

app = Flask(__name__)
CORS(app, supports_credentials=True, resources="/*")  # 跨域

# 解决与 vue 冲突
app.jinja_env.variable_start_string = '[['
app.jinja_env.variable_end_string = ']]'

def request_parse(req_data: request) -> dict:
    '''解析请求数据并以字典的形式返回'''
    if req_data.method == 'POST':
        data = req_data.form

    elif req_data.method == 'GET':
        data = req_data.args

    return dict(data)

class BaseResponse(BaseModel):
    """返回的响应"""
    status: int = 0  # 状态码 0-->成功 1-->失败
    msg: str = "前端显示的简短信息"
    data: Optional[str]

    @property
    def resp(self):
        '''BaseModel类型返回json'''
        response = make_response(
            json.dumps(
                self.dict(),
                ensure_ascii=False,
                sort_keys=False
            ),
        )
        response.mimetype = 'application/json'
        # 跨域设置
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Methods'] = 'OPTIONS,HEAD,GET,POST'
        response.headers['Access-Control-Allow-Headers'] = 'x-requested-with'
        return response

@app.route("/", methods=['GET'])
def index():
    return render_template('admin.html')

@app.route("/testapi/", methods=['POST'])
@logger.catch
def testapi():
    brs = BaseResponse()
    # 需要传入 json 数据
    try:
        jsonData = request.get_json()
        api = API(**jsonData)
        phone = jsonData.get('phone')
        if not phone:
            raise ValueError("参数 phone 没有！")
        try:
            resp = test_resq(api, phone)
            brs.status = 0
            brs.msg = f"请求成功！{resp}"
            brs.data = resp.text
        except Exception as why:
            brs.status = 1
            brs.msg = f"请求失败：{why}"
    except Exception as why:
        brs.status = 1
        brs.msg = f"参数有误：{why}"
    return brs.resp

@app.route("/submitapi/", methods=['POST'])
def submitapi():
    """提交API到json文件"""
    # 需要传入 json 数据
    jsonData = request.get_json()
    api = API(**jsonData).handle_API()
    data = json.loads(json_path.read_text(encoding='utf8'))
    with open(json_path, mode="w", encoding="utf8") as j:
        try:
            data.append(api.dict())
            json.dump(data, j, ensure_ascii=False, sort_keys=False)
            return BaseResponse(status=0, msg="写入成功!").resp
        except Exception as why:
            return BaseResponse(status=1, msg=f"写入失败!{why}").resp

@app.route("/backapi/", methods=['GET', 'POST'])
def backjson():
    """备份json文件"""
    try:
        timeStruct = time.localtime(int(time.time()))
        strTime = time.strftime("%Y_%m_%d_%H_%M_%S", timeStruct)
        Path(json_path.parent, 'apiback').mkdir(exist_ok=True)
        json_back_path = Path(json_path.parent, 'apiback',
                              f"api_back_{strTime}.json")
        with open(json_back_path, mode="w") as j:
            j_data = json.loads(json_path.read_text(encoding='utf8'))
            json.dump(j_data, j, ensure_ascii=False, sort_keys=False)
        return BaseResponse(status=0, msg="备份成功!").resp
    except Exception as why:
        return BaseResponse(status=1, msg=f"备份失败{why}").resp

@app.route("/downloadapi/", methods=['GET'])
def downloadapi():
    """下载接口文件"""
    return json_path.read_text(encoding='utf8')

app.run(host="0.0.0.0", port=10981, debug=True)


from datetime import datetime, timedelta

from vk_bot import VkBot
import threading
import schedule
import time
from news_adding import set_news_data
from crawlers import SPbSUCrawler, ITMOCrawler, PolitehCrawler

vk_bot = VkBot()

def vk_start():
    vk_bot.run()

def set_new_news_to_database():
    start_date = datetime.today() - timedelta(days=1)
    set_news_data(vk_bot, SPbSUCrawler, start_date, "СПбГУ")
    set_news_data(vk_bot, ITMOCrawler, start_date, "ИТМО")
    set_news_data(vk_bot, PolitehCrawler, start_date, "Политех")

def send_news():
    current_datetime = datetime.today() + timedelta(hours=1)
    possible_sending_time = [
        current_datetime.strftime('M-%d-%H'),
        current_datetime.strftime('W-%u-%H'),
        current_datetime.strftime('%H')
    ]

    users = vk_bot.db.get_subscribed_users_to_send_news(possible_sending_time, current_datetime.date())
    for user in users:
        news = vk_bot.db.get_news(user.universities, user.last_sending_date, user.topics)
        vk_bot.send_news_out_of_state_handling(user.vk_id, news)

def start_schedule():
    schedule.every().hour.at(":00").do(send_news)
    schedule.every().hour.at(":30").do(set_new_news_to_database)
    while True:
        schedule.run_pending()
        time.sleep(30)

thread_for_schedule = threading.Thread(target=start_schedule)
thread_for_schedule.start()

thread_for_bot = threading.Thread(target=vk_start)
thread_for_bot.start()


#!/usr/bin/python3
def add_tuple(tuple_a=(), tuple_b=()):
    length1 = len(tuple_a)
    length2 = len(tuple_b)
    tuple1 = tuple_a
    tuple2 = tuple_b
    tuple = ()
    if length1 == 1:
        tuple1 += 0,
    elif length1 == 0:
        tuple1 = (0, 0)
    if length2 == 1:
        tuple2 += 0,
    elif length2 == 0:
        tuple2 = (0, 0)
    for i in range(2):
        tuple += (tuple1[i] + tuple2[i]),
    return tuple


# Author : Arjo Ghosh আর্য্য ঘোষ

import requests
from bs4 import BeautifulSoup
x=input("Search a term : ")
x=x.replace("What do you mean by","")
x=x.replace("Define","")
x=x.replace("?","")
x=x.replace(".","")
x=x.strip()
x=x.lower()
r = requests.get("http://www.oxforddictionaries.com/definition/english/"+x)
html=r.content
bsObj = BeautifulSoup(html,"html.parser")
bsObj = bsObj.select('div.senseInnerWrapper span.definition')
for link in bsObj:
    m=link.get_text()
    m=m[:-1]
    print(m+'.')
    break


from random import randint

import pygame

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 560

class MainGame:
    zombie_list = []
    bullets = []
    maps_list = []
    plant_list = []
    points_list = []
    money = 200
    remnant_score = 100
    score = 0
    level = 1
    screen = None
    clock = pygame.time.Clock()
    zombie_counter = 0
    zombie_distance = 100

    def __init__(self):
        # 设定窗口的大小
        pygame.display.init()
        MainGame.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        # 显示帮助文字
        self.init_points_list()
        self.init_maps_list()
        self.produce_zombie()

        while True:
            MainGame.clock.tick(240)
            self.handle_events()
            MainGame.screen.fill((255, 255, 255))
            self.load_maps_list()
            self.load_plant_list()
            # 每次都要重新绘制
            self.load_help_text()
            self.load_bullets()
            self.load_zombie_list()
            MainGame.zombie_counter += 1
            if MainGame.zombie_counter == MainGame.zombie_distance:
                self.produce_zombie()
                MainGame.zombie_counter = 0
            pygame.display.update()

    # font_style 需要通过元组(name, size, color)的形式传入
    # 我们需要得到一个已经加工好的 Surface 文本
    @staticmethod
    def text_render(content, font_style):
        (name, size, color) = font_style
        pygame.font.init()
        font = pygame.font.SysFont(name, size)
        text = font.render(content, True, color)
        return text

    def load_help_text(self):
        name = "Microsoft YaHei UI"
        size = 26
        color = (255, 0, 0)
        text = self.text_render("1.左键种植向日葵，2.右键种植豌豆射手", (name, size, color))
        MainGame.screen.blit(text, (5, 0))
        text = self.text_render(
            "当前关数：{}， 当前得分：{}，距离下关还差：{}，金钱：{}".format(
                MainGame.level, MainGame.score, MainGame.remnant_score, MainGame.money
            ), (name, size, color)
        )
        MainGame.screen.blit(text, (5, 40))

    @staticmethod
    def init_points_list():
        for top in range(1, 7):
            points = []
            for left in range(10):
                points.append((left, top))
            MainGame.points_list.append(points)
            print(points)

    @staticmethod
    def init_maps_list():
        # 通过坐标点的二维列表得到二维的所以地图
        for points in MainGame.points_list:
            maps = []
            for point in points:
                (left, top) = point
                # 通过坐标点生成地图实例
                m = Map(left, top)
                maps.append(m)
            MainGame.maps_list.append(maps)

    @staticmethod
    def load_maps_list():
        for maps in MainGame.maps_list:
            for m in maps:
                m.display()

    @staticmethod
    def handle_events():
        event_list = pygame.event.get()
        for e in event_list:
            if e.type == pygame.MOUSEBUTTONDOWN:
                print(e.pos)
                (left, top) = e.pos
                left = left // 80
                top = top // 80
                if top == 0:
                    continue
                m = MainGame.maps_list[top - 1][left]
                if m.can_grow:
                    if e.button == pygame.BUTTON_LEFT:
                        plant = SunFlower(left * 80, top * 80)
                        m.can_grow = False
                        MainGame.plant_list.append(plant)
                        print("种植向日葵")
                        pass
                    elif e.button == pygame.BUTTON_RIGHT:
                        plant = PeaShooter(left * 80, top * 80)
                        m.can_grow = False
                        MainGame.plant_list.append(plant)
                        print("种植豌豆射手")
                        pass

    @staticmethod
    def load_plant_list():
        for plant in MainGame.plant_list:
            # 如果植物活着
            if plant.live:
                if isinstance(plant, SunFlower):
                    plant.produce_money()
                elif isinstance(plant, PeaShooter):
                    # 发射子弹
                    plant.shot()
                plant.display()
            else:
                MainGame.plant_list.remove(plant)

    @staticmethod
    def load_bullets():
        for bullet in MainGame.bullets:
            if bullet.live:
                bullet.display()
                bullet.move()
                bullet.hit_zombie()
            else:
                MainGame.bullets.remove(bullet)

    @staticmethod
    def produce_zombie():
        for i in range(1, 7):
            left = randint(1, 5) * 200 + 800
            top = i * 80
            zombie = Zombie(left, top)
            MainGame.zombie_list.append(zombie)

    @staticmethod
    def load_zombie_list():
        for zombie in MainGame.zombie_list:
            if isinstance(zombie, Zombie):
                if zombie.live:
                    zombie.display()
                    zombie.move()
                    zombie.hit_plant()
                else:
                    MainGame.zombie_list.remove(zombie)

class Map:
    def __init__(self, left, top):
        #
        index = (left + top) % 2 + 1
        self.image = pygame.image.load('imgs/map{}.png'.format(index))
        self.position = (left * 80, top * 80)
        self.can_grow = True

    def display(self):
        MainGame.screen.blit(self.image, self.position)

class Plant(pygame.sprite.Sprite):
    def __init__(self, left, top, image):
        super(Plant, self).__init__()
        self.image = pygame.image.load(image)
        self.rect = self.image.get_rect()
        self.rect.left = left
        self.rect.top = top
        self.live = True
        self.price = 50
        self.hp = 200

    def display(self):
        MainGame.screen.blit(self.image, self.rect)

class SunFlower(Plant):
    def __init__(self, left, top):
        super(SunFlower, self).__init__(left, top, 'imgs/sun-flower.png')
        self.time_counter = 0

    def produce_money(self):
        if self.live:
            self.time_counter += 1
            if self.time_counter == 25:
                MainGame.money += 5
                self.time_counter = 0

class PeaShooter(Plant):
    def __init__(self, left, top):
        super(PeaShooter, self).__init__(left, top, 'imgs/pea-shooter.png')
        self.time_counter = 0

    def shot(self):
        self.time_counter += 1
        # 遍历僵尸列表查看该行是否有僵尸存在
        should_shot = False
        for zombie in MainGame.zombie_list:
            if zombie.rect.top == self.rect.top and self.rect.left < zombie.rect.left < 800:
                should_shot = True

        if self.live and should_shot:
            if self.time_counter == 25:
                # 生成子弹
                bullet = PeaShooterBullet(self)
                # 加入到列表中
                MainGame.bullets.append(bullet)
                self.time_counter = 0

# 定义豌豆射手子弹
class PeaShooterBullet(pygame.sprite.Sprite):
    def __init__(self, pea_shooter: PeaShooter):
        super(PeaShooterBullet, self).__init__()
        self.image = pygame.image.load('imgs/pea-bullet.png')
        self.rect = self.image.get_rect()
        self.rect.left = pea_shooter.rect.left + 40
        self.rect.top = pea_shooter.rect.top + 20
        self.speed = 10
        self.damage = 100
        self.live = True

    def move(self):
        if self.rect.left < SCREEN_WIDTH:
            self.rect = self.rect.move(self.speed, 0)
        else:
            self.live = False

    def hit_zombie(self):
        for zombie in MainGame.zombie_list:
            # 判断是否碰到僵尸
            if pygame.sprite.collide_rect(self, zombie):
                # 减少僵尸的血量
                zombie.hp -= self.damage
                # 把子弹删除掉
                self.live = False
                if zombie.hp <= 0:
                    # 把僵尸的状态设置为死亡，等待 load_zombie_list 中删除僵尸
                    zombie.live = False
                    self.next_level()

    @staticmethod
    def next_level():
        MainGame.score += 20
        MainGame.remnant_score -= 20
        for i in range(1, 100):
            if MainGame.score == i * 100 and MainGame.remnant_score == 0:
                MainGame.remnant_score = 100 * i
                MainGame.level += 1
                MainGame.zombie_distance -= 2

    def display(self):
        MainGame.screen.blit(self.image, self.rect)

class Zombie(pygame.sprite.Sprite):
    # Surface # Rect
    def __init__(self, left, top):
        super(Zombie, self).__init__()
        self.live = True
        self.image = pygame.image.load('./imgs/zombie.png')
        self.rect = self.image.get_rect()
        self.rect.left = left
        self.rect.top = top
        self.can_move = True
        # 伤害
        self.damage = 20
        self.hp = 1000
        self.speed = 1

    # 僵尸移动
    def move(self):
        if self.can_move:
            self.rect = self.rect.move(self.speed * -1, 0)
            # todo: 到最左边就要结束游戏

    # 碰撞植物
    def hit_plant(self):
        for plant in MainGame.plant_list:
            if pygame.sprite.collide_rect(self, plant):
                self.can_move = False
                # todo: 调整吃的速度
                self.eat_plant(plant)

    def display(self):
        MainGame.screen.blit(self.image, self.rect)

    # 吃植物
    def eat_plant(self, plant):
        plant.hp -= self.damage
        print(plant.hp)
        if plant.hp <= 0:
            self.can_move = True
            left = plant.rect.left // 80
            top = plant.rect.top // 80
            m = MainGame.maps_list[top - 1][left]
            m.can_grow = True
            plant.live = False

if __name__ == '__main__':
    game = MainGame()


"""
17198 - Bucket Brigade

1. 아이디어
2. 시간복잡도
3. 자료구조
"""

import sys
from collections import deque
input = sys.stdin.readline

graph = [input().strip() for _ in range(10)]
dist = [[-1] * 10 for _ in range(10)]
dxy = [(1, 0), (0, 1), (-1, 0), (0, -1)]

def bfs(x, y):
    q = deque()
    q.append((x, y))
    dist[x][y] = 0
    while q:
        x, y = q.popleft()
        for dx, dy in dxy:
            nx, ny = x + dx, y + dy
            if nx < 0 or nx >= 10 or ny < 0 or ny >= 10:
                continue
            if dist[nx][ny] != -1:
                continue
            if graph[nx][ny] == 'R':
                continue
            if graph[nx][ny] == 'B':
                return dist[x][y]
            q.append((nx, ny))
            dist[nx][ny] = dist[x][y] + 1

for i in range(10):
    for j in range(10):
        if graph[i][j] == 'L':
            print(bfs(i, j))


# These functions are the suggested payoff_functions. That is, they
# calculate how much fitness a agent should  get/lose by
# playing a prisoners dilemma with another agent. They are
# the default payoff functions, but in the Tournament instance you
# could specify to use other functions.

def selfreward(agent):
    '''calculates how much reward a agent gets from its own internal market'''
    return agent.m

def reward(agent, other):
    '''calculates how much reward would change fitness'''
    return round((agent.d + agent.r) * other.m + (agent.w * agent.m), 2)

def temptation(agent, other):
    '''calculates how much temptation would change fitness'''
    return round((agent.d + 2 * agent.r) * other.m + (agent.w * agent.m), 2)

def sucker(agent, other):
    '''calculates how much sucker would change fitness'''
    return round(agent.w * agent.m, 2)

def punishment(agent, other):
    '''calculates how much punishment would chage fitness'''
    return round(agent.r * other.m + agent.w * agent.m, 2)

default_payoff_functions = {
        'R': reward,
        'T': temptation,
        'S': sucker,
        'P': punishment,
        'self_reward': selfreward
        }

traditional_payoff_functions = {
        'R': lambda *args: 3,
        'T': lambda *args: 5,
        'S': lambda *args: 0,
        'P': lambda *args: 1
        }

game_types = {

    "norm_mdr_max": {'M': [5, 12.5],
                        'D': [0.4, 1.25],
                        'R': [0.3, 1.25]},

    "norm_dr_max": {'M': [5, 1/10000],
                       'D': [0.4, 1.25],
                       'R': [0.3, 1.25]},

    "norm_m_max": {'M': [5, 12.5],
                   'D': [0.4, 1/10000],
                   'R': [0.3, 1/10000]},

    "pareto_mdr_max": {'M': ["power", 2.5, 1],
                       'D': ["power", 0.15, 1],
                       'R': ["power", 0.2, 1]},

    "pareto_dr_max": {'M': [5, 1/10000],
                      'D': ["power", 0.15, 1],
                      'R': ["power", 0.2, 1]},

    "pareto_m_max": {'M': ["power", 2.5, 1],
                     'D': [0.4, 1/10000],
                     'R': [0.3, 1/10000]},

    "homogenous": {'M': [5, 1/10000],
                   'D': [0.4, 1/10000],
                   'R': [0.3, 1/10000]}
}