#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node* next;
};

struct Node* head = NULL;

void insertAtBeginning(int value) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = value;
    newNode->next = head;
    head = newNode;
    printf("\nInsertion successful at beginning\n");
}

void insertAtEnd(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;
    printf("\nInsertion successful at end\n");
}

void insertAtPosition(int value, int position) {
    if(position < 1) {
        printf("\nInvalid position\n");
        return;
    }

    if(position == 1) {
        insertAtBeginning(value);
        return;
    }

    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = value;

    struct Node* temp = head;
    for(int i = 1; i < position-1 && temp != NULL; i++) {
        temp = temp->next;
    }

    if(temp == NULL) {
        printf("\nPosition exceeds list length\n");
        free(newNode);
        return;
    }

    newNode->next = temp->next;
    temp->next = newNode;
    printf("\nInsertion successful at position %d\n", position);
}

void deleteFromBeginning() {
    if(head == NULL) {
        printf("\nList is empty\n");
        return;
    }
    struct Node* temp = head;
    head = head->next;
    free(temp);
    printf("\nDeletion successful from beginning\n");
}

void deleteFromEnd() {
    if(head == NULL) {
        printf("\nList is empty\n");
        return;
    }
    if(head->next == NULL) {
        free(head);
        head = NULL;
        return;
    }
    struct Node* temp = head;
    while(temp->next->next != NULL) {
        temp = temp->next;
    }
    free(temp->next);
    temp->next = NULL;
    printf("\nDeletion successful from end\n");
}

void sortList() {
    if(head == NULL || head->next == NULL) {
        return;
    }

    struct Node *current, *index;
    int temp;

    for(current = head; current != NULL; current = current->next) {
        for(index = current->next; index != NULL; index = index->next) {
            if(current->data > index->data) {
                temp = current->data;
                current->data = index->data;
                index->data = temp;
            }
        }
    }
    printf("\nList sorted successfully\n");
}

void reverseList() {
    struct Node *prev = NULL, *current = head, *next = NULL;

    while(current != NULL) {
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
    head = prev;
    printf("\nList reversed successfully\n");
}

void display() {
    if(head == NULL) {
        printf("\nList is empty\n");
        return;
    }
    struct Node* temp = head;
    printf("\nList elements are: ");
    while(temp != NULL) {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

void search(int value) {
    struct Node* temp = head;
    int position = 1;
    while(temp != NULL) {
        if(temp->data == value) {
            printf("\nElement %d found at position %d\n", value, position);
            return;
        }
        temp = temp->next;
        position++;
    }
    printf("\nElement %d not found in the list\n", value);
}

int main() {
    int choice, value, position;

    while(1) {
        printf("\n1. Insert at beginning");
        printf("\n2. Insert at end");
        printf("\n3. Insert at specific position");
        printf("\n4. Delete from beginning");
        printf("\n5. Delete from end");
        printf("\n6. Sort list");
        printf("\n7. Reverse list");
        printf("\n8. Display");
        printf("\n9. Search");
        printf("\n10. Exit");
        printf("\nEnter your choice: ");
        scanf("%d", &choice);

        switch(choice) {
            case 1:
                printf("\nEnter value to insert: ");
                scanf("%d", &value);
                insertAtBeginning(value);
                break;
            case 2:
                printf("\nEnter value to insert: ");
                scanf("%d", &value);
                insertAtEnd(value);
                break;
            case 3:
                printf("\nEnter value to insert: ");
                scanf("%d", &value);
                printf("\nEnter position: ");
                scanf("%d", &position);
                insertAtPosition(value, position);
                break;
            case 4:
                deleteFromBeginning();
                break;
            case 5:
                deleteFromEnd();
                break;
            case 6:
                sortList();
                break;
            case 7:
                reverseList();
                break;
            case 8:
                display();
                break;
            case 9:
                printf("\nEnter value to search: ");
                scanf("%d", &value);
                search(value);
                break;
            case 10:
                printf("\nExiting program\n");
                exit(0);
            default:
                printf("\nInvalid choice\n");
        }
    }
    return 0;
}
