Skip to content

Commit

Permalink
added reduce optional argument and cmake test support
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGAzed committed Jun 23, 2024
1 parent 823652d commit 19962f3
Show file tree
Hide file tree
Showing 18 changed files with 261 additions and 230 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/cmake-single-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,7 @@ jobs:
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
run: |
./build/test/unit/UNITTESTS
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"ubench.h": "c",
"settings.h": "c",
"bit": "c",
"chrono": "c"
"chrono": "c",
"arc_consistency.h": "c",
"statistics.h": "c"
}
}
9 changes: 4 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ project(SLNOSLAV
LANGUAGES C
)

if(MSVC)
add_compile_options(/std:c17)
else()
set(CMAKE_C_FLAGS "-std=c17 -pg -Wall -Werror -ftest-coverage")
endif()
set(CMAKE_C_FLAGS "-std=c17 -pg -Wall -Werror -ftest-coverage")

add_subdirectory(external)
add_subdirectory(program)

include(CTest)
enable_testing()
add_subdirectory(test)
7 changes: 7 additions & 0 deletions external/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ add_library(NUKLEAR_LIB INTERFACE "")
set_target_properties(NUKLEAR_LIB PROPERTIES LINKER_LANGUAGE C)

target_include_directories(NUKLEAR_LIB INTERFACE nuklear/src)

add_subdirectory(glfw)

add_library(GLFW_LIB SHARED "" glfw/src)

target_include_directories(GLFW_LIB PUBLIC glfw/include)
set_target_properties(GLFW_LIB PROPERTIES LINKER_LANGUAGE C)
Empty file added external/nuklear.h
Empty file.
9 changes: 5 additions & 4 deletions program/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
add_executable(${PROJECT_NAME} main.c)

add_library(PROGRAM_LIB "")
add_library(PROGRAM_LIBRARY "")

target_sources(PROGRAM_LIB
target_sources(PROGRAM_LIBRARY
PRIVATE
source/algorithms/depth_first_search.c
source/algorithms/backtrack.c
source/algorithms/arc_consistency.c
source/algorithms/reduce.c
source/algorithms/forward_checking.c

source/instance/argument.c
Expand All @@ -19,6 +20,6 @@ target_sources(PROGRAM_LIB
source/slnoslav.c
)

target_include_directories(PROGRAM_LIB PUBLIC include)
target_include_directories(PROGRAM_LIBRARY PUBLIC include)

target_link_libraries(${PROJECT_NAME} PROGRAM_LIB)
target_link_libraries(${PROJECT_NAME} PROGRAM_LIBRARY)
1 change: 0 additions & 1 deletion program/include/algorithms/arc_consistency.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <structures/concrete/state.h>
#include <structures/concrete/board.h>

void reduce_tree(Kakuro board, SArray * initial_state);
bool look_ahead(Kakuro board, SArray * current_state);

#endif /* ALGORITHMS_ARC_CONSISTENCY_H */
9 changes: 9 additions & 0 deletions program/include/algorithms/reduce.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef ALGORITHMS_REDUCE_H
#define ALGORITHMS_REDUCE_H

#include <structures/concrete/state.h>
#include <structures/concrete/board.h>

void reduce(Kakuro board, SArray * initial_state);

#endif /* ALGORITHMS_REDUCE_H */
3 changes: 3 additions & 0 deletions program/include/instance/argument.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#define ARC_CONSISTENCY_FLAG_STRING_SHORT "-ac"
#define ARC_CONSISTENCY_FLAG_STRING_LONG "--arc-consistency"

#define REDUCE_FLAG_STRING_SHORT "-r"
#define REDUCE_FLAG_STRING_LONG "--reduce"

#define INFO_FLAG_STRING_SHORT "-i"
#define INFO_FLAG_STRING_LONG "--information"

Expand Down
1 change: 1 addition & 0 deletions program/include/instance/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ typedef struct settings {
bool is_backtrack;
bool is_forward_check;
bool is_arc_consistency;
bool is_reduce;
} Settings;

Settings * get_settings_singleton(void);
Expand Down
138 changes: 0 additions & 138 deletions program/source/algorithms/arc_consistency.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,11 @@
#define STACK_DATA_TYPE ksize_t
#include <structures/abstract/stack.h>

#define MAGIC_TABLE_LENGTH 7
#define BLOCK_LENGTH_REST 4
#define BLOCK_LENGTH_EIGHT 9
typedef struct magic_table {
size_t blocks[MAGIC_TABLE_LENGTH];
size_t lengths[MAGIC_TABLE_LENGTH];

state_t B[BLOCK_LENGTH_REST]; state_t C[BLOCK_LENGTH_REST];
state_t D[BLOCK_LENGTH_REST]; state_t E[BLOCK_LENGTH_REST];
state_t F[BLOCK_LENGTH_REST]; state_t G[BLOCK_LENGTH_REST];
state_t H[BLOCK_LENGTH_EIGHT];

state_t * united[MAGIC_TABLE_LENGTH];
} MTable;

typedef struct reduce_combinations {
SMatrix e_matrix;
ksize_t e_valid[MAX_BLOCK_VALUES][MAX_BLOCK_VALUES];
} Valid;

state_t _check_magic_table(ksize_t blocks, ksize_t sum);
state_t _check_one_blocks(ksize_t blocks, ksize_t sum);
state_t _check_even_two_blocks(ksize_t block, ksize_t sum);
state_t _check_high_end(ksize_t block, ksize_t sum);
state_t _check_low_end(ksize_t block, ksize_t sum);
void _reduce_multi_values(Kakuro board, SArray * initial_state);
void _reduce_row_multi_values(Kakuro board, SArray * initial_state, Check * checks, ksize_t index);
void _reduce_col_multi_values(Kakuro board, SArray * initial_state, Check * checks, ksize_t index);

void _reduce_one_values(Kakuro board, SArray * current_state, Check * checks);
void _reduce_row_one_values(Kakuro board, Stack * ones, SArray * current_state, ksize_t index, Check * checks);
void _reduce_col_one_values(Kakuro board, Stack * ones, SArray * current_state, ksize_t index, Check * checks);
Expand All @@ -50,13 +26,6 @@ bool _reduce_no_combination(Kakuro board, SArray * current_state, Check * check
bool _reduce_no_col_combination(Kakuro board, SArray * current_state, Check * checks, ksize_t index);
bool _reduce_no_row_combination(Kakuro board, SArray * current_state, Check * checks, ksize_t index);

void reduce_tree(Kakuro board, SArray * initial_state) {
assert(initial_state && "INITIAL STATE ARRAY IS NULL");
if (!(get_settings_singleton()->is_arc_consistency)) return;

_reduce_multi_values(board, initial_state);
}

bool look_ahead(Kakuro board, SArray * current_state) {
assert(current_state && "CURRENT STATE ARRAY IS NULL");
if (!(get_settings_singleton()->is_arc_consistency)) return true;
Expand All @@ -70,113 +39,6 @@ bool look_ahead(Kakuro board, SArray * current_state) {
return !invalid_state_look_ahead_stat(!valid_states(*current_state));
}

state_t _check_magic_table(ksize_t blocks, ksize_t sum) {
static MTable t = {
.blocks = { 2, 3, 4, 5, 6, 7, 8 },
.lengths = { 4, 4, 4, 4, 4, 4, 9 },

.B = { 0b000000011, 0b000000101, 0b101000000, 0b110000000, }, .C = { 0b000000111, 0b000001011, 0b110100000, 0b111000000, },
.D = { 0b000001111, 0b000010111, 0b111010000, 0b111100000, }, .E = { 0b000011111, 0b000101111, 0b111101000, 0b111110000, },
.F = { 0b000111111, 0b001011111, 0b111110100, 0b111111000, }, .G = { 0b001111111, 0b010111111, 0b111111010, 0b111111100, },
.H = { 0b011111111, 0b101111111, 0b110111111, 0b111011111, 0b111101111, 0b111110111, 0b111111011, 0b111111101, 0b111111110, },

.united[0] = t.B, .united[1] = t.C, .united[2] = t.D, .united[3] = t.E, .united[4] = t.F, .united[5] = t.G, .united[6] = t.H,
};

assert(blocks >= 1 && blocks <= 9 && "BLOCK SIZE NOT IN RANGE");

state_t s = FULL_STATE;
if (blocks == 1 || blocks == 9) return s;

for (ksize_t i = 0; i < t.lengths[blocks - 2]; i++) {
state_t temp = t.united[blocks - 2][i];
if (state_to_sums(temp) == sum) { s = temp; break; }
}
return s;
}

state_t _check_one_blocks(ksize_t blocks, ksize_t sum) {
state_t s = blocks == 1 ? get_one_state(sum) : FULL_STATE;
return s;
}

state_t _check_even_two_blocks(ksize_t block, ksize_t sum) {
state_t s = ((block == 2) && !(sum & 1)) ? FULL_STATE ^ (1 << ((sum >> 1) - 1)) : FULL_STATE;
return s;
}

state_t _check_high_end(ksize_t block, ksize_t sum) {
ksize_t block_sum = get_sums(block - 1, UPPER_EDGE);
state_t s = (LOWER_EDGE + block_sum < sum) ? get_edge_state((MAX_BLOCK_VALUES + 1) - (sum - block_sum), UPPER_EDGE) : FULL_STATE;
return s;
}

state_t _check_low_end(ksize_t block, ksize_t sum) {
ksize_t block_sum = get_sums(block - 1, LOWER_EDGE);
state_t s = (UPPER_EDGE + block_sum > sum) ? get_edge_state(sum - block_sum, LOWER_EDGE) : FULL_STATE;
return s;
}

void _reduce_multi_values(Kakuro board, SArray * current_state) {
Check checks[KAKURO_SIZE_MAX] = { 0 };

for (size_t i = 0; i < board.game.empty_count; i++) {
if (!(checks[i] & ROWCHECK)) _reduce_row_multi_values(board, current_state, checks, i);
if (!(checks[i] & COLCHECK)) _reduce_col_multi_values(board, current_state, checks, i);
add_check(board, checks, i);
}
}

void _reduce_row_multi_values(Kakuro board, SArray * current_state, Check * checks, ksize_t index) {
ksize_t row = board.coords[ROW][index], col = board.coords[COLUMN][index];
ksize_t block = board.blocks[ROW][index], sums = board.sums[ROW][index];
ksize_t empty_blocks = block, empty_sums = sums;
Stack multi = create_stack();

for (size_t i = 0; i < block; i++) {
state_t s = current_state->elements[board.grid[row][col + i]];
if (is_one_value(s)) { empty_blocks--; empty_sums -= state_to_sums(s); }
else push_stack(&multi, (ksize_t)board.grid[row][col + i]);
}

while (!is_empty_stack(multi)) {
ksize_t i = pop_stack(&multi);
state_t magic = _check_magic_table(empty_blocks, empty_sums);

if (magic != FULL_STATE) current_state->elements[i] &= magic;
else current_state->elements[i] &=
_check_one_blocks(empty_blocks, empty_sums) & _check_even_two_blocks(empty_blocks, empty_sums) &
_check_high_end(empty_blocks, empty_sums) & _check_low_end(empty_blocks, empty_sums);
}

destroy_stack(&multi, NULL);
}

void _reduce_col_multi_values(Kakuro board, SArray * current_state, Check * checks, ksize_t index) {
ksize_t row = board.coords[ROW][index], col = board.coords[COLUMN][index];
ksize_t block = board.blocks[COLUMN][index], sums = board.sums[COLUMN][index];
ksize_t empty_blocks = block, empty_sums = sums;
Stack multi = create_stack();

for (size_t i = 0; i < block; i++) {
state_t s = current_state->elements[board.grid[row + i][col]];
if (is_one_value(s)) { empty_blocks--; empty_sums -= state_to_sums(s); }
else push_stack(&multi, (ksize_t)board.grid[row + i][col]);
}

while (!is_empty_stack(multi)) {
ksize_t i = pop_stack(&multi);
state_t magic = _check_magic_table(empty_blocks, empty_sums);

if (magic != FULL_STATE) current_state->elements[i] &= magic;
else current_state->elements[i] &=
_check_one_blocks(empty_blocks, empty_sums) & _check_even_two_blocks(empty_blocks, empty_sums) &
_check_high_end(empty_blocks, empty_sums) & _check_low_end(empty_blocks, empty_sums);
}

destroy_stack(&multi, NULL);
}

void _reduce_one_values(Kakuro board, SArray * current_state, Check * checks) {
Stack ones = create_stack();

Expand Down
3 changes: 2 additions & 1 deletion program/source/algorithms/depth_first_search.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <algorithms/depth_first_search.h>
#include <algorithms/backtrack.h>
#include <algorithms/arc_consistency.h>
#include <algorithms/reduce.h>
#include <algorithms/forward_checking.h>

#include <instance/statistics.h>
Expand All @@ -18,7 +19,7 @@ SArray depth_first_search(Kakuro board) {

SArray initial = create_state_array(board.game.empty_count);
set_full_state_array(&initial);
reduce_tree(board, &initial);
reduce(board, &initial);
push_stack(&stack, initial);

SArray solution = { 0 };
Expand Down
Loading

0 comments on commit 19962f3

Please sign in to comment.