<commit_before>#!/usr/bin/env python3
import copy
import itertools


class Pynstein(object):

	def __init__(self):
		self._init()

	def _init(self):
		self.Set_Wrap(False)
		self._rows = None
		self._cols = None
		self._isPrepared = False
		self._items = []
		self._solutions = []
		self._conditions = {
			"info" : [],
			"position": {},
			"next_to": [],
			"left_of": []
		}

	def _unprepare(self):
		""" Reset the 'prepared'-status
		"""
		self._isPrepared = False

	def _checkColumn(self, column):
		assert isinstance(column, list), "Column has to be listtype!"
		assert len(column) > 0, "Could not find any data"
		assert len([c for c in column if c is not None]) > 0, "Could not find any non-none data!"

	def _checkPosition(self, position):
		assert isinstance(position, int), "Position has to be int!"
		assert position >= 0, "Position has to be int!"

	def _getPosition(self, maxRowIndex, column):
		""" Tries to find the position of a given column in the current puzzle-matrix
		Returns index >= 0 if found, -1 if only None-values were checked, else None
		"""
		firstIndex = None
		for rowIndex, item in enumerate(column):
			if rowIndex > maxRowIndex:
				break
			if item is not None:
				index = self._items[rowIndex].index(item)
				if firstIndex is not None:
					if index != firstIndex:
						return None
				else:
					firstIndex = index
		return firstIndex if firstIndex is not None else -1

	def _checkConditions(self, maxRowIndex):
		""" Checks all conditions
		Returns True, if all conditions are successfully met
		"""
		
		# position-conditions
		for position in self._conditions["position"]:
			for condition in self._conditions["position"][position]:
				# 'check XOR exclude' bust be true
				if self._checkAtPosition(maxRowIndex, condition["column"], position) == condition["exclude"]:
					return False

		# info-conditions
		for condition in self._conditions["info"]:
			if (self._getPosition(maxRowIndex, condition["column"]) is not None) == condition["exclude"]:
				return False

		# leftOf-conditions
		for condition in self._conditions["left_of"]:
			if self._checkLeftOf(maxRowIndex, condition["leftColumn"], condition["rightColumn"]) == condition["exclude"]:
				return False

		# nextTo-conditions
		for condition in self._conditions["next_to"]:
			if self._checkNextTo(maxRowIndex, condition["column1"], condition["column2"]) == condition["exclude"]:
				return False

		return True


	def _checkAtPosition(self, maxRowIndex, column, columnIndex):
		for rowIndex, item in enumerate(column):
			if rowIndex > maxRowIndex:
				break
			if item is not None:
				if not self._items[rowIndex][columnIndex] == item:
					return False
		return True

	def _checkLeftOf(self, maxRowIndex, leftColumn, rightColumn):
		leftIndex = self._getPosition(maxRowIndex, leftColumn)
		if leftIndex is not None:
			# only None-values so far
			if leftIndex == -1:
				return True
			rightIndex = self._getPosition(maxRowIndex, rightColumn)
			if rightIndex is not None:
				# only None-values so far
				if rightIndex == -1:
					return True
				if self._wrap:
					return (leftIndex == (rightIndex - 1)) or (leftIndex == (self._cols - 1) and rightIndex == 0)
				else:
					return leftIndex == (rightIndex - 1)
		return False

	def _checkNextTo(self, maxRowIndex, column1, column2):
		return self._checkLeftOf(maxRowIndex, column1, column2) or self._checkLeftOf(maxRowIndex, column2, column1)

	def _extractItems(self, items):
		for rowIndex, item in enumerate(items):
			if len(self._items) < (rowIndex + 1):
				self._items.append([])
			if item is not None:
				if item not in self._items[rowIndex]:
					self._items[rowIndex].append(item)

	def _checkItems(self):
		assert len([r for r in self._items if len(r) == len(self._items[0])]) == len(self._items), "Length of rows do not match. Did you miss any conditions?"

	def AddCondition_Info(self, column, exclude=False):
		""" Add an info condition
		Info contraints consist of just one column
		e.g. "The Englishman lives in the red house"
		"""
		self._checkColumn(column)
		self._unprepare()
		self._conditions["info"].append({"column": column, "exclude": exclude})

	def AddCondition_Position(self, column, position, exclude=False):
		""" Add a position condition
		Position conditions are like info conditions, but have a fixed position
		e.g. "The Norwegian lives in the first house"
		"""
		self._checkColumn(column)
		self._checkPosition(position)
		self._unprepare()
		if position not in self._conditions["position"]:
			self._conditions["position"][position] = []
		self._conditions["position"][position].append({"column": column, "exclude": exclude})

	def AddCondition_NextTo(self, column1, column2, exclude=False):
		""" Add a nextTo condition
		NextTo conditions mean that to columns are next to each other, regardles of the order
		e.g. "The man who smokes Chesterfields lives in the house next to the man with the fox"
		"""
		self._checkColumn(column1)
		self._checkColumn(column2)
		self._unprepare()
		self._conditions["next_to"].append({"column1": column1, "column2": column2, "exclude": exclude})

	def AddCondition_LeftOf(self, leftColumn, rightColumn, somewhere=False, exclude=False):
		""" Add a leftOf condition
		LeftOf conditions are like nextTo condions, but with a difinite order of the columns
		e.g. "The green house is immediately to the right/left of the ivory house"
		"""
		self._checkColumn(leftColumn)
		self._checkColumn(rightColumn)
		self._unprepare()
		self._conditions["left_of"].append({"leftColumn": leftColumn, "rightColumn": rightColumn, "somewhere": somewhere, "exclude": exclude})

	def AddCondition_RightOf(self, rightColumn, leftColumn, somewhere=False, exclude=False):
		""" Add a rightOf condition
		This is the same as the leftOf condition, just with swapped columns
		"""
		self.AddCondition_LeftOf(leftColumn, rightColumn, somewhere, exclude)

	def Set_Wrap(self, wrap):
		assert isinstance(wrap, bool), "Must be boolean value!"
		self._wrap = wrap

	def Prepare(self):
		for conditionType in self._conditions:
			if conditionType == "info":
				for condition in self._conditions["info"]:<commit_msg>[Imp] Added checks<commit_after>#!/usr/bin/env python3
import copy
import itertools


class Pynstein(object):

	def __init__(self):
		self._init()

	def _init(self):
		self.Set_Wrap(False)
		self._rows = None
		self._cols = None
		self._isPrepared = False
		self._items = []
		self._solutions = []
		self._conditions = {
			"info" : [],
			"position": {},
			"next_to": [],
			"left_of": []
		}

	def _unprepare(self):
		""" Reset the 'prepared'-status
		"""
		self._isPrepared = False

	def _checkColumn(self, column):
		assert isinstance(column, list), "Column has to be listtype!"
		assert len(column) > 0, "Could not find any data"
		assert len([c for c in column if c is not None]) > 0, "Could not find any non-none data!"

	def _checkPosition(self, position):
		assert isinstance(position, int), "Position has to be int!"
		assert position >= 0, "Position has to be int!"

	def _getPosition(self, maxRowIndex, column):
		""" Tries to find the position of a given column in the current puzzle-matrix
		Returns index >= 0 if found, -1 if only None-values were checked, else None
		"""
		firstIndex = None
		for rowIndex, item in enumerate(column):
			if rowIndex > maxRowIndex:
				break
			if item is not None:
				index = self._items[rowIndex].index(item)
				if firstIndex is not None:
					if index != firstIndex:
						return None
				else:
					firstIndex = index
		return firstIndex if firstIndex is not None else -1

	def _checkConditions(self, maxRowIndex):
		""" Checks all conditions
		Returns True, if all conditions are successfully met
		"""
		
		# position-conditions
		for position in self._conditions["position"]:
			for condition in self._conditions["position"][position]:
				# 'check XOR exclude' bust be true
				if self._checkAtPosition(maxRowIndex, condition["column"], position) == condition["exclude"]:
					return False

		# info-conditions
		for condition in self._conditions["info"]:
			if (self._getPosition(maxRowIndex, condition["column"]) is not None) == condition["exclude"]:
				return False

		# leftOf-conditions
		for condition in self._conditions["left_of"]:
			if self._checkLeftOf(maxRowIndex, condition["leftColumn"], condition["rightColumn"]) == condition["exclude"]:
				return False

		# nextTo-conditions
		for condition in self._conditions["next_to"]:
			if self._checkNextTo(maxRowIndex, condition["column1"], condition["column2"]) == condition["exclude"]:
				return False

		return True

	def _checkAtPosition(self, maxRowIndex, column, columnIndex):
		for rowIndex, item in enumerate(column):
			if rowIndex > maxRowIndex:
				break
			if item is not None:
				if not self._items[rowIndex][columnIndex] == item:
					return False
		return True

	def _checkLeftOf(self, maxRowIndex, leftColumn, rightColumn, somewhere):
		leftIndex = self._getPosition(maxRowIndex, leftColumn)
		if leftIndex is not None:
			# only None-values so far
			if leftIndex == -1:
				return True
			rightIndex = self._getPosition(maxRowIndex, rightColumn)
			if rightIndex is not None:
				# only None-values so far
				if rightIndex == -1:
					return True
				if not somewhere:
					if self._wrap:
						return (leftIndex == (rightIndex - 1)) or (leftIndex == (self._cols - 1) and rightIndex == 0)
					else:
						return leftIndex == (rightIndex - 1)
				else:
					return leftIndex < rightIndex
		return False

	def _checkNextTo(self, maxRowIndex, column1, column2):
		return self._checkLeftOf(maxRowIndex, column1, column2, somewhere) or self._checkLeftOf(maxRowIndex, column2, column1, somewhere)

	def _extractItems(self, items):
		for rowIndex, item in enumerate(items):
			if len(self._items) < (rowIndex + 1):
				self._items.append([])
			if item is not None:
				if item not in self._items[rowIndex]:
					self._items[rowIndex].append(item)

	def _checkItems(self):
		assert len([r for r in self._items if len(r) == len(self._items[0])]) == len(self._items), "Length of rows do not match. Did you miss any conditions?"

	def AddCondition_Info(self, column, exclude=False):
		""" Add an info condition
		Info contraints consist of just one column
		e.g. "The Englishman lives in the red house"
		"""
		self._checkColumn(column)
		self._unprepare()
		self._conditions["info"].append({"column": column, "exclude": exclude})

	def AddCondition_Position(self, column, position, exclude=False):
		""" Add a position condition
		Position conditions are like info conditions, but have a fixed position
		e.g. "The Norwegian lives in the first house"
		"""
		self._checkColumn(column)
		self._checkPosition(position)
		self._unprepare()
		if position not in self._conditions["position"]:
			self._conditions["position"][position] = []
		self._conditions["position"][position].append({"column": column, "exclude": exclude})

	def AddCondition_NextTo(self, column1, column2, exclude=False):
		""" Add a nextTo condition
		NextTo conditions mean that two columns are next to each other, regardles of the order
		e.g. "The man who smokes Chesterfields lives in the house next to the man with the fox"
		"""
		self._checkColumn(column1)
		self._checkColumn(column2)
		self._unprepare()
		self._conditions["next_to"].append({"column1": column1, "column2": column2, "exclude": exclude})

	def AddCondition_LeftOf(self, leftColumn, rightColumn, somewhere=False, exclude=False):
		""" Add a leftOf condition
		LeftOf conditions are like nextTo condions, but with a difinite order of the columns
		e.g. "The green house is immediately to the right/left of the ivory house"
		"""
		assert (not somewhere) or (not self._wrap), "Cannot set somewhere=True if wrapmode is enabled!"
		self._checkColumn(leftColumn)
		self._checkColumn(rightColumn)
		self._unprepare()
		self._conditions["left_of"].append({"leftColumn": leftColumn, "rightColumn": rightColumn, "somewhere": somewhere, "exclude": exclude})

	def AddCondition_RightOf(self, rightColumn, leftColumn, somewhere=False, exclude=False):
		""" Add a rightOf condition
		This is the same as the leftOf condition, just with swapped columns
		"""
		self.AddCondition_LeftOf(leftColumn, rightColumn, somewhere, exclude)

	def Set_Wrap(self, wrap):
		assert isinstance(wrap, bool), "Must be boolean value!"
		if wrap:
			# check if there is a condiotion with somewhere=True
			assert len([condition for condition in self._conditions["left_of"] if condition["somewhere"]]) == 0, "Cannot set wrapmode if a condition has somewhere=True"
		self._wrap = wrap

	def Prepare(self):
		for conditionType in self._conditions:
			if conditionType == "info":
				for condition in self._conditions["info"]:
{'fraction_non_alphanumeric': 0.11282697762369996, 'fraction_numerical': 0.0049637566971320515, 'mean_word_length': 4.28875, 'pattern_counts': {'":': 30, '<': 6, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6556676', 'n_tokens_mistral': 4284, 'n_tokens_neox': 3721, 'n_words': 1255}