# autobee 🐝

[![PyPI version](https://badge.fury.io/py/autobee.svg)](https://pypi.org/project/autobee/)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![CI](https://github.com/YOUR_USERNAME/autobee/actions/workflows/publish.yml/badge.svg)](https://github.com/YOUR_USERNAME/autobee/actions)

**A clean, one-line DSA toolkit for Python.**  
Perfect for students, interview prep, and quick prototyping.

```bash
pip install autobee
```

---

## ✨ Features

Every algorithm returns a clean dict with:
- **`result`** — the final answer
- **`steps`** — every intermediate state (great for visualization!)
- **`algo`** — algorithm name
- **`complexity`** — time and space complexity

---

## 🚀 Quick Start

```python
from autobee import bubble_sort, binary_search, bfs, fibonacci, BST

# Sorting — one line
bubble_sort([5, 2, 8, 1, 9])["result"]        # → [1, 2, 5, 8, 9]

# Searching
binary_search([1, 3, 5, 7, 9], 7)["found"]    # → True
binary_search([1, 3, 5, 7, 9], 7)["result"]   # → 3 (index)

# Graphs
g = {"A": ["B", "C"], "B": ["D"], "C": [], "D": []}
bfs(g, "A")["result"]                          # → ['A', 'B', 'C', 'D']

# Dynamic Programming
fibonacci(10)["result"]                        # → 55
fibonacci(10)["steps"]                         # → [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

# Data Structures
tree = BST()
for v in [5, 3, 7, 1, 4]: tree.insert(v)
tree.inorder()                                 # → [1, 3, 4, 5, 7]
tree.search(4)                                 # → True
```

---

## 📦 API Reference

### Sorting

All sorting functions accept a list and return `{"result", "steps", "algo", "complexity"}`.

| Function | Best | Average | Worst | Space | Stable |
|---|---|---|---|---|---|
| `bubble_sort(arr)` | O(n) | O(n²) | O(n²) | O(1) | ✅ |
| `insertion_sort(arr)` | O(n) | O(n²) | O(n²) | O(1) | ✅ |
| `selection_sort(arr)` | O(n²) | O(n²) | O(n²) | O(1) | ❌ |
| `merge_sort(arr)` | O(n log n) | O(n log n) | O(n log n) | O(n) | ✅ |
| `quick_sort(arr)` | O(n log n) | O(n log n) | O(n²) | O(log n) | ❌ |
| `heap_sort(arr)` | O(n log n) | O(n log n) | O(n log n) | O(1) | ❌ |

```python
from autobee import merge_sort

r = merge_sort([38, 27, 43, 3])
r["result"]       # [3, 27, 38, 43]
r["steps"]        # [[27, 38], [3, 43], [3, 27, 38, 43], ...]
r["complexity"]   # {"time_average": "O(n log n)", "space": "O(n)"}
```

---

### Searching

```python
from autobee import binary_search, linear_search

# Binary Search (auto-sorts input)
r = binary_search([10, 3, 7, 1, 5], 7)
r["result"]   # 2  (index in sorted array)
r["found"]    # True
r["steps"]    # [{"lo": 0, "hi": 4, "mid": 2, ...}, ...]

# Linear Search (works on any list including strings)
linear_search(["apple", "bee", "cat"], "bee")["result"]   # 1
```

---

### Graphs

Graphs are plain dicts. Unweighted uses `[neighbors]`, weighted uses `[(neighbor, weight)]`.

```python
from autobee import bfs, dfs, dijkstra

# Unweighted graph
g = {"A": ["B", "C"], "B": ["D"], "C": ["D"], "D": []}
bfs(g, "A")["result"]   # ['A', 'B', 'C', 'D']
dfs(g, "A")["result"]   # ['A', 'B', 'D', 'C']

# Weighted graph for Dijkstra
wg = {
    "A": [("B", 1), ("C", 4)],
    "B": [("C", 2), ("D", 5)],
    "C": [("D", 1)],
    "D": []
}
dijkstra(wg, "A")["result"]   # {'A': 0, 'B': 1, 'C': 3, 'D': 4}
```

---

### Dynamic Programming

```python
from autobee import fibonacci, knapsack, lcs

# Fibonacci
fibonacci(8)["result"]   # 21
fibonacci(8)["steps"]    # [0, 1, 1, 2, 3, 5, 8, 13, 21]

# 0/1 Knapsack
knapsack(
    weights=[1, 3, 4, 5],
    values= [1, 4, 5, 7],
    capacity=7
)["result"]   # 9

# Longest Common Subsequence
lcs("ABCBDAB", "BDCAB")["result"]   # 4
```

---

### Data Structures

#### Stack
```python
from autobee import Stack

s = Stack()
s.push(1); s.push(2); s.push(3)
s.peek()    # 3
s.pop()     # 3
s.size()    # 2
s.to_list() # [1, 2]
```

#### Queue
```python
from autobee import Queue

q = Queue()
q.enqueue("a"); q.enqueue("b"); q.enqueue("c")
q.dequeue()  # 'a'
q.peek()     # 'b'
q.size()     # 2
```

#### LinkedList
```python
from autobee import LinkedList

ll = LinkedList()
ll.append(1); ll.append(2); ll.append(3)
ll.prepend(0)
ll.to_list()       # [0, 1, 2, 3]
ll.delete(2)
ll.search(3)       # True
str(ll)            # "0 -> 1 -> 3"
```

#### BST (Binary Search Tree)
```python
from autobee import BST

tree = BST()
for v in [5, 3, 7, 1, 4, 6, 8]:
    tree.insert(v)

tree.inorder()     # [1, 3, 4, 5, 6, 7, 8]   ← sorted!
tree.preorder()    # [5, 3, 1, 4, 7, 6, 8]
tree.postorder()   # [1, 4, 3, 6, 8, 7, 5]
tree.height()      # 3
tree.search(4)     # True
tree.delete(3)
tree.to_dict()     # nested dict for visualization
```

---

## 🛠 Development Setup

```bash
git clone https://github.com/YOUR_USERNAME/autobee.git
cd autobee
pip install -e ".[dev]"
pytest tests/ -v
```

---

## 🚢 Publishing a New Version

1. Update `version` in `pyproject.toml`
2. Commit and push:
   ```bash
   git add .
   git commit -m "Release v0.2.0"
   git tag v0.2.0
   git push origin main --tags
   ```
3. GitHub Actions automatically runs tests → builds → publishes to PyPI ✅

---

## 🔐 PyPI Trusted Publishing Setup (One-time)

This repo uses **PyPI Trusted Publishing** — no API tokens or secrets needed!

1. Go to [pypi.org](https://pypi.org) → Your account → Publishing
2. Add a new trusted publisher:
   - **PyPI project name:** `autobee`
   - **Owner:** `YOUR_USERNAME`
   - **Repository:** `autobee`
   - **Workflow:** `publish.yml`
   - **Environment:** `pypi`
3. In your GitHub repo → Settings → Environments → create environment named `pypi`
4. That's it! Push a tag and watch it publish 🎉

---

## 📄 License

MIT © autobee contributors
