cs-2124: finish assignment 4

This commit is contained in:
Price Hiller 2024-04-08 23:13:51 -05:00
parent 31f2d077ca
commit d908cb2532
Signed by: Price
GPG Key ID: C3FADDE7A8534BEB
12 changed files with 753 additions and 0 deletions

View File

@ -0,0 +1,225 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: false
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
PPIndentWidth: -1
QualifierAlignment: Leave
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
...

View File

@ -0,0 +1,8 @@
bin
CMakeFiles
Makefile
CMakeCache.txt
cmake_install.cmake
README.pdf
*.tex
.tex-out

Binary file not shown.

View File

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.25)
set(SOURCES src/lib/vec.h src/lib/lib.h src/lib/lib.c)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
project(AssignmentFour LANGUAGES C)
add_executable(AvlTree src/avl_tree.c ${SOURCES})
add_executable(HuffHeap src/huffman_heap.c ${SOURCES})

View File

@ -0,0 +1,58 @@
* Assignment 4
- ABC123: =zfp106=
- Name: =Price Hiller=
- Course: =CS2124=
- Section: =0C3=
- Semester: =Spring 2024=
** Source Code
The full source code for this project can be found at
[[https://git.orion-technologies.io/Price/college/src/branch/Development/Spring-2023/CS-2124/Assignment-4]]
** Running the Programs
1. Install [[https://cmake.org/download/][cmake]] version 3.25 or greater.
2. Ensure you have a recent version of ~make~ at the time of writing. This project successfully
compiles with ~GNU make~ version ~4.4.1~.
3. Go the directory with ~CMakeLists.txt~ and run ~cmake .~ to generate a Makefile.
4. Run ~make all~ to compile all the programs.
5. Go into the newly created ~bin~ directory where all the compiled programs will be output to
6. Programs will be named ~PartOne~, ~PartTwo~, and ~PartThree~
** Questions/Prompts with Answers
*** Part One: Avl Tree (3 points)
- Prompt
- Write a program that will have pre-defined input as numbers (~1,2,3,4,5~)
- Then the program will create a BST of the input and print that out
- Then the program will balance the BST and print out the AVL tree (pre-order)
_Steps_:
- Create BST (0.5 points)
- Balance the tree (0.5 points)
_Output_:
- Print BST Pre-order (1 point)
- Print Balanced-AVL Pre-order (1 point)
- Output
[[./assets/PartOne/img1.png]]
*** Part Two: Building Huffman Tree using Heap (2 Points)
- Prompt
- Write code to generate a Huffman Encoding (Variable Bit) using Heap.
- The characters and their frequency can be seen in the output screen shot and in the Tables 1 & 2
- Despite the different variable bit coding (i.e. Table 1 & Table 2) the total bits are the same
- Include the Table for Total Bits in your PDF file with the output screenshot
- Output
- Table of total bits:
| Char | Code | Freq | Bits = Code * Freq |
|------------|------|------|--------------------|
| a | 100 | 5 | 15 |
| b | 101 | 9 | 27 |
| c | 00 | 12 | 24 |
| d | 01 | 13 | 26 |
| e | 11 | 16 | 32 |
|------------|------|------|--------------------|
| Total Bits | | | 124 |
|------------|------|------|--------------------|
- Screenshot of program running:
[[./assets/PartTwo/img1.png]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,181 @@
// ==== Intructions ====
// • Write a program that will have pre defined input as numbers (1,2,3,4,5)
// • Then program will first create a BST of the input and print that out
// • Then the program will balance the BST and print out the AVL tree
// (pre-order)
//
// Steps
// • Create BST (0.5-point)
// • Balance the tree (i.e. AVL tree) (0.5-point)
// Output:
// • Print BST Pre-order (1-point)
// • Print Balanced-AVL Pre-order (1-point)
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
int max(int a, int b) {
int max = (a > b) ? a : b;
return max;
}
typedef struct BstNode {
int value;
int height;
int balance;
struct BstNode *left;
struct BstNode *right;
} BstNode;
BstNode *bst_new(int value) {
BstNode *bst = (BstNode *)malloc(sizeof(BstNode));
bst->value = value;
bst->height = 0;
bst->balance = 0;
bst->left = NULL;
bst->right = NULL;
return bst;
}
void bst_print_preorder(BstNode *node) {
if (node == NULL) {
return;
}
printf("%d, ", node->value);
bst_print_preorder(node->left);
bst_print_preorder(node->right);
}
void bst_dbg(BstNode *node) {
bst_print_preorder(node);
printf("BstNode {\n value: %d,\n height: %d,\n balance: %d\n}\n",
node->value, node->height, node->balance);
}
BstNode *bst_search(BstNode *node, int value) {
if (node == NULL) {
return NULL;
}
if (node->value == value) {
return node;
}
if (value < node->value) {
return bst_search(node->left, value);
} else {
return bst_search(node->right, value);
}
}
bool bst_contains(BstNode *node, int value) {
return (bst_search(node, value) != NULL);
}
int bst_height(BstNode *node) {
if (node == NULL) {
return -1;
}
int left_height = bst_height(node->left);
int right_height = bst_height(node->right);
return max(left_height, right_height) + 1;
}
void bst_update(BstNode *node) {
int left_height = bst_height(node->left);
int right_height = bst_height(node->right);
node->height = max(left_height, right_height) + 1;
node->balance = left_height - right_height;
}
BstNode *avl_right_rotate(BstNode *node) {
BstNode *left_child = node->left;
node->left = left_child->right;
left_child->right = node;
bst_update(node);
bst_update(left_child);
return node;
}
BstNode *avl_left_rotate(BstNode *node) {
BstNode *right_child = node->right;
node->right = right_child->left;
right_child->left = node;
bst_update(node);
bst_update(right_child);
return right_child;
}
/**
* @brief Balances a single node according to the AVL algorithm
*
* @param node The node to balance
* @return The balanced node
*/
BstNode *avl_balance_node(BstNode *node) {
if (node->balance == 2) {
if (node->left->balance >= 0) {
node = avl_right_rotate(node);
} else {
node = avl_left_rotate(node->left);
node = avl_right_rotate(node);
}
} else if (node->balance == -2) {
if (node->right->balance <= 0) {
node = avl_left_rotate(node);
} else {
node = avl_right_rotate(node->right);
node = avl_left_rotate(node);
}
}
return node;
}
/**
* @brief Insert a value into a Binary Search Tree in place
*
* @param node The given binary search tree to insert into
* @param value The value to insert
* @param balance Whether to balance the insertion with AVL
*/
void bst_insert(BstNode **node, int value, bool balance) {
if (*node == NULL)
*node = bst_new(value);
else if ((*node)->value == value)
// No duplicates allowed in our implementation
return;
else if ((*node)->value > value)
bst_insert(&(*node)->left, value, balance);
else
bst_insert(&(*node)->right, value, balance);
bst_update(*node);
if (balance)
*node = avl_balance_node(*node);
}
int main(int argc, char *argv[]) {
printf("Price Hiller, zfp106 (Spring 2024)\n");
printf("==================================\n");
printf("Unbalanced BST Pre-Order: ");
BstNode *bst = bst_new(1);
int input[] = {2, 3, 4, 5};
for (int i = 0; i < sizeof(input)/sizeof(input[0]); i++) {
bst_insert(&bst, input[i], false);
}
bst_print_preorder(bst);
printf("\nBalanced AVL Tree Pre-Order: ");
BstNode *avl = bst_new(1);
for (int i = 0; i < sizeof(input)/sizeof(input[0]); i++) {
bst_insert(&avl, input[i], true);
}
bst_print_preorder(avl);
printf("\n");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,100 @@
#include "lib/vec.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct HuffCode {
char byte;
char *code;
int frequency;
} HuffCode;
bool huffcode_cmp(HuffCode *first, HuffCode *second) {
int lendiff = strlen(first->code) - strlen(second->code);
if (lendiff == 0) {
int first_code = strtol(first->code, NULL, 2);
int second_code = strtol(second->code, NULL, 2);
return first_code >= second_code;
} else if (lendiff > 0) {
return true;
} else {
return false;
}
}
DECL_VEC(HuffVec, HuffCode *);
typedef struct MinHeap {
HuffVec *arr;
} MinHeap;
int minheap_parent(int i) { return (i - 1) / 2; }
int minheap_left_child(int i) { return (2 * i + 1); }
int minheap_right_child(int i) { return (2 * i + 2); }
HuffCode *minheap_get_min(MinHeap *heap) { return heap->arr->data[0]; }
MinHeap *minheap_new(HuffVec *arr) {
MinHeap *minheap = (MinHeap *)malloc(sizeof(MinHeap));
minheap->arr = arr;
return minheap;
}
void minheap_swap(MinHeap *heap, int idx, int jdx) {
HuffCode *temp = heap->arr->data[idx];
heap->arr->data[idx] = heap->arr->data[jdx];
heap->arr->data[jdx] = temp;
}
void *minheap_insert(MinHeap **_heap, HuffCode *value) {
MinHeap *heap = (*_heap);
int curr = heap->arr->elem_count - 1;
HuffVec_push(heap->arr, value);
while (curr > 0 && huffcode_cmp(heap->arr->data[minheap_parent(curr)],
heap->arr->data[curr])) {
minheap_swap(heap, minheap_parent(curr), curr);
curr = minheap_parent(curr);
}
return heap;
}
void minheap_print(MinHeap *heap) {
for (int i = 0; i < heap->arr->elem_count; i++) {
HuffCode *huffcode = heap->arr->data[i];
printf("%c: %s\n", huffcode->byte, huffcode->code);
}
}
int main() {
printf("Price Hiller, zfp106 (Spring 2024)\n");
printf("==================================\n");
HuffVec arr = HuffVec_new(2);
MinHeap *heap = minheap_new(&arr);
char chars[] = {'a', 'b', 'c', 'd', 'e'};
char *codes[] = {"100", "101", "00", "01", "11"};
int frequencies[] = {5, 9, 12, 13, 16};
printf("Huffman Encoding (Variable Bit)\n");
printf("Char | Freq\n");
HuffCode huffs[sizeof(frequencies) / sizeof(frequencies[0])] = {};
// Two for loops like this to maintain ownership over the huffman codes
for (int i = 0; i < sizeof(frequencies) / sizeof(frequencies[0]); i++) {
HuffCode huff = {
.byte = chars[i], .code = codes[i], .frequency = frequencies[i]};
huffs[i] = huff;
printf("%c | %d\n", huff.byte, huff.frequency);
}
printf("----------\n");
for (int i = 0; i < sizeof(frequencies) / sizeof(frequencies[0]); i++) {
heap = minheap_insert(&heap, &huffs[i]);
}
minheap_print(heap);
return 0;
}

View File

@ -0,0 +1,57 @@
// Credit to
// https://stackoverflow.com/questions/40159892/using-asprintf-on-windows/49873938#49873938
// with modifications by me
#include <stdarg.h> /* needed for va_* */
#include <stdio.h> /* needed for vsnprintf */
#include <stdlib.h> /* needed for malloc, free */
#ifdef _MSC_VER
#include <direct.h>
#else
#include <linux/limits.h>
#endif
int vscprintf(const char *format, va_list ap) {
va_list ap_copy;
va_copy(ap_copy, ap);
int retval = vsnprintf(NULL, 0, format, ap_copy);
va_end(ap_copy);
return retval;
}
/*
* asprintf, vasprintf:
* MSVC does not implement these, thus we implement them here
* GNU-C-compatible compilers implement these with the same names, thus we
* don't have to do anything
*/
int vasprintf(char **strp, const char *format, va_list ap) {
int len = vscprintf(format, ap);
if (len == -1)
return -1;
char *str = (char *)malloc((size_t)len + 1);
if (!str)
return -1;
int retval = vsnprintf(str, len + 1, format, ap);
if (retval == -1) {
free(str);
return -1;
}
*strp = str;
return retval;
}
char* fmtstr(const char *format, ...) {
char *str = NULL;
va_list ap;
va_start(ap, format);
vasprintf(&str, format, ap);
va_end(ap);
return str;
}
void print_header() {
printf("Price Hiller, zfp106 (Spring 2024)\n");
}

View File

@ -0,0 +1,35 @@
// Credit to
// https://stackoverflow.com/questions/40159892/using-asprintf-on-windows/49873938#49873938
// with modifications by me
#ifndef FMTSTR_H
#define FMTSTR_H
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE /* needed for (v)asprintf, affects '#include <stdio.h>' */
#endif
#include <stdarg.h> /* needed for va_* */
/*
* vscprintf:
* MSVC implements this as _vscprintf, thus we just 'symlink' it here
* GNU-C-compatible compilers do not implement this, thus we implement it here
*/
#ifdef _MSC_VER
#define vscprintf _vscprintf
#endif
#ifdef _MSC_VER
int vasprintf(char **strp, const char *format, va_list ap);
#endif
#ifdef __GNUC__
int vscprintf(const char *format, va_list ap);
#endif
char* fmtstr(const char *format, ...);
void print_header();
#endif

View File

@ -0,0 +1,79 @@
#pragma once
#define VECTOR_LIB
#include <stdbool.h>
#include <stdlib.h>
// This code is pretty bad in all honesty, but I *really* didn't want to play
// the void pointer game.
#define DECL_VEC(type_name, type) \
typedef struct { \
size_t elem_count; \
size_t capacity; \
type *data; \
} type_name; \
\
type_name type_name##_new(size_t initial_capacity) { \
initial_capacity = (initial_capacity < 1) ? 1 : initial_capacity; \
type_name v = {.capacity = initial_capacity, \
.elem_count = 0, \
.data = malloc(sizeof(type *) * initial_capacity)}; \
return v; \
} \
\
bool type_name##_alloc(type_name *v, size_t extra_capacity) { \
if (extra_capacity == 0) { \
return false; \
} \
\
int desired_size = v->capacity + extra_capacity; \
type *newData = realloc(v->data, sizeof(type *) * desired_size); \
if (newData == NULL) \
return false; \
v->data = newData; \
v->capacity = desired_size; \
return true; \
} \
\
bool type_name##_ensure_capacity(type_name *v, size_t capacity) { \
if (v->capacity < capacity) \
return type_name##_alloc(v, capacity - v->capacity); \
return true; \
} \
\
void type_name##_push(type_name *v, type item) { \
type_name##_ensure_capacity(v, v->elem_count + 1); \
v->data[v->elem_count++] = item; \
} \
\
type *type_name##_get(type_name *v, size_t index) { \
if (index >= 0 && index < v->elem_count) \
return &v->data[index]; \
return NULL; \
} \
\
void type_name##_del(type_name *v, size_t index) { \
if (index >= 0 && index < v->elem_count) { \
for (int i = index; (i < v->elem_count - 1); ++i) { \
v->data[i] = v->data[i + 1]; \
} \
v->elem_count--; \
} \
} \
\
type type_name##_pop(type_name *v) { \
type popped_value = *type_name##_get(v, v->elem_count - 1); \
type_name##_del(v, v->elem_count - 1); \
return popped_value; \
} \
\
type type_name##_first(type_name *v) { \
type found_value = *type_name##_get(v, 0); \
type_name##_del(v, 0); \
return found_value; \
} \
\
type *type_name##_peek(type_name *v) { \
return type_name##_get(v, v->elem_count - 1); \
} \
\
void type_name##_free(type_name *v) { free(v->data); }