


'''simple docstring'''







import bisect
import copy
from collections import defaultdict

import numpy as np
from torch.utils.data import BatchSampler, Sampler

from utils import logger





def 						snake_case__ (lowerCAmelCase_					,  lowerCAmelCase_	):
    UpperCamelCase__      =			copy.deepcopy(lowerCAmelCase_	)
    UpperCamelCase__      =			sorted(lowerCAmelCase_	)
    UpperCamelCase__      =			[bisect.bisect_right(lowerCAmelCase_					,  lowerCAmelCase_	) for y in x]
    return quantized





def 						snake_case__ (lowerCAmelCase_					,  lowerCAmelCase_=0	):
    UpperCamelCase__      =			np.arange(start=3					,  stop=lowerCAmelCase_					,  step=4	).tolist() if k > 0 else [10]
    UpperCamelCase__      =			_quantize(lowerCAmelCase_					,  lowerCAmelCase_	)
    # count number of elements per group
    UpperCamelCase__      =			np.unique(lowerCAmelCase_					,  return_counts=lowerCAmelCase_	)[1]
    UpperCamelCase__      =			[0] + bins + [np.inf]
    logger.info("Using {} as bins for aspect lengths quantization".format(lowerCAmelCase_	)	)
    logger.info("Count of instances per bin: {}".format(lowerCAmelCase_	)	)
    return groups





class       lowerCamelCase_							(	lowerCAmelCase_  ):






   '''simple docstring'''

   def __init__(  self     ,						__UpperCamelCase     ,						__UpperCamelCase     ,						__UpperCamelCase ):
       if not isinstance(__UpperCamelCase     ,						__UpperCamelCase ):
           raise ValueError(
               "sampler should be an instance of torch.utils.data.Sampler, but got sampler={}".format(__UpperCamelCase ) )
       UpperCamelCase__      =			sampler
       UpperCamelCase__      =			group_ids
       UpperCamelCase__      =			batch_size


   def __iter__(  self ):
       UpperCamelCase__      =			defaultdict(__UpperCamelCase )
       UpperCamelCase__      =			defaultdict(__UpperCamelCase )

       UpperCamelCase__      =			0
       for idx in self.sampler:
           UpperCamelCase__      =			self.group_ids[idx]
           buffer_per_group[group_id].append(__UpperCamelCase )
           samples_per_group[group_id].append(__UpperCamelCase )
           if len(buffer_per_group[group_id] ) == self.batch_size:
               yield buffer_per_group[group_id]  # TODO
               num_batches += 1
               del buffer_per_group[group_id]
           assert len(buffer_per_group[group_id] ) < self.batch_size

       # now we have run out of elements that satisfy
       # the group criteria, let's return the remaining
       # elements so that the size of the sampler is
       # deterministic
       UpperCamelCase__      =			len(self )
       UpperCamelCase__      =			expected_num_batches - num_batches
       if num_remaining > 0:
           # for the remaining batches, group the batches by similar lengths
           UpperCamelCase__      =			[]
           for group_id, idxs in sorted(buffer_per_group.items()     ,						key=lambda __UpperCamelCase : x[0] ):
               batch_idx.extend(__UpperCamelCase )
               if len(__UpperCamelCase ) >= self.batch_size:
                   yield batch_idx[: self.batch_size]
                   UpperCamelCase__      =			batch_idx[self.batch_size :]
                   num_remaining -= 1
           if len(__UpperCamelCase ) > 0:
               yield batch_idx
               num_remaining -= 1
       assert num_remaining == 0







   def __len__(  self ):
       return (len(self.sampler ) + self.batch_size - 1) // self.batch_size









'''simple docstring'''







from math import radians as angle_to_radians
from math import sin

# Acceleration Constant on Earth (unit m/s^2)
lowercase__     :  str    					=			9.8_0_6_6_5





def 						snake_case__ (lowerCAmelCase_					,  lowerCAmelCase_	):

    # Ensure valid instance
    if not isinstance(lowerCAmelCase_					,  (int, float)	):
        raise TypeError("Invalid velocity. Should be a positive number."	)

    if not isinstance(lowerCAmelCase_					,  (int, float)	):
        raise TypeError("Invalid angle. Range is 1-90 degrees."	)

    # Ensure valid angle
    if angle > 90 or angle < 1:
        raise ValueError("Invalid angle. Range is 1-90 degrees."	)

    # Ensure valid velocity
    if init_velocity < 0:
        raise ValueError("Invalid velocity. Should be a positive number."	)





def 						snake_case__ (lowerCAmelCase_					,  lowerCAmelCase_	):
    check_args(lowerCAmelCase_					,  lowerCAmelCase_	)
    UpperCamelCase__      =			angle_to_radians(2 * angle	)
    return round(init_velocity**2 * sin(lowerCAmelCase_	) / g					,  2	)





def 						snake_case__ (lowerCAmelCase_					,  lowerCAmelCase_	):
    check_args(lowerCAmelCase_					,  lowerCAmelCase_	)
    UpperCamelCase__      =			angle_to_radians(lowerCAmelCase_	)
    return round(init_velocity**2 * sin(lowerCAmelCase_	) ** 2 / (2 * g)					,  2	)





def 						snake_case__ (lowerCAmelCase_					,  lowerCAmelCase_	):
    check_args(lowerCAmelCase_					,  lowerCAmelCase_	)
    UpperCamelCase__      =			angle_to_radians(lowerCAmelCase_	)
    return round(2 * init_velocity * sin(lowerCAmelCase_	) / g					,  2	)





def 						snake_case__ ():
    UpperCamelCase__    ,  UpperCamelCase__      =			25, 20
    assert horizontal_distance(lowerCAmelCase_					,  lowerCAmelCase_	) == 40.97
    assert max_height(lowerCAmelCase_					,  lowerCAmelCase_	) == 3.73
    assert total_time(lowerCAmelCase_					,  lowerCAmelCase_	) == 1.74


if __name__ == "__main__":
      from doctest import testmod

      testmod()

      # Get input from user
      lowercase__     :  Union[str, Any]    					=			float(input('Initial Velocity: ').strip())

      # Get input from user
      lowercase__     :  Any    					=			float(input('angle: ').strip())

      # Print results
      print()
      print('Results: ')
      print(F'''Horizontal Distance: {horizontal_distance(init_vel, angle)!s} [m]''')
      print(F'''Maximum Height: {max_height(init_vel, angle)!s} [m]''')
      print(F'''Total Time: {total_time(init_vel, angle)!s} [s]''')




