

import re
import string
from collections import Counter

import sacrebleu
import sacremoses
from packaging import version

import datasets


__A      		=       '''
@inproceedings{xu-etal-2016-optimizing,
    title = {Optimizing Statistical Machine Translation for Text Simplification},
    authors={Xu, Wei and Napoles, Courtney and Pavlick, Ellie and Chen, Quanze and Callison-Burch, Chris},
    journal = {Transactions of the Association for Computational Linguistics},
    volume = {4},
    year={2016},
    url = {https://www.aclweb.org/anthology/Q16-1029},
    pages = {401--415
},
@inproceedings{post-2018-call,
    title = "A Call for Clarity in Reporting {BLEU} Scores",
    author = "Post, Matt",
    booktitle = "Proceedings of the Third Conference on Machine Translation: Research Papers",
    month = oct,
    year = "2018",
    address = "Belgium, Brussels",
    publisher = "Association for Computational Linguistics",
    url = "https://www.aclweb.org/anthology/W18-6319",
    pages = "186--191",
}
'''

__A      		=       '''\
WIKI_SPLIT is the combination of three metrics SARI, EXACT and SACREBLEU
It can be used to evaluate the quality of machine-generated texts.
'''


__A      		=       '''
Calculates sari score (between 0 and 100) given a list of source and predicted
sentences, and a list of lists of reference sentences. It also computes the BLEU score as well as the exact match score.
Args:
    sources: list of source sentences where each sentence should be a string.
    predictions: list of predicted sentences where each sentence should be a string.
    references: list of lists of reference sentences where each sentence should be a string.
Returns:
    sari: sari score
    sacrebleu: sacrebleu score
    exact: exact score

Examples:
    >>> sources=["About 95 species are currently accepted ."]
    >>> predictions=["About 95 you now get in ."]
    >>> references=[["About 95 species are currently known ."]]
    >>> wiki_split = datasets.load_metric("wiki_split")
    >>> results = wiki_split.compute(sources=sources, predictions=predictions, references=references)
    >>> print(results)
    {\'sari\': 21.805555555555557, \'sacrebleu\': 14.535768424205482, \'exact\': 0.0}
'''



def 				snake_case_(_UpperCamelCase					)							->     List[Any]:



  """simple docstring"""






  def remove_articles(_UpperCamelCase					):
    _snake_case						=							re.compile(R'''\b(a|an|the)\b'''			,	re.UNICODE					)
    return re.sub(_UpperCamelCase			,	''' '''			,	_UpperCamelCase					)

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

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

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

  return white_space_fix(remove_articles(remove_punc(lower(_UpperCamelCase					)					)					)					)



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase					)							->     int:



  """simple docstring"""






  return int(normalize_answer(_UpperCamelCase					) == normalize_answer(_UpperCamelCase					)					)



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase					)							->     Union[str, Any]:



  """simple docstring"""






  _snake_case						=							[any(compute_exact(_UpperCamelCase			,	_UpperCamelCase					) for ref in refs					) for pred, refs in zip(_UpperCamelCase			,	_UpperCamelCase					)]
  return (sum(_UpperCamelCase					) / len(_UpperCamelCase					)) * 100



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					)							->     List[Any]:



  """simple docstring"""






  _snake_case						=							[rgram for rgrams in rgramslist for rgram in rgrams]
  _snake_case						=							Counter(_UpperCamelCase					)

  _snake_case						=							Counter(_UpperCamelCase					)
  _snake_case						=							Counter()
  for sgram, scount in sgramcounter.items():
    _snake_case						=							scount * numref

  _snake_case						=							Counter(_UpperCamelCase					)
  _snake_case						=							Counter()
  for cgram, ccount in cgramcounter.items():
    _snake_case						=							ccount * numref

  # KEEP
  _snake_case						=							sgramcounter_rep & cgramcounter_rep
  _snake_case						=							keepgramcounter_rep & rgramcounter
  _snake_case						=							sgramcounter_rep & rgramcounter

  _snake_case						=							0
  _snake_case						=							0
  for keepgram in keepgramcountergood_rep:
    keeptmpscorea += keepgramcountergood_rep[keepgram] / keepgramcounter_rep[keepgram]
    # Fix an alleged bug [2] in the keep score computation.
    # keeptmpscore2 += keepgramcountergood_rep[keepgram] / keepgramcounterall_rep[keepgram]
    keeptmpscorea += keepgramcountergood_rep[keepgram]
  # Define 0/0=1 instead of 0 to give higher scores for predictions that match
  #      a target exactly.
  _snake_case						=							1
  _snake_case						=							1
  if len(_UpperCamelCase					) > 0:
    _snake_case						=							keeptmpscorea / len(_UpperCamelCase					)
  if len(_UpperCamelCase					) > 0:
    # Fix an alleged bug [2] in the keep score computation.
    # keepscore_recall = keeptmpscore2 / len(keepgramcounterall_rep)
    _snake_case						=							keeptmpscorea / sum(keepgramcounterall_rep.values()					)
  _snake_case						=							0
  if keepscore_precision > 0 or keepscore_recall > 0:
    _snake_case						=							2 * keepscore_precision * keepscore_recall / (keepscore_precision + keepscore_recall)

  # DELETION
  _snake_case						=							sgramcounter_rep - cgramcounter_rep
  _snake_case						=							delgramcounter_rep - rgramcounter
  _snake_case						=							sgramcounter_rep - rgramcounter
  _snake_case						=							0
  _snake_case						=							0
  for delgram in delgramcountergood_rep:
    deltmpscorea += delgramcountergood_rep[delgram] / delgramcounter_rep[delgram]
    deltmpscorea += delgramcountergood_rep[delgram] / delgramcounterall_rep[delgram]
  # Define 0/0=1 instead of 0 to give higher scores for predictions that match
  # a target exactly.
  _snake_case						=							1
  if len(_UpperCamelCase					) > 0:
    _snake_case						=							deltmpscorea / len(_UpperCamelCase					)

  # ADDITION
  _snake_case						=							set(_UpperCamelCase					) - set(_UpperCamelCase					)
  _snake_case						=							set(_UpperCamelCase					) & set(_UpperCamelCase					)
  _snake_case						=							set(_UpperCamelCase					) - set(_UpperCamelCase					)

  _snake_case						=							0
  for addgram in addgramcountergood:
    addtmpscore += 1

  # Define 0/0=1 instead of 0 to give higher scores for predictions that match
  # a target exactly.
  _snake_case						=							1
  _snake_case						=							1
  if len(_UpperCamelCase					) > 0:
    _snake_case						=							addtmpscore / len(_UpperCamelCase					)
  if len(_UpperCamelCase					) > 0:
    _snake_case						=							addtmpscore / len(_UpperCamelCase					)
  _snake_case						=							0
  if addscore_precision > 0 or addscore_recall > 0:
    _snake_case						=							2 * addscore_precision * addscore_recall / (addscore_precision + addscore_recall)

  return (keepscore, delscore_precision, addscore)



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					)							->     str:



  """simple docstring"""






  _snake_case						=							len(_UpperCamelCase					)

  _snake_case						=							ssent.split(''' '''					)
  _snake_case						=							csent.split(''' '''					)
  _snake_case						=							[]
  _snake_case						=							[]
  _snake_case						=							[]
  _snake_case						=							[]
  _snake_case						=							[]
  _snake_case						=							[]

  _snake_case						=							[]
  _snake_case						=							[]
  _snake_case						=							[]
  _snake_case						=							[]
  for rsent in rsents:
    _snake_case						=							rsent.split(''' '''					)
    _snake_case						=							[]
    _snake_case						=							[]
    _snake_case						=							[]
    ragramslist.append(_UpperCamelCase					)
    for i in range(0			,	len(_UpperCamelCase					) - 1					):
      if i < len(_UpperCamelCase					) - 1:
        _snake_case						=							ragrams[i] + ''' ''' + ragrams[i + 1]
        ragrams.append(_UpperCamelCase					)
      if i < len(_UpperCamelCase					) - 2:
        _snake_case						=							ragrams[i] + ''' ''' + ragrams[i + 1] + ''' ''' + ragrams[i + 2]
        ragrams.append(_UpperCamelCase					)
      if i < len(_UpperCamelCase					) - 3:
        _snake_case						=							ragrams[i] + ''' ''' + ragrams[i + 1] + ''' ''' + ragrams[i + 2] + ''' ''' + ragrams[i + 3]
        ragrams.append(_UpperCamelCase					)
    ragramslist.append(_UpperCamelCase					)
    ragramslist.append(_UpperCamelCase					)
    ragramslist.append(_UpperCamelCase					)

  for i in range(0			,	len(_UpperCamelCase					) - 1					):
    if i < len(_UpperCamelCase					) - 1:
      _snake_case						=							sagrams[i] + ''' ''' + sagrams[i + 1]
      sagrams.append(_UpperCamelCase					)
    if i < len(_UpperCamelCase					) - 2:
      _snake_case						=							sagrams[i] + ''' ''' + sagrams[i + 1] + ''' ''' + sagrams[i + 2]
      sagrams.append(_UpperCamelCase					)
    if i < len(_UpperCamelCase					) - 3:
      _snake_case						=							sagrams[i] + ''' ''' + sagrams[i + 1] + ''' ''' + sagrams[i + 2] + ''' ''' + sagrams[i + 3]
      sagrams.append(_UpperCamelCase					)

  for i in range(0			,	len(_UpperCamelCase					) - 1					):
    if i < len(_UpperCamelCase					) - 1:
      _snake_case						=							cagrams[i] + ''' ''' + cagrams[i + 1]
      cagrams.append(_UpperCamelCase					)
    if i < len(_UpperCamelCase					) - 2:
      _snake_case						=							cagrams[i] + ''' ''' + cagrams[i + 1] + ''' ''' + cagrams[i + 2]
      cagrams.append(_UpperCamelCase					)
    if i < len(_UpperCamelCase					) - 3:
      _snake_case						=							cagrams[i] + ''' ''' + cagrams[i + 1] + ''' ''' + cagrams[i + 2] + ''' ''' + cagrams[i + 3]
      cagrams.append(_UpperCamelCase					)

  ((_snake_case),					(_snake_case),					(_snake_case))						=							SARIngram(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					)
  ((_snake_case),					(_snake_case),					(_snake_case))						=							SARIngram(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					)
  ((_snake_case),					(_snake_case),					(_snake_case))						=							SARIngram(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					)
  ((_snake_case),					(_snake_case),					(_snake_case))						=							SARIngram(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					)
  _snake_case						=							sum([keepascore, keepascore, keepascore, keepascore]					) / 4
  _snake_case						=							sum([delascore, delascore, delascore, delascore]					) / 4
  _snake_case						=							sum([addascore, addascore, addascore, addascore]					) / 4
  _snake_case						=							(avgkeepscore + avgdelscore + avgaddscore) / 3
  return finalscore



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase = True			,	_UpperCamelCase = "13a"			,	_UpperCamelCase = True					)							->     Tuple:



  """simple docstring"""






  if lowercase:
    _snake_case						=							sentence.lower()

  if tokenizer in ["13a", "intl"]:
    if version.parse(sacrebleu.__version__					).major >= 2:
      _snake_case						=							sacrebleu.metrics.bleu._get_tokenizer(_UpperCamelCase					)()(_UpperCamelCase					)
    else:
      _snake_case						=							sacrebleu.TOKENIZERS[tokenizer]()(_UpperCamelCase					)
  elif tokenizer == "moses":
    _snake_case						=							sacremoses.MosesTokenizer().tokenize(_UpperCamelCase			,	return_str=_UpperCamelCase			,	escape=_UpperCamelCase					)
  elif tokenizer == "penn":
    _snake_case						=							sacremoses.MosesTokenizer().penn_tokenize(_UpperCamelCase			,	return_str=_UpperCamelCase					)
  else:
    _snake_case						=							sentence

  if not return_str:
    _snake_case						=							normalized_sent.split()

  return normalized_sent



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					)							->     List[str]:



  """simple docstring"""






  if not (len(_UpperCamelCase					) == len(_UpperCamelCase					) == len(_UpperCamelCase					)):
    raise ValueError('''Sources length must match predictions and references lengths.'''					)
  _snake_case						=							0
  for src, pred, refs in zip(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase					):
    sari_score += SARIsent(normalize(_UpperCamelCase					)			,	normalize(_UpperCamelCase					)			,	[normalize(_UpperCamelCase					) for sent in refs]					)
  _snake_case						=							sari_score / len(_UpperCamelCase					)
  return 100 * sari_score



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase			,	_UpperCamelCase="exp"			,	_UpperCamelCase=None			,	_UpperCamelCase=False			,	_UpperCamelCase=False			,	_UpperCamelCase=False			,	)							->     List[str]:



  """simple docstring"""






  _snake_case						=							len(references[0]					)
  if any(len(_UpperCamelCase					) != references_per_prediction for refs in references					):
    raise ValueError('''Sacrebleu requires the same number of references for each prediction'''					)
  _snake_case						=							[[refs[i] for refs in references] for i in range(_UpperCamelCase					)]
  _snake_case						=							sacrebleu.corpus_bleu(
      _UpperCamelCase			,	_UpperCamelCase			,	smooth_method=_UpperCamelCase			,	smooth_value=_UpperCamelCase			,	force=_UpperCamelCase			,	lowercase=_UpperCamelCase			,	use_effective_order=_UpperCamelCase			,	)
  return output.score



@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION       ,							_KWARGS_DESCRIPTION					)
class   lowercase_   (  datasets.Metric					):



      def 						UpperCamelCase_		(      self				:    Optional[int]		)   ->					List[str]:
        return datasets.MetricInfo(
            description=_DESCRIPTION      , citation=_CITATION      , inputs_description=_KWARGS_DESCRIPTION      , features=datasets.Features(
                {
                    '''predictions''': datasets.Value('''string'''      , id='''sequence'''		),
                    '''references''': datasets.Sequence(datasets.Value('''string'''      , id='''sequence'''		)      , id='''references'''		),
                }		)      , codebase_urls=[
                '''https://github.com/huggingface/transformers/blob/master/src/transformers/data/metrics/squad_metrics.py''',
                '''https://github.com/cocoxu/simplification/blob/master/SARI.py''',
                '''https://github.com/tensorflow/tensor2tensor/blob/master/tensor2tensor/utils/sari_hook.py''',
                '''https://github.com/mjpost/sacreBLEU''',
            ]      , reference_urls=[
                '''https://www.aclweb.org/anthology/Q16-1029.pdf''',
                '''https://github.com/mjpost/sacreBLEU''',
                '''https://en.wikipedia.org/wiki/BLEU''',
                '''https://towardsdatascience.com/evaluating-text-output-in-nlp-bleu-at-your-own-risk-e8609665a213''',
            ]      , )







      def 						UpperCamelCase_		(      self				:    str      , A__				:    int      , A__				:    Tuple      , A__				:    int		)   ->					Optional[Any]:
        _snake_case						=							{}
        result.update({'''sari''': compute_sari(sources=A__      , predictions=A__      , references=A__		)}		)
        result.update({'''sacrebleu''': compute_sacrebleu(predictions=A__      , references=A__		)}		)
        result.update({'''exact''': compute_em(predictions=A__      , references=A__		)}		)
        return result




from math import factorial



def 				snake_case_(_UpperCamelCase			,	_UpperCamelCase					)							->     int:



  """simple docstring"""






  if n < k or k < 0:
    raise ValueError('''Please enter positive integers for n and k where n >= k'''					)
  return factorial(_UpperCamelCase					) // (factorial(_UpperCamelCase					) * factorial(n - k					))


if __name__ == "__main__":
 print(
     '''The number of five-card hands possible from a standard''',
     f'''fifty-two card deck is: {combinations(52, 5)}\n''',
 )

 print(
     '''If a class of 40 students must be arranged into groups of''',
     f'''4 for group projects, there are {combinations(40, 4)} ways''',
     '''to arrange them.\n''',
 )

 print(
     '''If 10 teams are competing in a Formula One race, there''',
     f'''are {combinations(10, 3)} ways that first, second and''',
     '''third place can be awarded.''',
 )

