
# This Python program implements an optimal binary search tree (abbreviated BST)
# building dynamic programming algorithm that delivers O(n^2) performance.
#
# The goal of the optimal BST problem is to build a low-cost BST for a
# given set of nodes, each with its own key and frequency. The frequency
# of the node is defined as how many time the node is being searched.
# The search cost of binary search tree is given by this formula:
#
# cost(1, n) = sum{i = 1 to n}((depth(node_i) + 1) * node_i_freq)
#
# where n is number of nodes in the BST. The characteristic of low-cost
# BSTs is having a faster overall search time than other implementations.
# The reason for their fast search time is that the nodes with high
# frequencies will be placed near the root of the tree while the nodes
# with low frequencies will be placed near the leaves of the tree thus
# reducing search time in the most frequent instances.
import sys
from random import randint

class     _SCREAMING_SNAKE_CASE							:





				def __init__(		self :		str					,      snake_case_ :		Union[str, Any]					,      snake_case_ :		Union[str, Any]							):


								"""simple docstring"""

								A     :  int   =				key
								A     :  Tuple   =				freq






				def __str__(		self :		Optional[int]							):


								"""simple docstring"""

								return f"""Node(key={self.key}, freq={self.freq})"""





def 							_lowerCamelCase			(					lowerCamelCase_:  Union[str, Any]				,	lowerCamelCase_:  Optional[Any]				,	lowerCamelCase_:  Tuple				,	lowerCamelCase_:  List[Any]				,	lowerCamelCase_:  Optional[Any]				,	lowerCamelCase_:  str		):



				'''simple docstring'''







				if i > j or i < 0 or j > len(lowerCamelCase_		) - 1:
								return

				A     :  Dict   =				root[i][j]
				if parent == -1:  # root does not have a parent
								print(f"""{key[node]} is the root of the binary search tree."""		)
				elif is_left:
								print(f"""{key[node]} is the left child of key {parent}."""		)
				else:
								print(f"""{key[node]} is the right child of key {parent}."""		)

				print_binary_search_tree(lowerCamelCase_				,	lowerCamelCase_				,	lowerCamelCase_				,	node - 1				,	key[node]				,	lowerCamelCase_		)
				print_binary_search_tree(lowerCamelCase_				,	lowerCamelCase_				,	node + 1				,	lowerCamelCase_				,	key[node]				,	lowerCamelCase_		)





def 							_lowerCamelCase			(					lowerCamelCase_:  List[Any]		):



				'''simple docstring'''







				nodes.sort(key=lambda lowerCamelCase_		: node.key		)

				A     :  List[Any]   =				len(lowerCamelCase_		)

				A     :  Optional[int]   =				[nodes[i].key for i in range(lowerCamelCase_		)]
				A     :  Dict   =				[nodes[i].freq for i in range(lowerCamelCase_		)]

				# This 2D array stores the overall tree cost (which's as minimized as possible);
				# for a single key, cost is equal to frequency of the key.
				A     :  Union[str, Any]   =				[[freqs[i] if i == j else 0 for j in range(lowerCamelCase_		)] for i in range(lowerCamelCase_		)]
				# sum[i][j] stores the sum of key frequencies between i and j inclusive in nodes
				# array
				A     :  List[str]   =				[[freqs[i] if i == j else 0 for j in range(lowerCamelCase_		)] for i in range(lowerCamelCase_		)]
				# stores tree roots that will be used later for constructing binary search tree
				A     :  Optional[Any]   =				[[i if i == j else 0 for j in range(lowerCamelCase_		)] for i in range(lowerCamelCase_		)]

				for interval_length in range(2				,	n + 1		):
								for i in range(n - interval_length + 1		):
												A     :  List[str]   =				i + interval_length - 1

												A     :  int   =				sys.maxsize  # set the value to "infinity"
												A     :  Optional[Any]   =				total[i][j - 1] + freqs[j]

												# Apply Knuth's optimization
												# Loop without optimization: for r in range(i, j + 1):
												for r in range(root[i][j - 1]				,	root[i + 1][j] + 1		):  # r is a temporal root
																A     :  Optional[int]   =				dp[i][r - 1] if r != i else 0  # optimal cost for left subtree
																A     :  Optional[int]   =				dp[r + 1][j] if r != j else 0  # optimal cost for right subtree
																A     :  Any   =				left + total[i][j] + right

																if dp[i][j] > cost:
																				A     :  int   =				cost
																				A     :  Tuple   =				r

				print('''Binary search tree nodes:'''		)
				for node in nodes:
								print(lowerCamelCase_		)

				print(f"""\nThe cost of optimal BST for given tree nodes is {dp[0][n - 1]}."""		)
				print_binary_search_tree(lowerCamelCase_				,	lowerCamelCase_				,	0				,	n - 1				,	-1				,	lowerCamelCase_		)





def 							_lowerCamelCase			(					):



				'''simple docstring'''







				A     :  Dict   =				[Node(lowerCamelCase_				,	randint(1				,	50		)		) for i in range(10				,	0				,	-1		)]
				find_optimal_binary_search_tree(lowerCamelCase_		)


if __name__ == "__main__":
					main()

def 							_lowerCamelCase			(					lowerCamelCase_:  list		):



				'''simple docstring'''







				A     :  Optional[int]   =				1.3
				A     :  List[str]   =				len(lowerCamelCase_		)
				A     :  Optional[Any]   =				False

				while not completed:
								# Update the gap value for a next comb
								A     :  str   =				int(gap / shrink_factor		)
								if gap <= 1:
												A     :  Tuple   =				True

								A     :  List[Any]   =				0
								while index + gap < len(lowerCamelCase_		):
												if data[index] > data[index + gap]:
																# Swap values
																A ,       A     :  int   =				data[index + gap], data[index]
																A     :  Dict   =				False
												index += 1

				return data


if __name__ == "__main__":
					import doctest

					doctest.testmod()

					UpperCamelCase_  =	input("Enter numbers separated by a comma:\n").strip()
					UpperCamelCase_  =	[int(item) for item in user_input.split(",")]
					print(comb_sort(unsorted))