



'''simple docstring'''


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

import numpy as np


lowercase							       =			re.compile(R'''\b(a|an|the)\b''', re.UNICODE)

lowercase							       =			None






def  UpperCAmelCase_       (		):


     '''simple docstring'''







     a_       		=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=lowercase__       ,	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=lowercase__       ,	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  UpperCAmelCase_       (		lowercase__       ):


     '''simple docstring'''







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






def  UpperCAmelCase_       (		lowercase__       ):


     '''simple docstring'''







     def remove_articles(lowercase__       ):
          return ARTICLES_REGEX.sub(" "       ,	lowercase__       )

     def white_space_fix(lowercase__       ):
          return " ".join(text.split()       )

     def remove_punc(lowercase__       ):
          a_       		=set(string.punctuation       )
          return "".join(ch for ch in text if ch not in exclude       )

     def lower(lowercase__       ):
          return text.lower()

     return white_space_fix(remove_articles(remove_punc(lower(lowercase__       )       )       )       )






def  UpperCAmelCase_       (		lowercase__       ):


     '''simple docstring'''







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






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     return int(normalize_answer(lowercase__       ) == normalize_answer(lowercase__       )       )






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     a_       		=get_tokens(lowercase__       )
     a_       		=get_tokens(lowercase__       )
     a_       		=collections.Counter(lowercase__       ) & collections.Counter(lowercase__       )
     a_       		=sum(common.values()       )
     if len(lowercase__       ) == 0 or len(lowercase__       ) == 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
     a_       		=1.0 * num_same / len(lowercase__       )
     a_       		=1.0 * num_same / len(lowercase__       )
     a_       		=(2 * precision * recall) / (precision + recall)
     return fa






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ):


     '''simple docstring'''







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






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     a_       		={}
     for qid, s in scores.items():
          a_       		=na_probs[qid] > na_prob_thresh
          if pred_na:
               a_       		=float(not qid_to_has_ans[qid]       )
          else:
               a_       		=s
     return new_scores






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__=None       ):


     '''simple docstring'''







     if not qid_list:
          a_       		=len(lowercase__       )
          return collections.OrderedDict(
              [
                  ("exact", 100.0 * sum(exact_scores.values()       ) / total),
                  ("f1", 100.0 * sum(fa_scores.values()       ) / total),
                  ("total", total),
              ]       )
     else:
          a_       		=len(lowercase__       )
          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  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     for k in new_eval:
          a_       		=new_eval[k]






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     plt.step(lowercase__       ,	lowercase__       ,	color="b"       ,	alpha=0.2       ,	where="post"       )
     plt.fill_between(lowercase__       ,	lowercase__       ,	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(lowercase__       )
     plt.savefig(lowercase__       )
     plt.clf()






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__=None       ,	lowercase__=None       ):


     '''simple docstring'''







     a_       		=sorted(lowercase__       ,	key=lambda lowercase__       : na_probs[k]       )
     a_       		=0.0
     a_       		=1.0
     a_       		=0.0
     a_       		=[1.0]
     a_       		=[0.0]
     a_       		=0.0
     for i, qid in enumerate(lowercase__       ):
          if qid_to_has_ans[qid]:
               true_pos += scores[qid]
          a_       		=true_pos / float(i + 1       )
          a_       		=true_pos / float(lowercase__       )
          if i == len(lowercase__       ) - 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(lowercase__       )
               recalls.append(lowercase__       )
     if out_image:
          plot_pr_curve(lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       )
     return {"ap": 100.0 * avg_prec}






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ):


     '''simple docstring'''







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






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     if not qid_list:
          return
     a_       		=[na_probs[k] for k in qid_list]
     a_       		=np.ones_like(lowercase__       ) / float(len(lowercase__       )       )
     plt.hist(lowercase__       ,	weights=lowercase__       ,	bins=2_0       ,	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(lowercase__       ,	F"""na_prob_hist_{name}.png"""       )       )
     plt.clf()






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     a_       		=sum(1 for k in qid_to_has_ans if not qid_to_has_ans[k]       )
     a_       		=num_no_ans
     a_       		=cur_score
     a_       		=0.0
     a_       		=sorted(lowercase__       ,	key=lambda lowercase__       : na_probs[k]       )
     for i, qid in enumerate(lowercase__       ):
          if qid not in scores:
               continue
          if qid_to_has_ans[qid]:
               a_       		=scores[qid]
          else:
               if preds[qid]:
                    a_       		=-1
               else:
                    a_       		=0
          cur_score += diff
          if cur_score > best_score:
               a_       		=cur_score
               a_       		=na_probs[qid]
     return 100.0 * best_score / len(lowercase__       ), best_thresh






def  UpperCAmelCase_       (		lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       ):


     '''simple docstring'''







     a_		,						a_       		=find_best_thresh(lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       )
     a_		,						a_       		=find_best_thresh(lowercase__       ,	lowercase__       ,	lowercase__       ,	lowercase__       )
     a_       		=best_exact
     a_       		=exact_thresh
     a_       		=best_fa
     a_       		=fa_thresh






def  UpperCAmelCase_       (		):


     '''simple docstring'''







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


if __name__ == "__main__":
  lowercase							       =			parse_args()
  if OPTS.out_image_dir:
    import matplotlib

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







'''simple docstring'''


import os

# Precomputes a list of the 100 first triangular numbers
lowercase							       =			[int(0.5 * n * (n + 1)) for n in range(1, 101)]






def  UpperCAmelCase_       (		):


     '''simple docstring'''







     a_       		=os.path.dirname(os.path.realpath(lowercase__       )       )
     a_       		=os.path.join(lowercase__       ,	"words.txt"       )

     a_       		=""
     with open(lowercase__       ) as f:
          a_       		=f.readline()

     a_       		=[word.strip("\""       ) for word in words.strip("\r\n"       ).split(","       )]
     a_       		=[
         word
         for word in [sum(ord(lowercase__       ) - 6_4 for x in word       ) for word in words]
         if word in TRIANGULAR_NUMBERS
     ]
     return len(lowercase__       )


if __name__ == "__main__":
  print(solution())


