print("DSA Package Loaded. Run dsa.help() for list of codes.")

def array_ops():
    print(r'''
#include <stdio.h>
#define SIZE 100

int insert(int arr[], int n, int pos, int value) {
    if (n >= SIZE) return n;
    for (int i = n; i > pos; i--) arr[i] = arr[i-1];
    arr[pos] = value;
    return n + 1;
}

int deleteElement(int arr[], int n, int pos) {
    if (n == 0 || pos >= n) return n;
    for (int i = pos; i < n - 1; i++) arr[i] = arr[i+1];
    return n - 1;
}

void main() {
    int arr[SIZE], n, i, pos, value;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter %d elements: ", n);
    for (i = 0; i < n; i++) scanf("%d", &arr[i]);

    printf("Enter index to insert at and value: ");
    scanf("%d %d", &pos, &value);
    n = insert(arr, n, pos, value);

    printf("Enter index to delete: ");
    scanf("%d", &pos);
    n = deleteElement(arr, n, pos);

    printf("Final Array: ");
    for (i = 0; i < n; i++) printf("%d ", arr[i]);
}
''')


def string_concat():
    print(r'''
#include <stdio.h>
#include <string.h>

void concatenate(char str1[], char str2[]) {
    char result[200];
    strcpy(result, str1);
    strcat(result, str2);
    printf("Concatenated String: %s\n", result);
}

void main() {
    char str1[100], str2[100];
    printf("Enter first string: ");
    scanf("%s", str1);
    printf("Enter second string: ");
    scanf("%s", str2);
    concatenate(str1, str2);
}
''')


def string_compare():
    print(r'''
#include <stdio.h>
#include <string.h>

void compare(char str1[], char str2[]) {
    int res = strcmp(str1, str2);
    if (res == 0) printf("Strings are equal.\n");
    else printf("Strings are not equal.\n");
}

void main() {
    char str1[100], str2[100];
    printf("Enter first string: ");
    scanf("%s", str1);
    printf("Enter second string: ");
    scanf("%s", str2);
    compare(str1, str2);
}
''')


def substring():
    print(r'''
#include <stdio.h>

void substring(char str[], int start, int length) {
    char sub[200];
    int i, j = 0;
    start--; 
    for (i = start; i < start + length && str[i] != '\0'; i++) {
        sub[j++] = str[i];
    }
    sub[j] = '\0';
    printf("Extracted Substring: %s\n", sub);
}

void main() {
    char str[100];
    int start, len;
    printf("Enter string: ");
    scanf("%s", str);
    printf("Enter start position and length: ");
    scanf("%d %d", &start, &len);
    substring(str, start, len);
}
''')


def queue_array():
    print(r'''
#include <stdio.h>
#define SIZE 5

int queue[SIZE], front = -1, rear = -1;

void enqueue(int value) {
    if (rear == SIZE - 1) { printf("Queue Full\n"); return; }
    if (front == -1) front = 0;
    queue[++rear] = value;
    printf("%d enqueued.\n", value);
}

void dequeue() {
    if (front == -1 || front > rear) { printf("Queue Empty\n"); return; }
    printf("%d dequeued.\n", queue[front++]);
}

void main() {
    int n, val;
    printf("How many elements to enqueue? ");
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        printf("Enter element: ");
        scanf("%d", &val);
        enqueue(val);
    }
    printf("Dequeuing one element...\n");
    dequeue();
}
''')


def linear_search():
    print(r'''
#include <stdio.h>

int linearSearch(int arr[], int n, int key) {
    for (int i = 0; i < n; i++) {
        if (arr[i] == key) return i;
    }
    return -1;
}

void main() {
    int arr[100], n, key, i;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements: ");
    for(i=0; i<n; i++) scanf("%d", &arr[i]);
    
    printf("Enter value to search: ");
    scanf("%d", &key);
    
    int result = linearSearch(arr, n, key);
    if(result != -1) printf("Found at index %d\n", result);
    else printf("Not Found\n");
}
''')


def binary_search():
    print(r'''
#include <stdio.h>

int binarySearch(int arr[], int n, int key) {
    int low = 0, high = n - 1, mid;
    while (low <= high) {
        mid = (low + high) / 2;
        if (arr[mid] == key) return mid;
        else if (arr[mid] < key) low = mid + 1;
        else high = mid - 1;
    }
    return -1;
}

void main() {
    int arr[100], n, key, i;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter sorted elements: ");
    for(i=0; i<n; i++) scanf("%d", &arr[i]);
    
    printf("Enter value to search: ");
    scanf("%d", &key);
    
    int result = binarySearch(arr, n, key);
    if(result != -1) printf("Found at index %d\n", result);
    else printf("Not Found\n");
}
''')


def queue_linkedlist():
    print(r'''
#include <stdio.h>
#include <stdlib.h>

struct Node { int data; struct Node* next; };
struct Node *front = NULL, *rear = NULL;

void enqueue(int value) {
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data = value; temp->next = NULL;
    if (rear == NULL) front = rear = temp;
    else { rear->next = temp; rear = temp; }
    printf("%d enqueued.\n", value);
}

void dequeue() {
    if (front == NULL) { printf("Queue Empty\n"); return; }
    struct Node* temp = front;
    printf("%d dequeued.\n", front->data);
    front = front->next;
    if (front == NULL) rear = NULL;
    free(temp);
}

void main() {
    int n, val;
    printf("How many elements to enqueue? ");
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        scanf("%d", &val);
        enqueue(val);
    }
    printf("Dequeuing first element...\n");
    dequeue();
}
''')


def bubble_sort():
    print(r'''
#include <stdio.h>

void bubbleSort(int arr[], int n) {
    int i, j, temp;
    for (i = 0; i < n - 1; i++) {
        for (j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp;
            }
        }
    }
}

void main() {
    int arr[100], n, i;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements: ");
    for(i=0; i<n; i++) scanf("%d", &arr[i]);

    bubbleSort(arr, n);
    
    printf("Sorted array: ");
    for(i=0; i<n; i++) printf("%d ", arr[i]);
}
''')


def selection_sort():
    print(r'''
#include <stdio.h>

void selectionSort(int arr[], int n) {
    int i, j, min, temp;
    for (i = 0; i < n - 1; i++) {
        min = i;
        for (j = i + 1; j < n; j++)
            if (arr[j] < arr[min]) min = j;
        
        temp = arr[i]; arr[i] = arr[min]; arr[min] = temp;
    }
}

void main() {
    int arr[100], n, i;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements: ");
    for(i=0; i<n; i++) scanf("%d", &arr[i]);

    selectionSort(arr, n);
    
    printf("Sorted array: ");
    for(i=0; i<n; i++) printf("%d ", arr[i]);
}
''')


def insertion_sort():
    print(r'''
#include <stdio.h>

void insertionSort(int arr[], int n) {
    int i, j, key;
    for (i = 1; i < n; i++) {
        key = arr[i];
        j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

void main() {
    int arr[100], n, i;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements: ");
    for(i=0; i<n; i++) scanf("%d", &arr[i]);

    insertionSort(arr, n);
    
    printf("Sorted array: ");
    for(i=0; i<n; i++) printf("%d ", arr[i]);
}
''')


def linked_list():
    print(r'''
#include <stdio.h>
#include <stdlib.h>

struct Node { int data; struct Node* next; };
struct Node* head = NULL;

void insertEnd(int value) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = value; newNode->next = NULL;
    if (head == NULL) { head = newNode; return; }
    struct Node* temp = head;
    while (temp->next != NULL) temp = temp->next;
    temp->next = newNode;
}

void deleteHead() {
    if (head == NULL) { printf("List Empty\n"); return; }
    struct Node* temp = head;
    head = head->next;
    printf("Deleted %d\n", temp->data);
    free(temp);
}

void display() {
    struct Node* temp = head;
    printf("List: ");
    while (temp != NULL) { printf("%d -> ", temp->data); temp = temp->next; }
    printf("NULL\n");
}

void main() {
    int n, val;
    printf("How many nodes to create? ");
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        printf("Enter value: ");
        scanf("%d", &val);
        insertEnd(val);
    }
    display();
    printf("Deleting head node...\n");
    deleteHead();
    display();
}
''')


def stack_array():
    print(r'''
#include <stdio.h>
#define SIZE 100

int stack[SIZE], top = -1;

void push(int value) {
    if (top == SIZE - 1) { printf("Stack Overflow\n"); return; }
    stack[++top] = value;
    printf("%d pushed.\n", value);
}

void pop() {
    if (top == -1) { printf("Stack Underflow\n"); return; }
    printf("%d popped.\n", stack[top--]);
}

void main() {
    int n, val;
    printf("How many elements to push? ");
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        scanf("%d", &val);
        push(val);
    }
    printf("Popping one element...\n");
    pop();
}
''')


def polynomial():
    print(r'''
#include <stdio.h>
#include <stdlib.h>

struct Term { int coeff; int exp; struct Term* next; };
struct Term* head = NULL;

void insertTerm(int coeff, int exp) {
    struct Term* newTerm = (struct Term*)malloc(sizeof(struct Term));
    newTerm->coeff = coeff; newTerm->exp = exp; newTerm->next = NULL;

    if (head == NULL || exp > head->exp) {
        newTerm->next = head; head = newTerm;
    } else {
        struct Term* temp = head;
        while (temp->next != NULL && temp->next->exp >= exp) temp = temp->next;
        newTerm->next = temp->next; temp->next = newTerm;
    }
}

void display() {
    struct Term* temp = head;
    printf("Polynomial: ");
    while (temp != NULL) {
        printf("%dx^%d + ", temp->coeff, temp->exp);
        temp = temp->next;
    }
    printf("0\n");
}

void main() {
    int n, coeff, exp;
    printf("Enter number of terms: ");
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        printf("Enter coeff and exp for term %d: ", i+1);
        scanf("%d %d", &coeff, &exp);
        insertTerm(coeff, exp);
    }
    display();
}
''')


def quick_sort():
    print(r'''
#include <stdio.h>

void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; }

int partition(int arr[], int low, int high) {
    int pivot = arr[high], i = (low - 1);
    for (int j = low; j < high; j++) {
        if (arr[j] < pivot) swap(&arr[++i], &arr[j]);
    }
    swap(&arr[i + 1], &arr[high]);
    return (i + 1);
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

void main() {
    int arr[100], n, i;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    printf("Enter elements: ");
    for(i=0; i<n; i++) scanf("%d", &arr[i]);

    quickSort(arr, 0, n - 1);
    
    printf("Sorted array: ");
    for(i=0; i<n; i++) printf("%d ", arr[i]);
}
''')


def circular_linkedlist():
    print(r'''
#include <stdio.h>
#include <stdlib.h>

struct Node { int data; struct Node* next; };
struct Node* last = NULL;

void insertAtBeginning(int value) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = value;
    if (last == NULL) { last = newNode; last->next = last; }
    else { newNode->next = last->next; last->next = newNode; }
}

void display() {
    if (last == NULL) { printf("Empty\n"); return; }
    struct Node* temp = last->next;
    printf("Circular List: ");
    do {
        printf("%d -> ", temp->data);
        temp = temp->next;
    } while (temp != last->next);
    printf("START\n");
}

void main() {
    int n, val;
    printf("How many nodes to insert? ");
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        scanf("%d", &val);
        insertAtBeginning(val);
    }
    display();
}
''')


def factorial():
    print(r'''
#include <stdio.h>

void main() {
    int n, i;
    unsigned long long fact = 1;
    
    printf("Enter a number: ");
    scanf("%d", &n);
    
    if(n < 0) printf("Error: Negative number.\n");
    else {
        for (i = 1; i <= n; i++) fact = fact * i;
        printf("Factorial of %d = %llu", n, fact);
    }
}
''')


def tree_inorder():
    print(r'''
#include <stdio.h>
#include <stdlib.h>

struct Node { int data; struct Node *left, *right; };

struct Node* create(int value) {
    struct Node* node = (struct Node*)malloc(sizeof(struct Node));
    node->data = value; node->left = node->right = NULL;
    return node;
}

void inorder(struct Node* root) {
    if (root != NULL) {
        inorder(root->left);
        printf("%d ", root->data);
        inorder(root->right);
    }
}

void main() {
    struct Node *root;
    int rootVal;
    
    printf("Enter root node value: ");
    scanf("%d", &rootVal);
    
    root = create(rootVal);
    root->left = create(20); 
    root->right = create(30);
    
    printf("Inorder Traversal (with hardcoded children 20, 30): "); 
    inorder(root);
}
''')


def doubly_linkedlist():
    print(r'''
#include <stdio.h>
#include <stdlib.h>

struct Node { int data; struct Node *prev, *next; };
struct Node *head = NULL;

void insertBeginning(int value) {
    struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = value; newNode->prev = NULL; newNode->next = head;
    if (head != NULL) head->prev = newNode;
    head = newNode;
    printf("%d inserted.\n", value);
}

void deleteBeginning() {
    if (head == NULL) { printf("List Empty\n"); return; }
    struct Node *temp = head;
    head = head->next;
    if (head != NULL) head->prev = NULL;
    free(temp);
    printf("Node deleted.\n");
}

void main() {
    int n, val;
    printf("How many elements to insert? ");
    scanf("%d", &n);
    for(int i=0; i<n; i++) {
        scanf("%d", &val);
        insertBeginning(val);
    }
    printf("Deleting one element from beginning...\n");
    deleteBeginning();
}
''')


def all():
    print("="*50)
    print(" PRINTING ALL DSA CODES ")
    print("="*50)
    print("\n--- ARRAY_OPS ---\n")
    array_ops()
    print("-" * 50)
    print("\n--- STRING_CONCAT ---\n")
    string_concat()
    print("-" * 50)
    print("\n--- STRING_COMPARE ---\n")
    string_compare()
    print("-" * 50)
    print("\n--- SUBSTRING ---\n")
    substring()
    print("-" * 50)
    print("\n--- QUEUE_ARRAY ---\n")
    queue_array()
    print("-" * 50)
    print("\n--- LINEAR_SEARCH ---\n")
    linear_search()
    print("-" * 50)
    print("\n--- BINARY_SEARCH ---\n")
    binary_search()
    print("-" * 50)
    print("\n--- QUEUE_LINKEDLIST ---\n")
    queue_linkedlist()
    print("-" * 50)
    print("\n--- BUBBLE_SORT ---\n")
    bubble_sort()
    print("-" * 50)
    print("\n--- SELECTION_SORT ---\n")
    selection_sort()
    print("-" * 50)
    print("\n--- INSERTION_SORT ---\n")
    insertion_sort()
    print("-" * 50)
    print("\n--- LINKED_LIST ---\n")
    linked_list()
    print("-" * 50)
    print("\n--- STACK_ARRAY ---\n")
    stack_array()
    print("-" * 50)
    print("\n--- POLYNOMIAL ---\n")
    polynomial()
    print("-" * 50)
    print("\n--- QUICK_SORT ---\n")
    quick_sort()
    print("-" * 50)
    print("\n--- CIRCULAR_LINKEDLIST ---\n")
    circular_linkedlist()
    print("-" * 50)
    print("\n--- FACTORIAL ---\n")
    factorial()
    print("-" * 50)
    print("\n--- TREE_INORDER ---\n")
    tree_inorder()
    print("-" * 50)
    print("\n--- DOUBLY_LINKEDLIST ---\n")
    doubly_linkedlist()
    print("-" * 50)


def help():
    print("\nAvailable Commands:")
    print("-------------------")
    methods = [
        'array_ops',
        'string_concat',
        'string_compare',
        'substring',
        'queue_array',
        'linear_search',
        'binary_search',
        'queue_linkedlist',
        'bubble_sort',
        'selection_sort',
        'insertion_sort',
        'linked_list',
        'stack_array',
        'polynomial',
        'quick_sort',
        'circular_linkedlist',
        'factorial',
        'tree_inorder',
        'doubly_linkedlist',
    ]
    for m in methods:
        print(f"dsa.{m}()")
    print("\nSpecial:")
    print("dsa.all()")
    print("dsa.help()")
