trying to work

This commit is contained in:
Maieul BOYER 2024-01-11 21:28:36 +01:00
parent 3d3d7a35ab
commit 2776ee1ebc
No known key found for this signature in database
25 changed files with 1621 additions and 0 deletions

231
src/app/lis/lis.c Normal file
View file

@ -0,0 +1,231 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* lis.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 18:50:35 by maiboyer #+# #+# */
/* Updated: 2024/01/11 21:27:36 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/element.h"
#include "me/mem/mem_alloc_array.h"
#include "me/printf/printf.h"
#include "me/vec/vec_element.h"
#include "me/vec/vec_i64.h"
#include <stdlib.h>
/*
P = array of length N
M = array of length N + 1
M[0] = -1 // undefined so can be set to any value
L = 0
for i in range 0 to N-1: //N-1 included
// Binary search for the smallest positive l ≤ L
// such that X[M[l]] > X[i]
lo = 1
hi = L + 1
while lo < hi:
mid = lo + floor((hi-lo)/2) // lo <= mid < hi
if X[M[mid]] >= X[i]
hi = mid
else: // if X[M[mid]] < X[i]
lo = mid + 1
// After searching, lo == hi is 1 greater than the
// length of the longest prefix of X[i]
newL = lo
// The predecessor of X[i] is the last index of
// the subsequence of length newL-1
P[i] = M[newL-1]
M[newL] = i
if newL > L:
// If we found a subsequence longer than any we've
// found yet, update L
L = newL
// Reconstruct the longest increasing subsequence
// It consists of the values of X at the L indices:
// ..., P[P[M[L]]], P[M[L]], M[L]
S = array of length L
k = M[L]
for j in range L-1 to 0: //0 included
S[j] = X[k]
k = P[k]
return S
*/
// static t_i64 binary_search(t_i64 L, t_i64 i, t_i64 m[], t_vec_element
// *elements)
//{
// return (low);
//}
// static t_vec_i64 lis_inner(t_vec_element *elements, t_i64 L, t_i64 m[],
// t_i64 p[])
//{
// }
/*
/// Finds one of the [longest increasing subsequences][1]
/// from the subsequence created by applying `selector` on each item in `items`.
/// The result is a vector of indices within `items`
/// corresponding to one of the longest increasing subsequences.
///
/// [1]: https://en.wikipedia.org/wiki/Longest_increasing_subsequence
pub fn lis<T, I: Ord, F: Fn(&T) -> I>(items: &[T], selector: F) -> Vec<usize> {
// This algorithm is adapted from
//
http://www.algorithmist.com/index.php?title=Longest_Increasing_Subsequence.cpp&oldid=13595
let mut result = Vec::new();
// If `items` is empty, then the result is also empty.
if items.is_empty() {
return result;
}
// This vector stores, for each item,
// the index of the largest item prior to itself that is smaller than
itself.
// We'll use this vector at the end to build the final result.
let mut previous_chain = vec![0; items.len()];
// Initially, we assume that the first item is part of the result.
// We will replace this index later if that's not the case.
result.push(0);
for i in 1..items.len() {
// If the next item is greater than the last item of the current longest
subsequence,
// push its index at the end of the result and continue.
if selector(&items[*result.last().unwrap()]) < selector(&items[i]) {
previous_chain[i] = *result.last().unwrap();
result.push(i);
continue;
}
// Perform a binary search to find the index of an item in `result` to
overwrite.
// We want to overwrite an index that refers to the smallest item that
is larger than `items[i]`.
// If there is no such item, then we do nothing.
let comparator = |&result_index| {
use std::cmp::Ordering;
// We don't return Ordering::Equal when we find an equal value,
// because we want to find the index of the first equal value.
if selector(&items[result_index]) < selector(&items[i]) {
Ordering::Less
} else {
Ordering::Greater
}
};
let next_element_index = match result.binary_search_by(comparator) {
Ok(index) | Err(index) => index,
};
if selector(&items[i]) < selector(&items[result[next_element_index]]) {
if next_element_index > 0 {
previous_chain[i] = result[next_element_index - 1];
}
result[next_element_index] = i;
}
}
// The last item in `result` is correct,
// but we might have started overwriting earlier items
// with what could have been a longer subsequence.
// Walk back `previous_chain` to restore the proper subsequence.
let mut u = result.len();
let mut v = *result.last().unwrap();
while u != 0 {
u -= 1;
result[u] = v;
v = previous_chain[v];
}
result
}
*/
t_i64 binary_search(t_vec_element *items, t_i64 i)
{
t_i64 lo;
t_i64 hi;
t_i64 mid;
lo = 0;
hi = items->len;
while (lo < hi)
{
mid = lo + (hi - lo) / 2;
if (items->buffer[mid].value < items->buffer[i].value)
lo = mid + 1;
else
hi = mid;
}
return (lo);
}
void lis_inner(t_vec_element *elements, t_vec_i64 *result,
t_vec_i64 *previous_chain)
{
t_i64 i;
t_i64 next_element_index;
i = 1;
while (i < (t_i64)elements->len)
{
if (elements->buffer[result->buffer[result->len - 1]].value <
elements->buffer[i].value)
{
previous_chain->buffer[i] = result->buffer[result->len - 1];
vec_i64_push(result, i++);
continue;
}
next_element_index = binary_search(elements, i);
if (elements->buffer[i].value >
elements->buffer[result->buffer[next_element_index]].value)
{
if (next_element_index > 0)
previous_chain->buffer[i] =
result->buffer[next_element_index - 1];
result->buffer[next_element_index] = i;
}
i++;
}
}
t_vec_i64 lis(t_vec_element *elements)
{
t_vec_i64 result;
t_i64 u;
t_i64 v;
t_vec_i64 previous_chain;
result = vec_i64_new(elements->len, NULL);
if (elements->len == 0)
return (result);
previous_chain = vec_i64_new(elements->len, NULL);
previous_chain.len = elements->len;
vec_i64_push(&result, 0);
lis_inner(elements, &result, &previous_chain);
u = result.len;
v = result.buffer[result.len - 1];
while (u != 0)
{
u--;
result.buffer[u] = v;
v = previous_chain.buffer[v];
}
return (result);
}

11
src/app/lis/lower_bound.c Normal file
View file

@ -0,0 +1,11 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* lower_bound.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 18:17:23 by maiboyer #+# #+# */
/* Updated: 2024/01/11 19:17:19 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */

180
src/app/main.c Normal file
View file

@ -0,0 +1,180 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 14:14:18 by maiboyer #+# #+# */
/* Updated: 2024/01/11 21:03:29 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/dup_state.h"
#include "app/element.h"
#include "app/lis.h"
#include "app/moves.h"
#include "app/state.h"
#include "me/convert/atoi.h"
#include "me/convert/itoa.h"
#include "me/printf/printf.h"
#include "me/string/str_clone.h"
#include "me/types.h"
#include "me/vec/vec_element.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
void free_element(t_element elem)
{
(void)(elem);
}
void free_state(t_state state)
{
vec_element_free(state.stack_a);
vec_element_free(state.stack_b);
}
t_error parse_element(t_str s, t_element *e)
{
t_usize i;
t_i64 value;
t_element out;
if (s == NULL || e == NULL)
return (ERROR);
i = 0;
if (s[i] == '-' || s[i] == '+')
i++;
while (s[i] && s[i] >= '0' && s[i] <= '9')
i++;
if (s[i] != '\0')
return (ERROR);
value = me_atoi_64(s);
if (value > INT_MAX || value < INT_MIN)
return (ERROR);
out.value = value;
*e = out;
return (NO_ERROR);
}
void check_eq(t_usize i, t_element *rhs, t_dup_state *dup_state)
{
dup_state->found_dup =
dup_state->found_dup ||
(i != dup_state->index_to_skip && rhs->value == dup_state->lhs->value);
}
void check_no_duplicate(t_vec_element *stack, t_vec_element *to_free_in_need)
{
t_usize i;
t_dup_state s;
i = 0;
while (i < stack->len)
{
s = (t_dup_state){
.lhs = &stack->buffer[i],
.index_to_skip = i,
.found_dup = false,
};
vec_element_iter(stack, (void (*)())check_eq, &s);
if (s.found_dup)
return (me_eprintf("Error:\nDuplicate numbers (%i)\n",
stack->buffer[i]),
vec_element_free(*stack),
vec_element_free(*to_free_in_need), exit(1));
i++;
}
}
t_state parses_arguments(t_usize count, t_str nums[])
{
t_state out;
t_usize i;
t_element e;
i = 0;
out.stack_a = vec_element_new(count * 2, free_element);
out.stack_b = vec_element_new(count * 2, free_element);
while (i < count)
{
if (parse_element(nums[i], &e))
(me_eprintf("Error:\nArgument '%s' isn't a valid number for this "
"program!\n",
nums[i]),
vec_element_free(out.stack_a), vec_element_free(out.stack_b),
exit(1));
vec_element_push(&out.stack_b, e);
i++;
}
while (!vec_element_pop(&out.stack_b, &e))
vec_element_push(&out.stack_a, e);
check_no_duplicate(&out.stack_a, &out.stack_b);
return out;
}
#define LEFT(str, w) \
({ \
int m = w + strlen(str); \
m % 2 ? (m + 1) / 2 : m / 2; \
})
#define RIGHT(str, w) \
({ \
int m = w - strlen(str); \
m % 2 ? (m - 1) / 2 : m / 2; \
})
#define STR_CENTER(str, width) LEFT(str, width), str, RIGHT(str, width), ""
#define STACK_WIDTH 12
void print_state(t_state *s)
{
t_usize max_len;
if (s->stack_a.len > s->stack_b.len)
max_len = s->stack_a.len;
else
max_len = s->stack_b.len;
printf("|%*s%*s|%*s%*s|\n", STR_CENTER("Stack A", STACK_WIDTH),
STR_CENTER("Stack B", STACK_WIDTH));
for (t_usize i = 0; i < max_len; i++)
{
t_str s_a;
t_str s_b;
if (i < s->stack_a.len)
s_a = me_itoa(s->stack_a.buffer[s->stack_a.len - i - 1].value);
else
s_a = str_clone("");
if (i < s->stack_b.len)
s_b = me_itoa(s->stack_b.buffer[s->stack_b.len - i - 1].value);
else
s_b = str_clone("");
printf("|%*s%*s|%*s%*s|\n", STR_CENTER(s_a, STACK_WIDTH),
STR_CENTER(s_b, STACK_WIDTH));
free(s_a);
free(s_b);
}
printf("\n");
}
int main(t_i32 argc, t_str argv[])
{
t_state state;
t_vec_i64 o;
state = parses_arguments(--argc, ++argv);
print_state(&state);
o = lis(&state.stack_a);
printf("len = %zu", o.len);
for (t_usize i = 0; i < o.len; i++)
printf("%zi\n", (t_isize)o.buffer[i]);
printf("\n");
free_state(state);
vec_i64_free(o);
return (0);
}

44
src/app/moves.c Normal file
View file

@ -0,0 +1,44 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* moves.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 16:17:26 by maiboyer #+# #+# */
/* Updated: 2024/01/11 16:31:56 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/moves.h"
#include "app/element.h"
#include "app/state.h"
void push_a(t_state *s);
void push_b(t_state *s);
void swap_a(t_state *s);
void swap_b(t_state *s);
void rotate_a(t_state *s);
void rotate_b(t_state *s);
void rev_rotate_a(t_state *s);
void rev_rotate_b(t_state *s);
void do_move(t_move m, t_state *s)
{
if (m & PUSH_A)
push_a(s);
if (m & PUSH_B)
push_b(s);
if (m & SWAP_A)
swap_a(s);
if (m & SWAP_B)
swap_b(s);
if (m & ROTATE_A)
rotate_a(s);
if (m & ROTATE_B)
rotate_b(s);
if (m & REVERSE_ROTATE_A)
rev_rotate_a(s);
if (m & REVERSE_ROTATE_B)
rev_rotate_b(s);
}

37
src/app/moves/push.c Normal file
View file

@ -0,0 +1,37 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* push.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 16:22:54 by maiboyer #+# #+# */
/* Updated: 2024/01/11 17:17:45 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/element.h"
#include "app/state.h"
#include "me/vec/vec_element.h"
static inline void push_inner(t_vec_element *to, t_vec_element *from,
t_const_str tag)
{
t_element e;
(void)(tag);
if (from->len == 0)
return;
vec_element_pop(from, &e);
vec_element_push(to, e);
}
void push_a(t_state *s)
{
push_inner(&s->stack_a, &s->stack_b, "Push A");
}
void push_b(t_state *s)
{
push_inner(&s->stack_b, &s->stack_a, "Push B");
}

View file

@ -0,0 +1,35 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* rev_rotate.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 16:26:04 by maiboyer #+# #+# */
/* Updated: 2024/01/11 17:31:44 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/element.h"
#include "app/state.h"
static inline void rev_rotate_inner(t_vec_element *stack, t_const_str tag)
{
t_element e;
(void)(tag);
if (stack->len <= 1)
return;
vec_element_pop(stack, &e);
vec_element_push_front(stack, e);
}
void rev_rotate_a(t_state *s)
{
rev_rotate_inner(&s->stack_a, "RevRotate A");
}
void rev_rotate_b(t_state *s)
{
rev_rotate_inner(&s->stack_b, "RevRotate B");
}

36
src/app/moves/rotate.c Normal file
View file

@ -0,0 +1,36 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* rotate.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 16:26:04 by maiboyer #+# #+# */
/* Updated: 2024/01/11 17:31:20 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/element.h"
#include "app/state.h"
static inline void rotate_inner(t_vec_element *stack, t_const_str tag)
{
t_element e;
(void)(tag);
if (stack->len <= 1)
return;
vec_element_pop(stack, &e);
vec_element_push_front(stack, e);
}
void rotate_a(t_state *s)
{
rotate_inner(&s->stack_a, "Rotate A");
}
void rotate_b(t_state *s)
{
rotate_inner(&s->stack_b, "Rotate B");
}

39
src/app/moves/swap.c Normal file
View file

@ -0,0 +1,39 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* swap.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 16:26:04 by maiboyer #+# #+# */
/* Updated: 2024/01/11 17:56:12 by maiboyer ### ########.fr */
/* */
/* ************************************************************************** */
#include "app/element.h"
#include "app/state.h"
#include "me/vec/vec_element.h"
static inline void swap_inner(t_vec_element *stack, t_const_str tag)
{
t_element first;
t_element second;
(void)(tag);
if (stack->len <= 1)
return;
vec_element_pop(stack, &first);
vec_element_pop(stack, &second);
vec_element_push(stack, first);
vec_element_push(stack, second);
}
void swap_a(t_state *s)
{
swap_inner(&s->stack_a, "Swap A");
}
void swap_b(t_state *s)
{
swap_inner(&s->stack_b, "Swap B");
}