void combine_ws_reg_files(program *prog, whitespace_info *whitespace_prog, char *file_one, char *file_two)
{
	initialise_whitespace_prog(whitespace_prog);

	open_program_file(file_one, prog);

	open_whitespace_program_file_verbatim(file_two, whitespace_prog);

	write_combination_to_file(prog, whitespace_prog);
}
예제 #2
0
/**
 * Iterates over the rows of the board, trying to complete one by one.
 *
 * @param board -- pointer to the two-dimensional array representing the board.
 * @param pieces -- pointer to the array of all pieces.
 * @param which_row -- indicates which row the algorithm is currently working on.
 * @param fp_constellations -- pointer to the output file.
 *
 */
void iter_rows(short board[][5], struct Piece* pieces, short const which_row, FILE* fp_constellations) {

	if(which_row == 11) {  // last row (11th row) was finished by placing a piece (purple) only within that row;
		write_combination_to_file(fp_constellations, pieces);
		return;
	}

	short nopen=5;  // number of free sites in the current row;
	for(short j=0; j<5; ++j) {
		nopen -= board[which_row][j];
	}

	if(nopen == 0) {  // row is already complete;
		if(which_row == 10) {  // is the last row;
			for(short i=0; i<12; ++i) {
				if(pieces[i].used == 0) pieces[i].skip = 1;  // set each unused piece on skip because skipped pieces are set on unskip after a row was completed in order to make them available for the next row. However there is no additional row after the last one and in case of solutions including only 9 pieces having unused, unskipped pieces can result in an infinite loop (as they will be used in place of the piece that completed the board in subsequent steps which makes it possible to use the completing piece again). Therefore skip them in case the algorithm found a solution.
			}
			write_combination_to_file(fp_constellations, pieces);
		} else {  // is not the last row;
			iter_rows(board, pieces, which_row+1, fp_constellations);  // move on to the next row;
		}
		return;
	}

	short nused=0;  // how many successive pieces (without gap, from the beginning) have already been used or are currently on skip. At the same time this indicates the position of the piece that will be used this step withing the array of pieces.
	struct Piece* piece = pieces;
	while((piece->used > 0 || piece->skip > 0) && nused<12) {
		piece += 1;
		nused += 1;
	}
	if(nused == 12) return;  // All pieces are either used or on skip for the current row -> no solution could be found.

	short x_max;  // x-value of the 'rightmost' site the piece can be placed on in order not to exceed the boundaries of the board;
	int success;  // indicates whether the current piece was placed successfully on the board;

	for(short rotation=0; rotation<4; ++rotation) {  // loop over rotations; rotation are to be regarded clockwise;

		if(piece->rotations[rotation] == 0) continue;  // rotation is redundant;

		if(rotation%2 == 0) {  // 0 degrees or 180 degrees;
			if(which_row + piece->y_range > 11) continue;  // piece would exceed y-range of the board;
			x_max = 5-piece->actual_x_range;  // x-extent of piece is 2;
		} else {  // 90 degrees or 270 degrees;
			if(which_row + piece->actual_x_range > 11) continue;  // piece would exceed y-range of the board;
			x_max = 5-piece->y_range;  // original y-range becomes x-range;
		}

		piece->x_range = piece->x_range_A;  // use version A for x_range;
		if(piece->x_range[rotation] <= nopen) {  // check if there are enough free sites in the current row;

			piece->version = &(piece->A);  // use version A;
			for(short x=0; x<=x_max; ++x) {  // x denotes the x-position of the left upper corner of the enclosing rectangle within which the piece will be placed;

				success = place_piece_on_board(board, piece, which_row, x, rotation);
				if(success == 0) {  // no overlap of pieces;

					piece->used = 1000 + 100*rotation + 10*which_row + x;  // mark piece as used (see declaration of Piece for encoding);
					nopen -= piece->x_range[rotation];  // adjust number of free sites;
					if(nopen == 0) {  // current row is complete;

						for(short i=0; i<12; ++i) {
							pieces[i].skip = 0;  // reset skip of pieces in order to make them available for the next row;
						}
						iter_rows(board, pieces, which_row+1, fp_constellations);  // move on to the next row;
					} else {  // row is not complete;

						iter_rows(board, pieces, which_row, fp_constellations);  // stay within the current row;
					}
					remove_piece_from_board(board, piece, which_row, x, rotation);  // after deeper recursions returned remove the piece from the board in order to place it at another location or to skip it for the current row;
					piece->used = 0;  // adjust used indicator;
					nopen += piece->x_range[rotation];  // adjust number of free sites;
					for(short i=nused+1; i<12; ++i) {
						pieces[i].skip = 0;  // reset skip of subsequent pieces so they can be used in the current row (their skip was set in deeper recursions); preceding pieces, if skipped, remain unchanged as their combination with other pieces was already checked in higher recursion levels (only 'forward' (or better 'downward') generation of combinations, no double generation);
					}
				}
			}
		}


		// repeat the above procedure for version B; for explanations/comments see the part for version A;
		piece->x_range = piece->x_range_B;
		if(piece->symmetric == 0 && piece->x_range[rotation] <= nopen) {  // only if the piece is not symmetric, otherwise version B is redundant; see declaration of struct Piece;

			piece->version = &(piece->B);
			for(short x=0; x<=x_max; ++x) {

				success = place_piece_on_board(board, piece, which_row, x, rotation);
				if(success == 0) {

					piece->used = 2000 + 100*rotation + 10*which_row + x;
					nopen -= piece->x_range[rotation];
					if(nopen == 0) {

						for(short i=0; i<12; ++i) {
							pieces[i].skip = 0;
						}
						iter_rows(board, pieces, which_row+1, fp_constellations);
					} else {

						iter_rows(board, pieces, which_row, fp_constellations);
					}
					remove_piece_from_board(board, piece, which_row, x, rotation);
					piece->used = 0;
					nopen += piece->x_range[rotation];
					for(short i=nused+1; i<12; ++i) {
						pieces[i].skip = 0;
					}
				}
			}
		}
	}

	// finally, do not use the current piece for the current row (so it can be used for subsequent rows);
	piece->skip = 1;
	iter_rows(board, pieces, which_row, fp_constellations);  // stay within the current row;
}