Skip to content

Commit

Permalink
implement push b segmented (#25)
Browse files Browse the repository at this point in the history
* update Makefile

* implement push_b_segmented

* rename

* add test

* fix test

* optimize push

* optimize number_of_segments
  • Loading branch information
rask24 committed Feb 12, 2024
1 parent 0209e74 commit 3ca79cc
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 21 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 \
Expand All @@ -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))

Expand Down
3 changes: 2 additions & 1 deletion include/large_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: reasuke <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */

Expand All @@ -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);
Expand Down
21 changes: 16 additions & 5 deletions src/sort/large_sort/large_sort.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* By: reasuke <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */

Expand All @@ -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)
Expand All @@ -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--)
{
Expand Down
96 changes: 96 additions & 0 deletions src/sort/large_sort/push_b_segmented.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* push_b_segmented.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: reasuke <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}
}
135 changes: 135 additions & 0 deletions test/test_push_b_segmented.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright 2024, reasuke

#include <algorithm>
#include <iostream>
#include <random>
#include <vector>

#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<t_content *>(p_content);
std::cout << c->index << "\n";
}

static void segmented_test_main1() {
std::vector<int> 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<int> 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);
}
27 changes: 13 additions & 14 deletions test/test_sort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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); }

0 comments on commit 3ca79cc

Please sign in to comment.