import chess
import chess.pgn

class Game:
    def __init__(self, model, model_format="lan", human_start=True, start_position=None):
        if start_position == None:
            self.board = chess.Board()
        else: # Play from any position
            self.board = chess.Board(fen=start_position)
        self.model = model
        self.model_format = model_format
        self.human_turn = human_start # True if human has first move, False if AI starts

        if model_format == "san" or "pgn": # python-chess requires an empty board to parse the move stack
            self.empty_board = chess.Board()

    def play(self):
        display(self.board) # Display the board position in a nice way
        print("Board position: ", self.get_board_position(self.model_format)) # Print board position in notation (this is what the model sees)

        move = self.get_move(self.human_turn)

        if move in self.board.legal_moves:
            self.board.push(move) # MAKE THE MOVE (most important line of code)
            self.human_turn = not self.human_turn # Switch turns

            if not self.board.is_game_over(): # Check if the game is over, if not play the next round
                self.play()
            else:
                display(self.board)
                print("Game over!")

        else:
            display(self.board)
            print("An invalid move was made and the game has ended.")

    def get_move(self, human_turn):
        # Get move from human
        if human_turn:
            try:
                move_text = str(input("Your move: "))
                move = self.board.parse_san(move_text)
            except:
                print("Invalid move text! Please try again.")
                move_text = str(input("Your move: "))
                move = self.board.parse_san(move_text)
            return move
        # Get move from AI
        else:
            board_position = self.get_board_position(self.model_format)
            if self.model_format == "pgn" or self.model_format == "san":
                moves = self.model.generate(board_position, 6, 5) # Generate top 5 strings of 6 tokens (the maximum length of a move in SAN notation)
                for move in moves:
                    move = move.replace(board_position+" ", "") # Keep only the newly generated string
                    move = move.split(" ")[0] # The first move in the string is the new move
                    try:
                        move = self.board.parse_san(move)
                    except:
                        continue
                    if move in self.board.legal_moves:
                        return move
            elif self.model_format == "lan" or self.model_format == "uci":
                moves = self.model.generate(board_position, 1, 5) # Generate top 5 strings of 1 token (each move is one token)
                for move in moves:
                    move = move.split(" ")[-1] # Take the last token, which is the new move
                    move = self.board.parse_san(move)
                    if move in self.board.legal_moves:
                        return move
            # No legal move found
            if self.model_format == "lan" or self.model_format == "uci": # If model uses UCI/LAN format, we can force a legal move with constrained beam search
                move = self.model.generate_legal_move(board_position, self.board)
                move = self.board.parse_san(move)
                return move
            else: # If model uses PGN/SAN format, we cannot use constrained beam search, as moves consist of multiple tokens
                #yprint("The model was not able to find a legal move. It will now resign.")
                raise(ValueError("The model was not able to find a legal move."))

    def get_board_position(self, format):
        if format == "uci" or format == "lan": # Return the board position in LAN notation
            # Found no way to get LAN notation directly in documentation, so it has to be created manually
            text = ""
            for index, move in enumerate(self.board.move_stack):
                if index % 2 == 0:
                    text += str(int(index/2)+1) + ". "
                text += str(move) + " "
            return text
        elif format == "pgn" or format == "san": # Return the board position in SAN notation
            return self.empty_board.variation_san(self.board.move_stack)
        elif format == "fen": # Return the board position in FEN notation
            return self.board.fen()
        else:
            raise ValueError("Invalid format. Please use 'lan' or 'pgn'.")


from http.server import HTTPServer, SimpleHTTPRequestHandler, test
import logging
import os
import shutil
import threading
import time

class CORSWebServer:
    def __init__(self):
        self.thread = None
        self.server = None

    def serve(self):
        outer = self

        class ClojureServer(HTTPServer):
            def __init__(self, *args, **kwargs):
                HTTPServer.__init__(self, *args, **kwargs)
                outer.server = self

        class CORSRequestHandler(SimpleHTTPRequestHandler):
            def end_headers(self):
                self.send_header("Access-Control-Allow-Origin", "*")
                SimpleHTTPRequestHandler.end_headers(self)

        test(CORSRequestHandler, ClojureServer)

    def start(self):
        self.thread = threading.Thread(target=self.serve)
        self.thread.start()

    def stop(self):
        if self.running:
            self.server.shutdown()
            self.server.server_close()
            self.thread.join()
            self.server = None
            self.thread = None

    @property
    def running(self):
        return self.server is not None

web_server = CORSWebServer()

def present_embeddings(destdir, run_server, labels, index, embeddings):
    log = logging.getLogger("projector")
    log.info("Writing Tensorflow Projector files...")
    if not os.path.isdir(destdir):
        os.makedirs(destdir)
    os.chdir(destdir)
    metaf = "id2vec_meta.tsv"
    with open(metaf, "w") as fout:
        if len(labels) > 1:
            fout.write("\t".join(labels) + "\n")
        for item in index:
            if len(labels) > 1:
                fout.write("\t".join(item) + "\n")
            else:
                fout.write(item + "\n")
        log.info("Wrote %s", metaf)
    dataf = "id2vec_data.tsv"
    with open(dataf, "w") as fout:
        for vec in embeddings:
            fout.write("\t".join(str(v) for v in vec))
            fout.write("\n")
        log.info("Wrote %s", dataf)
    jsonf = "id2vec.json"
    with open(jsonf, "w") as fout:
        fout.write("""{
  "embeddings": [
    {
      "tensorName": "id2vec",
      "tensorShape": [%s, %s],
      "tensorPath": "http://0.0.0.0:8000/%s",
      "metadataPath": "http://0.0.0.0:8000/%s"
    }
  ]
}
""" % (len(embeddings), len(embeddings[0]), dataf, metaf))
    log.info("Wrote %s", jsonf)
    if run_server and not web_server.running:
        web_server.start()
    url = "http://projector.tensorflow.org/?config=http://0.0.0.0:8000/" + jsonf
    log.info(url)
    if run_server:
        if shutil.which("xdg-open") is not None:
            os.system("xdg-open " + url)
        else:
            browser = os.getenv("BROWSER", "")
            if browser:
                os.system(browser + " " + url)
            else:
                print("\t" + url)

def wait():
    log = logging.getLogger("projector")
    secs = int(os.getenv("PROJECTOR_SERVER_TIME", "60"))
    log.info("Sleeping for %d seconds, safe to Ctrl-C" % secs)
    try:
        time.sleep(secs)
    except KeyboardInterrupt:
        pass
    web_server.stop()


import torch.nn as nn
from utils.Self_Adaptive_Conv import SAPConv
import torch

class SELayer(nn.Module):
    def __init__(self, channel, reduction=16):
        super(SELayer, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(channel // reduction, channel, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y.expand_as(x)

class BasicBlock(nn.Module):
    def __init__(self,
                 in_channels,
                 out_channels,
                 kernel_size,
                 stride=1,
                 downsample=False):
        super(BasicBlock, self).__init__()

        self.stride = stride
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.down = downsample

        # Both self.conv1 and self.downsample layers downsample the input when stride != 1
        self.conv1 = nn.Conv2d(self.in_channels,
                               self.out_channels,
                               self.kernel_size,
                               self.stride,
                               padding=1,
                               bias=False)
        self.bn1 = nn.BatchNorm2d(self.out_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(self.out_channels,
                               self.out_channels,
                               self.kernel_size,
                               padding=1,
                               bias=False)
        self.bn2 = nn.BatchNorm2d(self.out_channels)

        if self.down:
            self.downsample = nn.Sequential(
                nn.Conv2d(self.in_channels,
                          self.out_channels,
                          kernel_size=1,
                          stride=self.stride),
                nn.BatchNorm2d(self.out_channels))

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        if self.down:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

class MultiBlock(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size):
        super(MultiBlock, self).__init__()

        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size

        # Both self.conv1 and self.downsample layers downsample the input when stride != 1
        self.conv1 = nn.Conv2d(self.in_channels,
                               self.out_channels,
                               self.kernel_size,
                               stride=1,
                               padding=1,
                               bias=False)
        self.bn1 = nn.BatchNorm2d(self.out_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = SAPConv(self.out_channels,
                             self.out_channels,
                             is_bias=False)
        self.bn2 = nn.BatchNorm2d(self.out_channels)

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        out += identity
        out = self.relu(out)

        return out

class Resnet18(nn.Module):
    def __init__(self, K_bits=1000):
        super(Resnet18, self).__init__()
        self.conv1 = nn.Conv2d(3,
                               64,
                               kernel_size=7,
                               stride=2,
                               padding=3,
                               bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

        # yapf:disable
        self.layer1 = nn.Sequential(
            BasicBlock(64, 64, kernel_size=3),
            BasicBlock(64, 64, kernel_size=3))
        self.layer2 = nn.Sequential(
            BasicBlock(64, 128, kernel_size=3, stride=2, downsample=True),
            BasicBlock(128, 128, kernel_size=3))
        self.layer3 = nn.Sequential(
            BasicBlock(128, 256, kernel_size=3, stride=2, downsample=True),
            BasicBlock(256, 256, kernel_size=3))
        self.layer4 = nn.Sequential(
            BasicBlock(256, 512, kernel_size=3, stride=2, downsample=True),
            MultiBlock(512, 512, kernel_size=3))
        # MultiBlock(512, 512, kernel_size=3))
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Sequential(nn.BatchNorm1d(512), nn.Linear(512, K_bits))

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)

        x = self.layer1(x)
        x = self.layer2(x)
        x3 = self.layer3(x)
        x4 = self.layer4(x3)

        features = self.avgpool(x4)
        features = features.reshape(features.size(0), -1)
        real_hash = self.fc(features)
        return real_hash


from typing import ContextManager
from articles.models import Article
from django.shortcuts import redirect, render, get_object_or_404

# Create your views here.
def index(request):
    articles = Article.objects.order_by('-pk')
    context={
        'articles' : articles,
    }
    return render(request, 'articles/index.html', context)

# def new(request):
#     return render(request, 'articles/new.html')

def create(request):
    if request.method == "POST":
        title = request.POST.get('title')
        content = request.POST.get('content')

        article = Article(title=title, content=content)
        article.save()

        return redirect('articles:detail', article.pk)
    else:
        return render(request, 'articles/new.html')

def detail(request, article_pk):
    article = get_object_or_404(Article, pk=article_pk)

    context = {
        'article':article
    }
    return render(request, 'articles/detail.html', context)

def edit(request, article_pk):
    article = get_object_or_404(Article, pk=article_pk)

    context = {
        'article' : article
    }
    return render(request, 'articles/edit.html', context)

def update(request, article_pk):
    title = request.POST.get('title')
    content = request.POST.get('content')

    article = Article.objects.get(pk=article_pk)
    article.title = title
    article.content = content
    article.save()

    return redirect('articles:detail', article_pk)

def delete(request, article_pk):
    if request.method == 'POST':
        article = Article.objects.get(pk=article_pk)
        article.delete()

        return redirect('articles:index')


import io
import sys
import requests
import json
import bs4
import csv

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'}

baseUrl = 'https://www.zhihu.com/api/v4/questions/66515131/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit={0}&offset={1}' # from Inspect --> Network --> XHR
url = baseUrl.format('5', '0') # limit and offset, current max offset is 1075

answers = []
isEnd = False

while not isEnd:

    response = requests.get(url, headers=headers)
    response.encoding = 'utf-8'
    responseDict = json.loads(response.text)

    for answersHtml in responseDict['data']:

        answer = ''
        soup = bs4.BeautifulSoup(answersHtml['content'], 'html.parser')

        for paragraphHtml in soup.findAll('p'):

            answer += paragraphHtml.text
            answer += '\n\n'

        answers.append([answer]) # [] for csv writer use

    isEnd = responseDict['paging']['is_end']
    url = responseDict['paging']['next']

with open('rawAnswer.csv', 'w') as f:

    writer = csv.writer(f)

    for answer in answers:
        writer.writerow(answer)


def validIPAddresses(string):
	output = []
	backtrack(string, [], output,0)
	return output
def backtrack(string, curr, output, index):
	if index == len(string) and len(curr)==4:
		output.append(".".join(curr[:]))
	elif len(curr)<4:
		for i in range(index, min(index+4, len(string)+1)):
			toAdd = string[index:i]
			if toAdd and 0<=int(toAdd)<=255:
				if  len(toAdd)>1 and string[index]=="0":
					break
				curr.append(toAdd)
				backtrack(string, curr, output, i)
				curr.pop()
	return output


import cv2 as cv
import numpy as np
from google.colab.patches import cv2_imshow

img = cv.imread("imagem1.png")
imagemConvertida = "imagemconvertida.png"

def bitfield(n):
    return [int(digit) for digit in bin(n)[2:]]

def gerar_mensagem(mensagem):
    lista = []
    for m in mensagem:
        val = ord(m)
        bits = bitfield(val)

        if len(bits) < 8:
            for a in range(8-len(bits)):
                bits.insert(0,0)
        lista.append(bits)
    arr = np.array(lista)
    arr = arr.flatten()
    return arr

def converter_mensagem(saida):
    bits = np.array(saida)
    mensagem_out = ''
    bits = bits.reshape((int(len(saida)/8), 8))
    for b in bits:
        sum = 0
        for i in range(8):
            sum += b[i]*(2**(7-i))
        mensagem_out += chr(sum)
    return mensagem_out

def esconder_mensagem(mensagem):
  imgAltera = img.copy()
  altura, largura, x = img.shape
  tamanho_mensagem = len(mensagem)
  print("tamanho da mensagem = "+str(tamanho_mensagem))
  pos = 0

  for i in range(altura):
        for j in range(largura):
            if tamanho_mensagem > pos:
                p = img[i][j][2]
                valor = ((p // 10) * 10) + mensagem[pos]
                imgAltera[i][j][2] = valor
            elif tamanho_mensagem == pos:
                imgAltera[i][j][2] = ((p // 10) * 10) + 2
            pos = pos + 1

  cv2_imshow(imgAltera)
  cv.imwrite(imagemConvertida, imgAltera)
  cv.waitKey(0)

def encontra_mensagem():
    img2 = cv.imread(imagemConvertida)
    altura, largura, x = img.shape
    mensagem = []
    for i in range(altura):
        for j in range(largura):
            p = img2[i][j][2]
            # print(p)
            if (p % 10) < 2:
                mensagem.append(p % 10)
            elif (p % 10) >= 2:
                print("Mensagem encontrada: ")
                print(converter_mensagem(mensagem))
                return mensagem

texto = "Se alguma coisa pode dar errado, dará"
arrayBits = gerar_mensagem(texto)
print("mensagem em binario = " + str(arrayBits))
esconder_mensagem(arrayBits)
encontra_mensagem()
cv2_imshow(img)


# pypy3만 통과

import sys
from math import gcd

input = sys.stdin.readline

def lcm(a: int, b: int):
    return a * b / gcd(a, b)

def cain(m: int, n: int, x: int, y: int):
    limit = lcm(m, n)
    i, j = 0, 0
    tmpx, tmpy = x, y

    while tmpx <= limit and tmpy <= limit:
        if tmpx == tmpy:
            return tmpx
        if tmpx > tmpy:
            j += 1
        elif tmpx < tmpy:
            i += 1
        else:
            if tmpx + m > tmpy + n:
                j += 1
            else:
                i += 1
        tmpx, tmpy = x + m * i, y + n * j
    return -1

if __name__ == "__main__":
    t = int(input())
    for _ in range(t):
        m, n, x, y = map(int, input().split())
        print(cain(m, n, x, y))

###################################################################################################################

"""
jys9047's code
- https://www.acmicpc.net/source/25358405
"""

def euc(x: int, y: int):
    queue = []
    while y:
        queue.append(x // y)
        x, y = y, x % y
    queue.pop()
    a, b = 0, 1
    for i in queue[::-1]:
        a, b = b, a - i * b
    return x, a, b

t = int(input())
for _ in range(t):
    m, n, x, y = map(int, input().split())
    d = x - y
    g, a, b = euc(m, n)
    if d % g:
        print(-1)
    else:
        k = x - (d // g) * a * m
        print((k - 1) % (m // g * n) + 1)

###################################################################################################################

"""
https://pacific-ocean.tistory.com/126
"""

def num(m, n, x, y):
    while x <= m * n:
        if (x - y) % n == 0:
            return x
        x += m
    return -1

t = int(input())
for i in range(t):
    m, n, x, y = map(int, input().split())
    print(num(m, n, x, y))


"""
Created at 2019-12-09 19:00

@author: jinyanliu
"""
from enum import Enum

class Opcode(Enum):
    ADD = 1
    MULTIPLY = 2
    INPUT = 3
    OUTPUT = 4
    JUMP_IF_TRUE = 5
    JUMP_IF_FALSE = 6
    LESS_THAN = 7
    EQUALS = 8
    RELATIVE_BASE = 9
    HALT = 99

class ParametersMode(Enum):
    POSITION = 0
    IMMEDIATE = 1
    RELATIVE = 2

class InstructionDictKey(Enum):
    OPCODE = "opcode"
    FIRST_MODE = "first_mode"
    SECOND_MODE = "second_mode"
    THIRD_MODE = "third_mode"

def get_dict_of_int_input():
    dict_of_int_input = {}
    i = 0
    with open("day_9_input") as lines:
        list_of_string = lines.readline().split(',')
        for s in list_of_string:
            dict_of_int_input[i] = int(s)
            i += 1
    print(dict_of_int_input)
    return dict_of_int_input

def get_dict_instruction(digits):
    instruction_string = str(digits).zfill(5)
    instruction_dict = {InstructionDictKey.OPCODE.value: int(instruction_string[3] + instruction_string[4]),
                        InstructionDictKey.FIRST_MODE.value: int(instruction_string[2]),
                        InstructionDictKey.SECOND_MODE.value: int(instruction_string[1]),
                        InstructionDictKey.THIRD_MODE.value: int(instruction_string[0])}
    return instruction_dict

def get_instructions(instruction_code):
    dict_instruction = get_dict_instruction(instruction_code)
    opcode = dict_instruction[InstructionDictKey.OPCODE.value]
    first_mode = dict_instruction[InstructionDictKey.FIRST_MODE.value]
    second_mode = dict_instruction[InstructionDictKey.SECOND_MODE.value]
    third_mode = dict_instruction[InstructionDictKey.THIRD_MODE.value]
    return opcode, first_mode, second_mode, third_mode

def get_value(mode, input_dict, i, relative_base, number):
    if mode == ParametersMode.POSITION.value:
        return input_dict[input_dict[i + number]] if input_dict[i + number] in input_dict.keys() else 0
    elif mode == ParametersMode.IMMEDIATE.value:
        return input_dict[i + number]
    elif mode == ParametersMode.RELATIVE.value:
        relative_position = relative_base + input_dict[i + number]
        return input_dict[relative_position]

def get_replace_position(mode, input_dict, i, relative_base, number):
    if mode == ParametersMode.POSITION.value:
        return input_dict[i + number]
    elif mode == ParametersMode.RELATIVE.value:
        return relative_base + input_dict[i + number]

def get_last_output(list_of_input_integers, input_dict):
    i = 0
    step = 0
    output_value = None
    relative_base = 0
    while i + 1 < len(input_dict):
        should_increase_i = True

        opcode, first_mode, second_mode, third_mode = get_instructions(input_dict[i])

        if opcode == Opcode.ADD.value:
            first_value = get_value(first_mode, input_dict, i, relative_base, 1)
            second_value = get_value(second_mode, input_dict, i, relative_base, 2)
            replace_position = get_replace_position(third_mode, input_dict, i, relative_base, 3)
            input_dict[replace_position] = first_value + second_value
            step = 3

        elif opcode == Opcode.MULTIPLY.value:
            first_value = get_value(first_mode, input_dict, i, relative_base, 1)
            second_value = get_value(second_mode, input_dict, i, relative_base, 2)
            replace_position = get_replace_position(third_mode, input_dict, i, relative_base, 3)
            input_dict[replace_position] = first_value * second_value
            step = 3

        elif opcode == Opcode.INPUT.value:
            replace_position = get_replace_position(first_mode, input_dict, i, relative_base, 1)
            input_dict[replace_position] = list_of_input_integers[0]
            print("input_value = " + str(list_of_input_integers[0]))
            list_of_input_integers.pop(0)
            step = 1

        elif opcode == Opcode.OUTPUT.value:
            output_value = get_value(first_mode, input_dict, i, relative_base, 1)
            print("output_value = " + str(output_value))
            step = 1

        elif opcode == Opcode.JUMP_IF_TRUE.value:
            first_value = get_value(first_mode, input_dict, i, relative_base, 1)
            if first_value != 0:
                second_value = get_value(second_mode, input_dict, i, relative_base, 2)
                i = second_value
                should_increase_i = False
            step = 2

        elif opcode == Opcode.JUMP_IF_FALSE.value:
            first_value = get_value(first_mode, input_dict, i, relative_base, 1)
            if first_value == 0:
                second_value = get_value(second_mode, input_dict, i, relative_base, 2)
                i = second_value
                should_increase_i = False
            step = 2

        elif opcode == Opcode.LESS_THAN.value:
            first_value = get_value(first_mode, input_dict, i, relative_base, 1)
            second_value = get_value(second_mode, input_dict, i, relative_base, 2)
            place_to_store = get_replace_position(third_mode, input_dict, i, relative_base, 3)
            if first_value < second_value:
                input_dict[place_to_store] = 1
            else:
                input_dict[place_to_store] = 0
            step = 3

        elif opcode == Opcode.EQUALS.value:
            first_value = get_value(first_mode, input_dict, i, relative_base, 1)
            second_value = get_value(second_mode, input_dict, i, relative_base, 2)
            place_to_store = get_replace_position(third_mode, input_dict, i, relative_base, 3)
            if first_value == second_value:
                input_dict[place_to_store] = 1
            else:
                input_dict[place_to_store] = 0
            step = 3

        elif opcode == Opcode.RELATIVE_BASE.value:
            first_value = get_value(first_mode, input_dict, i, relative_base, 1)
            relative_base += first_value
            step = 1

        elif opcode == Opcode.HALT.value:
            break

        if should_increase_i:
            i += step + 1
    return output_value

def get_solution_1():
    return get_last_output([1], get_dict_of_int_input())

def get_solution_2():
    return get_last_output([2], get_dict_of_int_input())

if __name__ == "__main__":
    print(get_solution_1())
    print(get_solution_2())


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# Read the dataset from a CSV file
data = pd.read_csv('/Users/bunty/Documents/GitHub/21bq1a4264/Python/AdvancedPython/MUsigma/predicted_data.csv')

# Separate the independent variable (X) and dependent variable (y)
X = data.iloc[:, 2:].values # Independent variable (population values)
print(len(X))
Y = data.iloc[:, 2:].values   # Dependent variable (state of the elephants)
print(len(Y))
# Create a linear regression model
regressor = LinearRegression()

# Train the model
regressor.fit(X, Y)

# Predict the values for the scatter plot
y_pred = regressor.predict(X)

# Plot the scatter plot of the dataset
plt.scatter(X, Y, color='blue', label='Actual Data')

# Plot the regression line
plt.plot(X, y_pred, color='red', label='Regression Line')

# Set the labels and title of the plot
plt.xlabel('Population')
plt.ylabel('State of Elephants')
plt.title('Regression Line and Scatter Plot')

# Show the legend
plt.legend()

# Show the plot
plt.show()


import random
import getch
import gspread
from google.oauth2.service_account import Credentials

SCOPE = [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/drive"
    ]

CREDS = Credentials.from_service_account_file('creds.json')
SCOPED_CREDS = CREDS.with_scopes(SCOPE)
GSPREAD_CLIENT = gspread.authorize(SCOPED_CREDS)
SHEET = GSPREAD_CLIENT.open('2048')

print("\033c")

def is_cell_free(grid, row, cell):
    '''It returns true if an index is equal to 0'''
    return grid[row][cell] == 0

def get_free_cells(grid):
    '''It gets a list of indexes in the grid which equal 0'''
    free_cells = []
    row_count = -1

    for row in grid:
        row_count = row_count + 1
        index_count = -1
        for value_index in row:
            index_count = index_count + 1
            if value_index == 0:
                free_cells.append([row_count, index_count])
    return(free_cells)

def get_random_free_cell(grid):
    '''It gets a random index from the grid'''
    free_cells = get_free_cells(grid)
    random_free_cell = random.choice(free_cells)

    return(random_free_cell)

def place_random_number(grid):
    '''It places a 2 on a random index on the grid'''
    random_cell = get_random_free_cell(grid)

    array[random_cell[0]][random_cell[1]] = 2

def check_if_grid_is_full(grid):
    cells = []
    i = 0
    for x in grid:
        for y in x:
            cells.append(y)
    if i in cells:
        return False
    else:
        return True

array = [
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
]

place_random_number(array)
for row in array:
    print(row[0], row[1], row[2], row[3])
print('\n\nh = up\nj = down\nk = left\nl = right')

# Move Up Functionality

def get_columns_top_empty_cell(grid, row_index, cell_index):
    '''It returns the topmost cell in a column whos value equals 0'''

    for x in reversed(range(row_index + 1)):
        # If its any row, and any cell above is full, return index before full cell
        if is_cell_free(grid, x - 1, cell_index) is False:
            return([x, cell_index])
        # next, if its any row, and above cell is (empty && row 1) -> return row 1 index
        elif is_cell_free(grid, x - 1, cell_index) and x == 1:
            return([x - 1, cell_index])

def move_cell_up(grid, row_index, cell_index):
    '''It moves the current cell to the highest empty cell'''
    target_index = get_columns_top_empty_cell(grid, row_index, cell_index)
    cell_value = grid[row_index][cell_index]

    grid[int(target_index[0])][cell_index] = cell_value

    if row_index != target_index[0]:
        grid[row_index][cell_index] = 0
    return grid

# !!!This function is not in use yet!!!
def merge_cells(grid, cell, i, j):
    '''It will contain merge cells logic and reduce nested looping in move_grid_up'''
    for row in range(1, 4):
        if (cell != 0 and cell != grid[row][j] and grid[row][j]):
            continue
        elif (cell == grid[row][j]):
            array[i][j] = cell + grid[row][j]
            array[row][j] = 0

def move_grid_up(grid):
    '''It moves each cell on the board up'''
    # Loop over the array and merge a cell if the same cell is below it
    for x in range(4):
        for y in range(4):
            cell = grid[x][y]
            if (cell != 0):
               for n in range(x + 1, 4):
                if (cell != 0 and cell != grid[n][y] and grid[n][y] != 0):
                    continue
                elif (cell == grid[n][y]):
                    grid[x][y] = cell + cell
                    grid[n][y] = 0

    # Move all cells up to the highest 'empty' cell
    for x in range(4):
        for y in range(4):
            if is_cell_free(grid, x, y) is False and x != 0 and is_cell_free(grid, x - 1, y) is True:
                grid = move_cell_up(grid, x, y)

    place_random_number(array)
    for row in array:
        print(row[0], row[1], row[2], row[3])

# Move Down Functionality

def move_grid_down(grid):
    '''It moves each cell on the board down'''
    grid.reverse()

    # Loop over the array and merge a cell if the same cell is above it
    for x in range(4):
        for y in range(4):
            cell = grid[x][y]
            if (cell != 0):
               for n in range(x + 1, 4):
                if (cell != 0 and cell != grid[n][y] and grid[n][y] != 0):
                    continue
                elif (cell == grid[n][y]):
                    grid[x][y] = cell + cell
                    grid[n][y] = 0

    # Move all cells down to the lowest 'empty' cell
    for x in range(4):
        row = grid[x]
        for y in range(4):
            if is_cell_free(grid, x, y) is False and x != 0:
                move_cell_up(grid, x, y)

    grid.reverse()

    place_random_number(array)
    for row in array:
        print(row[0], row[1], row[2], row[3])

# Move Left Functionality

def get_rows_leftmost_empty_cell(grid, row_index, cell_index):
    '''It returns the leftmost cell in a row whos value equals 0'''
    for x in reversed(range(cell_index + 1)):
        # if its any cell, and any cell to the left is full, return index before full cell
        if is_cell_free(grid, row_index, x - 1) is False:
            return([row_index, x])
        # next, if its any row, and left cell is (empty && col 1) -> return col 1 index
        elif is_cell_free(grid, row_index, x - 1) and x == 1:
            return([row_index, x - 1])

def move_cell_left(grid, row_index, cell_index):
    '''It moves an individual cell left to the leftmost empty cell'''
    target_index = get_rows_leftmost_empty_cell(grid, row_index, cell_index)
    cell_value = grid[row_index][cell_index]

    grid[row_index][int(target_index[1])] = cell_value

    if cell_index != target_index[1]:
        grid[row_index][cell_index] = 0
    return grid

def move_grid_left(grid):
    '''It moves each cell on the board left'''
    for x in range(4):
        for y in range(4):
            current_cell = grid[x][y]
            if y == 0:
                continue
            if current_cell == grid[x][y - 1] and current_cell != 0:
                # merge cells
                grid[x][y - 1] = current_cell + current_cell
                grid[x][y] = 0
            elif is_cell_free(grid, x, y) is False and is_cell_free(grid, x, y - 1) is True:
                move_cell_left(grid, x, y)

    place_random_number(array)
    for row in array:
        print(row[0], row[1], row[2], row[3])

# Move Right Functionality

def get_rows_rightmost_empty_cell(grid, row_index, cell_index):
    '''It returns the rightmost cell in a row whos value equals 0'''
    for x in reversed(range(cell_index + 1)):
        # check column 3 with one empty ceel to right
        if x == 2 and grid[row_index][x + 1] == 0:
            return[row_index,x + 1]
        # check column 2 with two empty cells to right
        elif x == 1 and grid[row_index][x + 1] == 0 and grid[row_index][x + 2] == 0:
            return[row_index,x + 2]
        # check column 1 with three empty cells to right
        elif x == 0 and grid[row_index][x + 1] == 0 and grid[row_index][x + 2] == 0  and grid[row_index][x + 3] == 0:
            return[row_index,x + 3]
        # check column 2 with one empty cells to right
        elif x == 1 and  grid[row_index][x + 1] == 0 and grid[row_index][x + 2] != 0:
            return[row_index,x + 1]
        # check column 1 with two empty cells to right
        elif x == 0 and  grid[row_index][x + 1] == 0 and grid[row_index][x + 2] == 0  and grid[row_index][x + 3] != 0:
            return[row_index,x + 2]
        # check column 1 with one empty cell to right
        elif x == 0 and  grid[row_index][x + 1] == 0 and grid[row_index][x + 2] != 0  and grid[row_index][x + 3] != 0:
            return[row_index, x + 1]

def move_cell_right(grid, row_index, cell_index):
    '''It moves an individual cell right to the rightmost empty cell'''
    target_index = get_rows_rightmost_empty_cell(grid, row_index, cell_index)
    cell_value = grid[row_index][cell_index]

    grid[row_index][int(target_index[1])] = cell_value

    if cell_index != target_index[0]:
        grid[row_index][cell_index] = 0
    return grid

def move_grid_right(grid):
    '''It moves each cell on the board right'''
    for x in range(4):
        for y in reversed(range(4)):
            current_cell = grid[x][y]
            if y == 3:
                continue
            # merge cells
            if current_cell == grid[x][y + 1] and current_cell != 0:
                #print(f'merge {current_cell} + {grid[x][y + 1]}')
                grid[x][y + 1] = current_cell + current_cell
                grid[x][y] = 0
            # move any full cell to the right
            elif is_cell_free(grid, x, y) is False and is_cell_free(grid, x, y + 1) is True:
                move_cell_right(grid, x, y)

    place_random_number(array)
    for row in array:
        print(row[0], row[1], row[2], row[3])

# SCOREBOARD
def count_score(grid):
    '''It returns the highest number on the board'''
    cell_list = []
    for x in range(4):
        for y in range(4):
            cell_list.append(grid[x][y])

    current_score = max(cell_list)
    return(current_score)

# End Game & Update Leader Board
scores = SHEET.worksheet('scoreboard')
data = scores.get_all_values()

def update_high_score(data):
    '''It takes the highest number on the board, and updates google sheet if its a new high score'''

    scoreboard = SHEET.worksheet('scoreboard')

    high_score = scoreboard.acell('A2').value

    if int(data) > int(high_score):
        scoreboard.update('A2', data)
        print('New high score: ', data)
    else:
        print('Play again to try beat the high score')

# User presses h, j, k, l to play
while True:
    char = getch.getch()

    if char == 'h':
        if check_if_grid_is_full(array) is False:
            print("\033c")
            move_grid_up(array)
            print('\n\nh = up\nj = down\nk = left\nl = right')
        elif check_if_grid_is_full(array) is True:
            print('\nGAME OVER')
            score = count_score(array)
            update_high_score(score)

    elif char == 'j':
        if check_if_grid_is_full(array) is False:
            print("\033c")
            move_grid_down(array)
            print('\n\nh = up\nj = down\nk = left\nl = right')
        if check_if_grid_is_full(array) is True:
            print('\nGAME OVER')
            score = count_score(array)
            update_high_score(score)

    elif char == 'k':
        if check_if_grid_is_full(array) is False:
            print("\033c")
            move_grid_left(array)
            print('\n\nh = up\nj = down\nk = left\nl = right')
        if check_if_grid_is_full(array) is True:
            print('\nGAME OVER')
            score = count_score(array)
            update_high_score(score)

    elif char == 'l':
        if check_if_grid_is_full(array) is False:
            print("\033c")
            move_grid_right(array)
            print('\n\nh = up\nj = down\nk = left\nl = right')
        if check_if_grid_is_full(array) is True:
            print('\nGAME OVER')
            score = count_score(array)
            update_high_score(score)


import pygame as pg
# line 18

BLACK = pg.Color("black")
WHITE = pg.Color("white")

class TextPrint(object):
    def __init__(self, fontSize):
        self.fontSize = fontSize
        self.x = ""
        self.y = ""
        self.lineHeight = ""
        self.font = pg.font.Font(None, fontSize)
        self.reset()

    def tprint(self,screen,text):
        textBitMap = self.font.render(text, True, BLACK)
        screen.blit(textBitMap, (self.x, self.y))
        # Comment this out for text not to move
        self.y += self.lineHeight

    def reset(self):
        self.x = 15
        self.y = 15
        self.lineHeight = self.fontSize-5

    def indent(self):
        self.x += 10

    def unIndent(self):
        self.x -= 10

pg.init()
screen = pg.display.set_mode((500,900))
pg.display.set_caption("XBOX LIVE")

running = True

clock = pg.time.Clock()
fps = 40
text = TextPrint(25)
screen.fill(WHITE)
pg.joystick.init()
controllerList = ""

while running:

    # Tick Clock
    clock.tick(fps)

    # Get Input

    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False
        elif event.type == pg.JOYBUTTONDOWN:
            print("Pressed a button")
        elif event.type == pg.JOYBUTTONUP:
            print("Released a button")

    screen.fill(WHITE)
    text.reset()

    joyStickCount = pg.joystick.get_count()
    text.tprint(screen,"number of joysticks {}".format(joyStickCount))
    text.indent()

    for i in range(joyStickCount):
        controller = pg.joystick.Joystick(i)
        controller.init()

        try:
            controllerId = controller.get_instance_id()
        except AttributeError:
            controllerId = controller.get_id()
        text.tprint(screen, "Controller {}".format(controllerId))
        text.indent()

        controllerName = controller.get_name()
        text.tprint(screen, "controller name {}".format(controllerName))

        try:
            guid = controller.get_guid()
        except AttributeError:
            pass
        else:
            text.tprint(screen, "GUID {}".format(guid))

        axes = controller.get_numaxes()
        text.tprint(screen,"number of axes {}".format(axes))
        text.indent()
        for i in range(axes):
            axis = controller.get_axis(i)
            text.tprint(screen, "axis {} value {:>6.3f}".format(i, axis))
        text.unIndent()
        buttons = controller.get_numbuttons()
        text.tprint(screen, "number of buttons {}".format(buttons))
        text.indent()

        for i in range(buttons):
            button = controller.get_button(i)
            text.tprint(screen, "Button {:>2} value: {}".format(i, button))
        text.unIndent()

        hats = controller.get_numhats()
        text.tprint(screen, "Number of hats: {}".format(hats))
        text.indent()

        for i in range(hats):
            hat = controller.get_hat(i)
            text.tprint(screen, "Hat {} value: {}".format(i, str(hat)))
            text.indent()

    # Update
#0 A
#1 B
#2 X
#3 Y
#4 LB
#5 RB
#6 LMENU button
#7 RMENU button
#8 L3
#9 R3
# (0, 1) Forward
# (1, 0) Right
# (0 , -1) Down
# (-1, 0) Left

    # Draw
    text.reset()
    pg.display.flip()

pg.quit()
quit()


import os
import pathlib
import sys

import CppHeaderParser

headers: list[CppHeaderParser.CppHeader] = []

warn_noexcept = False

def absoluteFilePaths(directory: str):
    for dirpath, _, filenames in os.walk(directory):
        for f in filenames:
            yield os.path.abspath(os.path.join(dirpath, f))

def discoverParents(current: CppHeaderParser.CppClass, classes: list[CppHeaderParser.CppClass]) -> list[CppHeaderParser.CppClass]:
    parents: list[CppHeaderParser.CppClass] = []
    for cls in classes:
        for parent in current.get('inherits'):
            if cls.get('name') == parent.get('class'):
                if cls not in parents:
                    parents.append(cls)
                    parents += discoverParents(cls, classes)
    return parents

def getFullSignature(cls: CppHeaderParser.CppClass, method: CppHeaderParser.CppMethod)-> str:
    return f"{cls.get('namespace')}::{cls.get('name')}::{method.get('debug')}"

def getFullSignatureWithFileName(cls: CppHeaderParser.CppClass, method: CppHeaderParser.CppMethod)-> str:
    res = getFullSignature(cls, method)
    res += f" at line {method.get('line_number')} in file {method.get('filename')}"
    return res

def compareParams(lhs: CppHeaderParser.CppMethod, rhs: CppHeaderParser.CppMethod) -> tuple[bool, list[str]]:
    result: tuple[bool, list[str]] = (False, [])

    lhs_params = lhs.get('parameters')
    rhs_params = rhs.get('parameters')

    for i, l_param in enumerate(lhs_params):
        r_param = rhs_params[i]
        if(l_param.get('type') != r_param.get('type')) and (l_param.get('type').replace('const ','') != r_param.get('type').replace('const ','')):
            return (True, [])
        if(l_param.get('constant') != r_param.get('constant')):
            result[1].append(f"Potential const mismatch at parameter {i} ({r_param.get('name')})")
        #if(m lhs_params[i])
    return result

def compareMethods(lhs: CppHeaderParser.CppMethod, rhs: CppHeaderParser.CppMethod, parent: CppHeaderParser.CppClass, other: CppHeaderParser.CppClass):
    #different return type is enough distinction
    if (lhs.get('rtnType') != rhs.get('rtnType')):
        return

    #so is a different number of parameters
    if len(lhs.get('parameters')) != len(rhs.get('parameters')):
        return

    problems: list[str] = []
    #so are different types of params
    res = compareParams(lhs, rhs)

    #There were different param types
    if res[0]:
        return

    problems+= res[1]

    if lhs.get('const') != rhs.get('const'):
        problems.append(f'Methods {getFullSignature(parent, lhs)} and {getFullSignature(other, rhs)} have different const qualifiers.')

    if not lhs.get('virtual'):
        problems.append(f'Method {getFullSignature(parent, lhs)} is not marked virtual.')

    if warn_noexcept and (lhs.get('noexcept') != rhs.get('noexcept')):
        problems.append(f'Methods {getFullSignature(parent, lhs)} and {getFullSignature(other, rhs)} have different noexcept qualifiers.')

    if(len(problems) > 0):
        print(f'Summary for {getFullSignatureWithFileName(other, rhs)}:')
    else:
        if not other.get('override'):
            print(f"Method {getFullSignatureWithFileName(other, rhs)} seems to be an override, consider using the 'override' keyword when compiling with std=c++11 or newer.")

    for problem in problems:
        print(problem)

    return

def findSimilarMethodsInClass(parent: CppHeaderParser.CppClass, other: CppHeaderParser.CppMethod, other_cls: CppHeaderParser.CppClass):
    for method in parent.get('methods').get('public'):
        if method.get('name') == other.get('name'):
            compareMethods(method, other, parent, other_cls)
    return

def findSimilarMethods(classes: list[CppHeaderParser.CppClass], current: CppHeaderParser.CppClass):
    if (len(current.get('inherits')) == 0):
        return
    print(f"\nProcessing methods of {current.get('name')}")

    # discover parent tree
    parents = discoverParents(current, classes)

    for method in current.get('methods').get('public'):
        for cls in parents:
            findSimilarMethodsInClass(cls, method, current)

    for method in current.get('methods').get('protected'):
        for cls in parents:
            findSimilarMethodsInClass(cls, method, current)

def processDir(dirPath: str):
    paths = absoluteFilePaths(dirPath)

    for entry in paths:
        if os.path.isfile(entry):
            if (pathlib.Path(entry).suffix == ".h"):
                try:
                    headers.append(CppHeaderParser.CppHeader(entry))
                except CppHeaderParser.CppHeaderParser.CppParseError:
                    print(f'Excluded classes of header {entry} due to a c++ parser error.')
                except:
                    print(f'An unknown error occured while parsing header {entry}. Some classes may not get checked.')

    classes: list[CppHeaderParser.CppClass] = []
    for header in headers:
        for cls in header.classes:
            classes.append(header.classes.get(cls))

    # process loaded classes
    for cls in classes:
        findSimilarMethods(classes, cls)

def main(argv):
    in_path: str = argv[0]
    print(f'Processing files in directory {in_path}')
    processDir(in_path)

if __name__ == "__main__":
    if (len(sys.argv) > 1):
        sys.exit(main(sys.argv[1:]))
    else:
        sys.exit(main(["./testlib"])) #received no library path


from clean_text import cleanText
from tokenize import tokenize
from markov import markovChain, randomWalk

# set up flask app with mongodb
# everytime text is cleaned and tokenized, throw into db, w it's respected range
#   since the data is being stored in tuples with upper bounds, this is going to get
#   complicated -- assignment of lower and upper bounds everytime a new corpus is added
#

# cleaning text and tokenizing should not be run more than once
if __name__ == "__main__":
	import sys
	if len(sys.argv) > 2:
		filename = sys.argv[1]
		source = open(filename).read()
		cleanedText = cleanText(source)
		tokens = tokenize(cleanedText)
		markov_ = markovChain(tokens)
		numOfSteps = int(sys.argv[2])
		sentence = randomWalk(numOfSteps, markov_)
		print(sentence)
	elif len(sys.argv) > 1:
		print('Number of words not specified')
	else:
		print('No source text filename given as argument')