/* Convert a path represented by a list of indices to a mask. */ mask_t path_to_mask(path_t path, int start, int end) { mask_t mask = EMPTY_MASK; while (start < end) { mask = ADD_TO_MASK(mask, path[start++]); } return mask; }
/* Split a mask into a mask with just the cycles, and another mask with the remaining dots. */ void separate_cycles(mask_t mask, mask_t *cycles, mask_t *no_cycles) { int i, j; *cycles = mask; *no_cycles = 0; for (i = j = 0; i < NUM_DOTS; j = ++i) { if (MASK_CONTAINS(*cycles, j)) { /* Repeatedly remove dots that only have less than two neighbors and add * them to the mask that has no cycles. */ int num_neighbors; neighbors_t neighbors; get_neighbors(*cycles, j, &num_neighbors, neighbors); while (num_neighbors <= 1) { *cycles = REMOVE_FROM_MASK(*cycles, j); *no_cycles = ADD_TO_MASK(*no_cycles, j); if (num_neighbors == 0) { break; } j = neighbors[0]; get_neighbors(*cycles, j, &num_neighbors, neighbors); } } } }
/* * Convert the character representation of audit values into the au_mask_t * field. */ int getauditflagsbin(char *auditstr, au_mask_t *masks) { char class_ent_name[AU_CLASS_NAME_MAX]; char class_ent_desc[AU_CLASS_DESC_MAX]; struct au_class_ent c; char *tok; char sel, sub; char *last; bzero(&c, sizeof(c)); bzero(class_ent_name, sizeof(class_ent_name)); bzero(class_ent_desc, sizeof(class_ent_desc)); c.ac_name = class_ent_name; c.ac_desc = class_ent_desc; masks->am_success = 0; masks->am_failure = 0; tok = strtok_r(auditstr, flagdelim, &last); while (tok != NULL) { /* Check for the events that should not be audited. */ if (tok[0] == '^') { sub = 1; tok++; } else sub = 0; /* Check for the events to be audited for success. */ if (tok[0] == '+') { sel = AU_PRS_SUCCESS; tok++; } else if (tok[0] == '-') { sel = AU_PRS_FAILURE; tok++; } else sel = AU_PRS_BOTH; if ((getauclassnam_r(&c, tok)) != NULL) { if (sub) SUB_FROM_MASK(masks, c.ac_class, sel); else ADD_TO_MASK(masks, c.ac_class, sel); } else { errno = EINVAL; return (-1); } /* Get the next class. */ tok = strtok_r(NULL, flagdelim, &last); } return (0); }
mask_t random_mask() { mask_t mask = EMPTY_MASK; int col, row; for (col = 0; col < NUM_COLS; col++) { for (row = 0; row < NUM_ROWS; row++) { if (RAND_COLOR == RED) { mask = ADD_TO_MASK(mask, MASK_INDEX(row, col)); } } } return mask; }
/* Create a mask of all of the dots in a grid of a given color. */ mask_t get_color_mask(grid_t grid, color_t color) { mask_t mask = EMPTY_MASK; int col, row; column_t column; for (col = 0; col < NUM_COLS; col++) { column = grid[col]; for (row = 0; row < NUM_ROWS; row++) { if (GET_COLUMN_COLOR(column, row) == color) { mask = ADD_TO_MASK(mask, MASK_INDEX(row, col)); } } } return mask; }
/* Find a path through a mask. Returns the length of the path stored in `path`. The length is 0 if no path was found. */ int _mask_to_path(mask_t mask, mask_t visited, int index, int edges[NUM_DOTS][NUM_DOTS], int path_length, path_t path) { int j, num_neighbors, nowhere_to_go; neighbors_t neighbors; /* All of the branches of this DFS share the same buffer for path, but that's okay because it * quits as soon as it finds a path that uses all of the dots. */ path[path_length++] = index; visited = ADD_TO_MASK(visited, index); nowhere_to_go = 1; get_neighbors(mask, index, &num_neighbors, neighbors); for (j = 0; j < num_neighbors; j++) { int new_index = neighbors[j]; /* Don't follow the same edge twice. */ if (!edges[index][new_index]) { int final_path_length, new_edges[NUM_DOTS][NUM_DOTS]; nowhere_to_go = 0; /* Make a copy of the edges and mark the edge about to be traversed. */ memcpy(new_edges, edges, sizeof(new_edges)); new_edges[index][new_index] = 1; new_edges[new_index][index] = 1; final_path_length= _mask_to_path(mask, visited, new_index, new_edges, path_length, path); if (final_path_length > 0) { return final_path_length; } } } /* End condition: all dots have been visited and there is nowhere left to go. * This works even for cycles where it might visit the same dot twice. */ if (mask == visited && nowhere_to_go) { return path_length; } /* No path was found. */ return 0; }