diff --git a/Makefile b/Makefile index a167873..93e4df8 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ CXXFLAGS = -std=c++17 -Wall -Wextra -Werror PROD_FLAGS = -O3 DEV_FLAGS = -g -fsanitize=address -O0 -D DEV LEAK_FLAGS = -O0 -D DEV -D LEAK +DEPFLAGS = -MMD -MP INCLUDE = -I $(INC_DIR) SRC_DIR = src @@ -23,6 +24,7 @@ SRC = $(SRC_DIR)/main.c \ $(SRC_DIR)/sort/nano_sort.c \ $(SRC_DIR)/sort/is_sorted_stack.c \ $(SRC_DIR)/sort/large_sort/large_sort.c \ + $(SRC_DIR)/sort/large_sort/push_b_segmented.c \ $(SRC_DIR)/sort/large_sort/set_cost.c \ $(SRC_DIR)/sort/large_sort/set_opt.c \ $(SRC_DIR)/sort/large_sort/greedy_operation.c \ @@ -47,13 +49,13 @@ TEST_SRC = $(TEST_DIR)/test_check_args.cpp \ $(TEST_DIR)/test_reverse_rotate_stack.cpp \ $(TEST_DIR)/test_rotate_stack.cpp \ $(TEST_DIR)/test_swap_stack.cpp \ + $(TEST_DIR)/test_push_b_segmented.cpp \ $(TEST_DIR)/test_set_cost.cpp \ $(TEST_DIR)/test_set_opt_method.cpp \ $(TEST_DIR)/test_greedy_operation.cpp \ $(TEST_DIR)/test_is_sorted_stack.cpp \ $(TEST_DIR)/test_sort.cpp TEST_OBJ = $(patsubst $(TEST_DIR)/%.cpp, $(TEST_BUILD_DIR)/%.o, $(TEST_SRC)) -DEPFLAGS = -MMD -MP GTEST_SRC = $(GTEST_DIR)/gtest_main.cc $(GTEST_DIR)/gtest-all.cc GTEST_OBJ = $(patsubst $(GTEST_DIR)/%.cc, $(TEST_BUILD_DIR)/%.o, $(GTEST_SRC)) diff --git a/include/large_sort.h b/include/large_sort.h index 92c1c2d..163fea3 100644 --- a/include/large_sort.h +++ b/include/large_sort.h @@ -6,7 +6,7 @@ /* By: reasuke +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/02/11 12:36:38 by reasuke #+# #+# */ -/* Updated: 2024/02/11 12:37:50 by reasuke ### ########.fr */ +/* Updated: 2024/02/12 18:32:55 by reasuke ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,7 @@ # include "push_swap.h" void large_sort(t_stack **p_a, t_stack **p_b); +void push_b_segmented(t_stack **p_a, t_stack **p_b, int n, int num_seg); void set_cost(t_stack **p_a, t_stack **p_b); void set_opt(t_stack **p_b); void greedy_operation(t_stack **p_a, t_stack **p_b); diff --git a/src/sort/large_sort/large_sort.c b/src/sort/large_sort/large_sort.c index 3e77954..607a6bc 100644 --- a/src/sort/large_sort/large_sort.c +++ b/src/sort/large_sort/large_sort.c @@ -6,7 +6,7 @@ /* By: reasuke +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/01/22 16:55:10 by reasuke #+# #+# */ -/* Updated: 2024/02/11 12:53:49 by reasuke ### ########.fr */ +/* Updated: 2024/02/12 23:57:46 by reasuke ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,10 +15,21 @@ #include "sort.h" #include "stack_operations.h" -static void _push_b_n_times(t_stack **p_a, t_stack **p_b, int n) +// 0...200: 1 +// 200...300: 3 +// 300...400: 5 +// 400...500: 7 +// 450...550: 5 +// 550...650: 6 + +static int _calc_number_of_segments(int size_a) { - while (n--) - operate_pb(p_a, p_b); + int a; + + if (size_a <= 200) + return (1); + a = (size_a - 200) / 100; + return (2 * a + 3); } static void _sort_stack_a(t_stack **p_a, int num_a) @@ -42,7 +53,7 @@ void large_sort(t_stack **p_a, t_stack **p_b) size_a = stack_size(*p_a); size_b = size_a - 3; - _push_b_n_times(p_a, p_b, size_b); + push_b_segmented(p_a, p_b, size_b, _calc_number_of_segments(size_a)); nano_sort(p_a); while (size_b--) { diff --git a/src/sort/large_sort/push_b_segmented.c b/src/sort/large_sort/push_b_segmented.c new file mode 100644 index 0000000..808af83 --- /dev/null +++ b/src/sort/large_sort/push_b_segmented.c @@ -0,0 +1,96 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* push_b_segmented.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: reasuke +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/11 22:57:28 by reasuke #+# #+# */ +/* Updated: 2024/02/12 23:28:29 by reasuke ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "large_sort.h" +#include "push_swap.h" +#include "stack_operations.h" + +// 1 ~ 100 +// segment1: 1 ~ 20 +// segment1: 21 ~ 40 +// segment1: 41 ~ 60 +// segment1: 61 ~ 80 +// segment1: 81 ~ 100 + +// 123: 24 +// [0, 24) -> [0, seg_size) +// [24, 48) -> [seg_size, seg_size * 2) +// [48, 72) -> [seg_size * 2, seg_size * 3) +// [72, 96) -> [seg_size * 3, seg_size * 4) +// [96, 123) -> [seg_size * 4, N) + +static int _calc_segment_id(int target, int n, int segs) +{ + int seg_size; + int id; + + if (segs <= 0) + return (-1); + seg_size = n / segs; + id = 0; + while (id < segs) + { + if (id * seg_size <= target && target < (id + 1) * seg_size) + return (id); + id++; + } + if (target >= seg_size * segs) + return (segs - 1); + return (-1); +} + +// ft_printf("ns: %d, index: %d, pushed: %d, n: %d\n", num_segment, index, +// pushed, n); +static bool _should_push_b(int index, int pushed, int n, int segs) +{ + int seg_size; + int cur_id; + int inf; + int sup; + + seg_size = n / segs; + cur_id = _calc_segment_id(pushed, n, segs); + if (cur_id % 2 == 0) + { + inf = seg_size * cur_id; + sup = seg_size * (cur_id + 2); + } + else + { + inf = seg_size * (cur_id - 1); + sup = seg_size * (cur_id + 1); + } + if (cur_id == segs - 1) + return (inf < index && index <= n); + return (inf < index && index <= sup); +} + +void push_b_segmented(t_stack **p_a, t_stack **p_b, int n, int segs) +{ + int pushed; + int index; + + pushed = 0; + while (pushed < n) + { + index = get_content(*p_a)->index; + if (_should_push_b(index, pushed, n, segs)) + { + operate_pb(p_a, p_b); + if (_calc_segment_id(index - 1, n, segs) % 2 == 1) + operate_rb(p_b); + pushed++; + } + else + operate_ra(p_a); + } +} diff --git a/test/test_push_b_segmented.cpp b/test/test_push_b_segmented.cpp new file mode 100644 index 0000000..48c6407 --- /dev/null +++ b/test/test_push_b_segmented.cpp @@ -0,0 +1,135 @@ +// Copyright 2024, reasuke + +#include +#include +#include +#include + +#include "gtest/gtest.h" + +extern "C" { +#include "large_sort.h" +#include "push_swap.h" +} + +__attribute__((unused)) static void put_void(void *p_content) { + t_content *c = static_cast(p_content); + std::cout << c->index << "\n"; +} + +static void segmented_test_main1() { + std::vector v = {9, 14, 18, 13, 12, 19, 2, 8, 16, 6, + 10, 17, 7, 1, 20, 15, 3, 11, 4, 5}; + int size_a = v.size(); + + t_stack *stack_a = NULL; + t_stack *stack_b = NULL; + for (int &i : v) { + t_content *c = new t_content({i, 0, 0, 0, 0, 0, INIT, false}); + ft_lstadd_back(&stack_a, ft_lstnew(c)); + } + + push_b_segmented(&stack_a, &stack_b, size_a, 5); + + t_stack *st = stack_b; + for (int i = 0; i < size_a; ++i) { + if (i < 4) { + EXPECT_GE(get_content(st)->index, 17); + EXPECT_LE(get_content(st)->index, 20); + } else if (4 <= i && i < 8) { + EXPECT_GE(get_content(st)->index, 9); + EXPECT_LE(get_content(st)->index, 12); + } else if (8 <= i && i < 12) { + EXPECT_GE(get_content(st)->index, 1); + EXPECT_LE(get_content(st)->index, 4); + } else if (12 <= i && i < 16) { + EXPECT_GE(get_content(st)->index, 5); + EXPECT_LE(get_content(st)->index, 8); + } else { + EXPECT_GE(get_content(st)->index, 13); + EXPECT_LE(get_content(st)->index, 16); + } + st = st->next; + } +} + +TEST(push_b_segmented, case1) { + // save stdout + int stdout_copy = dup(STDOUT_FILENO); + // redirect stdout to /dev/null + int dev_null = open("/dev/null", O_WRONLY); + dup2(dev_null, 1); + close(dev_null); + + // execute test + segmented_test_main1(); + + // revert stdout + dup2(stdout_copy, STDOUT_FILENO); + close(stdout_copy); +} + +static void segmented_test_main2() { + int N = 20; + std::vector v(N); + for (int i = 0; i < N; ++i) { + v[i] = i + 1; + } + // shuffle vector + std::random_device seed_gen; + std::mt19937 engine(seed_gen()); + std::shuffle(v.begin(), v.end(), engine); + int size_a = N; + + t_stack *stack_a = NULL; + t_stack *stack_b = NULL; + for (int &i : v) { + t_content *c = new t_content({i, 0, 0, 0, 0, 0, INIT, false}); + ft_lstadd_back(&stack_a, ft_lstnew(c)); + } + + push_b_segmented(&stack_a, &stack_b, size_a - 3, 5); + t_stack *st = stack_b; + for (int i = 0; i < size_a - 3; ++i) { + if (i < 5) { + EXPECT_GE(get_content(st)->index, 13); + EXPECT_LE(get_content(st)->index, 17); + } else if (5 <= i && i < 8) { + EXPECT_GE(get_content(st)->index, 7); + EXPECT_LE(get_content(st)->index, 9); + } else if (8 <= i && i < 11) { + EXPECT_GE(get_content(st)->index, 1); + EXPECT_LE(get_content(st)->index, 3); + } else if (11 <= i && i < 14) { + EXPECT_GE(get_content(st)->index, 4); + EXPECT_LE(get_content(st)->index, 6); + } else { + EXPECT_GE(get_content(st)->index, 10); + EXPECT_LE(get_content(st)->index, 12); + } + st = st->next; + } + + st = stack_a; + while (st) { + EXPECT_GE(get_content(st)->index, 18); + EXPECT_LE(get_content(st)->index, 20); + st = st->next; + } +} + +TEST(push_b_segmented, case2) { + // // save stdout + // int stdout_copy = dup(STDOUT_FILENO); + // // redirect stdout to /dev/null + // int dev_null = open("/dev/null", O_WRONLY); + // dup2(dev_null, 1); + // close(dev_null); + + // execute test + segmented_test_main2(); + + // // revert stdout + // dup2(stdout_copy, STDOUT_FILENO); + // close(stdout_copy); +} diff --git a/test/test_sort.cpp b/test/test_sort.cpp index 520d6f1..aad5f26 100644 --- a/test/test_sort.cpp +++ b/test/test_sort.cpp @@ -66,7 +66,6 @@ static void random_sort_test_main(int N) { v[i] = i + 1; } // shuffle vector - std::cout << std::endl; std::random_device seed_gen; std::mt19937 engine(seed_gen()); std::shuffle(v.begin(), v.end(), engine); @@ -101,28 +100,28 @@ static void random_sort_test(int N) { close(stdout_copy); } -TEST(sort, oneElement) { sort_test(1); } +TEST(sort, element1) { sort_test(1); } -TEST(sort, twoElements) { sort_test(2); } +TEST(sort, elements2) { sort_test(2); } -TEST(sort, threeEelments) { sort_test(3); } +TEST(sort, elements3) { sort_test(3); } -TEST(sort, fourElements) { sort_test(4); } +TEST(sort, elements4) { sort_test(4); } -TEST(sort, fiveElements) { sort_test(5); } +TEST(sort, elements5) { sort_test(5); } -TEST(sort, sixElements) { sort_test(6); } +TEST(sort, elements6) { sort_test(6); } -TEST(sort, sevenElements) { sort_test(7); } +TEST(sort, elements7) { sort_test(7); } -TEST(sort, eightElementsRandom) { random_sort_test(8); } +TEST(sort, randomElements8) { random_sort_test(8); } -TEST(sort, nineElementsRandom) { random_sort_test(9); } +TEST(sort, randomElements9) { random_sort_test(9); } -TEST(sort, tenElementsRandom) { random_sort_test(10); } +TEST(sort, randomElements10) { random_sort_test(10); } -TEST(sort, hundredElementsRandom) { random_sort_test(100); } +TEST(sort, randomElements100) { random_sort_test(100); } -TEST(sort, twoHundredElementsRandom) { random_sort_test(200); } +TEST(sort, randomElements200) { random_sort_test(200); } -TEST(sort, thousandElementsRandom) { random_sort_test(500); } +TEST(sort, randomElements500) { random_sort_test(500); }