pushing read me

This commit is contained in:
Anas Rashid 2026-04-29 00:08:06 +02:00
parent df2141c62d
commit 35199019fe
2 changed files with 310 additions and 0 deletions

166
README.md Normal file
View File

@ -0,0 +1,166 @@
# Cut Rod Problem — Dynamic Programming
A complete implementation of the classic **Rod Cutting Problem** from *Introduction to Algorithms* (CLRS), with three algorithmic approaches and an interactive browser-based visualizer.
---
## The Problem
You have a rod of length **n** inches and a price table that tells you how much each cut length sells for. You want to cut the rod into pieces (or keep it whole) to **maximize total revenue**.
```
Length: 1 2 3 4 5 6 7 8 9 10
Price: 1 5 8 9 10 17 17 20 24 30
```
For a rod of length 4, the best strategy is two pieces of length 2 (5 + 5 = **$10**), not selling it whole for $9.
This is a classic **optimal substructure** problem: the best way to cut a rod of length n depends on the best ways to cut shorter rods — making it a perfect fit for dynamic programming.
---
## Algorithms
### 1. Naive Recursion — `simple_cut_rod(p, n)`
Tries every possible first cut at position i and recurses on the remainder.
```python
def simple_cut_rod(p, n):
if n == 0:
return 0
q = float('-inf')
for i in range(1, n + 1):
q = max(q, p[i] + simple_cut_rod(p, n - i))
return q
```
**Time complexity:** O(2ⁿ) — exponential. Each subproblem is recomputed from scratch.
---
### 2. Top-Down DP with Memoization — `memoized_cut_rod(p, n)`
Same recursion as above, but caches results in an array `r`. If `r[n]` has already been computed, return it immediately.
```python
def memoized_cut_rod(p, n):
r = [float('-inf')] * (n + 1)
return _memoized_cut_rod_aux(p, n, r)
```
**Time complexity:** O(n²) — each of the n subproblems is solved exactly once.
---
### 3. Bottom-Up DP — `bottom_up_cut_rod(p, n)`
Fills a table `r[0..n]` iteratively from the smallest subproblem up. For each rod length j, tries every first cut i from 1 to j and stores the best result.
```python
def bottom_up_cut_rod(p, n):
r = [0] * (n + 1)
for j in range(1, n + 1):
q = float('-inf')
for i in range(1, j + 1):
q = max(q, p[i] + r[j - i])
r[j] = q
return r[n]
```
**Time complexity:** O(n²) | **Space complexity:** O(n)
This is the approach animated in the visualizer.
---
## Complexity Comparison
| Approach | Time | Space | Notes |
|---|---|---|---|
| Naive recursion | O(2ⁿ) | O(n) call stack | Impractical for n > 30 |
| Top-down (memoized) | O(n²) | O(n) | Natural recursive structure |
| Bottom-up | O(n²) | O(n) | No recursion overhead, cache-friendly |
---
## Project Files
```
.
├── cut_rod.py # Python implementation (all 3 algorithms)
├── visualization.html # Interactive browser visualizer
└── Cut Rod Problem/
└── Cut Rod Problem/
├── Program.cs # Original C# implementation
└── Data.txt # Price table (33 prices, space-separated)
```
### `Data.txt` — Price Table
```
1 5 8 9 10 17 17 20 24 30 33 31 31 31 40 39 20 45 42 46 70 76 77 80 85 90 95 100 110 120 111 200 678
```
Prices for lengths 1 through 33 inches.
---
## Running the Python Version
```bash
python3 cut_rod.py
```
You will be prompted for a rod length. Switch between algorithms by uncommenting the desired line in `main()`:
```python
best_price = memoized_cut_rod(prices, n) # default
# best_price = bottom_up_cut_rod(prices, n)
# best_price = simple_cut_rod(prices, n) # slow for n > 25
```
**Example output for n = 10:**
```
Enter number of Inches: 10
Best Revenue is upto : 30
Time Elapsed : 0.000021875s
```
---
## Running the Visualizer
Open `visualization.html` directly in any modern browser — no server or dependencies needed.
```bash
open visualization.html # macOS
start visualization.html # Windows
xdg-open visualization.html # Linux
```
### Controls
| Control | Action |
|---|---|
| Rod Length | Set the rod length (125). Resets the animation. |
| Speed | Adjust playback speed (1× slow → 10× fast). |
| ▶ Play | Run the animation automatically. |
| ⏸ Pause | Pause at the current step. |
| ⏭ Step | Advance one step forward. |
| ⏮ Back | Go one step backward. |
| ↺ Reset | Restart from the beginning. |
---
## Example: Rod of Length 10
The algorithm finds that the maximum revenue is **$30**, achieved by keeping the rod uncut (selling the full 10-inch piece at $30).
For a rod of length 7, the optimal is **3 + 4 = $17** (8 + 9 = $17, compared to selling whole for $17 — same either way, but the s-table reveals the first cut chosen).
---
## References
- Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). *Introduction to Algorithms* (3rd ed.), Section 15.1 — Rod cutting.

View File

@ -314,6 +314,81 @@ input[type=range] { width: 110px; accent-color: var(--purple); }
.r { color: var(--red); } .r { color: var(--red); }
.p { color: var(--purple); } .p { color: var(--purple); }
.o { color: var(--orange); } .o { color: var(--orange); }
/* ── LEGEND ──────────────────────────────────── */
.legend {
display: flex;
flex-wrap: wrap;
gap: 10px 20px;
justify-content: center;
max-width: 1120px;
margin: 0 auto 20px;
padding: 12px 20px;
background: var(--surf);
border: 1px solid var(--border);
border-radius: 10px;
font-size: .78rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 7px;
color: var(--dim);
}
.swatch {
width: 14px;
height: 14px;
border-radius: 3px;
flex-shrink: 0;
}
.swatch-outline {
width: 14px;
height: 14px;
border-radius: 3px;
flex-shrink: 0;
border: 2px solid;
}
/* ── EXPLAINER ───────────────────────────────── */
.explainer {
max-width: 1120px;
margin: 20px auto 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
}
@media (max-width: 800px) {
.explainer { grid-template-columns: 1fr; }
}
.exp-card {
background: var(--surf);
border: 1px solid var(--border);
border-radius: 12px;
padding: 18px 20px;
}
.exp-card h3 {
font-size: .8rem;
text-transform: uppercase;
letter-spacing: .08em;
color: var(--dim);
margin-bottom: 12px;
}
.exp-card p, .exp-card li {
font-size: .83rem;
line-height: 1.65;
color: #a0aab4;
}
.exp-card ul { padding-left: 16px; }
.exp-card li { margin-bottom: 5px; }
.exp-card code {
font-family: 'SFMono-Regular', 'Consolas', monospace;
font-size: .8rem;
background: var(--bg);
padding: 1px 5px;
border-radius: 4px;
color: var(--orange);
}
.exp-card .accent { color: var(--text); font-weight: 600; }
</style> </style>
</head> </head>
<body> <body>
@ -339,6 +414,34 @@ input[type=range] { width: 110px; accent-color: var(--purple); }
<button class="btn btn-secondary" id="btn-reset">↺ Reset</button> <button class="btn btn-secondary" id="btn-reset">↺ Reset</button>
</div> </div>
<!-- LEGEND -->
<div class="legend">
<div class="legend-item">
<div class="swatch" style="background:var(--red)"></div>
<span>Cut piece — sells for <strong style="color:var(--text)">p[i]</strong></span>
</div>
<div class="legend-item">
<div class="swatch" style="background:var(--blue)"></div>
<span>Remainder — best revenue already known as <strong style="color:var(--text)">r[ji]</strong></span>
</div>
<div class="legend-item">
<div class="swatch-outline" style="border-color:var(--yellow);background:#2b2400"></div>
<span><strong style="color:var(--yellow)">Yellow cell</strong> — currently being computed</span>
</div>
<div class="legend-item">
<div class="swatch" style="background:#122620"></div>
<span><strong style="color:var(--green)">Green cell</strong> — finalized value</span>
</div>
<div class="legend-item">
<div class="swatch" style="background:#0d1f36"></div>
<span><strong style="color:var(--blue)">Blue cell</strong> — value being read (r[ji])</span>
</div>
<div class="legend-item">
<div class="swatch" style="background:#1a1030"></div>
<span><strong style="color:var(--purple)">Purple cell</strong> — optimal first cut stored in s[j]</span>
</div>
</div>
<div class="layout"> <div class="layout">
<!-- LEFT COLUMN --> <!-- LEFT COLUMN -->
@ -395,6 +498,47 @@ input[type=range] { width: 110px; accent-color: var(--purple); }
</div> </div>
<!-- EXPLAINER -->
<div class="explainer">
<div class="exp-card">
<h3>The Problem</h3>
<p>
You have a rod of length <span class="accent">n</span> inches and a price table
<code>p[1..n]</code> where <code>p[i]</code> is what a piece of length <code>i</code> sells for.
You can cut the rod into any combination of integer lengths. The goal is to
<span class="accent">maximize total revenue</span>.
</p>
<br>
<p>
A rod of length 4 sold whole earns $9, but two pieces of length 2 earn $5 + $5 = <span class="accent">$10</span>.
Finding the best combination by brute force takes O(2ⁿ) time — dynamic programming reduces this to <span class="accent">O(n²)</span>.
</p>
</div>
<div class="exp-card">
<h3>How the Algorithm Works</h3>
<ul>
<li><span class="accent">Build up from small rods.</span> Compute the best revenue for length 1, then 2, then 3 … up to n. Each answer reuses earlier answers.</li>
<li><span class="accent">For each length j</span>, try every possible first cut at position <code>i = 1 … j</code>. The candidate revenue is <code>p[i] + r[ji]</code>: sell the first piece and optimally cut the rest.</li>
<li><span class="accent">Store the best.</span> <code>r[j]</code> holds the maximum over all cuts. <code>s[j]</code> records which cut produced that maximum — used later to reconstruct the actual pieces.</li>
<li><span class="accent">Reconstruct.</span> Follow <code>s[n] → s[ns[n]] → …</code> to read off the optimal cut sequence.</li>
</ul>
</div>
<div class="exp-card">
<h3>Reading the Visualization</h3>
<ul>
<li><span class="accent">Rod bar:</span> the red segment is the piece being sold now (length <code>i</code>); the blue segment is the remainder whose best revenue is already in the table.</li>
<li><span class="accent">DP table row r[j]:</span> fills left-to-right. The yellow cell is being computed right now; blue cells are the ones being looked up.</li>
<li><span class="accent">DP table row s[j]:</span> once a cell is finalized (purple), it tells you the optimal first cut for that rod length.</li>
<li><span class="accent">Pseudocode:</span> the highlighted line shows exactly which line of the algorithm the current step corresponds to.</li>
<li><span class="accent">Optimal Solution</span> (shown at the end): the colored bar divides the rod into its best pieces, each labeled with its length and sale price.</li>
</ul>
</div>
</div>
<script> <script>
// ── DATA ──────────────────────────────────────── // ── DATA ────────────────────────────────────────
const PRICE_DATA = [0,1,5,8,9,10,17,17,20,24,30,33,31,31,31,40,39,20,45,42,46,70,76,77,80,85,90,95,100,110,120,111,200,678]; const PRICE_DATA = [0,1,5,8,9,10,17,17,20,24,30,33,31,31,31,40,39,20,45,42,46,70,76,77,80,85,90,95,100,110,120,111,200,678];