






import json
import os
import re
import unicodedata
from typing import Dict, List, Optional, Tuple

from ...tokenization_utils import PreTrainedTokenizer
from ...utils import logging


SCREAMING_SNAKE_CASE_				      =							logging.get_logger(__name__)

SCREAMING_SNAKE_CASE_				      =							{
    "src_vocab_file": "vocab-src.json",
    "tgt_vocab_file": "vocab-tgt.json",
    "merges_file": "merges.txt",
}

SCREAMING_SNAKE_CASE_				      =							{
    "src_vocab_file": {
        "stas/tiny-wmt19-en-de": "https://huggingface.co/stas/tiny-wmt19-en-de/resolve/main/vocab-src.json"
    },
    "tgt_vocab_file": {
        "stas/tiny-wmt19-en-de": "https://huggingface.co/stas/tiny-wmt19-en-de/resolve/main/vocab-tgt.json"
    },
    "merges_file": {"stas/tiny-wmt19-en-de": "https://huggingface.co/stas/tiny-wmt19-en-de/resolve/main/merges.txt"},
}

SCREAMING_SNAKE_CASE_				      =							{"stas/tiny-wmt19-en-de": 1_0_2_4}
SCREAMING_SNAKE_CASE_				      =							{
    "stas/tiny-wmt19-en-de": {
        "langs": ["en", "de"],
        "model_max_length": 1_0_2_4,
        "special_tokens_map_file": None,
        "full_tokenizer_file": None,
    }
}






def   lowerCAmelCase__			(					SCREAMING_SNAKE_CASE__		):
 __a    :	int									=						set()
 __a    :	str									=						word[0]
 for char in word[1:]:
  pairs.add((prev_char, char)		)
  __a    :	Tuple									=						char
 return pairs






def   lowerCAmelCase__			(					SCREAMING_SNAKE_CASE__		):
 __a    :	str									=						text.replace('，'       ,		','		)
 __a    :	List[Any]									=						re.sub(r'。\s*'       ,		'. '       ,		SCREAMING_SNAKE_CASE__		)
 __a    :	List[str]									=						text.replace('、'       ,		','		)
 __a    :	Optional[Any]									=						text.replace('”'       ,		'"'		)
 __a    :	Optional[Any]									=						text.replace('“'       ,		'"'		)
 __a    :	Any									=						text.replace('∶'       ,		':'		)
 __a    :	Any									=						text.replace('：'       ,		':'		)
 __a    :	List[str]									=						text.replace('？'       ,		'?'		)
 __a    :	Tuple									=						text.replace('《'       ,		'"'		)
 __a    :	List[Any]									=						text.replace('》'       ,		'"'		)
 __a    :	Tuple									=						text.replace('）'       ,		')'		)
 __a    :	Optional[Any]									=						text.replace('！'       ,		'!'		)
 __a    :	str									=						text.replace('（'       ,		'('		)
 __a    :	Dict									=						text.replace('；'       ,		';'		)
 __a    :	Optional[int]									=						text.replace('１'       ,		'1'		)
 __a    :	int									=						text.replace('」'       ,		'"'		)
 __a    :	str									=						text.replace('「'       ,		'"'		)
 __a    :	int									=						text.replace('０'       ,		'0'		)
 __a    :	Optional[Any]									=						text.replace('３'       ,		'3'		)
 __a    :	Union[str, Any]									=						text.replace('２'       ,		'2'		)
 __a    :	List[str]									=						text.replace('５'       ,		'5'		)
 __a    :	Any									=						text.replace('６'       ,		'6'		)
 __a    :	Dict									=						text.replace('９'       ,		'9'		)
 __a    :	Tuple									=						text.replace('７'       ,		'7'		)
 __a    :	Tuple									=						text.replace('８'       ,		'8'		)
 __a    :	Tuple									=						text.replace('４'       ,		'4'		)
 __a    :	Tuple									=						re.sub(r'．\s*'       ,		'. '       ,		SCREAMING_SNAKE_CASE__		)
 __a    :	int									=						text.replace('～'       ,		'~'		)
 __a    :	Optional[Any]									=						text.replace('’'       ,		'\''		)
 __a    :	Tuple									=						text.replace('…'       ,		'...'		)
 __a    :	Dict									=						text.replace('━'       ,		'-'		)
 __a    :	Optional[Any]									=						text.replace('〈'       ,		'<'		)
 __a    :	List[Any]									=						text.replace('〉'       ,		'>'		)
 __a    :	str									=						text.replace('【'       ,		'['		)
 __a    :	List[str]									=						text.replace('】'       ,		']'		)
 __a    :	List[Any]									=						text.replace('％'       ,		'%'		)
 return text






def   lowerCAmelCase__			(					SCREAMING_SNAKE_CASE__		):
 __a    :	Optional[Any]									=						[]
 for char in text:
  __a    :	Dict									=						unicodedata.category(SCREAMING_SNAKE_CASE__		)
  if cat.startswith('C'		):
   continue
  output.append(SCREAMING_SNAKE_CASE__		)
 return "".join(SCREAMING_SNAKE_CASE__		)




class 							lowerCAmelCase					(							lowerCamelCase__   ):







   """simple docstring"""







   _A						=   VOCAB_FILES_NAMES
   _A						=   PRETRAINED_VOCAB_FILES_MAP
   _A						=   PRETRAINED_INIT_CONFIGURATION
   _A						=   PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
   _A						=   ['input_ids', 'attention_mask']



   def __init__( self   ,   _A=None   ,   _A=None   ,   _A=None   ,   _A=None   ,   _A=False   ,   _A="<unk>"   ,   _A="<s>"   ,   _A="</s>"   ,   _A="<pad>"   ,   **_A   ,   )    ->   List[str]:
    super().__init__(
        langs=_A   ,   src_vocab_file=_A   ,   tgt_vocab_file=_A   ,   merges_file=_A   ,   do_lower_case=_A   ,   unk_token=_A   ,   bos_token=_A   ,   sep_token=_A   ,   pad_token=_A   ,   **_A   ,   )

    try:
     import sacremoses
    except ImportError:
     raise ImportError(
         'You need to install sacremoses to use XLMTokenizer. '
         'See https://pypi.org/project/sacremoses/ for installation.'			)

    __a    :	List[str]									=						sacremoses

    __a    :	Optional[Any]									=						src_vocab_file
    __a    :	Optional[int]									=						tgt_vocab_file
    __a    :	Dict									=						merges_file
    __a    :	int									=						do_lower_case

    # cache of sm.MosesPunctNormalizer instance
    __a    :	Optional[int]									=						{}
    # cache of sm.MosesTokenizer instance
    __a    :	Tuple									=						{}
    __a    :	Tuple									=						{}

    if langs and len(_A			) == 2:
     __a    :	Optional[Any]									=						langs
    else:
     raise ValueError(
         f'''arg `langs` needs to be a list of 2 langs, e.g. [\'en\', \'ru\'], but got {langs}. '''
         'Usually that means that tokenizer can\'t find a mapping for the given model path '
         'in PRETRAINED_VOCAB_FILES_MAP, and other maps of this tokenizer.'			)

    with open(_A   ,   encoding='utf-8'			) as src_vocab_handle:
     __a    :	List[Any]									=						json.load(_A			)
    with open(_A   ,   encoding='utf-8'			) as tgt_vocab_handle:
     __a    :	List[str]									=						json.load(_A			)
     __a    :	List[str]									=						{v: k for k, v in tgt_vocab.items()}
    with open(_A   ,   encoding='utf-8'			) as merges_handle:
     __a    :	Optional[int]									=						merges_handle.read().split('\n'			)[:-1]
    __a    :	List[Any]									=						[tuple(merge.split()[:2]			) for merge in merges]
    __a    :	str									=						dict(zip(_A   ,   range(len(_A			)			)			)			)
    __a    :	Union[str, Any]									=						{}



   def    __magic_name__    ( self			)    ->   Dict[str, int]:
    return self.get_src_vocab()



   @property
   def    __magic_name__    ( self			)    ->   int:
    return self.src_vocab_size



   def    __magic_name__    ( self   ,   _A   ,   _A			)    ->   Dict:
    if lang not in self.cache_moses_punct_normalizer:
     __a    :	Any									=						self.sm.MosesPunctNormalizer(lang=_A			)
     __a    :	Union[str, Any]									=						punct_normalizer
    return self.cache_moses_punct_normalizer[lang].normalize(_A			)



   def    __magic_name__    ( self   ,   _A   ,   _A			)    ->   Dict:
    if lang not in self.cache_moses_tokenizer:
     __a    :	Tuple									=						self.sm.MosesTokenizer(lang=_A			)
     __a    :	Union[str, Any]									=						moses_tokenizer
    return self.cache_moses_tokenizer[lang].tokenize(
        _A   ,   aggressive_dash_splits=_A   ,   return_str=_A   ,   escape=_A			)



   def    __magic_name__    ( self   ,   _A   ,   _A			)    ->   Tuple:
    if lang not in self.cache_moses_detokenizer:
     __a    :	Optional[Any]									=						self.sm.MosesDetokenizer(lang=_A			)
     __a    :	Dict									=						moses_detokenizer
    return self.cache_moses_detokenizer[lang].detokenize(_A			)



   def    __magic_name__    ( self   ,   _A   ,   _A			)    ->   Tuple:
    __a    :	Any									=						replace_unicode_punct(_A			)
    __a    :	Any									=						self.moses_punct_norm(_A   ,   _A			)
    __a    :	Tuple									=						remove_non_printing_char(_A			)
    return text



   @property
   def    __magic_name__    ( self			)    ->   Union[str, Any]:
    return len(self.encoder			)



   @property
   def    __magic_name__    ( self			)    ->   Optional[int]:
    return len(self.decoder			)



   def    __magic_name__    ( self			)    ->   str:
    return dict(self.encoder   ,   **self.added_tokens_encoder			)



   def    __magic_name__    ( self			)    ->   List[str]:
    return dict(self.decoder   ,   **self.added_tokens_decoder			)



   def    __magic_name__    ( self   ,   _A			)    ->   List[Any]:
    __a    :	Union[str, Any]									=						tuple(token[:-1]			) + (token[-1] + '</w>',)
    if token in self.cache:
     return self.cache[token]
    __a    :	Tuple									=						get_pairs(_A			)

    if not pairs:
     return token + "</w>"

    while True:
     __a    :	Dict									=						min(_A   ,   key=lambda _A			: self.bpe_ranks.get(_A   ,   float('inf'			)			)			)
     if bigram not in self.bpe_ranks:
      break
     __a    :	List[Any]									=						bigram
     __a    :	List[Any]									=						[]
     __a    :	str									=						0
     while i < len(_A			):
      try:
       __a    :	Any									=						word.index(_A   ,   _A			)
      except ValueError:
       new_word.extend(word[i:]			)
       break
      else:
       new_word.extend(word[i:j]			)
       __a    :	Tuple									=						j

      if word[i] == first and i < len(_A			) - 1 and word[i + 1] == second:
       new_word.append(first + second			)
       i += 2
      else:
       new_word.append(word[i]			)
       i += 1
     __a    :	Dict									=						tuple(_A			)
     __a    :	Dict									=						new_word
     if len(_A			) == 1:
      break
     else:
      __a    :	List[str]									=						get_pairs(_A			)
    __a    :	List[Any]									=						' '.join(_A			)
    if word == "\n  </w>":
     __a    :	Tuple									=						'\n</w>'
    __a    :	Dict									=						word
    return word



   def    __magic_name__    ( self   ,   _A   ,   _A="en"   ,   _A=False			)    ->   Optional[Any]:
    __a    :	Optional[Any]									=						self.src_lang

    if self.do_lower_case:
     __a    :	Optional[int]									=						text.lower()

    if bypass_tokenizer:
     __a    :	List[Any]									=						text.split()
    else:
     __a    :	str									=						self.moses_pipeline(_A   ,   lang=_A			)
     __a    :	Optional[Any]									=						self.moses_tokenize(_A   ,   lang=_A			)

    __a    :	int									=						[]
    for token in text:
     if token:
      split_tokens.extend(list(self.bpe(_A			).split(' '			)			)			)

    return split_tokens



   def    __magic_name__    ( self   ,   _A			)    ->   str:
    return self.encoder.get(_A   ,   self.encoder.get(self.unk_token			)			)



   def    __magic_name__    ( self   ,   _A			)    ->   List[str]:
    return self.decoder.get(_A   ,   self.unk_token			)



   def    __magic_name__    ( self   ,   _A			)    ->   Any:
    __a    :	Union[str, Any]									=						[t.replace(' '   ,   ''			).replace('</w>'   ,   ' '			) for t in tokens]
    __a    :	Any									=						''.join(_A			).split()
    # detokenize
    __a    :	Optional[int]									=						self.moses_detokenize(_A   ,   self.tgt_lang			)
    return text



   def    __magic_name__    ( self   ,   _A   ,   _A = None			)    ->   List[int]:
    __a    :	Any									=						[self.sep_token_id]

    # no bos used in fairseq
    if token_ids_a is None:
     return token_ids_a + sep
    return token_ids_a + sep + token_ids_a + sep



   def    __magic_name__    ( self   ,   _A   ,   _A = None   ,   _A = False			)    ->   List[int]:

    if already_has_special_tokens:
     return super().get_special_tokens_mask(
         token_ids_a=_A   ,   token_ids_a=_A   ,   already_has_special_tokens=_A			)
    # no bos used in fairseq
    if token_ids_a is not None:
     return ([0] * len(_A			)) + [1] + ([0] * len(_A			)) + [1]
    return ([0] * len(_A			)) + [1]



   def    __magic_name__    ( self   ,   _A   ,   _A = None			)    ->   List[int]:
    __a    :	Optional[int]									=						[self.sep_token_id]

    # no bos used in fairseq
    if token_ids_a is None:
     return len(token_ids_a + sep			) * [0]
    return len(token_ids_a + sep			) * [0] + len(token_ids_a + sep			) * [1]



   def    __magic_name__    ( self   ,   _A   ,   _A = None			)    ->   Tuple[str]:
    if not os.path.isdir(_A			):
     logger.error(f'''Vocabulary path ({save_directory}) should be a directory'''			)
     return

    __a    :	Tuple									=						os.path.join(
        _A   ,   (filename_prefix + '-' if filename_prefix else '') + VOCAB_FILES_NAMES['src_vocab_file']			)
    __a    :	List[Any]									=						os.path.join(
        _A   ,   (filename_prefix + '-' if filename_prefix else '') + VOCAB_FILES_NAMES['tgt_vocab_file']			)
    __a    :	Tuple									=						os.path.join(
        _A   ,   (filename_prefix + '-' if filename_prefix else '') + VOCAB_FILES_NAMES['merges_file']			)

    with open(_A   ,   'w'   ,   encoding='utf-8'			) as f:
     f.write(json.dumps(self.encoder   ,   indent=2   ,   sort_keys=_A   ,   ensure_ascii=_A			) + '\n'			)

    with open(_A   ,   'w'   ,   encoding='utf-8'			) as f:
     __a    :	int									=						{v: k for k, v in self.decoder.items()}
     f.write(json.dumps(_A   ,   indent=2   ,   sort_keys=_A   ,   ensure_ascii=_A			) + '\n'			)

    __a    :	Any									=						0
    with open(_A   ,   'w'   ,   encoding='utf-8'			) as writer:
     for bpe_tokens, token_index in sorted(self.bpe_ranks.items()   ,   key=lambda _A			: kv[1]			):
      if index != token_index:
       logger.warning(
           f'''Saving vocabulary to {merges_file}: BPE merge indices are not consecutive.'''
           ' Please check that the tokenizer is not corrupted!'			)
       __a    :	Union[str, Any]									=						token_index
      writer.write(' '.join(_A			) + '\n'			)
      index += 1

    return src_vocab_file, tgt_vocab_file, merges_file



   def __getstate__( self			)    ->   Union[str, Any]:
    __a    :	Union[str, Any]									=						self.__dict__.copy()
    __a    :	Optional[int]									=						None
    return state



   def __setstate__( self   ,   _A			)    ->   Dict:
    __a    :	int									=						d

    try:
     import sacremoses
    except ImportError:
     raise ImportError(
         'You need to install sacremoses to use XLMTokenizer. '
         'See https://pypi.org/project/sacremoses/ for installation.'			)

    __a    :	str									=						sacremoses












'''simple docstring'''


from __future__ import annotations

import random

from matplotlib import animation
from matplotlib import pyplot as plt

# Frame rate of the animation
SCREAMING_SNAKE_CASE_				      =							2_0

# Time between time steps in seconds
SCREAMING_SNAKE_CASE_				      =							INTERVAL / 1_0_0_0




class 							lowerCAmelCase					:







   """simple docstring"""







   def __init__( self   ,   _A   ,   _A   ,   _A   ,   _A   ,   _A = 1.0   ,   _A = 1.0   ,   _A = "blue"   ,   )    ->   None:
    __a    :	str									=						position_x
    __a    :	Optional[Any]									=						position_y
    __a    :	List[Any]									=						velocity_x
    __a    :	Tuple									=						velocity_y
    __a    :	Dict									=						mass
    __a    :	int									=						size
    __a    :	Tuple									=						color



   @property
   def    __magic_name__    ( self			)    ->   tuple[float, float]:
    return self.position_x, self.position_y



   @property
   def    __magic_name__    ( self			)    ->   tuple[float, float]:
    return self.velocity_x, self.velocity_y



   def    __magic_name__    ( self   ,   _A   ,   _A   ,   _A			)    ->   None:
    self.velocity_x += force_x * delta_time
    self.velocity_y += force_y * delta_time



   def    __magic_name__    ( self   ,   _A			)    ->   None:
    self.position_x += self.velocity_x * delta_time
    self.position_y += self.velocity_y * delta_time




class 							lowerCAmelCase					:







   """simple docstring"""







   def __init__( self   ,   _A   ,   _A = 1.0   ,   _A = 1.0   ,   _A = 0.0   ,   )    ->   None:
    __a    :	List[str]									=						bodies
    __a    :	List[str]									=						gravitation_constant
    __a    :	int									=						time_factor
    __a    :	List[str]									=						softening_factor



   def __len__( self			)    ->   int:
    return len(self.bodies			)



   def    __magic_name__    ( self   ,   _A			)    ->   None:
    for bodya in self.bodies:
     __a    :	Any									=						0.0
     __a    :	str									=						0.0
     for bodya in self.bodies:
      if bodya != bodya:
       __a    :	Optional[Any]									=						bodya.position_x - bodya.position_x
       __a    :	Dict									=						bodya.position_y - bodya.position_y

       # Calculation of the distance using Pythagoras's theorem
       # Extra factor due to the softening technique
       __a    :	Optional[Any]									=						(dif_x**2 + dif_y**2 + self.softening_factor) ** (
           1 / 2
       )

       # Newton's law of universal gravitation.
       force_x += (
           self.gravitation_constant * bodya.mass * dif_x / distance**3
       )
       force_y += (
           self.gravitation_constant * bodya.mass * dif_y / distance**3
       )

            # Update the body's velocity once all the force components have been added
     bodya.update_velocity(_A   ,   _A   ,   delta_time * self.time_factor			)

    # Update the positions only after all the velocities have been updated
    for body in self.bodies:
     body.update_position(delta_time * self.time_factor			)






def   lowerCAmelCase__			(					SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__		):
 body_system.update_system(SCREAMING_SNAKE_CASE__		)

 # Update the positions of the patches
 for patch, body in zip(SCREAMING_SNAKE_CASE__       ,		body_system.bodies		):
  __a    :	Dict									=						(body.position_x, body.position_y)






def   lowerCAmelCase__			(					SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__ = -1       ,		SCREAMING_SNAKE_CASE__ = 1       ,		SCREAMING_SNAKE_CASE__ = -1       ,		SCREAMING_SNAKE_CASE__ = 1       ,		):
 __a    :	int									=						plt.figure()
 fig.canvas.set_window_title(SCREAMING_SNAKE_CASE__		)
 __a    :	int									=						plt.axes(
     xlim=(x_start, x_end)       ,		ylim=(y_start, y_end)		)  # Set section to be plotted
 plt.gca().set_aspect('equal'		)  # Fix aspect ratio

 # Each body is drawn as a patch by the plt-function
 __a    :	str									=						[
     plt.Circle((body.position_x, body.position_y)       ,		body.size       ,		fc=body.color		)
     for body in body_system.bodies
 ]

 for patch in patches:
  ax.add_patch(SCREAMING_SNAKE_CASE__		)

 # Function called at each step of the animation
 def update(SCREAMING_SNAKE_CASE__		) -> list[plt.Circle]:
  update_step(SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__		)
  return patches

 __a    :	Dict									=						animation.FuncAnimation(  # noqa: F841
     SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		interval=SCREAMING_SNAKE_CASE__       ,		blit=SCREAMING_SNAKE_CASE__		)

 plt.show()






def   lowerCAmelCase__			(					):
 __a    :	Dict									=						0.970_0436
 __a    :	List[Any]									=						-0.2430_8753
 __a    :	Union[str, Any]									=						0.4_6620_3685
 __a    :	Any									=						0.4323_6573

 __a    :	Optional[int]									=						[
     Body(SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		size=0.2       ,		color='red'		),
     Body(-position_x       ,		-position_y       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		size=0.2       ,		color='green'		),
     Body(0       ,		0       ,		-2 * velocity_x       ,		-2 * velocity_y       ,		size=0.2       ,		color='blue'		),
 ]
 return BodySystem(SCREAMING_SNAKE_CASE__       ,		time_factor=3		)






def   lowerCAmelCase__			(					):
 __a    :	Optional[int]									=						7.34_76E22
 __a    :	List[Any]									=						5.9_72E24
 __a    :	List[Any]									=						1022
 __a    :	str									=						384399000
 __a    :	Optional[int]									=						6.6_74E-11

 # Calculation of the respective velocities so that total impulse is zero,
 # i.e. the two bodies together don't move
 __a    :	str									=						earth_mass * velocity_dif / (earth_mass + moon_mass)
 __a    :	Optional[int]									=						moon_velocity - velocity_dif

 __a    :	Union[str, Any]									=						Body(-earth_moon_distance       ,		0       ,		0       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		10000000       ,		'grey'		)
 __a    :	Union[str, Any]									=						Body(0       ,		0       ,		0       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		50000000       ,		'blue'		)
 return BodySystem([earth, moon]       ,		SCREAMING_SNAKE_CASE__       ,		time_factor=1000000		)






def   lowerCAmelCase__			(					):
 __a    :	Tuple									=						[]
 for _ in range(10		):
  __a    :	Dict									=						random.uniform(-0.5       ,		0.5		)
  __a    :	Optional[int]									=						random.uniform(-0.5       ,		0.5		)

  # Bodies are created pairwise with opposite velocities so that the
  # total impulse remains zero
  bodies.append(
      Body(
          random.uniform(-0.5       ,		0.5		)       ,		random.uniform(-0.5       ,		0.5		)       ,		SCREAMING_SNAKE_CASE__       ,		SCREAMING_SNAKE_CASE__       ,		size=0.05       ,		)		)
  bodies.append(
      Body(
          random.uniform(-0.5       ,		0.5		)       ,		random.uniform(-0.5       ,		0.5		)       ,		-velocity_x       ,		-velocity_y       ,		size=0.05       ,		)		)
 return BodySystem(SCREAMING_SNAKE_CASE__       ,		0.01       ,		10       ,		0.1		)


if __name__ == "__main__":
  plot("Figure-8 solution to the 3-body-problem", example_a(), -2, 2, -2, 2)
  plot(
      "Moon's orbit around the earth",
      example_a(),
      -4_3_0_0_0_0_0_0_0,
      4_3_0_0_0_0_0_0_0,
      -4_3_0_0_0_0_0_0_0,
      4_3_0_0_0_0_0_0_0,
  )
  plot("Random system with many bodies", example_a(), -1.5, 1.5, -1.5, 1.5)




