#include #include #include #include #include #include #include #include #include using namespace std; ////////////////////////////////////////////////////////////////////////////// #define MAX_SECONDS_STOP 58 #define MIN_SECONDS_SPLIT 15 // Do not split before 15 seconds passed #define NO_CHANGE_LIMIT 8 #define ADJUST_EVENT_LIMIT 3 #define NUM_RANDOM_CHANGES 3 #define MAX_COST 2147483647 bool WeCanSplit() { return ((clock()/CLOCKS_PER_SEC)>=MIN_SECONDS_SPLIT); } bool WeShouldStop() { return ((clock()/CLOCKS_PER_SEC)>=MAX_SECONDS_STOP); } ////////////////////////////////////////////////////////////////////////////// #define mymin(x,y) (((x)<(y))?(x):(y)) #define mymax(x,y) (((x)>(y))?(x):(y)) bool myisupper(char ch) {return (ch>='A' && ch<='Z');} #define MAX_ROW 80 #define MAX_COL 5 bool on_my_machine; string start_grid[MAX_COL]; string goal_grid[MAX_COL]; int num_rows; // This struct is concerned only with Operations (Kill, Delete, Insert) which are done // in sequence at some position (pos), and there is no intermediate top-down-left-right-endline.. // commands, (shift) is used to know the new position of the other operations after executing // this operation #define NO_WAIT 0 #define WAIT_NEXT 1 #define WAITED_BY_PREV 2 #define REDUNDANT 3 #define PERFORM_FIRST 4 #define MAX_LINE_SOLUTIONS 100 // 60 #define MAX_LINE_OPERATIONS 10 //(6->7sec, 5-><3sec) #define MAX_INSERT 16 ////////////////////////////////////////////////////////////////////////////// struct Operation { short start_pos; // The cursor should be at start_pos to do this action short end_pos; // The cursor will be at end_pos after doing this action short shift; // All the following operations (start_pos, end_pos) will be incremented (go right) by (shift) after doing this action (may be -ve to go left) short cost; // The cost for this operation short wait; // WAIT_NEXT if this operation should wait for the next one (needed for kill_first), WAITED_BY_PREV if the previous operation is waiting it, NO_WAIT otherwise string seq; // The sequence of commands ////////////////////////////////////////////////////////////////////////////// Operation() {Set();} void Set(short _start_pos=0, short _end_pos=0, short _shift=0, short _cost=0, short _wait=0, string _seq="") { start_pos=_start_pos; end_pos=_end_pos; shift=_shift; cost=_cost; wait=_wait; seq=_seq; } ////////////////////////////////////////////////////////////////////////////// void InitializeKillFirst(short start_pos, short wait=NO_WAIT) { Set(start_pos, 0, -(start_pos+1), 1, wait, "<"); } void InitializeKillLast(short start_pos, short str_size, short wait = NO_WAIT) { Set(start_pos, (start_pos-1), -(str_size-start_pos), 1, wait, ">"); } void InitializeDelete(short start_pos, short num_deletions) { string str_comm; for (int i=0; i opers; int cost; short start_pos; short end_pos; bool operator < (const LineOperation& lo) const { if (cost == lo.cost) return (opers.size() all_operations[MAX_COL]; int LCS[MAX_ROW][MAX_ROW]; int LCS_DECISION[MAX_ROW][MAX_ROW]; #define LCS_STAY 0 #define LCS_S1 1 #define LCS_S2 2 ////////////////////////////////////////////////////////////////////////////// // Initialization takes place everytime first (of the start_string) is changed void InitializeGetTheBestOperations() { int i, j; for (i=0; ilcs2) { lcs = lcs1; LCS_DECISION[last_s1][last_s2]=LCS_S1; } else { lcs = lcs2; LCS_DECISION[last_s1][last_s2]=LCS_S2; } } LCS[last_s1][last_s2] = lcs; return LCS[last_s1][last_s2]; } ////////////////////////////////////////////////////////////////////////////// struct MatchingPos { int index_s1; int index_s2; }; vector GetTheLongestCommonSubsequence(int line, int first, int last) { // Get the longest common subsequence int lcs = GetLCS(line, first, last, goal_grid[line].size()-1); vector match_lcs; if (lcs > 0) { match_lcs.resize(lcs); int last_s1=last, last_s2=goal_grid[line].size()-1; int i=lcs-1; // i is the position to put the next common element int dec; while(i>=0) { dec = LCS_DECISION[last_s1][last_s2]; if (dec == LCS_STAY) { match_lcs[i].index_s1=last_s1; match_lcs[i].index_s2=last_s2; last_s1--; last_s2--; i--; } else if (dec == LCS_S1) { last_s1--; } else { last_s2--; } } } return match_lcs; } ////////////////////////////////////////////////////////////////////////////// bool GetTheBestOperations(int line, int first, int last, vector& line_operations) { vector match_lcs = GetTheLongestCommonSubsequence(line, first, last); // Handle the case in which we have some characters but no match ///////////////// // Do not do anything (This case we should delete all), and it is handled // separately at first if (match_lcs.size()==0) return false; // When we reach here, we have at least one matching // try to make benefit of it if (match_lcs[0].index_s1!=first) return false; if (match_lcs[match_lcs.size()-1].index_s1!=last) return false; // When we enter here, we have the first char in s1 matches a char in s2 // Also, we have the last char in s1 matches a char in s2 // Note: in the following cases, except the last, we try to match the 2 strings // until a matcning occurrence string& s1 = start_grid[line]; string& s2 = goal_grid[line]; int len1 = s1.size(); int len2 = s2.size(); int i; int match_s1=match_lcs[0].index_s1; int match_s2=match_lcs[0].index_s2; // Handle the starting case //////////////////////////////////////////// int kill_first = first-1; if (match_s2==0) // The first char in s1 matches the first char in s2 { if (kill_first >= 0) { Operation op_kill; op_kill.InitializeKillFirst(kill_first); line_operations.push_back(op_kill); } } else // The first char in s1 matches a char in s2 { if (kill_first >= 0) { // Make insert command (for chars in s2 before match), // and the kill_first will wait it if (kill_first-1 >= 0) { // Make Redundant Kill Operation op_kill; op_kill.InitializeKillFirst(kill_first-1, REDUNDANT); line_operations.push_back(op_kill); } Operation op_kill; op_kill.InitializeKillFirst(kill_first, WAIT_NEXT); line_operations.push_back(op_kill); Operation op_insert; op_insert.InitializeInsert(kill_first, s2.substr(0, match_s2), WAITED_BY_PREV); if (op_insert.cost > 1) line_operations.push_back(op_insert); } else // We will not take benefit of this case { return false; } } int prev_match_s1 = match_s1; int prev_match_s2 = match_s2; // End Handle the starting case //////////////////////////////////////////// // When we enter here, the 2 strings are matched upto and including // the first matching occurrence for (i=1; i 1) line_operations.push_back(op_insert); // Make the delete operations Operation op_delete; op_delete.InitializeDelete(prev_match_s1+1, match_s1-(prev_match_s1+1)); if (op_delete.cost > 0) line_operations.push_back(op_delete); } // Handle the end line case //////////////////////////////////////////// int kill_last = last+1; if (match_s2==len2-1) // The last char in s1 matches the last char in s2 { if (kill_last < len1) { Operation op_kill; op_kill.InitializeKillLast(kill_last, len1, NO_WAIT); line_operations.push_back(op_kill); } } else // The last char in s1 matches a char in s2 { if (kill_last < len1) { // Make insert command (for chars in s2 after match), and the kill_last // Make the insert command wait for the kill Operation op_insert; //op_insert.InitializeInsert(last, s2.substr(match_s2+1, len2-(match_s2+1)), WAIT_NEXT); op_insert.InitializeInsert(last, s2.substr(match_s2+1, len2-(match_s2+1)), NO_WAIT); if (op_insert.cost > 1) line_operations.push_back(op_insert); Operation op_kill; //op_kill.InitializeKillLast(kill_last, len1, WAITED_BY_PREV); op_kill.InitializeKillLast(kill_last, len1, NO_WAIT); line_operations.push_back(op_kill); } else { Operation op_insert; op_insert.InitializeInsert(last, s2.substr(match_s2+1, len2-(match_s2+1))); if (op_insert.cost > 1) line_operations.push_back(op_insert); } } // End Handle the end line case //////////////////////////////////////// return true; } ////////////////////////////////////////////////////////////////////////////// // This fn will change # of operations in the line so as it will be maximum # <= MAX_LINE_OPERATIONS void CombineLineOperations(vector& opers) { int i, j; while (opers.size() > MAX_LINE_OPERATIONS) { int iminspace = MAX_COST; int ifirst_oper=-1; int iminspace_cost=-1; for (i=0; i& line_operations) { LineOperation lo; lo.opers = line_operations; all_operations[line].push_back(lo); } ////////////////////////////////////////////////////////////////////////////// void GenerateTrivialCase1(int line, vector& line_operations) { // Make the trivial case of: // 1) Insert All chars in from the goal (st last of the start) // 2) kill_first all previously existing chars after the insertions if (start_grid[line].size()-2 >= 0) { // Make Redundant Kill Operation op_kill; op_kill.InitializeKillFirst(start_grid[line].size()-2, REDUNDANT); line_operations.push_back(op_kill); } Operation op_kill; op_kill.InitializeKillFirst(start_grid[line].size()-1, WAIT_NEXT); line_operations.push_back(op_kill); Operation op_insert; op_insert.InitializeInsert(start_grid[line].size()-1, goal_grid[line], WAITED_BY_PREV); if (op_insert.cost > 1) line_operations.push_back(op_insert); } ////////////////////////////////////////////////////////////////////////////// void GenerateTrivialCase2(int line, vector& line_operations) { // Make the trivial case of: // 1) kill_first all elements then insert all elements at the empty line Operation op_trivial; op_trivial.seq = "& line_operations) { // Make the trivial case of: // 1) kill_last all elements then insert all elements at the empty line Operation op_trivial; op_trivial.seq = ">a"; op_trivial.seq += goal_grid[line]; op_trivial.cost = 2+2*goal_grid[line].size(); op_trivial.start_pos = 0; op_trivial.end_pos = goal_grid[line].size()-1; op_trivial.shift = goal_grid[line].size()-start_grid[line].size(); op_trivial.wait = NO_WAIT; line_operations.push_back(op_trivial); } ////////////////////////////////////////////////////////////////////////////// void CombineLineOperationsAll(int line) { int j; for (j=0; j& opers = all_operations[line][j].opers; if (opers.size() >= 2 && opers[0].wait != REDUNDANT) { if (opers[0].seq == "<" && opers[0].start_pos == 0) { if (opers[1].seq.size() >= 2 && opers[1].seq[0] == 'a' && opers[1].start_pos == 0) { if (opers[1].seq[1] == start_grid[line][0]) { opers[1].seq.erase(1, 1); opers[1].cost -= 2; opers[1].shift--; opers[1].end_pos--; opers[1].wait = NO_WAIT; if (opers[1].cost == 1) { opers.erase(opers.begin()+1); } opers.erase(opers.begin()); if (opers.size() == 0) { Operation op_none; opers.push_back(op_none); } } } } } CombineLineOperations(all_operations[line][j].opers); } } ////////////////////////////////////////////////////////////////////////////// void ComputeLineOperations(int line) { string& s1 = start_grid[line]; string& s2 = goal_grid[line]; int len1 = s1.size(); int len2 = s2.size(); int kill_first, kill_last; // kill_first will kill chars upto this index // kill_first will kill chars from this index and upto last // Do not try to delete the whole line! vector line_operations; if (s1==s2) { Operation op_none; line_operations.push_back(op_none); UseTheOperationIfBetter(line, line_operations); return; } line_operations.clear(); GenerateTrivialCase1(line, line_operations); UseTheOperationIfBetter(line, line_operations); line_operations.clear(); GenerateTrivialCase2(line, line_operations); UseTheOperationIfBetter(line, line_operations); line_operations.clear(); GenerateTrivialCase3(line, line_operations); UseTheOperationIfBetter(line, line_operations); // Try all combinations of kill_first and kill_last // But avoid killing the whole line, because when we do this, // we will not be able to insert anything in it for (kill_first=-1; kill_first<=len1-2; kill_first++) { InitializeGetTheBestOperations(); for (kill_last=kill_first+2; kill_last<=len1; kill_last++) { line_operations.clear(); if (GetTheBestOperations(line, kill_first+1, kill_last-1, line_operations)) UseTheOperationIfBetter(line, line_operations); } } } //**************************************************************************** ////////////////////////////////////////////////////////////////////////////// // We will create array of PerformOperation and we will index it // For each time of different indexing, we will reset all things in this array struct PerformOperation { short start_pos_old; // Used for restoring short end_pos_old; // Used for restoring short shift_old; // Used for restoring short start_pos; // The cursor should be at start_pos to do this action short end_pos; // The cursor will be at end_pos after doing this action short shift; // All the following operations (start_pos, end_pos) will be incremented (go right) by (shift) after doing this action (may be -ve to go left) short cost; // The cost for this operation short wait; // WAIT_NEXT if this operation should wait for the next one (needed for kill_first), WAITED_BY_PREV if the previous operation is waiting it, NO_WAIT otherwise string seq; // The sequence of commands short index; // The index of this operation in the array which indexes these operations bool done; void Set(short _start_pos=0, short _end_pos=0, short _shift=0, short _cost=0, short _wait=0, string _seq="") { start_pos_old=start_pos=_start_pos; end_pos_old=end_pos=_end_pos; shift_old=shift=_shift; cost=_cost; wait=_wait; seq=_seq; } void InitializeInsert(short start_pos, string str_insert, short wait=NO_WAIT) { short num_insertions = str_insert.size(); string str_comm="a"; str_comm = str_comm+str_insert; Set(start_pos, start_pos+num_insertions, num_insertions, 2*num_insertions+1, wait, str_comm); done = false; } }; ////////////////////////////////////////////////////////////////////////////// void SplitLineOperations(vector& opers) { int i; while (opers.size() < MAX_LINE_OPERATIONS) { int ioper=-1; int max_insert=-1; int max_type=-1; for (i=0; i0 && opers[i].seq[0] == 'a') { type=0; } else if (opers[i].seq.size()>1 && opers[i].seq[1] == 'a' && (opers[i].seq[0]=='<' || opers[i].seq[0]=='>')) { type=1; } else { continue; } // Check that all chars are uppercase letters bool all_insert = true; for (int j=type+1; j MAX_INSERT && num_insert > max_insert) { max_insert = num_insert; ioper = i; max_type = type; } } if (max_insert == -1) return; i = ioper; string cur_seq = opers[i].seq.substr(max_type+1, opers[i].seq.size()-1); int ifirst_half = cur_seq.size()/2; int isecond_half = cur_seq.size()-ifirst_half; PerformOperation oper1, oper2; string str_first_half = cur_seq.substr(0, ifirst_half); string str_second_half = cur_seq.substr(ifirst_half, isecond_half); if (max_type==0) { oper1.InitializeInsert( opers[i].start_pos, str_first_half, opers[i].wait); oper2.InitializeInsert( opers[i].start_pos, str_second_half, NO_WAIT); } else { oper1.seq = opers[i].seq.substr(0, 2); oper1.seq += str_first_half; oper1.cost = 2+2*str_first_half.size(); oper1.start_pos_old = oper1.start_pos = opers[i].start_pos; oper1.end_pos_old = oper1.end_pos = str_first_half.size()-1; oper1.shift_old = oper1.shift = str_first_half.size()-1; oper1.wait = PERFORM_FIRST; oper2.InitializeInsert( 0, str_second_half, NO_WAIT); } opers[i] = oper1; opers.insert(opers.begin()+(i+1), oper2); } } ////////////////////////////////////////////////////////////////////////////// struct CursorPos { short row; short col; }; ////////////////////////////////////////////////////////////////////////////// struct PerformOperIndex { short iline; short ioper; }; #define NO_MOVE 0 #define MOVE_MOVE 1 #define SWAP_MOVE 2 struct SolutionMove { char type; short index1; short index2; }; struct Solution { short line_operations_used[MAX_COL]; // The index of the used operation vector for the line i vector indexed_operations; // The real order of execution of perform_operations vector perform_operations[MAX_COL]; int all_cost; string str_moves; SolutionMove last_move; bool operator < (const Solution& sol) const { return (this->all_cost < sol.all_cost); } }; Solution best_sol; Solution restore_sol; #define MAX_SOLS_LEV2 5 #define MAX_SOLS_LEV3 5 // 10 takes about 10 secs (For each iteration) #define MAX_HASH (1000001) bool enable_hash; char hash_table[MAX_HASH]; Solution all_sols[MAX_SOLS_LEV2]; int num_sols; ////////////////////////////////////////////////////////////////////////////// // These members will be generated every time short line_sizes[MAX_COL]; CursorPos cp; ////////////////////////////////////////////////////////////////////////////// // Solution cur_sol; // The following 4 members for the current solution short line_operations_used[MAX_COL]; // The index of the used operation vector for the line i vector indexed_operations; // The real order of execution of perform_operations vector perform_operations[MAX_COL]; int all_cost; string str_moves; SolutionMove last_move; ////////////////////////////////////////////////////////////////////////////// void CopySolution(Solution& dst, Solution& src) { dst.all_cost = src.all_cost; dst.str_moves = src.str_moves; dst.indexed_operations = src.indexed_operations; dst.last_move = src.last_move; for (int i=0; i cp2.row) { cp1.row--; if (line_sizes[cp1.row] <= cp1.col) cp1.col=line_sizes[cp1.row]-1; str_go = str_go + "u"; } } int iNumMovesDirect = abs(cp1.col-cp2.col); int iNumMovesEnd = 1+((line_sizes[cp1.row]-1)-cp2.col); int iNumMovesStart = 1+(cp2.col); int iNumMovesMin = mymin(iNumMovesDirect, mymin(iNumMovesEnd, iNumMovesStart)); if (iNumMovesMin == iNumMovesDirect) { for (i=0; i cp2.col) str_go = str_go + "l"; else str_go = str_go + "r"; } } else if (iNumMovesMin == iNumMovesEnd) { str_go = str_go + "e"; for (i=0; i<((line_sizes[cp1.row]-1)-cp2.col); i++) str_go = str_go + "l"; } else { str_go = str_go + "b"; for (i=0; i0 && myisupper(str_moves[str_moves.size()-1]) && perform_oper.seq.size()>0 && perform_oper.seq[0]=='a') { str_moves += perform_oper.seq.substr(1, perform_oper.seq.size()-1); all_cost += perform_oper.cost-1; } else { str_moves += perform_oper.seq; all_cost += perform_oper.cost; } cp.col = perform_oper.end_pos; line_sizes[poi.iline] += perform_oper.shift; for (i=poi.ioper+1; i all_sols[max_cost_index].all_cost) { max_cost_index = i; } } return max_cost_index; } ////////////////////////////////////////////////////////////////////////////// string test_grid[MAX_COL]; bool TestOutput(string& moves) { CursorPos cp_test; cp_test.row = 0; cp_test.col = 0; bool insert_mode = false; char c; int i; for (i=0; i=moves.size()) return false; if (!myisupper(moves[i+1])) return false; } else { insert_mode=false; } if (c=='b') { if (cp_test.col == 0) return false; cp_test.col = 0; } if (c=='e') { if (cp_test.col == test_grid[cp_test.row].size()-1) return false; cp_test.col = test_grid[cp_test.row].size()-1; } if (c=='l') { cp_test.col--; if (cp_test.col<0) return false; } if (c=='r') { cp_test.col++; if (cp_test.col>=test_grid[cp_test.row].size()) return false; } if (c=='u') { cp_test.row--; if (cp_test.row<0) return false; if (cp_test.col>=test_grid[cp_test.row].size()) { cp_test.col=test_grid[cp_test.row].size()-1; } } if (c=='d') { cp_test.row++; if (cp_test.row>=num_rows) return false; if (cp_test.col>=test_grid[cp_test.row].size()) { cp_test.col=test_grid[cp_test.row].size()-1; } } if (c=='x') { test_grid[cp_test.row].erase(cp_test.col,1); } if (c=='<') { if (cp_test.col == test_grid[cp_test.row].size()-1) { if (i+2>=moves.size()) return false; if (moves[i+1]!='a' || !myisupper(moves[i+2])) return false; if (insert_mode) return false; insert_mode=true; test_grid[cp_test.row] = moves[i+2]; cp_test.col = 0; i++; i++; } else { test_grid[cp_test.row].erase(0,cp_test.col+1); cp_test.col = 0; } } if (c=='>') { if (cp_test.col == 0) { if (i+2>=moves.size()) return false; if (moves[i+1]!='a' || !myisupper(moves[i+2])) return false; if (insert_mode) return false; insert_mode=true; test_grid[cp_test.row] = moves[i+2]; cp_test.col = 0; i++; i++; } else { test_grid[cp_test.row].erase(cp_test.col, test_grid[cp_test.row].size()-cp_test.col); cp_test.col = test_grid[cp_test.row].size()-1; } } } bool bSuccess = true; for (i=0; i=0; i--) { int cost_this; PerformOperation& po = perform_operations[indexed_operations[i].iline][indexed_operations[i].ioper]; if (po.wait == REDUNDANT) { cost_this=0; } else { cost_this=po.cost; if (po.seq.size()>0 && po.seq[0]=='a') cost_this--; } accum_cost[i]=cost_this+accum_cost[i+1]; } for (i=0; i max_cost) { delete[] accum_cost; return; } } delete[] accum_cost; AdjustBestSolution(max_cost_index); } ////////////////////////////////////////////////////////////////////////////// void GetInfoFromBasicOperations(int line, int ioper, PerformOperation& oper) { vector& current_opers = all_operations[line][line_operations_used[line]].opers; oper.done = false; oper.start_pos_old = oper.start_pos = current_opers[ioper].start_pos; oper.end_pos_old = oper.end_pos = current_opers[ioper].end_pos; oper.shift_old = oper.shift = current_opers[ioper].shift; oper.cost = current_opers[ioper].cost; oper.wait = current_opers[ioper].wait; oper.seq = current_opers[ioper].seq; } ////////////////////////////////////////////////////////////////////////////// int GetNumberOfOperationsInCurrentLineSol(int line) { return all_operations[line][line_operations_used[line]].opers.size(); } ////////////////////////////////////////////////////////////////////////////// // In this function, you should reset perform_operations to its original values // This function prepare the current solution to be a copy of a previous solution (ready to be modified) ////////////////////////////////////////////////////////////////////////////// // In this function, you should reset perform_operations to its original values // This function prepare the current solution to be a copy of a previous solution (ready to be modified) void ResetCurrentSolution() { int i, j; for (i=0; i= index2) { return false; } if (perform_operations[indexed_operations[index2].iline][indexed_operations[index2].ioper].wait == WAITED_BY_PREV && perform_operations[indexed_operations[index2].iline][indexed_operations[index2].ioper-1].index == index1) { return false; } } // The following for not moving redundant kill // The only available move for the redundant kill when index1 > index2 is to move // it to become in the position of the kill operation which after it if (index1 > index2 && perform_operations[indexed_operations[index1].iline][indexed_operations[index1].ioper].wait == REDUNDANT && perform_operations[indexed_operations[index1].iline][indexed_operations[index1].ioper+1].index != index2) { return false; } // Do not move the element which has been lastly moved if (last_move.type == MOVE_MOVE) { if (last_move.index2 == index1) { return false; } } return true; } ////////////////////////////////////////////////////////////////////////////// bool MoveOneOperation(short index1, short index2) { int i; // Move index1 to index2 if (index1 < index2) { PerformOperIndex poi_temp = indexed_operations[index1]; for (i=index1+1; i<=index2; i++) { indexed_operations[i-1] = indexed_operations[i]; } indexed_operations[index2] = poi_temp; } else { PerformOperIndex poi_temp = indexed_operations[index1]; for (i=index1-1; i>=index2; i--) { indexed_operations[i+1] = indexed_operations[i]; } indexed_operations[index2] = poi_temp; } for (int w=0; w= min_index) { return false; } if (perform_operations[indexed_operations[min_index].iline][indexed_operations[min_index].ioper].wait == WAITED_BY_PREV && perform_operations[indexed_operations[min_index].iline][indexed_operations[min_index].ioper-1].index <= max_index) { return false; } // The following for not swapping redundant kill if it has no effect // (occurs after its friend kill) if (perform_operations[indexed_operations[index1].iline][indexed_operations[index1].ioper].wait == REDUNDANT && perform_operations[indexed_operations[index1].iline][indexed_operations[index1].ioper+1].index < index1) { return false; } if (perform_operations[indexed_operations[index2].iline][indexed_operations[index2].ioper].wait == REDUNDANT && perform_operations[indexed_operations[index2].iline][indexed_operations[index2].ioper+1].index < index2) { return false; } // Do not swap the elements which have been lastly swapped if (last_move.type == SWAP_MOVE) { if (last_move.index1 == index1 && last_move.index2 == index2 || last_move.index1 == index2 && last_move.index2 == index1) { return false; } } return true; } ////////////////////////////////////////////////////////////////////////////// bool SwapTwoOperations(short index1, short index2) { // Swap the two indexes perform_operations[indexed_operations[index1].iline][indexed_operations[index1].ioper].index = index2; perform_operations[indexed_operations[index2].iline][indexed_operations[index2].ioper].index = index1; PerformOperIndex poi_temp = indexed_operations[index1]; indexed_operations[index1] = indexed_operations[index2]; indexed_operations[index2] = poi_temp; last_move.type = SWAP_MOVE; last_move.index1 = index1; last_move.index2 = index2; int i; for (i=0; i& current_opers = all_operations[line][k].opers; for (j=0; j MAX_LINE_SOLUTIONS) all_operations[line].pop_back(); } ////////////////////////////////////////////////////////////////////////////// struct LineOperationState { short line_operations_used[MAX_COL]; int cost; CursorPos cp_end; bool operator < (const LineOperationState& lo) const { return (cost < lo.cost); } }; ////////////////////////////////////////////////////////////////////////////// void FindSolutionLev1() { best_sol.all_cost = MAX_COST; num_sols = MAX_SOLS_LEV2; // For each good solution, Fill line_operations_used[] with the line indexes, // then call TryInitialSolution() int i, j, k; LineOperationState line_opers_states[MAX_LINE_SOLUTIONS]; int cur_line = 0; int num_states = all_operations[cur_line].size(); for (i=0; i MAX_LINE_SOLUTIONS) { num_states = MAX_LINE_SOLUTIONS; } for (i=0; i indexed_operations_saved = indexed_operations; for (int i=0; i<20; i++) { short index1 = rand()%num_opers; short index2 = rand()%num_opers; if (abs(index1-index2)>1 && CanMoveOneOperation(index1, index2)) { if (MoveOneOperation(index1, index2)) break; indexed_operations = indexed_operations_saved; for (int w=0; w= NO_CHANGE_LIMIT) { no_change = 0; adjust_events++; if (adjust_events >= ADJUST_EVENT_LIMIT && !splitted && WeCanSplit()) { splitted = true; memset(hash_table, 0, sizeof(hash_table)); for (i=0; i