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

def linear_search():
    print(r'''
#include <iostream>
using namespace std;

int main() {
    int arr[] = {10, 50, 30, 70, 80, 20};
    int n = 6, key = 30;
    bool found = false;

    for (int i = 0; i < n; i++) {
        if (arr[i] == key) {
            found = true;
            break;
        }
    }
    if(found) cout << "Found"; else cout << "Not Found";
    return 0;
}
''')


def binary_search():
    print(r'''
#include <iostream>
using namespace std;

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

int main() {
    int arr[] = {10, 20, 30, 40, 50}; // Sorted
    int index = binarySearch(arr, 5, 30);
    if(index != -1) cout << "Found at index " << index;
    else cout << "Not Found";
    return 0;
}
''')


def bubble_sort():
    print(r'''
#include <iostream>
using namespace std;

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

int main() {
    int arr[] = {64, 34, 25, 12, 22};
    bubbleSort(arr, 5);
    for (int i : arr) cout << i << " ";
    return 0;
}
''')


def selection_sort():
    print(r'''
#include <iostream>
using namespace std;

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

int main() {
    int arr[] = {64, 25, 12, 22, 11};
    selectionSort(arr, 5);
    for (int i : arr) cout << i << " ";
    return 0;
}
''')


def insertion_sort():
    print(r'''
#include <iostream>
using namespace std;

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

int main() {
    int arr[] = {12, 11, 13, 5, 6};
    insertionSort(arr, 5);
    for (int i : arr) cout << i << " ";
    return 0;
}
''')


def merge_sort():
    print(r'''
#include <iostream>
using namespace std;

void merge(int arr[], int l, int m, int r) {
    int n1 = m - l + 1, n2 = r - m;
    int L[n1], R[n2];
    for (int i = 0; i < n1; i++) L[i] = arr[l + i];
    for (int j = 0; j < n2; j++) R[j] = arr[m + 1 + j];

    int i = 0, j = 0, k = l;
    while (i < n1 && j < n2) arr[k++] = (L[i] <= R[j]) ? L[i++] : R[j++];
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
}

void mergeSort(int arr[], int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;
        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);
        merge(arr, l, m, r);
    }
}

int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    mergeSort(arr, 0, 5);
    for (int i : arr) cout << i << " ";
    return 0;
}
''')


def quick_sort():
    print(r'''
#include <iostream>
using namespace std;

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);
    }
}

int main() {
    int arr[] = {10, 7, 8, 9, 1, 5};
    quickSort(arr, 0, 5);
    for (int i : arr) cout << i << " ";
    return 0;
}
''')


def linked_list():
    print(r'''
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
    Node(int v) : data(v), next(nullptr) {}
};

class LinkedList {
    Node* head = nullptr;
public:
    void insert(int val) {
        Node* n = new Node(val);
        n->next = head;
        head = n;
    }
    void display() {
        Node* temp = head;
        while (temp) { cout << temp->data << " -> "; temp = temp->next; }
        cout << "NULL";
    }
};

int main() {
    LinkedList list;
    list.insert(30); list.insert(20); list.insert(10);
    list.display();
    return 0;
}
''')


def stack_array():
    print(r'''
#include <iostream>
using namespace std;

#define MAX 100
class Stack {
    int top;
    int arr[MAX];
public:
    Stack() { top = -1; }
    void push(int x) { if (top < MAX - 1) arr[++top] = x; }
    int pop() { return (top >= 0) ? arr[top--] : -1; }
    int peek() { return (top >= 0) ? arr[top] : -1; }
};

int main() {
    Stack s;
    s.push(10); s.push(20);
    cout << "Top: " << s.peek() << ", Popped: " << s.pop();
    return 0;
}
''')


def postfix_eval():
    print(r'''
#include <iostream>
#include <stack>
#include <cctype>
using namespace std;

int evaluatePostfix(string exp) {
    stack<int> s;
    for (char c : exp) {
        if (isdigit(c)) s.push(c - '0');
        else {
            int val1 = s.top(); s.pop();
            int val2 = s.top(); s.pop();
            if (c == '+') s.push(val2 + val1);
            else if (c == '-') s.push(val2 - val1);
            else if (c == '*') s.push(val2 * val1);
            else if (c == '/') s.push(val2 / val1);
        }
    }
    return s.top();
}

int main() {
    string exp = "231*+9-";
    cout << "Result: " << evaluatePostfix(exp);
    return 0;
}
''')


def queue_array():
    print(r'''
#include <iostream>
using namespace std;

#define MAX 100
class Queue {
    int front, rear, arr[MAX];
public:
    Queue() { front = -1; rear = -1; }
    void enqueue(int x) {
        if (rear == MAX - 1) return;
        if (front == -1) front = 0;
        arr[++rear] = x;
    }
    void dequeue() {
        if (front == -1 || front > rear) return;
        front++;
    }
    void display() {
        if (front == -1) return;
        for (int i = front; i <= rear; i++) cout << arr[i] << " ";
    }
};

int main() {
    Queue q;
    q.enqueue(10); q.enqueue(20); q.dequeue();
    q.display();
    return 0;
}
''')


def tree_traversals():
    print(r'''
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node *left, *right;
    Node(int val) : data(val), left(NULL), right(NULL) {}
};

void inorder(Node* root) {
    if (!root) return;
    inorder(root->left); cout << root->data << " "; inorder(root->right);
}

void preorder(Node* root) {
    if (!root) return;
    cout << root->data << " "; preorder(root->left); preorder(root->right);
}

void postorder(Node* root) {
    if (!root) return;
    postorder(root->left); postorder(root->right); cout << root->data << " ";
}

int main() {
    Node* root = new Node(1);
    root->left = new Node(2); root->right = new Node(3);
    cout << "Inorder: "; inorder(root);
    return 0;
}
''')


def bst():
    print(r'''
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node *left, *right;
    Node(int val) : data(val), left(NULL), right(NULL) {}
};

Node* insert(Node* root, int val) {
    if (!root) return new Node(val);
    if (val < root->data) root->left = insert(root->left, val);
    else root->right = insert(root->right, val);
    return root;
}

int main() {
    Node* root = NULL;
    root = insert(root, 50); insert(root, 30); insert(root, 70);
    cout << "Root: " << root->data << ", Left: " << root->left->data;
    return 0;
}
''')


def bfs_dfs():
    print(r'''
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

void BFS(vector<int> adj[], int V, int s) {
    vector<bool> visited(V, false);
    queue<int> q;
    visited[s] = true; q.push(s);
    
    cout << "BFS: ";
    while(!q.empty()) {
        int u = q.front(); q.pop();
        cout << u << " ";
        for(int v : adj[u]) if(!visited[v]) { visited[v] = true; q.push(v); }
    }
    cout << endl;
}

void DFSUtil(vector<int> adj[], int u, vector<bool> &visited) {
    visited[u] = true;
    cout << u << " ";
    for(int v : adj[u]) if(!visited[v]) DFSUtil(adj, v, visited);
}

int main() {
    int V = 4;
    vector<int> adj[V];
    adj[0] = {1, 2}; adj[1] = {2}; adj[2] = {0, 3}; adj[3] = {3};
    
    BFS(adj, V, 2);
    
    vector<bool> visited(V, false);
    cout << "DFS: "; DFSUtil(adj, 2, visited);
    return 0;
}
''')


def magic_square():
    print(r'''
#include <iostream>
#include <vector>
using namespace std;

void magicSquare(int n) {
    vector<vector<int>> magic(n, vector<int>(n, 0));
    int i = n/2, j = n-1;

    for (int num = 1; num <= n*n; ) {
        if (i == -1 && j == n) { j = n-2; i = 0; }
        else { if (j == n) j = 0; if (i < 0) i = n-1; }
        
        if (magic[i][j]) { j -= 2; i++; continue; }
        else magic[i][j] = num++;
        j++; i--;
    }
    cout << "Magic Square (" << n << "x" << n << "):\n";
    for(auto row : magic) { for(int x : row) cout << x << " "; cout << endl; }
}

int main() {
    magicSquare(3);
    return 0;
}
''')


def n_queens():
    print(r'''
#include <iostream>
#include <vector>
using namespace std;

bool isSafe(vector<string> &board, int row, int col, int n) {
    for(int i=0; i<row; i++) if(board[i][col] == 'Q') return false;
    for(int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) if(board[i][j] == 'Q') return false;
    for(int i=row-1, j=col+1; i>=0 && j<n; i--, j++) if(board[i][j] == 'Q') return false;
    return true;
}

void solve(int row, int n, vector<string> &board) {
    if (row == n) {
        for(string s : board) cout << s << endl;
        cout << endl; return;
    }
    for (int col = 0; col < n; col++) {
        if (isSafe(board, row, col, n)) {
            board[row][col] = 'Q';
            solve(row + 1, n, board);
            board[row][col] = '.';
        }
    }
}

int main() {
    int n = 4;
    vector<string> board(n, string(n, '.'));
    solve(0, n, board);
    return 0;
}
''')


def prims_mst():
    print(r'''
#include <iostream>
#include <climits>
using namespace std;

#define V 5

int main() {
    int graph[V][V] = { {0, 2, 0, 6, 0}, {2, 0, 3, 8, 5}, {0, 3, 0, 0, 7}, {6, 8, 0, 0, 9}, {0, 5, 7, 9, 0} };
    int parent[V], key[V];
    bool mstSet[V];

    for (int i = 0; i < V; i++) key[i] = INT_MAX, mstSet[i] = false;
    key[0] = 0; parent[0] = -1;

    for (int count = 0; count < V - 1; count++) {
        int u, min = INT_MAX;
        for (int v = 0; v < V; v++) if (!mstSet[v] && key[v] < min) min = key[v], u = v;
        mstSet[u] = true;
        for (int v = 0; v < V; v++)
            if (graph[u][v] && !mstSet[v] && graph[u][v] < key[v])
                parent[v] = u, key[v] = graph[u][v];
    }

    cout << "Edge \tWeight\n";
    for (int i = 1; i < V; i++) cout << parent[i] << " - " << i << " \t" << graph[i][parent[i]] << "\n";
    return 0;
}
''')


def all():
    print("="*50)
    print(" PRINTING ALL C++ DSA CODES ")
    print("="*50)
    print("\n--- LINEAR_SEARCH ---\n")
    linear_search()
    print("-" * 50)
    print("\n--- BINARY_SEARCH ---\n")
    binary_search()
    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--- MERGE_SORT ---\n")
    merge_sort()
    print("-" * 50)
    print("\n--- QUICK_SORT ---\n")
    quick_sort()
    print("-" * 50)
    print("\n--- LINKED_LIST ---\n")
    linked_list()
    print("-" * 50)
    print("\n--- STACK_ARRAY ---\n")
    stack_array()
    print("-" * 50)
    print("\n--- POSTFIX_EVAL ---\n")
    postfix_eval()
    print("-" * 50)
    print("\n--- QUEUE_ARRAY ---\n")
    queue_array()
    print("-" * 50)
    print("\n--- TREE_TRAVERSALS ---\n")
    tree_traversals()
    print("-" * 50)
    print("\n--- BST ---\n")
    bst()
    print("-" * 50)
    print("\n--- BFS_DFS ---\n")
    bfs_dfs()
    print("-" * 50)
    print("\n--- MAGIC_SQUARE ---\n")
    magic_square()
    print("-" * 50)
    print("\n--- N_QUEENS ---\n")
    n_queens()
    print("-" * 50)
    print("\n--- PRIMS_MST ---\n")
    prims_mst()
    print("-" * 50)


def help():
    print("\nAvailable C++ Commands:")
    print("-------------------")
    methods = [
        'linear_search',
        'binary_search',
        'bubble_sort',
        'selection_sort',
        'insertion_sort',
        'merge_sort',
        'quick_sort',
        'linked_list',
        'stack_array',
        'postfix_eval',
        'queue_array',
        'tree_traversals',
        'bst',
        'bfs_dfs',
        'magic_square',
        'n_queens',
        'prims_mst',
    ]
    for m in methods:
        print(f"dsa.{m}()")
    print("\nSpecial:")
    print("dsa.all()")
    print("dsa.help()")
