Submission by: [Utkarsh Verma, MTech - IIT Kanpur] | Date: April 2026 | Python: 3.9+
WagonTrain/
├── solution.py ← MAIN SCRIPT — run this
├── assignment_wagon_data.csv ← raw input sensor data (6,195 rows)
├── assignment_weighbridge.pdf ← original problem statement
├── requirement.txt ← pip dependencies
├── summary.txt ← personal insights & contributions (~600 words)
└── output/ ← pre-generated reference outputs
├── output.csv ← GROUND TRUTH: 59 wagon-weight pairs
├── flagged_data.csv ← input CSV annotated with wagon IDs & allotment flags
├── logic.py ← standalone processing script (no dependencies)
├── logic_description.md ← full algorithm technical document
├── logic_description.html ← rendered version with pipeline diagrams
├── dashboard.html ← interactive data dashboard
├── report.html ← analysis report with all findings
└── figures/ ← 8 diagnostic plots (PNG)
├── 01_train_structure.png
├── 02_weight_detection.png
├── 03_digit_variability.png
├── 04_prefix_distribution.png
├── 05_camera_consistency.png
├── 06_prefix_map.png
├── 07_serial_pattern.png
└── 08_final_pipeline.png
Step 1 — Create virtual environment
python -m venv venv_wagon
Step 2 — Activate it
# Windows
venv_wagon\Scripts\activate
# macOS / Linux
source venv_wagon/bin/activate
Step 3 — Install dependencies
pip install -r requirement.txt
Step 4 — Run the pipeline
python solution.py "assignment_wagon_data.csv"
This performs a single sequential pass over the input CSV (no look-ahead) and
generates a fresh output/ folder containing output.csv, flagged_data.csv,
8 diagnostic plots, and a chapter-by-chapter terminal breakdown of every
algorithmic decision.
Note:
matplotlibandnumpyare required only for plot generation. If unavailable, the script runs cleanly and producesoutput.csvandflagged_data.csvwithout plots. Core logic has zero external dependencies.
Once the script completes, cross-check the freshly generated output against
the pre-generated reference in output/output.csv. Expected terminal summary:
Train: [2 Engine] + [58 Cargo] + [Guard Van]
Weights: 58 cargo (73.2t–94.6t) + guard van (22.6t)
OCR: 48 default + 10 diff allotment + 1 guard van
Check: 48/59 pass
Output: 59 rows in output/output.csv
To run a standalone minimal version (no matplotlib required):
python output/logic.py assignment_wagon_data.csv my_output.csv
Then diff my_output.csv against output/output.csv — both should be identical.
| File | Purpose |
|---|---|
solution.py |
Full pipeline — algorithm + design decisions + diagnostics |
output/logic.py |
Standalone core logic — clean, no analysis overhead |
output/logic_description.md |
Technical write-up with ASCII diagrams |
output/output.csv |
Final answer — 59 wagon-number + weight pairs |
summary.txt |
Personal contribution narrative — unique data insights |
The pipeline processes one CSV row at a time through three independent components: a 6-frame signal debouncer that converts noisy per-frame wagon classifier outputs into clean ENTER/EXIT boundary events; a last-valid-state 4-cycle weight tracker that counts mechanical axle-pair oscillations to register confirmed tonnage; and a PREFIX-SUFFIX OCR resolver that exploits the structural asymmetry of Indian Railway 11-digit wagon numbers — the first 6 digits (type/owner/year) are shared across a rake and resolved by camera consensus, while the last 5 digits (serial+check) are unique per wagon and resolved by cross-camera consistency voting. The three streams synchronise via two FIFO queues and produce 59 wagon–weight pairs in a single pass with zero look-ahead and O(1) state per component.