import argparse
import csv
import json
import math
import time

import numpy as np
import torch
import torch.optim as optim
import torch.utils.data as data
from nltk.tokenize.treebank import TreebankWordDetokenizer
from pplm_classification_head import ClassificationHead
from torch import nn
from torchtext import data as torchtext_data
from torchtext import datasets
from tqdm import tqdm, trange

from transformers import GPTaLMHeadModel, GPTaTokenizer


torch.manual_seed(0)
np.random.seed(0)
snake_case__						      =			1E-10
snake_case__						      =			'This is incredible! I love it, this is the best chicken I have ever had.'
snake_case__						      =			100



class 			UpperCamelCase					(			nn.Module			):

     '''simple docstring'''

     def __init__(       self					,					A_					,					A_="gpt2-medium"					,					A_=False					,					A_="cpu"    )			->					str:






           """simple docstring"""
           super().__init__()
           _lowerCamelCase           =					GPTaTokenizer.from_pretrained(__SCREAMING_SNAKE_CASE    )
           _lowerCamelCase           =					GPTaLMHeadModel.from_pretrained(__SCREAMING_SNAKE_CASE    )
           _lowerCamelCase           =					self.encoder.transformer.config.hidden_size
           _lowerCamelCase           =					ClassificationHead(class_size=__SCREAMING_SNAKE_CASE					,					embed_size=self.embed_size    )
           _lowerCamelCase           =					cached_mode
           _lowerCamelCase           =					device



     def 		UpperCamelCase_    (       self    )			->					str:






           """simple docstring"""
           return self.classifier_head



     def 		UpperCamelCase_    (       self    )			->					int:






           """simple docstring"""
           for param in self.encoder.parameters():
                 _lowerCamelCase           =					False
           self.classifier_head.train()



     def 		UpperCamelCase_    (       self					,					A_    )			->					Tuple:






           """simple docstring"""
           _lowerCamelCase           =					x.ne(0    ).unsqueeze(2    ).repeat(1					,					1					,					self.embed_size    ).float().to(self.device    ).detach()
           _lowerCamelCase           =					self.encoder.transformer(__SCREAMING_SNAKE_CASE    )['''last_hidden_state''']
           _lowerCamelCase           =					hidden * mask
           _lowerCamelCase           =					torch.sum(__SCREAMING_SNAKE_CASE					,					dim=1    ) / (torch.sum(__SCREAMING_SNAKE_CASE					,					dim=1    ).detach() + EPSILON)
           return avg_hidden





     def 		UpperCamelCase_    (       self					,					A_    )			->					Tuple:






           """simple docstring"""
           if self.cached_mode:
                 _lowerCamelCase           =					x.to(self.device    )
           else:
                 _lowerCamelCase           =					self.avg_representation(x.to(self.device    )    )

           _lowerCamelCase           =					self.classifier_head(__SCREAMING_SNAKE_CASE    )
           _lowerCamelCase           =					nn.functional.log_softmax(__SCREAMING_SNAKE_CASE					,					dim=-1    )

           return probs





class 			UpperCamelCase					(			data.Dataset			):

     '''simple docstring'''

     def __init__(       self					,					A_					,					A_    )			->					int:






           """simple docstring"""
           _lowerCamelCase           =					X
           _lowerCamelCase           =					y



     def __len__(       self    )			->					List[str]:






           """simple docstring"""
           return len(self.X    )





     def __getitem__(       self					,					A_    )			->					int:






           """simple docstring"""
           _lowerCamelCase           =					{}
           _lowerCamelCase           =					self.X[index]
           _lowerCamelCase           =					self.y[index]
           return data





def    __magic_name__(	__UpperCAmelCase		)    ->     List[Any]:



      '''simple docstring'''

      def pad_sequences(__UpperCAmelCase		):
            _lowerCamelCase           =					[len(lowercase__		) for seq in sequences]

            _lowerCamelCase           =					torch.zeros(len(lowercase__		)			,    max(lowercase__		)		).long()  # padding value = 0

            for i, seq in enumerate(lowercase__		):
                  _lowerCamelCase           =					lengths[i]
                  _lowerCamelCase           =					seq[:end]

            return padded_sequences, lengths

      _lowerCamelCase           =					{}
      for key in data[0].keys():
            _lowerCamelCase           =					[d[key] for d in data]

      _lowerCamelCase     ,       _lowerCamelCase           =					pad_sequences(item_info['''X''']		)
      _lowerCamelCase           =					torch.tensor(item_info['''y''']			,    dtype=torch.long		)

      return x_batch, y_batch
def    __magic_name__(	__UpperCAmelCase		)    ->     Optional[Any]:



      '''simple docstring'''

      _lowerCamelCase           =					{}
      for key in data[0].keys():
            _lowerCamelCase           =					[d[key] for d in data]

      _lowerCamelCase           =					torch.cat(item_info['''X''']			,    0		)
      _lowerCamelCase           =					torch.tensor(item_info['''y''']			,    dtype=torch.long		)

      return x_batch, y_batch
def    __magic_name__(	__UpperCAmelCase			,    __UpperCAmelCase			,    __UpperCAmelCase			,    __UpperCAmelCase=0			,    __UpperCAmelCase=10			,    __UpperCAmelCase="cpu"		)    ->     List[Any]:



      '''simple docstring'''

      _lowerCamelCase           =					0
      discriminator.train_custom()
      for batch_idx, (input_t, target_t) in enumerate(lowercase__		):
            _lowerCamelCase     ,       _lowerCamelCase           =					input_t.to(lowercase__		), target_t.to(lowercase__		)

            optimizer.zero_grad()

            _lowerCamelCase           =					discriminator(lowercase__		)
            _lowerCamelCase           =					nn.functional.nll_loss(lowercase__			,    lowercase__		)
            loss.backward(retain_graph=lowercase__		)
            optimizer.step()

            samples_so_far += len(lowercase__		)

            if batch_idx % log_interval == 0:
                  print(
                      '''Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'''.format(
                          epoch + 1			,    lowercase__			,    len(data_loader.dataset		)			,    100 * samples_so_far / len(data_loader.dataset		)			,    loss.item()			,    )		)
def    __magic_name__(	__UpperCAmelCase			,    __UpperCAmelCase			,    __UpperCAmelCase="cpu"		)    ->     List[str]:



      '''simple docstring'''

      discriminator.eval()
      _lowerCamelCase           =					0
      _lowerCamelCase           =					0
      with torch.no_grad():
            for input_t, target_t in data_loader:
                  _lowerCamelCase     ,       _lowerCamelCase           =					input_t.to(lowercase__		), target_t.to(lowercase__		)
                  _lowerCamelCase           =					discriminator(lowercase__		)
                  # sum up batch loss
                  test_loss += nn.functional.nll_loss(lowercase__			,    lowercase__			,    reduction='''sum'''		).item()
                  # get the index of the max log-probability
                  _lowerCamelCase           =					output_t.argmax(dim=1			,    keepdim=lowercase__		)
                  correct += pred_t.eq(target_t.view_as(lowercase__		)		).sum().item()

      test_loss /= len(data_loader.dataset		)

      print(
          '''Performance on test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)'''.format(
              lowercase__			,    lowercase__			,    len(data_loader.dataset		)			,    100.0 * correct / len(data_loader.dataset		)		)		)
def    __magic_name__(	__UpperCAmelCase			,    __UpperCAmelCase			,    __UpperCAmelCase			,    __UpperCAmelCase=False			,    __UpperCAmelCase="cpu"		)    ->     Tuple:



      '''simple docstring'''

      _lowerCamelCase           =					model.tokenizer.encode(lowercase__		)
      _lowerCamelCase           =					torch.tensor([input_t]			,    dtype=torch.long			,    device=lowercase__		)
      if cached:
            _lowerCamelCase           =					model.avg_representation(lowercase__		)

      _lowerCamelCase           =					model(lowercase__		).data.cpu().numpy().flatten().tolist()
      print('''Input sentence:'''			,    lowercase__		)
      print(
          '''Predictions:'''			,    ''', '''.join('''{}: {:.4f}'''.format(lowercase__			,    math.exp(lowercase__		)		) for c, log_prob in zip(lowercase__			,    lowercase__		)		)			,    )
def    __magic_name__(	__UpperCAmelCase			,    __UpperCAmelCase			,    __UpperCAmelCase			,    __UpperCAmelCase=False			,    __UpperCAmelCase="cpu"		)    ->     List[Any]:



      '''simple docstring'''

      _lowerCamelCase           =					torch.utils.data.DataLoader(dataset=lowercase__			,    batch_size=lowercase__			,    collate_fn=lowercase__		)

      _lowerCamelCase           =					[]
      _lowerCamelCase           =					[]
      for batch_idx, (x, y) in enumerate(tqdm(lowercase__			,    ascii=lowercase__		)		):
            with torch.no_grad():
                  _lowerCamelCase           =					x.to(lowercase__		)
                  _lowerCamelCase           =					discriminator.avg_representation(lowercase__		).cpu().detach()
                  _lowerCamelCase           =					torch.unbind(avg_rep.unsqueeze(1		)		)
                  xs += avg_rep_list
                  ys += y.cpu().numpy().tolist()

      _lowerCamelCase           =					torch.utils.data.DataLoader(
          dataset=Dataset(lowercase__			,    lowercase__		)			,    batch_size=lowercase__			,    shuffle=lowercase__			,    collate_fn=lowercase__		)

      return data_loader
def    __magic_name__(	__UpperCAmelCase			,    __UpperCAmelCase=None			,    __UpperCAmelCase="gpt2-medium"			,    __UpperCAmelCase=10			,    __UpperCAmelCase=64			,    __UpperCAmelCase=10			,    __UpperCAmelCase=False			,    __UpperCAmelCase=False			,    __UpperCAmelCase=False			,    )    ->     Optional[Any]:



      '''simple docstring'''

      _lowerCamelCase           =					'''cuda''' if torch.cuda.is_available() and not no_cuda else '''cpu'''

      print('''Preprocessing {} dataset...'''.format(lowercase__		)		)
      _lowerCamelCase           =					time.time()

      if dataset == "SST":
            _lowerCamelCase           =					['''positive''', '''negative''', '''very positive''', '''very negative''', '''neutral''']
            _lowerCamelCase           =					{c: i for i, c in enumerate(lowercase__		)}

            _lowerCamelCase           =					Discriminator(
                class_size=len(lowercase__		)			,    pretrained_model=lowercase__			,    cached_mode=lowercase__			,    device=lowercase__		).to(lowercase__		)

            _lowerCamelCase           =					torchtext_data.Field()
            _lowerCamelCase           =					torchtext_data.Field(sequential=lowercase__		)
            _lowerCamelCase     ,       _lowerCamelCase     ,       _lowerCamelCase           =					datasets.SST.splits(
                lowercase__			,    lowercase__			,    fine_grained=lowercase__			,    train_subtrees=lowercase__			,    )

            _lowerCamelCase           =					[]
            _lowerCamelCase           =					[]
            for i in trange(len(lowercase__		)			,    ascii=lowercase__		):
                  _lowerCamelCase           =					TreebankWordDetokenizer().detokenize(vars(train_data[i]		)['''text''']		)
                  _lowerCamelCase           =					discriminator.tokenizer.encode(lowercase__		)
                  _lowerCamelCase           =					torch.tensor([5_0256] + seq			,    device=lowercase__			,    dtype=torch.long		)
                  x.append(lowercase__		)
                  y.append(classaidx[vars(train_data[i]		)['''label''']]		)
            _lowerCamelCase           =					Dataset(lowercase__			,    lowercase__		)

            _lowerCamelCase           =					[]
            _lowerCamelCase           =					[]
            for i in trange(len(lowercase__		)			,    ascii=lowercase__		):
                  _lowerCamelCase           =					TreebankWordDetokenizer().detokenize(vars(test_data[i]		)['''text''']		)
                  _lowerCamelCase           =					discriminator.tokenizer.encode(lowercase__		)
                  _lowerCamelCase           =					torch.tensor([5_0256] + seq			,    device=lowercase__			,    dtype=torch.long		)
                  test_x.append(lowercase__		)
                  test_y.append(classaidx[vars(test_data[i]		)['''label''']]		)
            _lowerCamelCase           =					Dataset(lowercase__			,    lowercase__		)

            _lowerCamelCase           =					{
                '''class_size''': len(lowercase__		),
                '''embed_size''': discriminator.embed_size,
                '''pretrained_model''': pretrained_model,
                '''class_vocab''': classaidx,
                '''default_class''': 2,
            }

      elif dataset == "clickbait":
            _lowerCamelCase           =					['''non_clickbait''', '''clickbait''']
            _lowerCamelCase           =					{c: i for i, c in enumerate(lowercase__		)}

            _lowerCamelCase           =					Discriminator(
                class_size=len(lowercase__		)			,    pretrained_model=lowercase__			,    cached_mode=lowercase__			,    device=lowercase__		).to(lowercase__		)

            with open('''datasets/clickbait/clickbait_train_prefix.txt'''		) as f:
                  _lowerCamelCase           =					[]
                  for i, line in enumerate(lowercase__		):
                        try:
                              data.append(eval(lowercase__		)		)
                        except Exception:
                              print('''Error evaluating line {}: {}'''.format(lowercase__			,    lowercase__		)		)
                              continue
            _lowerCamelCase           =					[]
            _lowerCamelCase           =					[]
            with open('''datasets/clickbait/clickbait_train_prefix.txt'''		) as f:
                  for i, line in enumerate(tqdm(lowercase__			,    ascii=lowercase__		)		):
                        try:
                              _lowerCamelCase           =					eval(lowercase__		)
                              _lowerCamelCase           =					discriminator.tokenizer.encode(d['''text''']		)

                              if len(lowercase__		) < max_length_seq:
                                    _lowerCamelCase           =					torch.tensor([5_0256] + seq			,    device=lowercase__			,    dtype=torch.long		)
                              else:
                                    print('''Line {} is longer than maximum length {}'''.format(lowercase__			,    lowercase__		)		)
                                    continue
                              x.append(lowercase__		)
                              y.append(d['''label''']		)
                        except Exception:
                              print('''Error evaluating / tokenizing line {}, skipping it'''.format(lowercase__		)		)
                              pass

            _lowerCamelCase           =					Dataset(lowercase__			,    lowercase__		)
            _lowerCamelCase           =					int(0.9 * len(lowercase__		)		)
            _lowerCamelCase           =					len(lowercase__		) - train_size
            _lowerCamelCase     ,       _lowerCamelCase           =					torch.utils.data.random_split(lowercase__			,    [train_size, test_size]		)

            _lowerCamelCase           =					{
                '''class_size''': len(lowercase__		),
                '''embed_size''': discriminator.embed_size,
                '''pretrained_model''': pretrained_model,
                '''class_vocab''': classaidx,
                '''default_class''': 1,
            }

      elif dataset == "toxic":
            _lowerCamelCase           =					['''non_toxic''', '''toxic''']
            _lowerCamelCase           =					{c: i for i, c in enumerate(lowercase__		)}

            _lowerCamelCase           =					Discriminator(
                class_size=len(lowercase__		)			,    pretrained_model=lowercase__			,    cached_mode=lowercase__			,    device=lowercase__		).to(lowercase__		)

            _lowerCamelCase           =					[]
            _lowerCamelCase           =					[]
            with open('''datasets/toxic/toxic_train.txt'''		) as f:
                  for i, line in enumerate(tqdm(lowercase__			,    ascii=lowercase__		)		):
                        try:
                              _lowerCamelCase           =					eval(lowercase__		)
                              _lowerCamelCase           =					discriminator.tokenizer.encode(d['''text''']		)

                              if len(lowercase__		) < max_length_seq:
                                    _lowerCamelCase           =					torch.tensor([5_0256] + seq			,    device=lowercase__			,    dtype=torch.long		)
                              else:
                                    print('''Line {} is longer than maximum length {}'''.format(lowercase__			,    lowercase__		)		)
                                    continue
                              x.append(lowercase__		)
                              y.append(int(np.sum(d['''label''']		) > 0		)		)
                        except Exception:
                              print('''Error evaluating / tokenizing line {}, skipping it'''.format(lowercase__		)		)
                              pass

            _lowerCamelCase           =					Dataset(lowercase__			,    lowercase__		)
            _lowerCamelCase           =					int(0.9 * len(lowercase__		)		)
            _lowerCamelCase           =					len(lowercase__		) - train_size
            _lowerCamelCase     ,       _lowerCamelCase           =					torch.utils.data.random_split(lowercase__			,    [train_size, test_size]		)

            _lowerCamelCase           =					{
                '''class_size''': len(lowercase__		),
                '''embed_size''': discriminator.embed_size,
                '''pretrained_model''': pretrained_model,
                '''class_vocab''': classaidx,
                '''default_class''': 0,
            }

      else:  # if dataset == "generic":
            # This assumes the input dataset is a TSV with the following structure:
            # class \t text

            if dataset_fp is None:
                  raise ValueError('''When generic dataset is selected, dataset_fp needs to be specified aswell.'''		)

            _lowerCamelCase           =					set()
            with open(lowercase__		) as f:
                  _lowerCamelCase           =					csv.reader(lowercase__			,    delimiter='''\t'''		)
                  for row in tqdm(lowercase__			,    ascii=lowercase__		):
                        if row:
                              classes.add(row[0]		)

            _lowerCamelCase           =					sorted(lowercase__		)
            _lowerCamelCase           =					{c: i for i, c in enumerate(lowercase__		)}

            _lowerCamelCase           =					Discriminator(
                class_size=len(lowercase__		)			,    pretrained_model=lowercase__			,    cached_mode=lowercase__			,    device=lowercase__		).to(lowercase__		)

            _lowerCamelCase           =					[]
            _lowerCamelCase           =					[]
            with open(lowercase__		) as f:
                  _lowerCamelCase           =					csv.reader(lowercase__			,    delimiter='''\t'''		)
                  for i, row in enumerate(tqdm(lowercase__			,    ascii=lowercase__		)		):
                        if row:
                              _lowerCamelCase           =					row[0]
                              _lowerCamelCase           =					row[1]

                              try:
                                    _lowerCamelCase           =					discriminator.tokenizer.encode(lowercase__		)
                                    if len(lowercase__		) < max_length_seq:
                                          _lowerCamelCase           =					torch.tensor([5_0256] + seq			,    device=lowercase__			,    dtype=torch.long		)

                                    else:
                                          print('''Line {} is longer than maximum length {}'''.format(lowercase__			,    lowercase__		)		)
                                          continue

                                    x.append(lowercase__		)
                                    y.append(classaidx[label]		)

                              except Exception:
                                    print('''Error tokenizing line {}, skipping it'''.format(lowercase__		)		)
                                    pass

            _lowerCamelCase           =					Dataset(lowercase__			,    lowercase__		)
            _lowerCamelCase           =					int(0.9 * len(lowercase__		)		)
            _lowerCamelCase           =					len(lowercase__		) - train_size
            _lowerCamelCase     ,       _lowerCamelCase           =					torch.utils.data.random_split(lowercase__			,    [train_size, test_size]		)

            _lowerCamelCase           =					{
                '''class_size''': len(lowercase__		),
                '''embed_size''': discriminator.embed_size,
                '''pretrained_model''': pretrained_model,
                '''class_vocab''': classaidx,
                '''default_class''': 0,
            }

      _lowerCamelCase           =					time.time()
      print('''Preprocessed {} data points'''.format(len(lowercase__		) + len(lowercase__		)		)		)
      print('''Data preprocessing took: {:.3f}s'''.format(end - start		)		)

      if cached:
            print('''Building representation cache...'''		)

            _lowerCamelCase           =					time.time()

            _lowerCamelCase           =					get_cached_data_loader(lowercase__			,    lowercase__			,    lowercase__			,    shuffle=lowercase__			,    device=lowercase__		)

            _lowerCamelCase           =					get_cached_data_loader(lowercase__			,    lowercase__			,    lowercase__			,    device=lowercase__		)

            _lowerCamelCase           =					time.time()
            print('''Building representation cache took: {:.3f}s'''.format(end - start		)		)

      else:
            _lowerCamelCase           =					torch.utils.data.DataLoader(
                dataset=lowercase__			,    batch_size=lowercase__			,    shuffle=lowercase__			,    collate_fn=lowercase__		)
            _lowerCamelCase           =					torch.utils.data.DataLoader(dataset=lowercase__			,    batch_size=lowercase__			,    collate_fn=lowercase__		)

      if save_model:
            with open('''{}_classifier_head_meta.json'''.format(lowercase__		)			,    '''w'''		) as meta_file:
                  json.dump(lowercase__			,    lowercase__		)

      _lowerCamelCase           =					optim.Adam(discriminator.parameters()			,    lr=0.0_0_0_1		)

      for epoch in range(lowercase__		):
            _lowerCamelCase           =					time.time()
            print('''\nEpoch'''			,    epoch + 1		)

            train_epoch(
                discriminator=lowercase__			,    data_loader=lowercase__			,    optimizer=lowercase__			,    epoch=lowercase__			,    log_interval=lowercase__			,    device=lowercase__			,    )
            evaluate_performance(data_loader=lowercase__			,    discriminator=lowercase__			,    device=lowercase__		)

            _lowerCamelCase           =					time.time()
            print('''Epoch took: {:.3f}s'''.format(end - start		)		)

            print('''\nExample prediction'''		)
            predict(lowercase__			,    lowercase__			,    lowercase__			,    cached=lowercase__			,    device=lowercase__		)

            if save_model:
                  # torch.save(discriminator.state_dict(),
                  #           "{}_discriminator_{}.pt".format(
                  #               args.dataset, epoch + 1
                  #               ))
                  torch.save(
                      discriminator.get_classifier().state_dict()			,    '''{}_classifier_head_epoch_{}.pt'''.format(lowercase__			,    epoch + 1		)			,    )


if __name__ == "__main__":
     snake_case__						      =			argparse.ArgumentParser(description='Train a discriminator on top of GPT-2 representations')
     parser.add_argument(
         '--dataset',
         type=str,
         default='SST',
         choices=('SST', 'clickbait', 'toxic', 'generic'),
         help=(
             'dataset to train the discriminator on.'
             'In case of generic, the dataset is expected'
             'to be a TSBV file with structure: class \\t text'
         ),
     )
     parser.add_argument(
         '--dataset_fp',
         type=str,
         default='',
         help='File path of the dataset to use. Needed only in case of generic datadset',
     )
     parser.add_argument(
         '--pretrained_model', type=str, default='gpt2-medium', help='Pretrained model to use as encoder'
     )
     parser.add_argument('--epochs', type=int, default=10, metavar='N', help='Number of training epochs')
     parser.add_argument(
         '--batch_size', type=int, default=64, metavar='N', help='input batch size for training (default: 64)'
     )
     parser.add_argument(
         '--log_interval',
         type=int,
         default=10,
         metavar='N',
         help='how many batches to wait before logging training status',
     )
     parser.add_argument('--save_model', action='store_true', help='whether to save the model')
     parser.add_argument('--cached', action='store_true', help='whether to cache the input representations')
     parser.add_argument('--no_cuda', action='store_true', help='use to turn off cuda')
     snake_case__						      =			parser.parse_args()

     train_discriminator(**(vars(args)))


"""simple docstring"""




import sys

sys.set_int_max_str_digits(0)  # type: ignore
def   __SCREAMING_SNAKE_CASE		(		lowercase__ ):
					"""simple docstring"""
					A     =   [0] * 11
					A     =   [0] * 11

					# mark last 9 numbers
					for _ in range(9 ):
										A     =   1
										A     =   number // 10
					# flag
					A     =   True

					# check last 9 numbers for pandigitality

					for x in range(9 ):
										if not check_last[x + 1]:
															A     =   False
					if not f:
										return f

					# mark first 9 numbers
					A     =   int(str(lowercase__ )[:9] )

					for _ in range(9 ):
										A     =   1
										A     =   number // 10

					# check first 9 numbers for pandigitality

					for x in range(9 ):
										if not check_front[x + 1]:
															A     =   False
					return f
def   __SCREAMING_SNAKE_CASE		(		lowercase__ ):
					"""simple docstring"""
					A     =   [0] * 11

					# mark last 9 numbers
					for _ in range(9 ):
										A     =   1
										A     =   number // 10
					# flag
					A     =   True

					# check last 9 numbers for pandigitality

					for x in range(9 ):
										if not check_last[x + 1]:
															A     =   False
					return f
def   __SCREAMING_SNAKE_CASE		(		):
					"""simple docstring"""
					A     =   1
					A     =   1
					A     =   2
					# temporary Fibonacci numbers

					A     =   1
					A     =   1
					A     =   2
					# temporary Fibonacci numbers mod 1e9

					# mod m=1e9, done for fast optimisation
					A     =   [0] * 1_000_000
					A     =   1_000_000_000

					for x in range(1_000_000 ):
										A     =   (aa + ba) % m
										A     =   ba % m
										A     =   ca % m
										if checka(lowercase__ ):
															A     =   1

					for x in range(1_000_000 ):
										A     =   a + b
										A     =   b
										A     =   c
										# perform check only if in tocheck
										if tocheck[x + 3] and check(lowercase__ ):
															return x + 3  # first 2 already done
					return -1


if __name__ == "__main__":
	print(f"""{solution() = }""")





