<commit_before>/*global jsobj */
/*jslint plusplus: true, continue: true, bitwise: true */

(function (jsobj) {
	"use strict";

	if (jsobj.rules === undefined) {
		jsobj.rules = {};
	}

	// Hidden Pairs rule removes possible values from cells.
	// It looks in rows, columns, and blocks for any 2 cells containing the only instances of two possible remaining values,
	// and removes any other possible values from those 2 cells.
	jsobj.rules.hiddenpairs = function (grid) {
		var progress = false,
			allGroups = grid.allGroups(),	// rows, cols, blocks
			groupnum,
			group,
			cellsByVal,
			cellIndex,
			cell,
			cellValues,
			possIndex,
			safeFlags,
			targetIdx,
			targetFlags,
			flagValue,
			removed;

		// Iterate through each row, column, and block looking for Hidden Pairs
		for (groupnum = 0; groupnum < allGroups.length; groupnum++) {
			group = allGroups[groupnum];
			cellsByVal = {};
			if (group.possibleValues().length < 3) {
				continue;
			}
			// index cells in group by which possible values they contain
			for (cellIndex = 0; cellIndex < 9; cellIndex++) {
				cell = group.cells()[cellIndex];
				if (cell.value() !== undefined) {
					continue;
				}
				cellValues = cell.possibleValues();
				for (possIndex = 0; possIndex < cellValues.length; possIndex++) {
					if (cellsByVal[cellValues[possIndex]] === undefined) {
						cellsByVal[cellValues[possIndex]] = [];
					}
					cellsByVal[cellValues[possIndex]].push(cell);
				}
			}
			// filter down to possible values existing in exactly 2 cells
			cellsByVal = cellsByVal.where(function (el) {
				return el.length === 2;
			});
			// for each possible value with 2 cells, check all others for a matching set of cells
			cellsByVal.each(function (el, idx) {
				cellsByVal.each(function (otherEl, otherIdx) {
					if (otherIdx > idx && el[0] === otherEl[0] && el[1] === otherEl[1]) {
						for (targetIdx = 0; targetIdx < 2; targetIdx++) {
							// remove all other possible values from the cell pair
							safeFlags = Math.pow(2, idx) | Math.pow(2, otherIdx);
							targetFlags = el[targetIdx].possibleFlags() ^ safeFlags;	// remaining flags can be removed
							flagValue = 9;
							while (targetFlags > 0) {
								if ((targetFlags & 1) > 0) {
									removed = el[targetIdx].removePossible(flagValue);
									progress = progress || removed;
								}
								flagValue--;
								targetFlags = targetFlags << 1;
							}
						}
					}
				});
			});

		}

		// rules return boolean indicating whether they made any progress
		return progress;
	};
}(jsobj));<commit_msg>rule hidden pairs - fix bitwise shift for target flags<commit_after>/*global jsobj */
/*jslint plusplus: true, continue: true, bitwise: true */

(function (jsobj) {
	"use strict";

	if (jsobj.rules === undefined) {
		jsobj.rules = {};
	}

	// Hidden Pairs rule removes possible values from cells.
	// It looks in rows, columns, and blocks for any 2 cells containing the only instances of two possible remaining values,
	// and removes any other possible values from those 2 cells.
	jsobj.rules.hiddenpairs = function (grid) {
		var progress = false,
			allGroups = grid.allGroups(),	// rows, cols, blocks
			groupnum,
			group,
			cellsByVal,
			cellIndex,
			cell,
			cellValues,
			possIndex,
			safeFlags,
			targetIdx,
			targetFlags,
			flagValue,
			removed;

		// Iterate through each row, column, and block looking for Hidden Pairs
		for (groupnum = 0; groupnum < allGroups.length; groupnum++) {
			group = allGroups[groupnum];
			cellsByVal = {};
			if (group.possibleValues().length < 3) {
				continue;
			}
			// index cells in group by which possible values they contain
			for (cellIndex = 0; cellIndex < 9; cellIndex++) {
				cell = group.cells()[cellIndex];
				if (cell.value() !== undefined) {
					continue;
				}
				cellValues = cell.possibleValues();
				for (possIndex = 0; possIndex < cellValues.length; possIndex++) {
					if (cellsByVal[cellValues[possIndex]] === undefined) {
						cellsByVal[cellValues[possIndex]] = [];
					}
					cellsByVal[cellValues[possIndex]].push(cell);
				}
			}
			// filter down to possible values existing in exactly 2 cells
			cellsByVal = cellsByVal.where(function (el) {
				return el.length === 2;
			});
			// for each possible value with 2 cells, check all others for a matching set of cells
			cellsByVal.each(function (el, idx) {
				cellsByVal.each(function (otherEl, otherIdx) {
					if (otherIdx > idx && el[0] === otherEl[0] && el[1] === otherEl[1]) {
						safeFlags = Math.pow(2, idx) | Math.pow(2, otherIdx);
						for (targetIdx = 0; targetIdx < 2; targetIdx++) {
							// remove all other possible values from the cell pair
							targetFlags = el[targetIdx].possibleFlags() ^ safeFlags;	// remaining flags can be removed
							flagValue = 9;
							while (targetFlags > 0) {
								if ((targetFlags & 1) > 0) {
									removed = el[targetIdx].removePossible(flagValue);
									progress = progress || removed;
								}
								flagValue--;
								targetFlags = targetFlags >> 1;
							}
						}
					}
				});
			});

		}

		// rules return boolean indicating whether they made any progress
		return progress;
	};
}(jsobj));
{'fraction_non_alphanumeric': 0.12306800618238022, 'fraction_numerical': 0.008887171561051005, 'mean_word_length': 2.8692077727952165, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 11, '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': '2325177', 'n_tokens_mistral': 2030, 'n_tokens_neox': 1558, 'n_words': 487}