diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..6b13f20 --- /dev/null +++ b/.clang-format @@ -0,0 +1,9 @@ +BasedOnStyle: Microsoft +IndentWidth: 4 +ColumnLimit: 80 +UseTab: Always +SortIncludes: CaseInsensitive +IndentPPDirectives: AfterHash +PPIndentWidth: 1 +AllowShortIfStatementsOnASingleLine: false +AlignConsecutiveDeclarations: true diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..1c222e6 --- /dev/null +++ b/.clangd @@ -0,0 +1,16 @@ +CompileFlags: # Tweak the parse settings + Add: + - "-I/usr/include/" + - "-I/home/maix/school/push_swap/mecstd/include/" + - "-I/home/maix/school/push_swap/mecstd/output/include/" + - "-I/home/maix/school/push_swap/mecstd/generic_sources/header/" + - "-I/home/maix/school/push_swap/include/" + - "-I/home/maix/school/push_swap/output/include/" + - "-I/home/maix/school/push_swap/generic_sources/header/" + - "-I/home/maiboyer/Documents/ring-1/push_swap/mecstd/include/" + - "-I/home/maiboyer/Documents/ring-1/push_swap/mecstd/output/include/" + - "-I/home/maiboyer/Documents/ring-1/push_swap/mecstd/generic_sources/header/" + - "-I/home/maiboyer/Documents/ring-1/push_swap/include/" + - "-I/home/maiboyer/Documents/ring-1/push_swap/output/include/" + - "-I/home/maiboyer/Documents/ring-1/push_swap/generic_sources/header/" + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ce2fd6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +./generic +.direnv +test +output/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..92ca1ba --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "mecstd"] + path = mecstd + url = git@github.com:Maix0/mecstd.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..780fe88 --- /dev/null +++ b/Makefile @@ -0,0 +1,135 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: maiboyer +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2023/11/03 13:20:01 by maiboyer #+# #+# # +# Updated: 2024/01/11 14:14:03 by maiboyer ### ########.fr # +# # +# **************************************************************************** # + +define_module = $(addprefix $(1)/, $(2)) + +BUILD_DIR = build +SRC_DIR = src +INCLUDE_DIR = include +LIBS_DIR = . +GENERIC_DIR = output/src +GENERIC_INCLUDE = output/include + +ifeq ($(MAKECMDGOALS), bonus) + CFLAGS += -DBONUS + BUILD_DIR := $(BUILD_DIR)/bonus/ +endif + +NAME = push_swap +LIB_NAME ?= +TARGET = $(NAME) +CC = clang +CFLAGS += -Wall -Wextra -Werror -g2 -lme -L$(BUILD_DIR) -Wno-unused-command-line-argument -MMD +BONUS_FILES = +LIBS_NAME = mecstd +SUBJECT_URL = 'https://cdn.intra.42.fr/pdf/pdf/118610/en.subject.pdf' + +GENERIC_FILES = $(shell cat ./gen.list) +SRC_FILES = $(shell cat ./src.list) +BONUS = $(addsuffix .c,$(addprefix $(SRC_DIR)/,$(BONUS_FILES))) +SRC = $(addsuffix .c,$(addprefix $(SRC_DIR)/,$(SRC_FILES))) \ + $(addsuffix .c,$(addprefix $(GENERIC_DIR)/,$(GENERIC_FILES))) +BONUS_OBJ = $(addsuffix .o,$(addprefix $(BUILD_DIR)/,$(BONUS_FILES))) +OBJ = $(addsuffix .o,$(addprefix $(BUILD_DIR)/,$(SRC_FILES))) \ + $(addsuffix .o,$(addprefix $(BUILD_DIR)/,$(GENERIC_FILES))) +DEPS = $(addsuffix .d,$(addprefix $(BUILD_DIR)/,$(SRC_FILES))) \ + $(addsuffix .d,$(addprefix $(BUILD_DIR)/,$(GENERIC_FILES))) +LIBS = $(addprefix $(LIBS_DIR)/,$(LIBS_NAME)) +INCLUDES = $(addprefix -I,$(INCLUDE_DIR) $(GENERIC_INCLUDE) $(LIBS) $(addsuffix /include,$(LIBS))) +COL_GRAY = \\e[90m +COL_WHITE = \\e[37m +COL_GREEN = \\e[32m +COL_BOLD = \\e[1m +COL_RESET = \\e[0m + + +.PHONY: remove_name clean all fclean bonus format re generate_filelist subject get_lib + +all: $(NAME) + +bonus: all + @printf \\n$(COL_GRAY)Building\ Output\ \(with\ bonus\)\ $(COL_WHITE)$(COL_BOLD)%-28s$(COL_RESET)\ \ + $(NAME) + @printf $(COL_RESET)$(COL_GREEN)done$(COL_RESET)\\n + +get_lib: + @printf $(LIB_NAME)/$(NAME) + +$(NAME): $(OBJ) libs_build + @printf \\n$(COL_GRAY)Building\ Output\ $(COL_WHITE)$(COL_BOLD)%-28s$(COL_RESET)\ \ + $(NAME) + @$(CC) $(INCLUDES) $(OBJ) $(CFLAGS) -o $(NAME) + @#ar rcs $(BUILD_DIR)/$(NAME) $(OBJ) + @printf $(COL_GREEN)done$(COL_RESET)\\n + +libs_build: + @- $(foreach LIB,$(LIBS),\ + printf \\n; \ + printf $(COL_GRAY)Building\ library\ $(COL_RESET); \ + printf $(COL_WHITE)$(COL_BOLD)%-25s$(COL_RESET)\\n $(LIB); \ + make LIB_NAME=$(LIB)/ BUILD_DIR=$(realpath $(BUILD_DIR)) -C $(LIB) --no-print-directory all; \ + printf \\n; \ + ) + +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c + @mkdir -p $(dir $@) + @printf $(COL_GRAY)Building\ $(COL_BOLD)$(COL_WHITE)%-50s\ $(LIB_NAME)$< + @$(CC) $(CFLAGS) $(WERROR) $(INCLUDES) -c $< -o $@ + @printf $(COL_RESET)$(COL_GREEN)done$(COL_RESET)\\n + +$(BUILD_DIR)/%.o: $(GENERIC_DIR)/%.c + @mkdir -p $(dir $@) + @printf $(COL_GRAY)Building\ $(COL_BOLD)$(COL_WHITE)%-50s\ $(LIB_NAME)$< + @$(CC) $(CFLAGS) $(WERROR) $(INCLUDES) -c $< -o $@ + @printf $(COL_RESET)$(COL_GREEN)done$(COL_RESET)\\n + +clean: + @- $(foreach LIB,$(LIBS), \ + make clean LIB_NAME=$(LIB)/ BUILD_DIR=$(realpath $(BUILD_DIR)) -C $(LIB) --no-print-directory || true;\ + ) + @- $(if $(LIB_NAME),,\ + printf $(COL_WHITE)Clearing\ Artefacts\ ; \ + printf $(COL_GRAY)\%-25s$(COL_RESET)\ \($(BUILD_DIR)\); \ + rm -rf $(BUILD_DIR); \ + printf $(COL_GREEN)done$(COL_RESET)\\n; \ + ) + @echo >/dev/null + +fclean: clean + @- $(foreach LIB,$(LIBS), \ + make fclean LIB_NAME=$(LIB)/ BUILD_DIR=$(realpath $(BUILD_DIR)) -C $(LIB) --no-print-directory || true;\ + ) + @printf $(COL_WHITE)Clearing\ Output\ $(COL_GRAY)%-28s$(COL_RESET)\ \ + \($(LIB_NAME)$(NAME)\) + @rm -f $(BUILD_DIR)$(NAME) + @printf $(COL_GREEN)done$(COL_RESET)\\n + +re: fclean all + +generate_filelist: + @/usr/bin/env zsh -c "tree -iFf --noreport output | rg '^output/src/(.*)\.c\$$' --replace '\$$1' | sort -u" > ./gen.list + @/usr/bin/env zsh -c "tree -iFf --noreport src | rg '^src/(.*)\.c\$$' --replace '\$$1' | sort -u" > ./src.list + +format: + @zsh -c "c_formatter_42 **/*.c **/*.h" + +subject: subject.txt + @bat --plain subject.txt + +subject.txt: + @curl $(SUBJECT_URL) | pdftotext -layout -nopgbrk - subject.txt + +fuck_raphael: + @echo "Oh que oui~~~\net jte nioc" + +-include $(DEPS) + diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..24419ec --- /dev/null +++ b/flake.nix @@ -0,0 +1,39 @@ +{ + description = "Flake utils demo"; + + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + generic_c.url = "github:maix0/generic_c"; + c_formatter_42.url = "github:maix0/c_formatter_42-flake"; + }; + outputs = { + self, + nixpkgs, + flake-utils, + generic_c, + c_formatter_42, + }: + flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShell = pkgs.mkShell { + packages = [ + pkgs.xorg.libXext + pkgs.xorg.libX11 + pkgs.clang + pkgs.clang-tools + pkgs.norminette + generic_c.packages.${system}.default + c_formatter_42.packages.${system}.default + pkgs.poppler_utils + pkgs.minilibx + pkgs.valgrind + pkgs.libbsd + pkgs.tree + pkgs.fastmod + ]; + }; + } + ); +} diff --git a/gen.list b/gen.list new file mode 100644 index 0000000..7728ddd --- /dev/null +++ b/gen.list @@ -0,0 +1,6 @@ +vec/vec_element +vec/vec_element_functions2 +vec/vec_element_functions3 +vec/vec_i64 +vec/vec_i64_functions2 +vec/vec_i64_functions3 diff --git a/include/app/dup_state.h b/include/app/dup_state.h new file mode 100644 index 0000000..69abfeb --- /dev/null +++ b/include/app/dup_state.h @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* dup_state.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 15:58:29 by maiboyer #+# #+# */ +/* Updated: 2024/01/11 15:59:29 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef DUP_STATE_H +#define DUP_STATE_H + +#include "app/element.h" +#include "me/types.h" + +typedef struct s_dup_state +{ + t_element *lhs; + t_usize index_to_skip; + bool found_dup; +} t_dup_state; + +#endif /* DUP_STATE_H */ diff --git a/include/app/element.h b/include/app/element.h new file mode 100644 index 0000000..74d625f --- /dev/null +++ b/include/app/element.h @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* element.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 14:28:41 by maiboyer #+# #+# */ +/* Updated: 2024/01/11 14:34:27 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef ELEMENT_H +#define ELEMENT_H + +#include "me/types.h" + +typedef struct s_element +{ + t_i64 value; +} t_element; + +void free_element(t_element elem); + +#endif /* ELEMENT_H */ diff --git a/include/app/lis.h b/include/app/lis.h new file mode 100644 index 0000000..c1f757b --- /dev/null +++ b/include/app/lis.h @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* lis.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 19:03:30 by maiboyer #+# #+# */ +/* Updated: 2024/01/11 20:50:43 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef LIS_H +#define LIS_H + +#include "me/types.h" +#include "me/vec/vec_element.h" +#include "me/vec/vec_i64.h" + +t_vec_i64 lis(t_vec_element *elements); + +#endif /* LIS_H */ diff --git a/include/app/moves.h b/include/app/moves.h new file mode 100644 index 0000000..677abe7 --- /dev/null +++ b/include/app/moves.h @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* moves.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 16:13:08 by maiboyer #+# #+# */ +/* Updated: 2024/01/11 16:18:49 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MOVES_H +#define MOVES_H + +#include "app/element.h" +#include "app/state.h" +#include "me/types.h" + +typedef enum e_move +{ + SWAP_A = 1 << 0, + SWAP_B = 1 << 1, + SWAP_BOTH = SWAP_A | SWAP_B, + PUSH_A = 1 << 2, + PUSH_B = 1 << 3, + ROTATE_A = 1 << 4, + ROTATE_B = 1 << 5, + ROTATE_BOTH = ROTATE_A | ROTATE_B, + REVERSE_ROTATE_A = 1 << 6, + REVERSE_ROTATE_B = 1 << 7, + REVERSE_ROTATE_BOTH = REVERSE_ROTATE_A | REVERSE_ROTATE_B, +} t_move; + +void do_move(t_move m, t_state *s); + +#endif /* MOVES_H */ diff --git a/include/app/state.h b/include/app/state.h new file mode 100644 index 0000000..15d0529 --- /dev/null +++ b/include/app/state.h @@ -0,0 +1,28 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* state.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 14:27:25 by maiboyer #+# #+# */ +/* Updated: 2024/01/11 14:36:28 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef STATE_H +#define STATE_H + +#include "me/types.h" +#include "me/vec/vec_element.h" + +typedef struct s_state +{ + t_vec_element stack_a; + t_vec_element stack_b; +} t_state; + +t_state parses_arguments(t_usize count, t_str nums[]); +void free_state(t_state state); + +#endif /* STATE_H */ diff --git a/input.toml b/input.toml new file mode 100644 index 0000000..9371862 --- /dev/null +++ b/input.toml @@ -0,0 +1,40 @@ +[definition.vec] +headers = ["mecstd/generic_sources/header/vec_C__PREFIX__.h__TEMPLATE__"] +sources = [ + "mecstd/generic_sources/src/vec_C__PREFIX__.c__TEMPLATE__", + "mecstd/generic_sources/src/vec_C__PREFIX___functions2.c__TEMPLATE__", + "mecstd/generic_sources/src/vec_C__PREFIX___functions3.c__TEMPLATE__", +] +replace.C__TYPENAME__ = "type" +replace.C__TYPEHEADER__ = "header_include" +replace.C__PREFIX__ = "prefix" +replace.C__PREFIXUP__ = "prefix" + + +[definition.hashmap] +headers = ["mecstd/generic_sources/header/hashmap_C__PREFIX__.h__TEMPLATE__"] +sources = [ + "mecstd/generic_sources/src/hashmap_C__PREFIX__.c__TEMPLATE__", + "mecstd/generic_sources/src/hashmap_C__PREFIX___utils.c__TEMPLATE__", +] +replace.C__VALTYPE__ = "type" +replace.C__KEYTYPE__ = "type" +replace.C__TYPEHEADER__ = "header_include" +replace.C__PREFIX__ = "prefix" +replace.C__PREFIXUP__ = "prefix" + +[[create.vec]] +sources_output = "src/vec/" +headers_output = "include/me/vec/" +replace.C__TYPENAME__ = "t_element" +replace.C__TYPEHEADER__ = '#include "app/element.h"' +replace.C__PREFIX__ = "element" +replace.C__PREFIXUP__ = "ELEMENT" + +[[create.vec]] +sources_output = "src/vec/" +headers_output = "include/me/vec/" +replace.C__TYPENAME__ = "t_i64" +replace.C__TYPEHEADER__ = '' +replace.C__PREFIX__ = "i64" +replace.C__PREFIXUP__ = "I64" diff --git a/mecstd b/mecstd new file mode 160000 index 0000000..f9c81ca --- /dev/null +++ b/mecstd @@ -0,0 +1 @@ +Subproject commit f9c81caf38361c927fa81f72a1e832bbb619e161 diff --git a/push_swap b/push_swap new file mode 100755 index 0000000..865eaa5 Binary files /dev/null and b/push_swap differ diff --git a/src.list b/src.list new file mode 100644 index 0000000..1fef610 --- /dev/null +++ b/src.list @@ -0,0 +1,8 @@ +app/lis/lis +app/lis/lower_bound +app/main +app/moves +app/moves/push +app/moves/rev_rotate +app/moves/rotate +app/moves/swap diff --git a/src/app/lis/lis.c b/src/app/lis/lis.c new file mode 100644 index 0000000..b8e85b3 --- /dev/null +++ b/src/app/lis/lis.c @@ -0,0 +1,231 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* lis.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +/* +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 I>(items: &[T], selector: F) -> Vec { + // 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); +} diff --git a/src/app/lis/lower_bound.c b/src/app/lis/lower_bound.c new file mode 100644 index 0000000..79bceeb --- /dev/null +++ b/src/app/lis/lower_bound.c @@ -0,0 +1,11 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* lower_bound.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/11 18:17:23 by maiboyer #+# #+# */ +/* Updated: 2024/01/11 19:17:19 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ diff --git a/src/app/main.c b/src/app/main.c new file mode 100644 index 0000000..755a321 --- /dev/null +++ b/src/app/main.c @@ -0,0 +1,180 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 +#include +#include +#include +#include + +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); +} diff --git a/src/app/moves.c b/src/app/moves.c new file mode 100644 index 0000000..a24428c --- /dev/null +++ b/src/app/moves.c @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* moves.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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); +} diff --git a/src/app/moves/push.c b/src/app/moves/push.c new file mode 100644 index 0000000..26379bf --- /dev/null +++ b/src/app/moves/push.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* push.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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"); +} diff --git a/src/app/moves/rev_rotate.c b/src/app/moves/rev_rotate.c new file mode 100644 index 0000000..7344e6c --- /dev/null +++ b/src/app/moves/rev_rotate.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* rev_rotate.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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"); +} diff --git a/src/app/moves/rotate.c b/src/app/moves/rotate.c new file mode 100644 index 0000000..6a78f8f --- /dev/null +++ b/src/app/moves/rotate.c @@ -0,0 +1,36 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* rotate.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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"); +} diff --git a/src/app/moves/swap.c b/src/app/moves/swap.c new file mode 100644 index 0000000..62a316d --- /dev/null +++ b/src/app/moves/swap.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* swap.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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"); +} diff --git a/subject.txt b/subject.txt new file mode 100644 index 0000000..83b2e90 --- /dev/null +++ b/subject.txt @@ -0,0 +1,556 @@ + Push_swap + Because Swap_push isn’t as natural + + + + + Summary: +This project will make you sort data on a stack, with a limited set of instructions, using + the lowest possible number of actions. To succeed you’ll have to manipulate various + types of algorithms and choose the most appropriate solution (out of many) for an + optimized data sorting. + + Version: 7 +Contents +I Foreword 2 + +II Introduction 4 + +III Objectives 5 + +IV Common Instructions 6 + +V Mandatory part 8 + V.1 The rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 + V.2 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 + V.3 The "push_swap" program . . . . . . . . . . . . . . . . . . . . . . . . 10 + +VI Bonus part 12 + VI.1 The "checker" program . . . . . . . . . . . . . . . . . . . . . . . . . . 12 + +VII Submission and peer-evaluation 14 + + + + + 1 +Chapter I + +Foreword + + • C + #include + + int main(void) + { + printf("hello, world\n"); + return 0; + } + + + + • ASM + cseg segment + assume cs:cseg, ds:cseg + org 100h + main proc + jmp debut + mess db 'Hello world!$' + debut: + mov dx, offset mess + mov ah, 9 + int 21h + ret + main endp + cseg ends + end main + + + + • LOLCODE + HAI + CAN HAS STDIO? + VISIBLE "HELLO WORLD!" + KTHXBYE + + + + • PHP + + + + + • BrainFuck + ++++++++++[>+++++++>++++++++++>+++>+<<<<-] + >++.>+.+++++++..+++.>++. + <<+++++++++++++++.>.+++.------.--------.>+.>. + + + + + 2 +Push_swap Because Swap_push isn’t as natural + + + • C# + using System; + + public class HelloWorld { + public static void Main () { + Console.WriteLine("Hello world!"); + } + } + + + + • HTML5 + + + + + Hello world ! + + +

Hello World !

+ + + + + + • YASL + "Hello world!" + print + + + + • OCaml + let main () = + print_endline "Hello world !" + + let _ = main () + + + + + 3 +Chapter II + +Introduction + +The Push swap project is a very simple and a highly straightforward algorithm project: +data must be sorted. + + You have at your disposal a set of integer values, 2 stacks, and a set of instructions +to manipulate both stacks. + + Your goal? Write a program in C called push_swap which calculates and displays +on the standard output the smallest program, made of Push swap language instructions, +that sorts the integers received as arguments. + + Easy? + + We’ll see... + + + + + 4 +Chapter III + +Objectives + +Writing a sorting algorithm is always a very important step in a developer’s journey. It +is often the first encounter with the concept of complexity. + + Sorting algorithms and their complexity are part of the classic questions discussed +during job interviews. It’s probably a good time to look at these concepts since you’ll +have to face them at some point. + + The learning objectives of this project are rigor, use of C, and use of basic algorithms. +Especially focusing on their complexity. + + Sorting values is simple. To sort them the fastest way possible is less simple. Especially +because from one integers configuration to another, the most efficient sorting solution can +differ. + + + + + 5 +Chapter IV + +Common Instructions + + • Your project must be written in C. + + • Your project must be written in accordance with the Norm. If you have bonus + files/functions, they are included in the norm check and you will receive a 0 if there + is a norm error inside. + + • Your functions should not quit unexpectedly (segmentation fault, bus error, double + free, etc) apart from undefined behaviors. If this happens, your project will be + considered non functional and will receive a 0 during the evaluation. + + • All heap allocated memory space must be properly freed when necessary. No leaks + will be tolerated. + + • If the subject requires it, you must submit a Makefile which will compile your + source files to the required output with the flags -Wall, -Wextra and -Werror, use + cc, and your Makefile must not relink. + + • Your Makefile must at least contain the rules $(NAME), all, clean, fclean and + re. + + • To turn in bonuses to your project, you must include a rule bonus to your Makefile, + which will add all the various headers, librairies or functions that are forbidden on + the main part of the project. Bonuses must be in a different file _bonus.{c/h} if + the subject does not specify anything else. Mandatory and bonus part evaluation + is done separately. + + • If your project allows you to use your libft, you must copy its sources and its + associated Makefile in a libft folder with its associated Makefile. Your project’s + Makefile must compile the library by using its Makefile, then compile the project. + + • We encourage you to create test programs for your project even though this work + won’t have to be submitted and won’t be graded. It will give you a chance + to easily test your work and your peers’ work. You will find those tests especially + useful during your defence. Indeed, during defence, you are free to use your tests + and/or the tests of the peer you are evaluating. + + • Submit your work to your assigned git repository. Only the work in the git reposi- + tory will be graded. If Deepthought is assigned to grade your work, it will be done + + + 6 +Push_swap Because Swap_push isn’t as natural + + + after your peer-evaluations. If an error happens in any section of your work during + Deepthought’s grading, the evaluation will stop. + + + + + 7 +Chapter V + +Mandatory part + +V.1 The rules + • You have 2 stacks named a and b. + • At the beginning: + + ◦ The stack a contains a random amount of negative and/or positive numbers + which cannot be duplicated. + ◦ The stack b is empty. + + • The goal is to sort in ascending order numbers into stack a. To do so you have the + following operations at your disposal: + + sa (swap a): Swap the first 2 elements at the top of stack a. + Do nothing if there is only one or no elements. + sb (swap b): Swap the first 2 elements at the top of stack b. + Do nothing if there is only one or no elements. + ss : sa and sb at the same time. + pa (push a): Take the first element at the top of b and put it at the top of a. + Do nothing if b is empty. + pb (push b): Take the first element at the top of a and put it at the top of b. + Do nothing if a is empty. + ra (rotate a): Shift up all elements of stack a by 1. + The first element becomes the last one. + rb (rotate b): Shift up all elements of stack b by 1. + The first element becomes the last one. + rr : ra and rb at the same time. + rra (reverse rotate a): Shift down all elements of stack a by 1. + The last element becomes the first one. + rrb (reverse rotate b): Shift down all elements of stack b by 1. + The last element becomes the first one. + rrr : rra and rrb at the same time. + + + 8 +Push_swap Because Swap_push isn’t as natural + + +V.2 Example +To illustrate the effect of some of these instructions, let’s sort a random list of integers. +In this example, we’ll consider that both stacks grow from the right. + +---------------------------------------------------------------------------------------------------------- +Init a and b: +2 +1 +3 +6 +5 +8 +_ _ +a b +---------------------------------------------------------------------------------------------------------- +Exec sa: +1 +2 +3 +6 +5 +8 +_ _ +a b +---------------------------------------------------------------------------------------------------------- +Exec pb pb pb: +6 3 +5 2 +8 1 +_ _ +a b +---------------------------------------------------------------------------------------------------------- +Exec ra rb (equiv. to rr): +5 2 +8 1 +6 3 +_ _ +a b +---------------------------------------------------------------------------------------------------------- +Exec rra rrb (equiv. to rrr): +6 3 +5 2 +8 1 +_ _ +a b +---------------------------------------------------------------------------------------------------------- +Exec sa: +5 3 +6 2 +8 1 +_ _ +a b +---------------------------------------------------------------------------------------------------------- +Exec pa pa pa: +1 +2 +3 +5 +6 +8 +_ _ +a b +---------------------------------------------------------------------------------------------------------- + + Integers from a get sorted in 12 instructions. Can you do better? + + + + + 9 +Push_swap Because Swap_push isn’t as natural + + +V.3 The "push_swap" program + + Program name push_swap + Turn in files Makefile, *.h, *.c + Makefile NAME, all, clean, fclean, re + Arguments stack a: A list of integers + External functs. + + • read, write, malloc, free, + exit + • ft_printf and any equivalent + YOU coded + + Libft authorized Yes + Description Sort stacks + + + + Your project must comply with the following rules: + + • You have to turn in a Makefile which will compile your source files. It must not + relink. + + • Global variables are forbidden. + + • You have to write a program named push_swap that takes as an argument the stack + a formatted as a list of integers. The first argument should be at the top of the + stack (be careful about the order). + + • The program must display the smallest list of instructions possible to sort the stack + a, the smallest number being at the top. + + • Instructions must be separated by a ’\n’ and nothing else. + + • The goal is to sort the stack with the lowest possible number of operations. During + the evaluation process, the number of instructions found by your program will be + compared against a limit: the maximum number of operations tolerated. If your + program either displays a longer list or if the numbers aren’t sorted properly, your + grade will be 0. + + • If no parameters are specified, the program must not display anything and give the + prompt back. + + • In case of error, it must display "Error" followed by a ’\n’ on the standard error. + Errors include for example: some arguments aren’t integers, some arguments are + bigger than an integer and/or there are duplicates. + + + + + 10 +Push_swap Because Swap_push isn’t as natural + + +$>./push_swap 2 1 3 6 5 8 +sa +pb +pb +pb +sa +pa +pa +pa +$>./push_swap 0 one 2 3 +Error +$> + + + + During the evaluation process, a binary will be provided in order to properly check +your program. + + It will work as follows: + +$>ARG="4 67 3 87 23"; ./push_swap $ARG | wc -l + 6 +$>ARG="4 67 3 87 23"; ./push_swap $ARG | ./checker_OS $ARG +OK +$> + + + + If the program checker_OS displays "KO", it means that your push_swap came up +with a list of instructions that doesn’t sort the numbers. + + + The checker_OS program is available in the resources of the project + in the intranet. + You can find a description of how it works in the Bonus Part of this + document. + + + + + 11 +Chapter VI + +Bonus part + +This project leaves little room for adding extra features due to its simplicity. However, +how about creating your own checker? + + + Thanks to the checker program, you will be able to check whether + the list of instructions generated by the push_swap program actually + sorts the stack properly. + + + + +VI.1 The "checker" program + + Program name checker + Turn in files *.h, *.c + Makefile bonus + Arguments stack a: A list of integers + External functs. + + • read, write, malloc, free, + exit + • ft_printf and any equivalent + YOU coded + + Libft authorized Yes + Description Execute the sorting instructions + + • Write a program named checker that takes as an argument the stack a formatted + as a list of integers. The first argument should be at the top of the stack (be careful + about the order). If no argument is given, it stops and displays nothing. + • It will then wait and read instructions on the standard input, each instruction will + be followed by ’\n’. Once all the instructions have been read, the program has to + execute them on the stack received as an argument. + + 12 +Push_swap Because Swap_push isn’t as natural + + + • If after executing those instructions, the stack a is actually sorted and the stack b + is empty, then the program must display "OK" followed by a ’\n’ on the standard + output. + + • In every other case, it must display "KO" followed by a ’\n’ on the standard output. + + • In case of error, you must display "Error" followed by a ’\n’ on the standard er- + ror. Errors include for example: some arguments are not integers, some arguments + are bigger than an integer, there are duplicates, an instruction doesn’t exist and/or + is incorrectly formatted. + + +$>./checker 3 2 1 0 +rra +pb +sa +rra +pa +OK +$>./checker 3 2 1 0 +sa +rra +pb +KO +$>./checker 3 2 one 0 +Error +$>./checker "" 1 +Error +$> + + + + + You DO NOT have to reproduce the exact same behavior as the provided + binary. It is mandatory to manage errors but it is up to you to + decide how you want to parse the arguments. + + + + + The bonus part will only be assessed if the mandatory part is + PERFECT. Perfect means the mandatory part has been integrally done + and works without malfunctioning. If you have not passed ALL the + mandatory requirements, your bonus part will not be evaluated at all. + + + + + 13 +Chapter VII + +Submission and peer-evaluation + +Turn in your assignment in your Git repository as usual. Only the work inside your repos- +itory will be evaluated during the defense. Don’t hesitate to double check the names of +your files to ensure they are correct. + + As these assignments are not verified by a program, feel free to organize your files as +you wish, as long as you turn in the mandatory files and comply with the requirements. + + + + + file.bfe:VABB7yO9xm7xWXROeASsmsgnY0o0sDMJev7zFHhwQS8mvM8V5xQQp + Lc6cDCFXDWTiFzZ2H9skYkiJ/DpQtnM/uZ0 + + + + + 14