"""Utility functions for SLaQ"""
import numpy as np
from igraph import Graph
import scipy.sparse
from scipy.sparse.base import spmatrix

def laplacian(adjacency, normalized = True):
    """Computes the sparse Laplacian matrix given sparse adjacency matrix as input.

    Args:
        adjacency (spmatrix): Input adjacency matrix of a graph.
        normalized (bool): If True, return the normalized version of the Laplacian.

    Returns:
        spmatrix: Sparse Laplacian matrix of the graph.
    """
    degree = np.squeeze(np.asarray(adjacency.sum(axis=1)))
    if not normalized:
        return scipy.sparse.diags(degree) - adjacency
    with np.errstate(divide='ignore'): # Ignore the warning for divide by 0 case.
        degree = 1. / np.sqrt(degree)
    degree[degree == np.inf] = 0
    degree = scipy.sparse.diags(degree)
    return scipy.sparse.eye(adjacency.shape[0], dtype=np.float32) - degree @ adjacency @ degree

def get_adjacency(graph):
    vcount = graph.vcount()
    adjacency = scipy.sparse.dok_matrix((vcount, vcount), dtype=np.float32)
    for e in graph.get_edgelist():
        adjacency[e[0], e[1]] = 1
        adjacency[e[1], e[0]] = 1
    # Convert to the compressed sparse row format for efficiency.
    adjacency = adjacency.tocsr()
    adjacency.data = np.ones(adjacency.data.shape, dtype=np.float32) # Set all elements to one in case of duplicate rows.

    return adjacency


import copy
from collections import deque

n,m = map(int,input().split())
arr = [list(map(int,input().split())) for _ in range(n)]
res = 0
visited = [[False] * m for _ in range(n)]
dy = [1,-1,0,0]
dx = [0,0,1,-1]
max_value = max(map(max,arr))

def dfs(y,x,ans,cnt):
    global res
    #만약 남은 블록을 다 최대값으로 더해도 현재 최대값보다 작으면 걍 조기 종료
    #이런 조기 종료 규칙이 진심 시간 복잡도 확 줄여줌..
    if res >= ans + max_value * (4-cnt) :
        return
    if cnt == 4 :
        res = max(res,ans)
        return

    else :
        for i in range(4):
            ny = y + dy[i]
            nx = x + dx[i]

            if 0<= ny < n and 0<= nx < m and not visited[ny][nx] :

                if cnt == 2 :
                    # ㅗ 모양 체크
                    visited[ny][nx] = True
                    dfs(y,x,ans+arr[ny][nx],cnt+1)
                    visited[ny][nx] = False
                #나머지 모든 모양 체크
                visited[ny][nx] = True
                dfs(ny,nx,ans+arr[ny][nx],cnt+1)
                visited[ny][nx] = False

for i in range(n):
    for j in range(m):
        visited[i][j] = True
        dfs(i,j,arr[i][j],1)
        visited[i][j] = False

print(res)

# long_dy = [3,0]
# long_dx = [0,3]
# visited = [[False] * m for _ in range(n)]
# res = 0

# def long_check(visited_original):
#     global res
#     visited = copy.deepcopy(visited_original)
#     q = deque([])
#     q.append([0,0])

#     while q :
#         y,x = q.popleft()
#         visited[y][x] = True

#         for i in range(2):
#             ny = y + long_dy[i]
#             nx = x + long_dx[i]

#             if 0<=ny<n and 0<=nx<m :
#                 tmp = 0
#                 if i == 0 :
#                     tmp += arr[y][nx]
#                     tmp += arr[y+1][nx]
#                     tmp += arr[y+2][nx]
#                     tmp += arr[y+3][nx]
#                 else :
#                     tmp += arr[ny][x]
#                     tmp += arr[ny][x+1]
#                     tmp += arr[ny][x+2]
#                     tmp += arr[ny][x+3]
#                 res = max(res,tmp)

#                 if x == m-1 :
#                     q.append([y+1,0])
#                 else :
#                     q.append([y,x+1])

# long_check(visited)
# print(res)

삼성 기출/[진짜 어려움]14500 테트로미노.py

[진짜 어려움]14500 테트로미노.py


import sys

from queue import Queue
from PIL import Image
from convertImage import *

import pylab
import matplotlib.pyplot as plt
import matplotlib.pyplot as mplt
import numpy as np

#almostEqual for pixels
def almostEqual(x,y,epsilon=3):
    return abs(x[0]-y[0])<epsilon and abs(x[1]-y[1])<epsilon

##Input Start/Out Mode
#returns (start,end)
def readStartEnd(imageName):
    x1 = mplt.imread(imageName)
    fig1 = pylab.figure(1, figsize=(11,9))
    ax1 = fig1.add_subplot(1,1,1)
    ax1.imshow(x1)
    ax1.axis('image')
    ax1.axis('off')
    print("Click start and end coords")
    x = fig1.ginput(2)
    print("click the top left and bottom right corner")
    y = fig1.ginput(2)
    XBounds = (y[0][0],y[1][0])
    YBounds = (y[0][1],y[1][1])
    mplt.close(fig1)

    return(x[0],x[1],XBounds,YBounds)

#BFS general structure is taken from
#http://stackoverflow.com/questions/12995434/representing-and-solving-a-maze-given-an-image
#Modified from...

def BFS(start, end, pixels, XBounds, YBounds):
    lowXBound,highXBound = XBounds
    lowYBound,highYBound = YBounds

    def getAdjacent(n,step = 1):
        x,y = n
        return [(x-step,y),(x,y-step),(x+step,y),(x,y+step)] #ENWS

    def isLegal(pixels,x,y):
        nonlocal lowXBound,highXBound,lowYBound,highYBound
        R,B,G = pixels[x,y]
        t = 200
        if ((x < lowXBound) or (x > highXBound) or
        (y < lowYBound) or (y > highYBound) or
        R<t):
            return False # off-board!
        else: return True

    queue = Queue()
    queue.put([start]) # Wrapping the start tuple in a list

    while not queue.empty():

        path = queue.get()
        pixel = path[-1]
        #print(pixel,end = '  ')

        #if pixel == end:
        if almostEqual(pixel,end):
            return path

        #loop through all directions by factor of step
        for adjacent in getAdjacent(pixel,step=2):
            x,y = adjacent
            if isLegal(pixels,x,y):
                pixels[x,y] = (127,127,127) # see note
                new_path = list(path)
                new_path.append(adjacent)
                queue.put(new_path)
    print ("Queue has been exhausted. No answer was found.")

if __name__ == '__main__':

    mazeFile = "maze4.jpg"

    start,end,XBounds,YBounds = readStartEnd(mazeFile)

    base_img = Image.open(mazeFile)
    base_pixels = base_img.load()

    convertFromRGBToBW2(base_pixels,base_img)

    path = BFS(start, end, base_pixels, XBounds, YBounds)

    path_img = Image.open(mazeFile)
    path_pixels = path_img.load()

    for position in path:
        x,y = position
        path_pixels[x,y] = (255,0,0) # red

    path_img.show()


import lib
import logging
import sys

class LocalAccountReport(object):
    def __init__(self):
        self.config = lib.ConfigHelper()
        self.server = lib.ServerController()
        self.dict = lib.DictController(self.config)
        self.csv_writer = lib.CsvWriter(self.config)
        self.csv_columns = self.config.csv_columns

    def get_servers(self, args):
        return self.server.list_servers_under_group(args)

    def run(self, servers):
        for server in servers:
            accounts = self.server.list_local_accounts(server["id"])
            for account in accounts:
                data = self.dict.build_dict(account, server["id"])
                self.csv_writer.write(self.csv_columns.values(), data)
def main():
    sys.stdout.write("start retreiving server information")
    report = LocalAccountReport()

    args = report.config.argparse()

    servers = report.get_servers(args)

    report.run(servers)
    sys.stdout.write("finish writing out report")

if __name__ == "__main__":
    sys.stdout = lib.Logger(logging.info)
    sys.stderr = lib.Logger(logging.warning)
    main()


import pytest

from alarm_backends.core.cache.strategy import StrategyCacheManager
from constants.data_source import DataSourceLabel

pytestmark = pytest.mark.django_db

item = {
    "query_configs": [
        {
            "agg_method": "AVG",
            "agg_dimension": ["ip", "bk_cloud_id"],
            "agg_condition": [
                {"value": "0", "method": "eq", "key": "bk_cloud_id"},
                {"value": "10.0.1.11", "key": "bk_target_ip", "condition": "or", "method": "eq"},
            ],
            "agg_interval": 60,
            "metric_field": "usage",
            "result_table_id": "system.cpu_summary",
            "unit": "%",
            "metric_id": "system.cpu_summary.usage",
            "data_source_label": "bk_monitor",
            "data_type_label": "time_series",
        }
    ],
    "algorithms": [
        {
            "config": [{"threshold": 90, "method": "gte"}],
            "level": 1,
            "type": "Threshold",
        }
    ],
    "id": 6,
    "no_data_config": {"is_enabled": False, "continuous": 5},
    "name": "usage",
}

class TestStrategyGroup(object):
    def test_query_config_md5(self):
        query_md5 = StrategyCacheManager.get_query_md5(2, item)
        assert query_md5 == "4ca8defa2aed29a8371e665b610a2044"
        item["query_configs"][0]["agg_condition"] = [
            {"value": "10.0.1.11", "key": "bk_target_ip", "method": "eq"},
            {"value": "0", "method": "eq", "key": "bk_cloud_id", "condition": "or"},
        ]
        query_md5 = StrategyCacheManager.get_query_md5(2, item)
        assert query_md5 == "6e2170c2323fb98bdb9c31f6416cfd9e"

        item["query_configs"][0]["agg_condition"] = []
        empty_condition_query_md5 = StrategyCacheManager.get_query_md5(2, item)

        # 条件包含正则等高级方法时的查询md5
        item["query_configs"][0]["agg_condition"] = [{"value": "10.0.1.11", "key": "bk_target_ip", "method": "reg"}]
        query_md5 = StrategyCacheManager.get_query_md5(2, item)
        assert empty_condition_query_md5 != query_md5

        item["query_configs"][0]["data_source_label"] = DataSourceLabel.BK_DATA

        item["query_configs"][0]["agg_condition"] = []
        empty_condition_query_md5 = StrategyCacheManager.get_query_md5(2, item)

        item["query_configs"][0]["agg_condition"] = [{"value": "10.0.1.11", "key": "bk_target_ip", "method": "reg"}]
        query_md5 = StrategyCacheManager.get_query_md5(2, item)
        assert empty_condition_query_md5 == query_md5

    def test_cache(self):
        pass


def _mapPotential(self, index):
    """
    Maps a column to its input bits. This method encapsulates the topology of
    the region. It takes the index of the column as an argument and determines
    what are the indices of the input vector that are located within the
    column's potential pool. The return value is a list containing the indices
    of the input bits. The current implementation of the base class only
    supports a 1 dimensional topology of columns with a 1 dimensional topology
    of inputs. To extend this class to support 2-D topology you will need to
    override this method. Examples of the expected output of this method:
    * If the potentialRadius is greater than or equal to the largest input
      dimension then each column connects to all of the inputs.
    * If the topology is one dimensional, the input space is divided up evenly
      among the columns and each column is centered over its share of the
      inputs.  If the potentialRadius is 5, then each column connects to the
      input it is centered above as well as the 5 inputs to the left of that
      input and the five inputs to the right of that input, wrapping around if
      wrapAround=True.
    * If the topology is two dimensional, the input space is again divided up
      evenly among the columns and each column is centered above its share of
      the inputs.  If the potentialRadius is 5, the column connects to a square
      that has 11 inputs on a side and is centered on the input that the column
      is centered above.

    Parameters:
    ----------------------------
    :param index:   The index identifying a column in the permanence, potential
                    and connectivity matrices.
    """

    centerInput = self._mapColumn(index)
    columnInputs = self._getInputNeighborhood(centerInput).astype(uintType)

    # Select a subset of the receptive field to serve as the
    # the potential pool
    numPotential = int(columnInputs.size * self._potentialPct + 0.5)
    selectedInputs = numpy.empty(numPotential, dtype=uintType)
    self._random.sample(columnInputs, selectedInputs)

    potential = numpy.zeros(self._numInputs, dtype=uintType)
    potential[selectedInputs] = 1

    return potential


import Globals as gb
import os
all_projectiles = []
class Projectile():
    def __init__(self, image, x, y, direction):
        self.setup(image)
        self.pic = image
        self.rect = self.image.get_rect()
        self.direction = direction
        self.speed = 15
        all_projectiles.append(self)
        self.rect.x = x
        self.rect.y = y
        self.flying = False

    def setup(self, image):
        img_file = os.path.join('img', image)
        self.image = gb.pygame.image.load(img_file)

def Update():

    if all_projectiles:
        for pro in all_projectiles:
            gb.maps.checkCollisions(pro, "projectile")
            if pro.direction == "left":
                pro.rect.x -= pro.speed
            if pro.direction == "right":
                pro.rect.x += pro.speed
            if pro.direction == "up":
                pro.rect.y -= pro.speed
            if pro.direction == "down":
                pro.rect.y += pro.speed
def Render():
    for pro in all_projectiles:

        gb.window.screen.blit(pro.image, (pro.rect.x - gb.cam.rect.x,
            pro.rect.y - gb.cam.rect.y))


from chunk import *
import probabilityhelpers as ph
import rhythmhelpers as rhy
import random
from constants import *
import music21helpers as mh
import scale as sc
import preferences as pref

p_cell_dict = {}
p_cell_dict['scalewise'] = 0.2
p_cell_dict['usual'] = 0.3
p_cell_dict['chordal'] = 0.5

#generate scalewise cells
def genScalewiseCell(length, prev_note = 0, first_note = None, chord = [], durs = [], key = 0):
    if durs == []:
        rhythm = rhy.randomDuration(length)
    else:
        rhythm = durs
    direction = 1
    if first_note != None:
        pitches = [first_note]
    elif prev_note % 7 == 6 and chord == [0,2,4]:
        pitches = [prev_note + 1]
    elif prev_note % 7 == 3 and chord == [0,2,4]:
        pitches = [prev_note - 1]
    else:
        if chord == []:
            pitches = [prev_note + random.choice([1,-1])]
        else:
            pitches = [sc.closestNoteDegreeInChord(prev_note, chord, True, 0)]
    if rhythm[0] < 0:
        pitches.append(sc.closestNoteDegreeInChord(prev_note, chord, True, 0))
        i_continue = 2
    else:
        i_continue = 1
    for i in range(i_continue, len(rhythm)):
        if pitches[-1] % 7 == 6 and chord == [0,2,4]:
            pitches.append(pitches[-1] + 1)
        elif pitches[-1] % 7 == 3 and chord == [0,2,4]:
            pitches.append(pitches[-1] - 1)
        else:
            direction = direction if random.uniform(0,1) < 0.7 else direction * -1
            if pitches[i - 1] > 14:
                direction = -1
            elif pitches[i - 1] < 0:
                direction = 1
            pitches.append(pitches[i - 1] + direction)
    return_val = Chunk(pits=pitches, durs=rhythm, chord=chord, key=key)
    if pref.goodCell(return_val) or random.uniform(0,1) < 0.05:
        return return_val
    else:
        return genScalewiseCell(length, prev_note, first_note, chord, durs)

#get random next degree
def randomNextDegree(prev_note, up_down):
    if prev_note <= 0:
        up_down = 1
    direction = up_down if random.uniform(0,1) < 0.63 else up_down * -1
    new_note = prev_note + 1*direction
    return new_note

#gen next chord note up or down a certain amount
def getNthChordNote(prev_note, cord, up_down, how_many):
    n = 0
    if n == 0:
        prev_note = sc.closestNoteDegreeInChord(prev_note, cord, True, up_down)
    elif prev_note <= 0:
        up_down == 1
    while n < how_many:
        prev_note += up_down
        if prev_note % 7 in [i % 7 for i in cord]:
            n += 1
    return prev_note

#get a random chord note
def randomChordNote(prev_note, cord, per_up = '0.5', sixteenth = False):
    """if sixteenth:
        how_many = 1
    else:
        how_many = ph.probDictToChoice({0:0.1, 1:0.9})"""
    how_many = 1
    upOrDown = 1 if random.uniform(0,1) < per_up else -1
    if prev_note <= -3:
        how_many = 2
    if prev_note <= 0:
        upOrDown = 1
    if prev_note > 10:
        upOrDown = -1
    if getNthChordNote(prev_note, cord, upOrDown, how_many) == prev_note:
        print('in')
    return getNthChordNote(prev_note, cord, upOrDown, how_many)

#generate chordal cells
def genChordalCell(length, prev_note = 0, first_note = None, cord = [], durs = [], key = 0):
    pitches = []
    def strToNum(string):
        return [int(i) for i in string.split()]
    if cord == []:
        cord = strToNum(ph.probDictToChoice({'0 2 4':0.5, '4 6 8':0.3, '3 5 7':0.2}))
    if durs == []:
        durs = rhy.randomDuration(length)
    if first_note != None:
        pitches = [first_note]
    elif prev_note % 7 == 6 and cord == [0,2,4]:
        pitches = [prev_note + 1]
    elif prev_note % 7 == 3 and cord == [0,2,4]:
        pitches = [prev_note - 1]
    else:
        pitches = [sc.closestNoteDegreeInChord(prev_note, cord, 1, False)]
    for i in range(1, len(durs)):
        pitches.append(randomChordNote(pitches[-1], cord, durs[i] == 0.25))
    return Chunk(pits=pitches, durs=durs, chord=cord, key = key)

#generate usual cells
def genUsualCell(length, prev_note = 0, first_note = None, cord = [], durs = [], key=0):
    pitches = []
    def strToNum(string):
        return [int(i) for i in string.split()]
    if cord == []:
        cord = strToNum(ph.probDictToChoice({'0 2 4':0.5, '4 6 8':0.3, '3 5 7':0.2}))
    if durs == []:
        durs = rhy.randomDuration(length)
    if first_note != None:
        pitches = [first_note]
    elif prev_note % 7 == 6 and cord == [0,2,4]:
        pitches = [prev_note + 1]
    elif prev_note % 7 == 3 and cord == [0,2,4]:
        pitches = [prev_note - 1]
    else:
        pitches = [sc.closestNoteDegreeInChord(prev_note, cord, 1, False)]
    if durs[0] < 0:
        pitches.append(sc.closestNoteDegreeInChord(prev_note, cord, 1, False))
        i_continue = 2
    else:
        i_continue = 1
    tot_durs = [sum(durs[:i]) for i in range(0, len(durs))]
    for i in range(i_continue, len(durs)):
        if tot_durs[i] % 1.0 == 0:
            if prev_note not in cord:
                pitches.append(sc.closestNoteDegreeInChord(prev_note, cord, True))
            else:
                pitches.append(randomChordNote(prev_note, cord))
        elif random.uniform(0,1) < 0.5:
            if prev_note not in cord:
                pitches.append(sc.closestNoteDegreeInChord(prev_note, cord, True))
            else:
                pitches.append(randomChordNote(prev_note, cord))
        else:
            pitches.append(randomNextDegree(prev_note, 1))
        prev_note = pitches[-1]
    return_val = Chunk(pitches, durs, chord=cord, key=key)
    if pref.goodCell(return_val) or random.uniform(0,1) < 0.05:
        return return_val
    else:
        return genUsualCell(length, prev_note, first_note, cord, durs)

def genProcessCell(prev_note = 0, first_note = None, chord = [0,2,4], key = 0):
    if first_note == None:
        pitches = [sc.closestNoteDegreeInChord(prev_note, chord=chord)]
    durs = rhy.strToRhy(ph.probDictToChoice({'0.5 0.25 0.25':0.1, '0.25 0.25 0.5':0.1, '0.5 0.5':0.5, '0.25 0.25 0.25 0.25':0.1}))

#get any type of cell
def genCell(length, prev_note = 0, first_note = None, chord = [], durs = [], cell_type = None, key=0):
    if cell_type == None:
        cell_type = ph.probDictToChoice(p_cell_dict)
    if cell_type == 'scalewise':
        return genScalewiseCell(length, prev_note, first_note, chord, durs, key)
    elif cell_type == 'chordal':
        return genChordalCell(length, prev_note, first_note, chord, durs, key)
    else:
        return genUsualCell(length, prev_note, first_note, chord, durs, key)

#create a resting cell
def genBlankCell(length):
    return Chunk(pits = [-36], durs = [-1*length])


# LeetCode 581. Shortest Unsorted Continuous Subarray `M`
# acc | 98% | 70'
# A~0g03

class Solution:
    def findUnsortedSubarray(self, nums: List[int]) -> int:
        i, j = 0, len(nums) - 1
        while i < j and nums[i] <= nums[i+1]:
            i += 1
        while i < j and nums[j-1] <= nums[j]:
            j -= 1

        if i == j:
            return 0

        minval = min(nums[i:j+1])
        maxval = max(nums[i:j+1])
        while j < len(nums) and nums[j] < maxval:
            j += 1
        while i >= 0 and nums[i] > minval:
            i -= 1
        return j - i - 1


# pyre-strict
# misc utility functions...

import sys
import os
import json
import logging
import signal
import threading
import time
import fcntl
import shutil
import hashlib
import uuid
from time import sleep
from datetime import datetime
from contextlib import contextmanager, AbstractContextManager
from typing import (
    Tuple,
    Dict,
    Set,
    Iterable,
    Iterator,
    List,
    TypeVar,
    Generic,
    Optional,
    Callable,
    Generator,
    Any,
)
from types import FrameType
from pythonjsonlogger import jsonlogger

__all__: List[str] = []

def export(obj) -> str:  # pyre-ignore
    __all__.append(obj.__name__)
    return obj

@export
def strip_leading_whitespace(txt: str) -> Tuple[int, str]:
    # Given a multi-line string, determine the largest w such that each line
    # begins with at least w whitespace characters. Return w and the string
    # with w characters removed from the beginning of each line.
    lines = txt.split("\n")

    to_strip = None
    for line in lines:
        lsl = len(line.lstrip())
        if lsl:
            c = len(line) - lsl
            assert c >= 0
            if to_strip is None or to_strip > c:
                to_strip = c
            # TODO: do something about mixed tabs & spaces

    if not to_strip:
        return (0, txt)

    for i, line_i in enumerate(lines):
        if line_i.lstrip():
            lines[i] = line_i[to_strip:]

    return (to_strip, "\n".join(lines))

T = TypeVar("T")

@export
class AdjM(Generic[T]):
    # A sparse adjacency matrix for topological sorting
    # which we should not have implemented ourselves
    _forward: Dict[T, Set[T]]
    _reverse: Dict[T, Set[T]]
    _unconstrained: Set[T]

    def __init__(self) -> None:
        self._forward = dict()
        self._reverse = dict()
        self._unconstrained = set()

    def sinks(self, source: T) -> Iterable[T]:
        for sink in self._forward.get(source, []):
            yield sink

    def sources(self, sink: T) -> Iterable[T]:
        for source in self._reverse.get(sink, []):
            yield source

    @property
    def nodes(self) -> Iterable[T]:
        for node in self._forward:
            yield node

    @property
    def unconstrained(self) -> Iterable[T]:
        for n in self._unconstrained:
            assert not self._reverse[n]
            yield n

    def add_node(self, node: T) -> None:
        if node not in self._forward:
            assert node not in self._reverse
            self._forward[node] = set()
            self._reverse[node] = set()
            self._unconstrained.add(node)
        else:
            assert node in self._reverse

    def add_edge(self, source: T, sink: T) -> None:
        self.add_node(source)
        self.add_node(sink)
        if sink not in self._forward[source]:
            self._forward[source].add(sink)
            self._reverse[sink].add(source)
            if sink in self._unconstrained:
                self._unconstrained.remove(sink)
        else:
            assert source in self._reverse[sink]
            assert sink not in self._unconstrained

    def remove_edge(self, source: T, sink: T) -> None:
        if source in self._forward and sink in self._forward[source]:
            self._forward[source].remove(sink)
            self._reverse[sink].remove(source)
            if not self._reverse[sink]:
                self._unconstrained.add(sink)
        else:
            assert not (sink in self._reverse and source in self._reverse[sink])

    def remove_node(self, node: T) -> None:
        for source in list(self.sources(node)):
            self.remove_edge(source, node)
        for sink in list(self.sinks(node)):
            self.remove_edge(node, sink)
        del self._forward[node]
        del self._reverse[node]
        self._unconstrained.remove(node)

@export
def topsort(adj: AdjM[T]) -> List[T]:
    # topsort node IDs in adj (destroys adj)
    # if there's a cycle, raises err: StopIteration with err.node = ID of a
    # node involved in a cycle.
    ans = []
    node = next(adj.unconstrained, None)  # pyre-ignore
    while node:
        adj.remove_node(node)
        ans.append(node)
        node = next(adj.unconstrained, None)  # pyre-ignore
    node = next(adj.nodes, None)  # pyre-ignore
    if node:
        err = StopIteration()
        setattr(err, "node", node)
        raise err
    return ans

@export
def write_atomic(contents: str, filename: str, end: str = "\n") -> None:
    # 04-JUN-2021 changed to use UUID filename instead of relying on open(tn, "x") in case network
    # filesystem is wonky with O_EXCL.
    tn = filename + ".tmp." + str(uuid.uuid1())
    with open(tn, "w") as outfile:
        print(contents, file=outfile, end=end)
    os.rename(tn, filename)

@export
def rmtree_atomic(path: str) -> None:
    """
    Recursively delete a directory (or single file) after first renaming it to a temporary name in
    the same parent directory. The atomic rename step ensures a "partial" directory won't be left
    behind in its original location, should anything go wrong whilst deleting its contents.
    """
    path = os.path.abspath(path)
    assert path and path.strip("/")
    tmp_path = os.path.join(os.path.dirname(path), ".rmtree_atomic." + str(uuid.uuid1()))
    os.renames(path, tmp_path)
    shutil.rmtree(tmp_path)

@export
def symlink_force(src: str, dst: str, hard: bool = False) -> None:
    """
    Create a symbolic pointing to src named dst, atomically replacing any existing symbolic or
    hard link at dst.
    """
    assert not dst.endswith("/")
    tn = dst + ".tmp." + str(uuid.uuid1())
    if hard:
        os.link(src, tn)
    else:
        os.symlink(src, tn)
    os.rename(tn, dst)

@export
def link_force(src: str, dst: str) -> None:
    """
    Create a hard link pointing to src named dst, atomically replacing any existing symbolic or hard
    link at dst.
    """
    symlink_force(src, dst, hard=True)

@export
def write_values_json(
    values_env: "Env.Bindings[Value.Base]", filename: str, namespace: str = ""  # noqa
) -> None:
    from . import values_to_json

    write_atomic(
        json.dumps(
            # pyre-ignore
            values_to_json(values_env, namespace=namespace),
            indent=2,
            sort_keys=True,
        ),
        filename,
    )

@export
def provision_run_dir(name: str, parent_dir: Optional[str], last_link: bool = False) -> str:
    here = (
        (parent_dir in [".", "./"] or parent_dir.endswith("/.") or parent_dir.endswith("/./"))
        if parent_dir
        else False
    )
    parent_dir = os.path.abspath(parent_dir or os.getcwd())

    run_dir = None
    if here:
        # user wants to use parent_dir exactly
        run_dir = parent_dir
        os.makedirs(run_dir, exist_ok=True)
        parent_dir = os.path.dirname(parent_dir)
    else:
        # create timestamp-named directory
        while not run_dir:
            run_dir = os.path.join(
                parent_dir, datetime.today().strftime("%Y%m%d_%H%M%S") + "_" + name
            )
            try:
                os.makedirs(run_dir, exist_ok=False)
            except FileExistsError:
                run_dir = None
                sleep(0.5)
    assert run_dir

    # update the _LAST link
    if last_link and run_dir != parent_dir:
        last_link_name = os.path.join(parent_dir, "_LAST")
        if os.path.islink(last_link_name) or not (here or os.path.lexists(last_link_name)):
            symlink_force(os.path.basename(run_dir), last_link_name)

    return run_dir

@export
class StructuredLogMessage:
    message: str
    kwargs: Dict[str, Any]

    # from https://docs.python.org/3.8/howto/logging-cookbook.html#implementing-structured-logging
    def __init__(self, _message: str, **kwargs) -> None:  # pyre-fixme
        self.message = _message
        self.kwargs = kwargs

    def __str__(self) -> str:
        return (
            f"{self.message} :: {', '.join(k+ ': ' + json.dumps(v) for k,v in self.kwargs.items())}"
        )

class StructuredLogMessageJSONFormatter(jsonlogger.JsonFormatter):
    "JSON formatter for StructuredLogMessages"

    def format(self, rec: logging.LogRecord) -> str:
        if isinstance(rec.msg, StructuredLogMessage):
            ans = {"level": rec.levelname, "message": rec.msg.message}
            for k, v in rec.msg.kwargs.items():
                if k not in ans:
                    ans[k] = v
            rec.msg = ans
        return super().format(rec)

    def add_fields(
        self, log_record: Dict[str, Any], record: logging.LogRecord, message_dict: Dict[str, Any]
    ) -> None:
        super().add_fields(log_record, record, message_dict)
        log_record["timestamp"] = round(record.created, 3)
        log_record["source"] = record.name
        log_record["level"] = record.levelname
        log_record["levelno"] = record.levelno

VERBOSE_LEVEL = 15
__all__.append("VERBOSE_LEVEL")
logging.addLevelName(VERBOSE_LEVEL, "VERBOSE")

def verbose(self, message, *args, **kws):  # pyre-fixme
    if self.isEnabledFor(VERBOSE_LEVEL):
        self._log(VERBOSE_LEVEL, message, args, **kws)

logging.Logger.verbose = verbose
NOTICE_LEVEL = 25
__all__.append("NOTICE_LEVEL")
logging.addLevelName(NOTICE_LEVEL, "NOTICE")

def notice(self, message, *args, **kws):  # pyre-fixme
    if self.isEnabledFor(NOTICE_LEVEL):
        self._log(NOTICE_LEVEL, message, args, **kws)

logging.Logger.notice = notice

@export
class ANSI:
    # https://gist.github.com/RabaDabaDoba/145049536f815903c79944599c6f952a
    # https://espterm.github.io/docs/VT100%20escape%20codes.html
    CLEAR: str = "\x1b[2K\r"
    RESET: str = "\x1b[0m"
    BOLD: str = "\x1b[1m"

    RED: str = "\x1b[0;31m"
    BRED: str = "\x1b[1;31m"
    HRED: str = "\x1b[0;91m"
    BHRED: str = "\x1b[1;91m"

    HIDE_CURSOR: str = "\x1b[?25l"
    SHOW_CURSOR: str = "\x1b[?25h"

def _ansilen(parts: List[str]) -> int:
    return sum([len(s) for s in parts if s[0] != "\x1b"])

LOGGING_FORMAT = "%(asctime)s.%(msecs)03d %(name)s %(levelname)s %(message)s"
COLORED_LOGGING_FORMAT = "%(asctime)s.%(msecs)03d %(name)s %(message)s"  # colors obviate levelname
__all__.append("LOGGING_FORMAT")

@export
@contextmanager
def configure_logger(
    force_tty: bool = False, json: bool = False
) -> Iterator[Callable[[str], None]]:
    """
    contextmanager to set up the root/stderr logger; yields a function to set the status line at
    the bottom of the screen (if stderr isatty, else it does nothing)
    """
    import coloredlogs  # delayed heavy import

    class _StatusLineStandardErrorHandler(coloredlogs.StandardErrorHandler):
        """
        This subclass augments coloredlogs.StandardErrorHandler to maintain a "status line" which
        remains in place at the bottom of the screen as log records scroll by. The content of the
        status line can be set at any time. It will be truncated to the terminal width.
        """

        _singleton: "Optional[_StatusLineStandardErrorHandler]" = None
        _status: str = ""

        def __init__(self, *args, **kwargs):  # pyre-ignore
            super().__init__(*args, **kwargs)
            assert not self.__class__._singleton
            self.__class__._singleton = self

        def emit(self, record: logging.LogRecord) -> None:
            self.acquire()
            try:
                sys.stderr.write(ANSI.CLEAR)
                super().emit(record)
                self.emit_status()
            finally:
                self.release()

        def emit_status(self) -> None:
            self.acquire()
            try:
                sys.stderr.write(ANSI.CLEAR + self._status + ANSI.RESET)
                self.flush()
            finally:
                self.release()

        def set_status(self, new_status: List[str]) -> None:
            cols = shutil.get_terminal_size().columns
            if _ansilen(new_status) > cols:
                new_status = new_status.copy()
                while new_status and (_ansilen(new_status) > cols or new_status[-1][0] == "\x1b"):
                    new_status.pop()
            self._status = "".join(new_status)
            self.emit_status()

    logger = logging.getLogger()

    if json:
        logger.handlers[0].setFormatter(StructuredLogMessageJSONFormatter())
        yield (lambda ignore: None)
    else:
        level_styles = {}
        field_styles = {}
        fmt = LOGGING_FORMAT
        tty = force_tty or (sys.stderr.isatty() and "NO_COLOR" not in os.environ)

        if tty:
            level_styles = dict(coloredlogs.DEFAULT_LEVEL_STYLES)
            level_styles["debug"]["color"] = 242
            level_styles["notice"] = {"color": "green", "bold": True}
            level_styles["error"]["bold"] = True
            level_styles["warning"]["bold"] = True
            level_styles["info"] = {}
            field_styles = dict(coloredlogs.DEFAULT_FIELD_STYLES)
            field_styles["asctime"] = {"color": "blue"}
            field_styles["name"] = {"color": "magenta"}
            fmt = COLORED_LOGGING_FORMAT

            # monkey-patch _StatusLineStandardErrorHandler over coloredlogs.StandardErrorHandler for
            # coloredlogs.install() to instantiate
            coloredlogs.StandardErrorHandler = _StatusLineStandardErrorHandler
            sys.stderr.write(ANSI.HIDE_CURSOR)  # hide cursor

        try:
            coloredlogs.install(
                level=logger.getEffectiveLevel(),
                logger=logger,
                level_styles=level_styles,
                field_styles=field_styles,
                fmt=fmt,
            )
            yield (
                lambda status: _StatusLineStandardErrorHandler._singleton.set_status(  # pyre-fixme
                    status
                )
                if _StatusLineStandardErrorHandler._singleton
                else None
            )
        finally:
            if tty:
                sys.stderr.write(ANSI.CLEAR)  # wipe the status line
                sys.stderr.write(ANSI.SHOW_CURSOR)  # un-hide cursor

@export
@contextmanager
def PygtailLogger(
    logger: logging.Logger,
    filename: str,
    callback: Optional[Callable[[str], None]] = None,
    level: int = VERBOSE_LEVEL,
) -> Iterator[Callable[[], None]]:
    """
    Helper for streaming task stderr into logger using pygtail. Context manager yielding a function
    which reads the latest lines from the file and writes them into logger at verbose level. This
    function also runs automatically on context exit.

    Stops if it sees a line greater than 4KB, in case writer goes haywire.
    """
    from pygtail import Pygtail  # delayed heavy import

    pygtail = None
    if logger.isEnabledFor(level):
        pygtail = Pygtail(filename, full_lines=True)
    logger2 = logger.getChild("stderr")

    def default_callback(line: str) -> None:
        assert len(line) <= 4096, "line > 4KB"
        logger2.log(level, line.rstrip())

    callback = callback or default_callback

    def poll() -> None:
        nonlocal pygtail
        if pygtail:
            try:
                for line in pygtail:
                    callback(line)
            except Exception as exn:
                # cf. https://github.com/bgreenlee/pygtail/issues/48
                logger.warning(
                    StructuredLogMessage(
                        "log stream is incomplete", filename=filename, error=str(exn)
                    )
                )
                pygtail = None

    try:
        yield poll
    finally:
        poll()

_terminating: Optional[bool] = None
_terminating_lock: threading.Lock = threading.Lock()

@export
@contextmanager
def TerminationSignalFlag(logger: logging.Logger) -> Iterator[Callable[[], bool]]:
    """
    Context manager installing termination signal handlers (SIGTERM, SIGQUIT, SIGINT, SIGHUP) which
    set a global flag indicating whether such a signal has been received. Yields a function which
    returns this flag.

    Should be opened on the main thread wrapping all the desired operations. Once this is so, more
    instances can be opened on any thread without interfering with each other, as long as they're
    nested within the main one.
    """
    signals = [
        signal.SIGTERM,
        signal.SIGQUIT,
        signal.SIGINT,
        signal.SIGHUP,
        signal.SIGUSR1,
        signal.SIGALRM,  # used in unit test
        # don't trap SIGPIPE -- Python has a default handler to generate BrokenPipeError
    ]

    def handle_signal(sig: int, frame: FrameType) -> None:
        global _terminating
        if not _terminating:
            if sig != signal.SIGUSR1:
                logger.critical(StructuredLogMessage("aborting workflow", signal=sig))
            else:
                # SIGUSR1 comes from ourselves, as the signal to abort after something else has
                # already gone wrong
                logger.notice("aborting workflow")  # pyre-fixme
        _terminating = True

    global _terminating
    global _terminating_lock
    restore_signal_handlers = None
    with _terminating_lock:
        if _terminating is None:
            restore_signal_handlers = dict(
                (sig, signal.signal(sig, handle_signal)) for sig in signals
            )
            _terminating = False
    try:
        yield lambda: _terminating
    finally:
        if restore_signal_handlers:
            with _terminating_lock:
                for sig, handler in restore_signal_handlers.items():
                    signal.signal(sig, handler)
                _terminating = None

byte_size_units = {
    "B": 1,
    "K": 1000,
    "KB": 1000,
    "Ki": 1024,
    "KiB": 1024,
    "M": 1000000,
    "MB": 1000000,
    "Mi": 1048576,
    "MiB": 1048576,
    "G": 1000000000,
    "GB": 1000000000,
    "Gi": 1073741824,
    "GiB": 1073741824,
    "T": 1000000000000,
    "TB": 1000000000000,
    "Ti": 1099511627776,
    "TiB": 1099511627776,
}

@export
def parse_byte_size(s: str) -> int:
    """
    convert strings like "2000", "4G", "1.5 TiB" to a positive number of bytes
    """

    s = s.strip()
    N = None
    unit = None
    for i in range(len(s)):
        if s[i].isdigit() or s[i] == ".":
            N = float(s[: i + 1])
            unit = s[i + 1 :].lstrip()
        else:
            break
    if N and unit:
        if unit in byte_size_units:
            N *= byte_size_units[unit]
        else:
            N = None
    if N is None or N < 0:
        raise ValueError("invalid byte size string, " + s)
    return int(N)

@export
def pathsize(path: str) -> int:
    """
    get byte size of file, or total size of all files under directory & subdirectories (symlinks
    excluded)
    """

    if not os.path.isdir(path):
        return os.path.getsize(path)

    def raiser(exc: OSError):
        raise exc

    ans = 0
    for root, subdirs, files in os.walk(path, onerror=raiser, followlinks=False):
        for fn in files:
            fn = os.path.join(root, fn)
            if not os.path.islink(fn):
                ans += os.path.getsize(fn)

    return ans

def splitall(path: str) -> List[str]:
    """
    https://www.oreilly.com/library/view/python-cookbook/0596001673/ch04s16.html
    """
    allparts = []
    while 1:
        parts = os.path.split(path)
        if parts[0] == path:  # sentinel for absolute paths
            allparts.insert(0, parts[0])
            break
        elif parts[1] == path:  # sentinel for relative paths
            allparts.insert(0, parts[1])
            break
        else:
            path = parts[0]
            allparts.insert(0, parts[1])
    return allparts

@export
def path_really_within(lhs: str, rhs: str) -> bool:
    """
    After resolving symlinks, is path lhs either equal to or nested within path rhs?
    """
    lhs_cmp = splitall(os.path.realpath(lhs))
    rhs_cmp = splitall(os.path.realpath(rhs))
    return len(lhs_cmp) >= len(rhs_cmp) and lhs_cmp[: len(rhs_cmp)] == rhs_cmp

@export
def chmod_R_plus(path: str, file_bits: int = 0, dir_bits: int = 0) -> None:
    """
    recursive chmod to add permission bits (possibly different for files and subdirectiores)
    does not follow symlinks
    """

    def do1(path1: str, bits: int) -> None:
        assert 0 <= bits < 0o10000
        if not os.path.islink(path1) and path_really_within(path1, path):
            os.chmod(path1, (os.stat(path1).st_mode & 0o7777) | bits)

    def raiser(exc: OSError):
        raise exc

    if os.path.isdir(path):
        do1(path, dir_bits)
        for root, subdirs, files in os.walk(path, onerror=raiser, followlinks=False):
            for dn in subdirs:
                do1(os.path.join(root, dn), dir_bits)
            for fn in files:
                do1(os.path.join(root, fn), file_bits)
    else:
        do1(path, file_bits)

@export
@contextmanager
def LoggingFileHandler(
    logger: logging.Logger, filename: str, json: bool = False
) -> Iterator[logging.FileHandler]:
    """
    Context manager which opens a logging.FileHandler and adds it to the logger; on exit, closes
    the log file and removes the handler.
    """
    fh = logging.FileHandler(filename)
    fh.setFormatter(
        StructuredLogMessageJSONFormatter()
        if json
        else logging.Formatter(LOGGING_FORMAT, datefmt="%Y-%m-%d %H:%M:%S")
    )
    try:
        logger.addHandler(fh)
        yield fh
    finally:
        fh.flush()
        fh.close()
        logger.removeHandler(fh)

@export
@contextmanager
def compose_coroutines(  # pyre-fixme
    generators: List[Callable[[Any], Generator[Any, Any, None]]], x: Any  # pyre-fixme
) -> Iterator[Generator[Any, Any, None]]:
    """
    Coroutine (generator) which composes several other coroutines to run in lockstep for one or
    more "rounds." On each round, caller sends a value, which is sent to the first coroutine; the
    value it yields is sent to the second coroutine; and so on until finally the value yielded by
    the last coroutine is yielded back to the caller. Exceptions propagate in the same way, so a
    coroutine can catch and manipulate (but not suppress) an exception raised by the caller or by
    one of the other coroutines.
    """

    def _impl() -> Generator[Any, Any, None]:  # pyre-fixme
        # start the coroutines by invoking each generator and taking the first value it yields
        nonlocal x
        cors = []
        try:
            for gen in generators:
                cor = gen(x)
                x = next(cor)
                cors.append(cor)
            while True:  # GeneratorExit will break
                # yield to caller and get updated value back
                try:
                    x = yield x
                except Exception as exn:
                    for cor in cors:
                        try:
                            cor.throw(exn)
                        except Exception as exn2:
                            exn = exn2
                    raise exn
                # pass value through coroutines
                exn = None
                for cor in cors:
                    try:
                        if not exn:
                            x = cor.send(x)
                        else:
                            cor.throw(exn)
                    except Exception as exn2:
                        exn = exn2
                if exn:
                    raise exn
        finally:
            close_exn = None
            for cor in cors:
                try:
                    cor.close()
                except Exception as exn2:
                    close_exn = close_exn or exn2
            if close_exn:
                raise close_exn

    # this outer contextmanager is for closing the coroutines promptly and propagating any caller
    # exceptions back through them. see: https://stackoverflow.com/a/58854646
    chain = _impl()
    try:
        yield chain
    except Exception as exn:
        chain.throw(exn)  # pyre-ignore
        raise
    finally:
        chain.close()

@export
class FlockHolder(AbstractContextManager):
    """
    Context manager exposing a method to take an advisory lock on a file (flock) and hold it until
    context exit. The context manager is reentrant; locks are released upon exit of the outermost
    nested context.
    """

    _lock: threading.Lock
    _flocks: Dict[str, Tuple[int, bool]]
    _entries: int
    _logger: logging.Logger

    def __init__(self, logger: Optional[logging.Logger] = None) -> None:
        self._lock = threading.Lock()
        self._flocks = {}
        self._entries = 0
        self._logger = (
            logger.getChild("FlockHolder") if logger else logging.getLogger("FlockHolder")
        )

    def __enter__(self) -> "FlockHolder":
        assert self._entries > 0 or not self._flocks
        self._entries += 1
        return self

    def __exit__(self, *exc_details) -> None:  # pyre-fixme
        assert self._entries > 0, "FlockHolder context exited prematurely"
        self._entries -= 1
        if self._entries == 0:
            exn = None
            with self._lock:
                for fn, (fd, exclusive) in self._flocks.items():
                    self._logger.debug(StructuredLogMessage("close", file=fn, exclusive=exclusive))
                    try:
                        os.close(fd)
                    except Exception as exn2:
                        exn = exn or exn2
                self._flocks = {}
            if exn:
                raise exn

    def __del__(self) -> None:
        assert self._entries == 0 and not self._flocks, "FlockHolder context was not exited"

    def flock(
        self,
        filename: str,
        mode: Optional[int] = None,
        exclusive: bool = False,
        wait: bool = False,
    ) -> int:
        """
        Open a file and an advisory lock on it. The file is closed and the lock released upon exit
        of the outermost context. Returns the open file descriptor, which the caller shouldn't
        close (managed by the object).

        :param filename: file to open & lock
        :param mode: os.open() mode flags, default: OS.O_RDWR if exclusive else os.O_RDONLY
        :param exclusive: True to open an exclusive lock (default: shared lock)
        :param wait: True to wait as long as needed to obtain the lock, otherwise (default) raise
                     OSError if the lock isn't available immediately. Self-deadlock is possible;
                     see Python fcntl.flock docs for further details.
        """
        assert self._entries, "FlockHolder.flock() used out of context"
        while True:
            realfilename = os.path.realpath(filename)
            with self._lock:  # only needed to synchronize self._flocks
                if realfilename in self._flocks and not exclusive:
                    self._logger.debug(
                        StructuredLogMessage(
                            "reuse prior flock",
                            filename=filename,
                            realpath=realfilename,
                            exclusive=self._flocks[realfilename][1],
                        )
                    )
                    return self._flocks[realfilename][0]
                openfile = os.open(
                    realfilename,
                    mode if mode is not None else (os.O_RDWR if exclusive else os.O_RDONLY),
                )
                try:
                    op = fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH
                    if not wait:
                        op |= fcntl.LOCK_NB
                    self._logger.debug(
                        StructuredLogMessage(
                            "flock",
                            file=filename,
                            realpath=realfilename,
                            exclusive=exclusive,
                            wait=wait,
                        )
                    )
                    fcntl.flock(openfile, op)
                    # the flock will release whenever we ultimately openfile.close()

                    file_st = os.stat(openfile)

                    # Even if all concurrent processes obey the advisory flocks, the filename link
                    # could have been replaced or removed in the duration between our open() and
                    # fcntl() syscalls.
                    # - if it was removed, the following os.stat will trigger FileNotFoundError,
                    #   which is reasonable to propagate.
                    # - if it was replaced, the subsequent condition won't hold, and we'll loop
                    #   around to try again on the replacement file.
                    filename_st = os.stat(realfilename)
                    self._logger.debug(
                        StructuredLogMessage(
                            "flocked",
                            file=filename,
                            realpath=realfilename,
                            exclusive=exclusive,
                            name_inode=filename_st.st_ino,
                            fd_inode=file_st.st_ino,
                        )
                    )
                    if (
                        filename_st.st_dev == file_st.st_dev
                        and filename_st.st_ino == file_st.st_ino
                    ):
                        assert realfilename not in self._flocks
                        self._flocks[realfilename] = (openfile, exclusive)
                        return openfile
                except:
                    os.close(openfile)
                    raise
                os.close(openfile)  # NOT finally -- for next while-loop iteration

def bump_atime(filename: str) -> None:
    fd = os.open(os.path.realpath(filename), os.O_RDONLY)
    try:
        file_st = os.stat(fd)
        os.utime(fd, ns=(int(time.time() * 1e9), file_st.st_mtime_ns))
    finally:
        os.close(fd)

@export
class RepeatTimer(threading.Timer):
    def run(self) -> None:
        while not self.finished.wait(self.interval):  # pyre-ignore
            self.function(*self.args, **self.kwargs)  # pyre-ignore

def currently_in_container() -> bool:
    # https://github.com/containers/podman/issues/3586#issuecomment-512191693
    try:
        with open(f"/proc/{os.getpid()}/mounts") as infile:
            return " / overlay" in infile.read()
    except:
        return False


#right angle triangle star pattern:
'''ros = int(input("enter the value: "))
for i in range(1,ros+1):
  print("* " * i)'''

#inverse right angle triangle pattern:

'''totalrows = int(input("enter the values: "))
for row in range(1, totalrows+1):

#logic for space :
  for space in range(1, (totalrows - row) + 1):
   print(" ", end ="")

#logic for star:
  for star in range(1, row+1):
   print("*", end ="")

  print()
  '''

'''#Printing numbers in X shape :
n = int(input("Enter the values:"))
for row in range(n):
  for column in range(n):
    if(row == column) or ((row+column)==n-1):
      print("{0}".format(column), end="")
    else:
      print("  ", end="")
  print()'''

#printing chars in x shape:
name = input("Enter the name: ")
target = len(name)
for row in range(target):
  for col in range(target):
    if (row == col) or ((row+col == target -1)):
     print("{}".format(name[row]), end="")
    else:
     print("  ", end="")
  print()


import argparse
import logging
import shutil
import subprocess
import sys
import tempfile
from collections import defaultdict
from dataclasses import dataclass
from pathlib import Path
from typing import List

from func_adl_types_atlas.build_xaod_edm import build_xaod_edm  # type: ignore
from rich.console import Console
from rich.table import Table

from func_adl_servicex_type_generator import generate_package

valid_tests = ["jets_uncalib", "jets_calib", "met", "error_bad_argument"]

def run_command(cmd: str | List[str]):
    """Run a command and dump the resulting output to logging,
    depending on the return code.

    Args:
        cmd (str): Command to run
    """
    if not isinstance(cmd, list):
        cmd = [cmd]

    command_line = ";".join(cmd) if len(cmd) > 1 else f"{cmd[0]}"
    logging.debug(f"Running command: {command_line}")

    try:
        result = subprocess.run(
            command_line,
            capture_output=True,
            text=True,
        )

        level = logging.INFO
        if result.returncode != 0:
            level = logging.ERROR

        logging.log(level, f"Result code from running {cmd}: {result.returncode}")
        for line in result.stdout.split("\n"):
            logging.log(level, f"stdout: {line}")
        for line in result.stderr.split("\n"):
            logging.log(level, f"stderr: {line}")

        if result.returncode != 0:
            raise RuntimeError(
                f"Failed to execute (return code {result.returncode}): {command_line}"
            )
    except Exception:
        logging.error("Exception was thrown running the following commands:")
        for ln in cmd:
            logging.error(f"  {ln}")
        raise

def create_type_json(
    release: str, clean: bool, location: Path, cmd_location: Path
) -> Path:
    """Create the type json file for a release.

    Args:
        release (_type_): Release name - an image tag
        clean (_type_): If true, then refresh even if yaml file is present.
    """
    logging.info(f"Building JSON file for {release}")

    # Can we skip?
    yaml_path = location / f"{release}.yaml"
    if yaml_path.exists() and (not clean):
        logging.debug(f"YAML type file for {release} already exists. Not rebuilding")
        return yaml_path

    # Do the build.
    yaml_path.parent.mkdir(parents=True, exist_ok=True)
    logging.debug(f"Running container to build json type file for {release}")
    build_xaod_edm(release, yaml_path)
    logging.debug(f"Finished building json type file for {release}")

    return yaml_path

def create_python_package(
    release: str, package_version: str, clean: bool, json_location: Path, location: Path
) -> Path:
    """Given the type json file already exists, create the python
    package for the full type information.

    Args:
        release (str): The name of the release
        clean (bool): If true, remake the package from scratch.
                    Otherwise, only if it isn't there already.
        json_location (Path): Location of the json yaml file
        location (Path): Directory to house the created package

    Returns:
        Path: Location of the package
    """
    logging.info(f"Creating python package for release {release}")

    # See if we can bail out quickly
    package_location = location / release
    if package_location.exists() and (not clean):
        logging.debug(
            f"Python package for release {release} already exists. Not rebuilding."
        )
        return package_location

    # Re-create it.
    generate_package(json_location, package_version, package_location)

    # Next we need to find the package - the actual name of the folder might vary a
    # little bit due to the release series.

    return package_location

def do_build_for_release(release, args):
    yaml_location = create_type_json(
        release, args.clean, args.type_json, args.command_location
    )
    return create_python_package(
        release, args.package_version, args.clean, yaml_location, args.type_package
    )

def do_build(args):
    """Iterator that builds a package for each release.

    Args:
        args (): Command line arguments

    Yields:
        Path: THe path where the package is located
    """
    for r in args.release:
        do_build_for_release(r, args)
    return 0

def do_yaml(args):
    for r in args.release:
        create_type_json(r, args.clean, args.type_json, args.command_location)

def do_test(args):
    """After making sure that the packages are built, run the requested tests

    Args:
        args (): Command line arguments
    """
    for r in args.release:
        package_path = do_build_for_release(r, args)
        logging.debug(f"Running tests for release {r} in {package_path}")

        # Build the commands to create the env and setup/run the test.
        commands = []

        test_packages_path = Path(__file__).parent / "test_packages.py"
        assert (
            test_packages_path.exists()
        ), f"Configuration error: cannot find {test_packages_path}"

        logging.debug("About to create the temp directory")
        with tempfile.TemporaryDirectory() as release_dir_tmp:
            release_dir = release_dir_tmp if args.test_dir is None else args.test_dir

            commands.append(f"cd {release_dir}")
            commands.append("python -m venv .venv")
            commands.append(". .venv/Scripts/Activate.ps1")
            commands.append("python -m pip install --upgrade pip")

            # Install the package. We want to run locally, so need to install
            # a special flavor of func_adl_servicex.
            commands.append("python -m pip install func_adl_servicex[local]")
            commands.append(f"python -m pip install -e {package_path.absolute()}")

            # Copy over the script to make it easy to "run".
            shutil.copy(test_packages_path.absolute(), release_dir)

            # Commands to run the scripts
            all_tests = args.test if len(args.test) > 0 else valid_tests
            test_args = " ".join([f"--test {t}" for t in all_tests])
            verbose_arg = (" -" + "v" * int(args.verbose)) if args.verbose > 0 else ""

            commands.append(f"python test_packages.py {test_args}{verbose_arg}")

            # Finally, run the commands.
            logging.debug(f"Running tests for release {r} - commands are:")
            for cmd in commands:
                logging.debug(f"  {cmd}")
            run_command(commands)
    return 0

@dataclass
class ReleaseInfo:
    """Information about a release"""

    has_type_json: bool = False
    has_package: bool = False

def do_list(args):
    """Look through all the types and releases and report which are built
    in a table to the user"""

    info = defaultdict(ReleaseInfo)

    # first, look for the type json files
    for f in Path(args.type_json).glob("*.yaml"):
        info[f.stem].has_type_json = True

    # Next, lets look at the package directory for releases
    for f in Path(args.type_package).glob("*"):
        info[f.name].has_package = True

    # Dump the info out as a rich table
    table = Table(title="Release Information")
    table.add_column("Release", justify="right", style="cyan", no_wrap=True)
    table.add_column("Type JSON", justify="right", style="magenta", no_wrap=True)
    table.add_column("Python Package", justify="right", style="green", no_wrap=True)

    for r in info:
        table.add_row(
            r,
            "Yes" if info[r].has_type_json else "No",
            "Yes" if info[r].has_package else "No",
        )

    console = Console()
    console.print(table)

def do_delete(args):
    """Delete the release packages"""
    for r in args.release:
        # Delete the type packages
        package_path = Path(args.type_package) / r
        if package_path.exists():
            logging.debug(f"Removing package {package_path}")
            shutil.rmtree(package_path)

        # Delete the type json file
        json_path = Path(args.type_json) / f"{r}.yaml"
        if json_path.exists():
            logging.debug(f"Removing type json {json_path}")
            json_path.unlink()
    return 0

def main():
    parser = argparse.ArgumentParser(
        prog="atlas_release_type_builder",
        description="Build and test atlas release types",
        epilog="Building type libraries can take considerable time. Unless the --clean"
        " option is used, previous outputs are used rather than regenerating from "
        "scratch.",
    )
    parser.add_argument(
        "-v",
        "--verbose",
        action="count",
        default=0,
        help="Verbosity Level (-v, or -vv))",
    )

    commands = parser.add_subparsers(help="sub-command help")

    # The "build" an atlas release command
    build_command = commands.add_parser(
        "build", help="Build type library for a release"
    )

    def add_build_args(parser, add_release=True, package_flags=True):
        if add_release:
            parser.add_argument(
                "release", type=str, help="List of releases to build", action="append"
            )
            parser.add_argument(
                "--clean",
                type=bool,
                action=argparse.BooleanOptionalAction,
                default=False,
            )
        parser.add_argument(
            "--type_json",
            type=Path,
            default=Path("../type_files"),
            help="Location where yaml type files should be written",
        )
        if package_flags:
            parser.add_argument(
                "--type_package",
                type=Path,
                default=Path(
                    "../type_packages",
                    help="Location where the python type package should be created",
                ),
            )
            parser.add_argument(
                "--package_version",
                type=str,
                default="2.0.0a1",
                help="Version of the python package to create",
            )
        parser.add_argument(
            "--command_location",
            type=Path,
            default=Path("../../"),
            help="Location of the scripts to run to build the type json file",
        )

    add_build_args(build_command)
    build_command.set_defaults(func=do_build)

    # The build yaml command - just does the first part of the build.
    build_yaml_command = commands.add_parser(
        "yaml", help="Build type yaml for a release"
    )
    add_build_args(build_yaml_command, package_flags=False)
    build_yaml_command.set_defaults(func=do_yaml)

    # The test command
    test_command = commands.add_parser("test", help="Run tests for a release")
    test_command.add_argument(
        "--test", choices=valid_tests, default=[], action="append"
    )
    test_command.add_argument(
        "--test_dir",
        type=Path,
        help="Path to place (and leave) test directory",
        default=None,
    )
    add_build_args(test_command)
    test_command.set_defaults(func=do_test)

    # The list command - list all releases that are built one way or the other.
    list_command = commands.add_parser("list", help="List all releases")
    list_command.set_defaults(func=do_list)
    add_build_args(list_command, add_release=False)

    # delete command - will delete a release(s) (type and package files).
    delete_command = commands.add_parser("delete", help="Delete a release")
    add_build_args(delete_command)
    delete_command.set_defaults(func=do_delete)

    args = parser.parse_args()

    # Global flags
    logging.basicConfig()
    if args.verbose:
        logging.getLogger().setLevel(logging.INFO)
        if int(args.verbose) > 1:
            logging.getLogger().setLevel(logging.DEBUG)

    # Now execute the command
    if not hasattr(args, "func"):
        logging.error("No command found on command line")
        parser.print_help()
        exit(1)

    sys.exit(args.func(args))

if __name__ == "__main__":
    main()


from django.urls import path
from .views import *

app_name = 'accounts_api'

urlpatterns = [
    # path('change-password/<int:id>/', ChangePasswordView.as_view(), name='change-password'),
    path('add-to-wishlist/', AddToWishlist.as_view(), name='add-to-wishlist'),
    path('remove-from-wishlist/', RemoveFromWishlist.as_view(), name='remove-from-wishlist'),
    path('add-to-cart/', AddToCart.as_view(), name='add-to-cart'),
    path('remove-from-cart/', RemoveFromCart.as_view(), name='remove-from-cart'),
]


from collections import *

"""
    1st: line sweeping + merge intervals

    Time    O(N + NlogN)
    Space   O(N)
    1292 ms, faster than 100.00%
"""

class Solution:
    def averageHeightOfBuildings(self, buildings: List[List[int]]) -> List[List[int]]:
        heights = Counter()
        counts = Counter()

        # line sweeping
        for s, e, h in buildings:
            heights[s] += h
            counts[s] += 1
            heights[e] -= h
            counts[e] -= 1

        # merge intervals
        keys = sorted(heights.keys())
        curHegiht = heights[keys[0]]
        curCount = counts[keys[0]]
        prevCount = 0
        res = []
        for i in range(1, len(keys)):
            _k = keys[i-1]
            k = keys[i]
            if curCount > 0:
                avg = curHegiht//curCount
                if len(res) > 0 and avg == res[-1][2] and prevCount > 0:
                    res[-1][1] = k
                else:
                    res.append([_k, k, avg])
            prevCount = curCount
            curHegiht += heights[k]
            curCount += counts[k]

        return res


#!/bin/python
import sys
import copy
from cell import Cell
from board import Board
from minimax import getNextMove
from minimax import interfaceBoard

class DoubleCard():
    def __init__(self):
        self.board = Board()
        self.turn = 0
        self.prev_board = copy.deepcopy(self.board)
        self.trace = True
        self.prev_move = []
        self.history = []
        self.player_option = 1
        self.ai_player = 99999

    def start_menu(self):
        print("Welcome to Double Card Game!")
        while (True):
            option = input("""============================
Select Game Mode:
1) Player VS Player
2) Player VS AI

Option: """)
            self.flush()
            if option == '1':
                print("Player VS Player Mode Selected")
                self.win_condition()
                self.flush()
                break
            elif option == '2':
                print("Player VS AI Mode Selected")
                self.ai_condition()
                self.flush()
                self.win_condition()
                self.flush()
                break
            else:
                print("Invalid option selected!")

    def ai_condition(self):
        trace_text = "Do you want to have an output of the trace?(Y/N): "
        choice_text = """Choose AI to start 1st or 2nd:
1) 1st
2) 2nd
Option: """
        while(True):
            choice=input(trace_text)
            if choice in ['Y', 'N']:
                if choice == 'Y':
                    self.trace = True
                else:
                    self.trace = False
                break
            self.flush()

        while(True):
            self.flush()
            choice=input(choice_text)
            if choice in ['1', '2']:
                self.ai_player = int(choice)
                break

    def win_condition(self):
        choice_text = """Choose Player 1 Winning condition:
1) Colors
2) Dots
Option: """
        while(True):
            choice=input(choice_text)
            if choice in ['1', '2']:
                self.player_option = int(choice)
                break
            self.flush()

    def letter_to_int(self, move):
        letter_map = {'A':0, 'B':1, 'C':2, 'D':3, 'E':4, 'F':5, 'G':6, 'H':7}
        return letter_map.setdefault(move, None)

    def start(self):
        self.first_load()
        while True:
            if self.history:
                print ("Turn {}: Move placed is {}".format(self.turn, self.history[-1]))
            print (self.board)
            if self.turn == 40:
                break
            self.command_parser()
            self.prev_board = copy.deepcopy(self.board)
        print("Game End with Draw")

    def first_load(self):
        self.start_menu()

    def print_history(self):
        for x,y in enumerate(self.history):
            print("""Turn {}:
Player {} : {}""".format(x+1,x%2+1,y))

    def same_move(self, parsed_command):
        prev_move = self.prev_move
        if len(prev_move)!= 7:
            return False
        if parsed_command == prev_move:
            return True
        if set(parsed_command[0:4]) == set(prev_move[0:4]):
            print(parsed_command[4])
            if parsed_command[4] == prev_move[4]:
                return True
        return False

    def move_prev_card(self, parsed_command):
        prev_move = self.prev_move
        if len(prev_move)!= 7:
            prev_card = self.prev_move[2:4]
        else:
            prev_card = self.prev_move[5:7]

        c1 = parsed_command[0:2]
        c2 = parsed_command[2:4]

        if prev_card == c1 or prev_card == c2:
            return True
        return False

    def string_to_int(self, commands_list):
        for x,y in enumerate(commands_list):
            if y.isnumeric():
              commands_list[x] = int(y)
        return commands_list

    def validate(self, cmds):
        valid = True
        move_type = len(cmds)
        cmds = self.string_to_int(cmds)
        if move_type == 1:
            if cmds != "history": # View History
                valid = False
        elif move_type == 4: # Regular Move (eg. 0 7 A 1)
            int_letter = self.letter_to_int(cmds[2])
            if cmds[0] != 0:
                valid = False
            elif type(cmds[1]) != int:
                valid = False
            elif type(cmds[3]) != int:
                valid = False
            elif cmds[1] > 8 or cmds[1] <1:
                valid = False
            elif int_letter is None:
                valid = False
            elif cmds[3] > 12 or cmds[3] <1:
                valid = False
        elif move_type == 7: # Recycling move (eg. A 1 A 2 7 A 1)
            int_letter_0 = self.letter_to_int(cmds[0])
            int_letter_2 = self.letter_to_int(cmds[2])
            int_letter_5 = self.letter_to_int(cmds[5])

            if int_letter_0 is None:
                valid = False
            elif type(cmds[1]) != int:
                valid = False
            elif type(cmds[3]) != int:
                valid = False
            elif type(cmds[4]) != int:
                valid = False
            elif type(cmds[6]) != int:
                valid = False
            elif cmds[1] > 12 or cmds[1] <1:
                valid = False
            elif int_letter_2 is None:
                valid = False
            elif cmds[3] > 12 or cmds[3] <1:
                valid = False
            elif cmds[4] > 8 or cmds[4] <1:
                valid = False
            elif int_letter_5 is None:
                valid = False
            elif cmds[6] > 12 or cmds[6] <1:
                valid = False
        else:
            valid = False
        return valid

    def command_parser(self):
        curr_player = self.turn%2 + 1
        curr_ai = (self.ai_player == curr_player)
        if not curr_ai:
            command = input("[{}'s Turn] Place your move: ".format("Player {}".format(curr_player)))
        else:
            ai_type = 0 if self.player_option == 1 else 1
            if self.turn >= 24:
                command = getNextMove(self.board, ai_type, show_stats=self.trace,recycling=True,prev_move=self.history[-1])
            else:
                command = getNextMove(self.board, ai_type, show_stats=self.trace)
            # command = "0 2 A 1" # TODO place output of minimax algo here
            print("[AI's Turn] Place your move: {}".format(command))
        self.flush()
        print ("{player} Input: {command}".format(player="Player" if not curr_ai else "AI" ,command=command))
        parsed_command = command.split(' ')

        if parsed_command[0] == 'history':
            self.print_history()
            return
        if parsed_command[0] == 'export':
            print(interfaceBoard(self.board))
            return
        if not self.validate(parsed_command):
            self.illegal_move("Invalid command!")
            return
        elif parsed_command[0] == 0:
            if len(parsed_command) != 4:
                print("Invalid Move!")
                return

            if self.turn >= 24:
                print("Cannot use Regular Moves!")
                return
            else:
                start_cell = self.letter_to_int(parsed_command[2]) + (parsed_command[3]-1)*8
                self.place_card(parsed_command[1], start_cell)
                self.prev_move = parsed_command
                self.history.append(command)
        else:
            if len(parsed_command) != 7 or self.turn <24:
                print("Invalid Move!")
                return
            if self.same_move(parsed_command):
                self.illegal_move("Same Move")
                return
            if self.move_prev_card(parsed_command):
                self.illegal_move("Moving Same Card as Previous Move")
                return
            start_cell = self.letter_to_int(parsed_command[0]) + (parsed_command[1]-1)*8
            neighbour_cell = self.letter_to_int(parsed_command[2]) + (parsed_command[3]-1)*8
            new_cell = self.letter_to_int(parsed_command[5]) + (parsed_command[6]-1)*8
            if self.remove_card(start_cell, neighbour_cell):
                self.place_card(parsed_command[4], new_cell)

                if self.board == self.prev_board:
                    self.illegal_move("Move did not change to the board")
                    self.turn -= 1
                    return
                self.prev_move = parsed_command
                self.history.append(command)

    def check_win(self, cell_num):

        directions =['vertical', 'horizontal', 'diag-left', 'diag-right']
        wins = [0,0,0,0]
        winning_nums = [2*3*5*7, 3*5*7*11, 5*7*11*13, 7*11*13*17]
        for direction in directions:
            x = self.tabulate(cell_num, direction)
            for y,z in enumerate(x):
                if list(filter(lambda x: z%x==0, winning_nums)):
                    # print("Possible win with {}".format(direction))
                    wins[y] = 1
        return wins

    def remove_card(self, start_cell, neighbour_cell):
        # check if cells are linked
        c1 = self.board.get(start_cell)
        c2 = self.board.get(neighbour_cell)
        def in_bound(cell_num):
            return cell_num >= 0 and cell_num < 8*12

        illegal = False
        if c1.link == c2.id and c2.link == c1.id:
            c1.clear()
            c2.clear()
            for c in [start_cell,neighbour_cell]:
                if in_bound(c+8):
                    if self.board.get(c+8).occupied:
                        illegal = True
        else:
            illegal = True

        if illegal:
            self.illegal_move("Removal not possible")
            return False
        return True

    def illegal_move(self, reason):
        print("Illegal Move! - {}".format(reason))
        self.board = copy.deepcopy(self.prev_board)

    def tabulate(self, cell_num, direction):
        red = 1
        white = 1
        cross = 1
        circle = 1
        primes = [2,3,5,7,11,13,17]
        if direction == 'horizontal':
            extend_cell_num = cell_num+3
            if int(extend_cell_num / 8) != int(cell_num / 8):
                extend_cell_num = (int(cell_num / 8)+1)*8-1
        if direction == "vertical":
            extend_cell_num = cell_num+3*8
        if direction == 'diag-left':
            extend_cell_num = cell_num+3*8+3
        if direction == 'diag-right':
            extend_cell_num = cell_num+3*8-3
        for x in range(7):
            curr_cell = None
            if direction == 'vertical':
                curr_cell_num = extend_cell_num-8*x
            elif direction == 'horizontal':
                curr_cell_num = extend_cell_num-x
                if int(curr_cell_num / 8) != int(cell_num / 8):
                    continue
            elif direction == 'diag-left':
                curr_cell_num = extend_cell_num-8*x-x
                if int(curr_cell_num / 8) != int(cell_num / 8)+3-x:
                    continue
            elif direction == 'diag-right':
                curr_cell_num = extend_cell_num-8*x+x
                if int(curr_cell_num / 8) != int(cell_num / 8)+3-x:
                    continue

            # check if out of board
            if curr_cell_num >= 0 and curr_cell_num < 8*12:
                curr_cell = self.board.get(curr_cell_num)
            if curr_cell is None:
                continue
            if curr_cell.color is 'Red':
                red *= primes[x]
            elif curr_cell.color is 'White':
                white *= primes[x]
            if curr_cell.symbol == '\u2022':
                circle *= primes[x]
            elif curr_cell.symbol == '\u25E6':
                cross *= primes[x]
        return [red, white, circle, cross]

    def place_card(self, variant, start_cell):
        neighbour_cell = start_cell+1 if variant%2 == 1 else start_cell+8
        if self.check_illegal(start_cell, neighbour_cell):
            self.illegal_move("Placement not possible")
            return
        color = 'Red' if variant in [1,4,5,8] else 'White'
        symbol = '\u25E6' if variant in [2,3,5,8] else "\u2022"

        def opp_color(color):
            return 'White' if color is 'Red' else 'Red'

        def opp_symbol(symbol):
            return "\u2022" if symbol == '\u25E6' else '\u25E6'

        self.board.get(start_cell).fill(color, symbol, neighbour_cell, variant)
        self.board.get(neighbour_cell).fill(opp_color(color), opp_symbol(symbol), start_cell, variant)
        wins = self.check_win(start_cell)
        wins.extend(self.check_win(neighbour_cell))
        self.who_win(wins)
        self.turn += 1

    def who_win(self, result):
        player = self.turn % 2 + 1
        player1_win = False
        player2_win = False

        win_cases = [i for i, x in enumerate(result) if x == 1]
        if [i for i in [0,1,4,5] if i in win_cases]:
            if self.player_option == 1:
                player1_win = True
            else:
                player2_win = True
        if [i for i in [2,3,6,7] if i in win_cases]:
            if self.player_option == 1:
                player2_win = True
            else:
                player1_win = True
        if player1_win and player2_win:
            print("Player {} wins".format(player))
        elif player1_win:
            print("Player 1 wins")
        elif player2_win:
            print("Player 2 wins")
        if player2_win or player1_win:
            print(self.board)
            exit()

    def flush(self):
        print(chr(27) + "[2J")

    def check_illegal(self, start_cell, neighbour_cell):
        # check if out of bound
        def check_in_bound(cell):
            return cell < 8*12 and cell >= 0

        def floating_cell(cell):
            if cell-8 <0:
                return False
            else:
                return self.board.get(cell-8).occupied == False
        def occupied_cell(cell):
            return self.board.get(cell).occupied

        if check_in_bound(start_cell) and check_in_bound(neighbour_cell):
            if occupied_cell(start_cell) or occupied_cell(neighbour_cell):
                # print("HERE OCCUPIED")
                return True
            if floating_cell(start_cell) or floating_cell(neighbour_cell):
                if neighbour_cell - start_cell == 8:
                    return floating_cell(start_cell) and floating_cell(neighbour_cell)
                # print("HERE FLOATING")
                return True
            if neighbour_cell - start_cell == 1:
                return int(neighbour_cell/8) != int(start_cell/8)
            return False
        else:
            return True

x = DoubleCard()
x.start()


def read_stream(schema, stream, *, buffer_size=io.DEFAULT_BUFFER_SIZE):
    """Using a schema, deserialize a stream of consecutive Avro values.

    :param str schema: json string representing the Avro schema
    :param file-like stream: a buffered stream of binary input
    :param int buffer_size: size of bytes to read from the stream each time
    :return: yields a sequence of python data structures deserialized
        from the stream

    """
    reader = _lancaster.Reader(schema)
    buf = stream.read(buffer_size)
    remainder = b''
    while len(buf) > 0:
        values, n = reader.read_seq(buf)
        yield from values
        remainder = buf[n:]
        buf = stream.read(buffer_size)
        if len(buf) > 0 and len(remainder) > 0:
            ba = bytearray()
            ba.extend(remainder)
            ba.extend(buf)
            buf = memoryview(ba).tobytes()
    if len(remainder) > 0:
        raise EOFError('{} bytes remaining but could not continue reading '
                       'from stream'.format(len(remainder)))


from math import sqrt as s
def check(c):
    if c<2:
        return False
    if c==2:
        return True
    for i in range(2,int(s(c))+1):
        if c%i==0:
            return False
    return True
n=int(input())
for k in range(n):
    a=int(input())
    if check(a):
        print(a)
    else:
        m=2
        for i in range(2,int(s(a))+1):
            while a%i==0:
                m=max(2,i)
                a//=i
        if check(a) and a>m:
            print(a)
        else:
            print(m)


import numpy as np
import time

def get_distance2_matrix(centers, moving=None):
    dists = np.zeros((centers.shape[0], centers.shape[0], 2))
    dists[:] = centers
    if not (moving is None):
        d = dists[moving, :, :]
        c = centers[moving, :]
    else:
        d = dists
        c = centers

    d[:, :, 0] -= c[:, 0][:, None]
    d[:, :, 1] -= c[:, 1][:, None]

    return d[:, :, 0]*d[:, :, 0] + d[:, :, 1]*d[:,:,1]

def get_collisions(centers, r2=1, moving=None):
    dists = get_distance2_matrix(centers, moving)
    i1, i2 = np.where(dists < r2)
    i1_ = (np.arange(centers.shape[0])[moving])[i1]
    same = i2 != i1_
    return i2[same], i1_[same]

def get_average_distance(centers):
    closest_circs = np.min(np.sqrt(get_distance2_matrix(centers)) + np.identity(centers.shape[0]) * 1e10, axis=1)
    return np.mean(closest_circs)

def unify_speed(v, uni_speed):
    v_norm = np.sqrt(np.sum(v**2, axis=1))
    return v/v_norm[:,None] * uni_speed

def correct_center(v1, v2, c1, c2, r2):
    delta_v = v1 - v2
    alpha = c1 - c2
    cur_dist = (alpha**2).sum()
    delta_v_norm = (delta_v**2).sum()
    scalar = np.multiply(alpha,delta_v).sum()
    lambda_correct = (scalar + 0.5 * np.sqrt(4*scalar**2 - 4*delta_v_norm*(cur_dist-r2)))/delta_v_norm
    return lambda_correct

def update_vectors(x1_inds, x2_inds, v, c, r2):
    match_dict = {}
    for i, k in zip(x1_inds, x2_inds):
        tup = (min(i,k), max(i,k))
        if not (tup in match_dict):

            match_dict[tup] = 1
            l = correct_center(v[i], v[k], c[i], c[k], r2 + 0.01)
            c_i = c[i] - l*v[i]
            c_k = c[k] - l*v[k]
            c[i, :] = c_i
            c[k, :] = c_k

            alpha = c[k, :] - c[i, :]
            alpha2 = alpha**2

            delta_alpha = alpha2[1] - alpha2[0]
            norm_alpha = alpha2[0] + alpha2[1]
            mult_alpha = alpha[0]*alpha[1]

            new_vx = (delta_alpha * v[i, 0] - 2*mult_alpha*v[i, 1])/norm_alpha
            new_vy = (-delta_alpha * v[i, 1] - 2*mult_alpha*v[i, 0])/norm_alpha
            v[i, 0] = new_vx
            v[i, 1] = new_vy

            new_vx = (delta_alpha * v[k, 0] - 2*mult_alpha*v[k, 1])/norm_alpha
            new_vy = (-delta_alpha * v[k, 1] - 2*mult_alpha*v[k, 0])/norm_alpha

            v[k, 0] = new_vx
            v[k, 1] = new_vy

    return v, c

if __name__ == "__main__":
    print("Test1: ", update_vectors(np.array([0]), np.array([1]), np.array([[2, 2], [-2, -2]],dtype=np.float64), np.array([[0, 0], [2, 4]])))
    print("Test2: ", update_vectors(np.array([0]), np.array([1]), np.array([[2, 2], [-2, -2]],dtype=np.float64), np.array([[0, 0], [4, 4]])))
    print("Test3: ", update_vectors(np.array([0]), np.array([1]), np.array([[1, 0], [0, 0]],dtype=np.float64), np.array([[0, 0], [4, 0]])))
    print("Test4: ", update_vectors(np.array([0, 1]), np.array([1, 2]), np.array([[2, 2], [-2, 2], [-2, -2]],dtype=np.float64), np.array([[0, 0], [4, 4], [8, 8]])))
    exit()

    for N in [200, 500, 1000, 10000, 20000]:
        x = np.arange(0, N, 2, dtype=int)
        y = np.arange(0, N, 2, dtype=int)
        centers = np.vstack((x, y)).T #Center points of circles
        velocities = np.vstack((np.random.normal(0, 1,size=N), np.random.normal(0, 1, size=N))).T

        t1 = time.time()
        inds1, inds2 = get_collisions(centers, 16)
        t2 = time.time()
        ret = update_vectors(inds1, inds2, velocities, centers)
        t3 = time.time()
        d1 = t2 - t1
        d2 = t3 - t2
        df = t3 - t1
        print("vectorize: ", N,df, d1/df, d2/df, (len(inds1)-len(x))/2)