"""simple docstring"""







import argparse
import copy



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Any      ):
     lowercase_	:				Union[str, Any]													=	{}

     with open(__SCREAMING_SNAKE_CASE      ) as f:
          for line in f:
               if line.split()[0] not in dict_of_neighbours:
                    lowercase_	:				Optional[int]													=	[]
                    _list.append([line.split()[1], line.split()[2]]      )
                    lowercase_	:				Tuple													=	_list
               else:
                    dict_of_neighbours[line.split()[0]].append(
                        [line.split()[1], line.split()[2]]      )
               if line.split()[1] not in dict_of_neighbours:
                    lowercase_	:				int													=	[]
                    _list.append([line.split()[0], line.split()[2]]      )
                    lowercase_	:				Any													=	_list
               else:
                    dict_of_neighbours[line.split()[1]].append(
                        [line.split()[0], line.split()[2]]      )

     return dict_of_neighbours



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Optional[int]     ,			__SCREAMING_SNAKE_CASE							:     Optional[Any]      ):

     with open(__SCREAMING_SNAKE_CASE      ) as f:
          lowercase_	:				List[str]													=	f.read(1      )
     lowercase_	:				str													=	start_node

     lowercase_	:				Optional[Any]													=	[]

     lowercase_	:				Union[str, Any]													=	start_node

     lowercase_	:				Optional[Any]													=	0
     while visiting not in first_solution:
          lowercase_	:				List[str]													=	1_00_00
          for k in dict_of_neighbours[visiting]:
               if int(k[1]      ) < int(__SCREAMING_SNAKE_CASE      ) and k[0] not in first_solution:
                    lowercase_	:				List[str]													=	k[1]
                    lowercase_	:				Union[str, Any]													=	k[0]

          first_solution.append(__SCREAMING_SNAKE_CASE      )
          lowercase_	:				List[Any]													=	distance_of_first_solution + int(__SCREAMING_SNAKE_CASE      )
          lowercase_	:				Union[str, Any]													=	best_node

     first_solution.append(__SCREAMING_SNAKE_CASE      )

     lowercase_	:				Union[str, Any]													=	0
     for k in dict_of_neighbours[first_solution[-2]]:
          if k[0] == start_node:
               break
          position += 1

     lowercase_	:				Dict													=	(
         distance_of_first_solution
         + int(dict_of_neighbours[first_solution[-2]][position][1]      )
         - 1_00_00
     )
     return first_solution, distance_of_first_solution



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Optional[Any]     ,			__SCREAMING_SNAKE_CASE							:     List[str]      ):
     lowercase_	:				Any													=	[]

     for n in solution[1:-1]:
          lowercase_	:				List[Any]													=	solution.index(__SCREAMING_SNAKE_CASE      )
          for kn in solution[1:-1]:
               lowercase_	:				Union[str, Any]													=	solution.index(__SCREAMING_SNAKE_CASE      )
               if n == kn:
                    continue

               lowercase_	:				Union[str, Any]													=	copy.deepcopy(__SCREAMING_SNAKE_CASE      )
               lowercase_	:				str													=	kn
               lowercase_	:				Dict													=	n

               lowercase_	:				List[str]													=	0

               for k in _tmp[:-1]:
                    lowercase_	:				Optional[Any]													=	_tmp[_tmp.index(__SCREAMING_SNAKE_CASE      ) + 1]
                    for i in dict_of_neighbours[k]:
                         if i[0] == next_node:
                              lowercase_	:				Optional[Any]													=	distance + int(i[1]      )
               _tmp.append(__SCREAMING_SNAKE_CASE      )

               if _tmp not in neighborhood_of_solution:
                    neighborhood_of_solution.append(_tmp      )

     lowercase_	:				Optional[int]													=	len(neighborhood_of_solution[0]      ) - 1

     neighborhood_of_solution.sort(key=lambda __SCREAMING_SNAKE_CASE      : x[index_of_last_item_in_the_list]      )
     return neighborhood_of_solution



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     Optional[Any]     ,			__SCREAMING_SNAKE_CASE							:     Dict     ,			__SCREAMING_SNAKE_CASE							:     str     ,			__SCREAMING_SNAKE_CASE							:     Union[str, Any]     ,			__SCREAMING_SNAKE_CASE							:     List[Any]      ):
     lowercase_	:				Union[str, Any]													=	1
     lowercase_	:				int													=	first_solution
     lowercase_	:				List[str]													=	[]
     lowercase_	:				Union[str, Any]													=	distance_of_first_solution
     lowercase_	:				Optional[int]													=	solution

     while count <= iters:
          lowercase_	:				Dict													=	find_neighborhood(__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      )
          lowercase_	:				Tuple													=	0
          lowercase_	:				str													=	neighborhood[index_of_best_solution]
          lowercase_	:				Optional[Any]													=	len(__SCREAMING_SNAKE_CASE      ) - 1

          lowercase_	:				int													=	False
          while not found:
               lowercase_	:				Union[str, Any]													=	0
               while i < len(__SCREAMING_SNAKE_CASE      ):
                    if best_solution[i] != solution[i]:
                         lowercase_	:				Optional[Any]													=	best_solution[i]
                         lowercase_	:				Union[str, Any]													=	solution[i]
                         break
                    lowercase_	:				List[str]													=	i + 1

               if [first_exchange_node, second_exchange_node] not in tabu_list and [
                   second_exchange_node,
                   first_exchange_node,
               ] not in tabu_list:
                    tabu_list.append([first_exchange_node, second_exchange_node]      )
                    lowercase_	:				List[Any]													=	True
                    lowercase_	:				Optional[int]													=	best_solution[:-1]
                    lowercase_	:				Any													=	neighborhood[index_of_best_solution][best_cost_index]
                    if cost < best_cost:
                         lowercase_	:				List[str]													=	cost
                         lowercase_	:				Dict													=	solution
               else:
                    lowercase_	:				Any													=	index_of_best_solution + 1
                    lowercase_	:				str													=	neighborhood[index_of_best_solution]

          if len(__SCREAMING_SNAKE_CASE      ) >= size:
               tabu_list.pop(0      )

          lowercase_	:				str													=	count + 1

     return best_solution_ever, best_cost



def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     List[str]=None      ):
     lowercase_	:				Any													=	generate_neighbours(args.File      )

     lowercase_							,  lowercase_	:				List[str]													=	generate_first_solution(
         args.File     ,			__SCREAMING_SNAKE_CASE      )

     lowercase_							,  lowercase_	:				Union[str, Any]													=	tabu_search(
         __SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE     ,			args.Iterations     ,			args.Size     ,			)

     print(F'''Best solution: {best_sol}, with total distance: {best_cost}.'''      )


if __name__ == "__main__":
       __SCREAMING_SNAKE_CASE    	=argparse.ArgumentParser(description="Tabu Search")
       parser.add_argument(
           "-f",
           "--File",
           type=str,
           help="Path to the file containing the data",
           required=True,
       )
       parser.add_argument(
           "-i",
           "--Iterations",
           type=int,
           help="How many iterations the algorithm should perform",
           required=True,
       )
       parser.add_argument(
           "-s", "--Size", type=int, help="Size of the tabu list", required=True
       )

       # Pass the arguments to main method
       main(parser.parse_args())


"""simple docstring"""







def 			lowercase__(       __SCREAMING_SNAKE_CASE							:     list      ):

     if len(__SCREAMING_SNAKE_CASE      ) < 2:
          return collection

     def circle_sort_util(__SCREAMING_SNAKE_CASE							:     list     ,			__SCREAMING_SNAKE_CASE							:     int     ,			__SCREAMING_SNAKE_CASE							:     int      ) -> bool:
          lowercase_	:				Any													=	False

          if low == high:
               return swapped

          lowercase_	:				str													=	low
          lowercase_	:				int													=	high

          while left < right:
               if collection[left] > collection[right]:
                    lowercase_							,  lowercase_	:				Optional[Any]													=	(
                        collection[right],
                        collection[left],
                    )
                    lowercase_	:				Tuple													=	True

               left += 1
               right -= 1

          if left == right and collection[left] > collection[right + 1]:
               lowercase_							,  lowercase_	:				Dict													=	(
                   collection[right + 1],
                   collection[left],
               )

               lowercase_	:				str													=	True

          lowercase_	:				Optional[Any]													=	low + int((high - low) / 2      )
          lowercase_	:				str													=	circle_sort_util(__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE     ,			__SCREAMING_SNAKE_CASE      )
          lowercase_	:				List[Any]													=	circle_sort_util(__SCREAMING_SNAKE_CASE     ,			mid + 1     ,			__SCREAMING_SNAKE_CASE      )

          return swapped or left_swap or right_swap

     lowercase_	:				Dict													=	True

     while is_not_sorted is True:
          lowercase_	:				Optional[Any]													=	circle_sort_util(__SCREAMING_SNAKE_CASE     ,			0     ,			len(__SCREAMING_SNAKE_CASE      ) - 1      )

     return collection


if __name__ == "__main__":
       __SCREAMING_SNAKE_CASE    	=input("Enter numbers separated by a comma:\n").strip()
       __SCREAMING_SNAKE_CASE    	=[int(item) for item in user_input.split(",")]
       print(circle_sort(unsorted))

