

import argparse
import collections
import json
import os
import re
import string
import sys

import numpy as np


__lowercase     : Optional[Any]       =						re.compile(r'''\b(a|an|the)\b''', re.UNICODE)

__lowercase     : Optional[int]       =						None







def       lowercase					(	)				->			Optional[Any]:





    '''simple docstring'''




    snake_case							:		int        =		argparse.ArgumentParser("""Official evaluation script for SQuAD version 2.0."""		)
    parser.add_argument("""data_file""" ,    metavar="""data.json""" ,    help="""Input data JSON file."""		)
    parser.add_argument("""pred_file""" ,    metavar="""pred.json""" ,    help="""Model predictions."""		)
    parser.add_argument(
        """--out-file""" ,    """-o""" ,    metavar="""eval.json""" ,    help="""Write accuracy metrics to file (default is stdout)."""		)
    parser.add_argument(
        """--na-prob-file""" ,    """-n""" ,    metavar="""na_prob.json""" ,    help="""Model estimates of probability of no answer."""		)
    parser.add_argument(
        """--na-prob-thresh""" ,    """-t""" ,    type=__A ,    default=1.0 ,    help="""Predict \"\" if no-answer probability exceeds this (default = 1.0).""" ,    )
    parser.add_argument(
        """--out-image-dir""" ,    """-p""" ,    metavar="""out_images""" ,    default=__A ,    help="""Save precision-recall curves to directory."""		)
    parser.add_argument("""--verbose""" ,    """-v""" ,    action="""store_true"""		)
    if len(sys.argv		) == 1:
        parser.print_help()
        sys.exit(1		)
    return parser.parse_args()







def       lowercase					(	__A :					Union[str, Any]		)				->			int:





    '''simple docstring'''




    snake_case							:		Any        =		{}
    for article in dataset:
        for p in article["paragraphs"]:
            for qa in p["qas"]:
                snake_case							:		int        =		bool(qa["""answers"""]["""text"""]		)
    return qid_to_has_ans







def       lowercase					(	__A :					int		)				->			Optional[int]:





    '''simple docstring'''




    def remove_articles(__A :					List[Any]		):
        return ARTICLES_REGEX.sub(""" """ ,    __A		)

    def white_space_fix(__A :					Union[str, Any]		):
        return " ".join(text.split()		)

    def remove_punc(__A :					Tuple		):
        snake_case							:		Optional[Any]        =		set(string.punctuation		)
        return "".join(ch for ch in text if ch not in exclude		)

    def lower(__A :					Any		):
        return text.lower()

    return white_space_fix(remove_articles(remove_punc(lower(__A		)		)		)		)







def       lowercase					(	__A :					List[str]		)				->			Union[str, Any]:





    '''simple docstring'''




    if not s:
        return []
    return normalize_answer(__A		).split()







def       lowercase					(	__A :					Optional[int] ,    __A :					int		)				->			List[Any]:





    '''simple docstring'''




    return int(normalize_answer(__A		) == normalize_answer(__A		)		)







def       lowercase					(	__A :					Any ,    __A :					Optional[Any]		)				->			List[str]:





    '''simple docstring'''




    snake_case							:		Tuple        =		get_tokens(__A		)
    snake_case							:		str        =		get_tokens(__A		)
    snake_case							:		Dict        =		collections.Counter(__A		) & collections.Counter(__A		)
    snake_case							:		Optional[int]        =		sum(common.values()		)
    if len(__A		) == 0 or len(__A		) == 0:
        # If either is no-answer, then F1 is 1 if they agree, 0 otherwise
        return int(gold_toks == pred_toks		)
    if num_same == 0:
        return 0
    snake_case							:		List[Any]        =		1.0 * num_same / len(__A		)
    snake_case							:		int        =		1.0 * num_same / len(__A		)
    snake_case							:		Dict        =		(2 * precision * recall) / (precision + recall)
    return fa







def       lowercase					(	__A :					List[Any] ,    __A :					int		)				->			str:





    '''simple docstring'''




    snake_case							:		Tuple        =		{}
    snake_case							:		Tuple        =		{}
    for article in dataset:
        for p in article["paragraphs"]:
            for qa in p["qas"]:
                snake_case							:		str        =		qa["""id"""]
                snake_case							:		Union[str, Any]        =		[t for t in qa["""answers"""]["""text"""] if normalize_answer(__A		)]
                if not gold_answers:
                    # For unanswerable questions, only correct answer is empty string
                    snake_case							:		Optional[Any]        =		[""""""]
                if qid not in preds:
                    print(f"""Missing prediction for {qid}"""		)
                    continue
                snake_case							:		Dict        =		preds[qid]
                # Take max over all gold answers
                snake_case							:		Union[str, Any]        =		max(compute_exact(__A ,    __A		) for a in gold_answers		)
                snake_case							:		Optional[int]        =		max(compute_fa(__A ,    __A		) for a in gold_answers		)
    return exact_scores, fa_scores







def       lowercase					(	__A :					str ,    __A :					Any ,    __A :					List[Any] ,    __A :					List[Any]		)				->			Dict:





    '''simple docstring'''




    snake_case							:		Optional[int]        =		{}
    for qid, s in scores.items():
        snake_case							:		Any        =		na_probs[qid] > na_prob_thresh
        if pred_na:
            snake_case							:		str        =		float(not qid_to_has_ans[qid]		)
        else:
            snake_case							:		List[Any]        =		s
    return new_scores







def       lowercase					(	__A :					Dict ,    __A :					Union[str, Any] ,    __A :					List[str]=None		)				->			int:





    '''simple docstring'''




    if not qid_list:
        snake_case							:		List[str]        =		len(__A		)
        return collections.OrderedDict(
            [
                ("""exact""", 100.0 * sum(exact_scores.values()		) / total),
                ("""f1""", 100.0 * sum(fa_scores.values()		) / total),
                ("""total""", total),
            ]		)
    else:
        snake_case							:		Any        =		len(__A		)
        return collections.OrderedDict(
            [
                ("""exact""", 100.0 * sum(exact_scores[k] for k in qid_list		) / total),
                ("""f1""", 100.0 * sum(fa_scores[k] for k in qid_list		) / total),
                ("""total""", total),
            ]		)







def       lowercase					(	__A :					Optional[Any] ,    __A :					Tuple ,    __A :					List[str]		)				->			Optional[Any]:





    '''simple docstring'''




    for k in new_eval:
        snake_case							:		str        =		new_eval[k]







def       lowercase					(	__A :					Tuple ,    __A :					int ,    __A :					Dict ,    __A :					Dict		)				->			int:





    '''simple docstring'''




    plt.step(__A ,    __A ,    color="""b""" ,    alpha=0.2 ,    where="""post"""		)
    plt.fill_between(__A ,    __A ,    step="""post""" ,    alpha=0.2 ,    color="""b"""		)
    plt.xlabel("""Recall"""		)
    plt.ylabel("""Precision"""		)
    plt.xlim([0.0, 1.05]		)
    plt.ylim([0.0, 1.05]		)
    plt.title(__A		)
    plt.savefig(__A		)
    plt.clf()







def       lowercase					(	__A :					Optional[Any] ,    __A :					Union[str, Any] ,    __A :					Dict ,    __A :					Tuple ,    __A :					Optional[Any]=None ,    __A :					List[str]=None		)				->			Union[str, Any]:





    '''simple docstring'''




    snake_case							:		Optional[int]        =		sorted(__A ,    key=lambda __A		: na_probs[k]		)
    snake_case							:		Any        =		0.0
    snake_case							:		str        =		1.0
    snake_case							:		Tuple        =		0.0
    snake_case							:		str        =		[1.0]
    snake_case							:		Any        =		[0.0]
    snake_case							:		Dict        =		0.0
    for i, qid in enumerate(__A		):
        if qid_to_has_ans[qid]:
            true_pos += scores[qid]
        snake_case							:		str        =		true_pos / float(i + 1		)
        snake_case							:		List[str]        =		true_pos / float(__A		)
        if i == len(__A		) - 1 or na_probs[qid] != na_probs[qid_list[i + 1]]:
            # i.e., if we can put a threshold after this point
            avg_prec += cur_p * (cur_r - recalls[-1])
            precisions.append(__A		)
            recalls.append(__A		)
    if out_image:
        plot_pr_curve(__A ,    __A ,    __A ,    __A		)
    return {"ap": 100.0 * avg_prec}







def       lowercase					(	__A :					Any ,    __A :					Optional[int] ,    __A :					Tuple ,    __A :					Tuple ,    __A :					List[Any] ,    __A :					Optional[Any]		)				->			Optional[Any]:





    '''simple docstring'''




    if out_image_dir and not os.path.exists(__A		):
        os.makedirs(__A		)
    snake_case							:		Tuple        =		sum(1 for v in qid_to_has_ans.values() if v		)
    if num_true_pos == 0:
        return
    snake_case							:		str        =		make_precision_recall_eval(
        __A ,    __A ,    __A ,    __A ,    out_image=os.path.join(__A ,    """pr_exact.png"""		) ,    title="""Precision-Recall curve for Exact Match score""" ,    )
    snake_case							:		int        =		make_precision_recall_eval(
        __A ,    __A ,    __A ,    __A ,    out_image=os.path.join(__A ,    """pr_f1.png"""		) ,    title="""Precision-Recall curve for F1 score""" ,    )
    snake_case							:		Dict        =		{k: float(__A		) for k, v in qid_to_has_ans.items()}
    snake_case							:		int        =		make_precision_recall_eval(
        __A ,    __A ,    __A ,    __A ,    out_image=os.path.join(__A ,    """pr_oracle.png"""		) ,    title="""Oracle Precision-Recall curve (binary task of HasAns vs. NoAns)""" ,    )
    merge_eval(__A ,    __A ,    """pr_exact"""		)
    merge_eval(__A ,    __A ,    """pr_f1"""		)
    merge_eval(__A ,    __A ,    """pr_oracle"""		)







def       lowercase					(	__A :					List[Any] ,    __A :					Union[str, Any] ,    __A :					Union[str, Any] ,    __A :					Optional[int]		)				->			Union[str, Any]:





    '''simple docstring'''




    if not qid_list:
        return
    snake_case							:		int        =		[na_probs[k] for k in qid_list]
    snake_case							:		List[str]        =		np.ones_like(__A		) / float(len(__A		)		)
    plt.hist(__A ,    weights=__A ,    bins=20 ,    range=(0.0, 1.0)		)
    plt.xlabel("""Model probability of no-answer"""		)
    plt.ylabel("""Proportion of dataset"""		)
    plt.title(f"""Histogram of no-answer probability: {name}"""		)
    plt.savefig(os.path.join(__A ,    f"""na_prob_hist_{name}.png"""		)		)
    plt.clf()







def       lowercase					(	__A :					List[Any] ,    __A :					Tuple ,    __A :					Tuple ,    __A :					Any		)				->			Dict:





    '''simple docstring'''




    snake_case							:		Optional[int]        =		sum(1 for k in qid_to_has_ans if not qid_to_has_ans[k]		)
    snake_case							:		str        =		num_no_ans
    snake_case							:		Optional[Any]        =		cur_score
    snake_case							:		Optional[Any]        =		0.0
    snake_case							:		List[Any]        =		sorted(__A ,    key=lambda __A		: na_probs[k]		)
    for i, qid in enumerate(__A		):
        if qid not in scores:
            continue
        if qid_to_has_ans[qid]:
            snake_case							:		Dict        =		scores[qid]
        else:
            if preds[qid]:
                snake_case							:		Dict        =		-1
            else:
                snake_case							:		str        =		0
        cur_score += diff
        if cur_score > best_score:
            snake_case							:		Union[str, Any]        =		cur_score
            snake_case							:		List[Any]        =		na_probs[qid]
    return 100.0 * best_score / len(__A		), best_thresh







def       lowercase					(	__A :					Dict ,    __A :					str ,    __A :					str ,    __A :					int ,    __A :					str ,    __A :					Any		)				->			List[str]:





    '''simple docstring'''




    snake_case      ,		snake_case							:		Optional[int]        =		find_best_thresh(__A ,    __A ,    __A ,    __A		)
    snake_case      ,		snake_case							:		str        =		find_best_thresh(__A ,    __A ,    __A ,    __A		)
    snake_case							:		List[str]        =		best_exact
    snake_case							:		List[Any]        =		exact_thresh
    snake_case							:		Optional[Any]        =		best_fa
    snake_case							:		Optional[int]        =		fa_thresh







def       lowercase					(	)				->			Any:





    '''simple docstring'''




    with open(OPTS.data_file		) as f:
        snake_case							:		Dict        =		json.load(__A		)
        snake_case							:		Union[str, Any]        =		dataset_json["""data"""]
    with open(OPTS.pred_file		) as f:
        snake_case							:		int        =		json.load(__A		)
    if OPTS.na_prob_file:
        with open(OPTS.na_prob_file		) as f:
            snake_case							:		Any        =		json.load(__A		)
    else:
        snake_case							:		Any        =		{k: 0.0 for k in preds}
    snake_case							:		Optional[int]        =		make_qid_to_has_ans(__A		)  # maps qid to True/False
    snake_case							:		Dict        =		[k for k, v in qid_to_has_ans.items() if v]
    snake_case							:		Optional[int]        =		[k for k, v in qid_to_has_ans.items() if not v]
    snake_case      ,		snake_case							:		Optional[Any]        =		get_raw_scores(__A ,    __A		)
    snake_case							:		Tuple        =		apply_no_ans_threshold(__A ,    __A ,    __A ,    OPTS.na_prob_thresh		)
    snake_case							:		Optional[Any]        =		apply_no_ans_threshold(__A ,    __A ,    __A ,    OPTS.na_prob_thresh		)
    snake_case							:		Optional[int]        =		make_eval_dict(__A ,    __A		)
    if has_ans_qids:
        snake_case							:		Any        =		make_eval_dict(__A ,    __A ,    qid_list=__A		)
        merge_eval(__A ,    __A ,    """HasAns"""		)
    if no_ans_qids:
        snake_case							:		str        =		make_eval_dict(__A ,    __A ,    qid_list=__A		)
        merge_eval(__A ,    __A ,    """NoAns"""		)
    if OPTS.na_prob_file:
        find_all_best_thresh(__A ,    __A ,    __A ,    __A ,    __A ,    __A		)
    if OPTS.na_prob_file and OPTS.out_image_dir:
        run_precision_recall_analysis(__A ,    __A ,    __A ,    __A ,    __A ,    OPTS.out_image_dir		)
        histogram_na_prob(__A ,    __A ,    OPTS.out_image_dir ,    """hasAns"""		)
        histogram_na_prob(__A ,    __A ,    OPTS.out_image_dir ,    """noAns"""		)
    if OPTS.out_file:
        with open(OPTS.out_file ,    """w"""		) as f:
            json.dump(__A ,    __A		)
    else:
        print(json.dumps(__A ,    indent=2		)		)


if __name__ == "__main__":
     __lowercase     : Union[str, Any]       =						parse_args()
     if OPTS.out_image_dir:
          import matplotlib

          matplotlib.use('''Agg''')
          import matplotlib.pyplot as plt
     main()





from __future__ import annotations




class 					lowerCamelCase__				:




	'''simple docstring'''




	def __init__(   self						:Dict	,  a						:str	,  a						:str		)						->					Union[str, Any]:
								__UpperCamelCase  ,		__UpperCamelCase      :  Optional[int]       =   text, pattern
								__UpperCamelCase  ,		__UpperCamelCase      :  Tuple       =   len(a		), len(a		)







	def   _lowerCamelCase							(   self						:Any	,  a						:str		)						->					int:

								for i in range(self.patLen - 1	,  -1	,  -1		):
															if char == self.pattern[i]:
																						return i
								return -1







	def   _lowerCamelCase							(   self						:str	,  a						:int		)						->					int:

								for i in range(self.patLen - 1	,  -1	,  -1		):
															if self.pattern[i] != self.text[current_pos + i]:
																						return current_pos + i
								return -1







	def   _lowerCamelCase							(   self						:Union[str, Any]		)						->					list[int]:
								# searches pattern in text and returns index positions
								__UpperCamelCase      :  Any       =   []
								for i in range(self.textLen - self.patLen + 1		):
															__UpperCamelCase      :  List[Any]       =   self.mismatch_in_text(a		)
															if mismatch_index == -1:
																						positions.append(a		)
															else:
																						__UpperCamelCase      :  Any       =   self.match_in_pattern(self.text[mismatch_index]		)
																						__UpperCamelCase      :  Dict       =   (
																						    mismatch_index - match_index
																						)  # shifting index lgtm [py/multiple-definition]
								return positions
lowercase    :   Any						=			'ABAABA'
lowercase    :   str						=			'AB'
lowercase    :   str						=			BoyerMooreSearch(text, pattern)
lowercase    :   Union[str, Any]						=			bms.bad_character_heuristic()

if len(positions) == 0:
		print('No match found')
else:
		print('Pattern found in following positions: ')
		print(positions)