#include <iostream>
#include <fstream>
#include <vector>
#include <unordered_set>
#include <string>
#include <queue>
using namespace std;
// ✅ LeetCode-like function to find the shortest ladder length (BFS)
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> wordSet(wordList.begin(), wordList.end());
if (!wordSet.count(endWord)) return 0;
queue<pair<string, int>> q;
q.push({beginWord, 1});
while (!q.empty()) {
auto [word, steps] = q.front(); q.pop();
if (word == endWord) return steps;
for (int i = 0; i < word.size(); i++) {
string temp = word;
for (char c = 'a'; c <= 'z'; c++) {
temp[i] = c;
if (wordSet.count(temp)) {
wordSet.erase(temp);
q.push({temp, steps + 1});
}
}
}
}
return 0; // no path found
}
// ✅ Checks if two words differ by exactly one letter
bool isOneLetterDiff(const string& a, const string& b) {
if (a.length() != b.length()) return false;
int diff = 0;
for (int i = 0; i < a.length(); ++i)
if (a[i] != b[i] && ++diff > 1)
return false;
return diff == 1;
}
// ✅ Validates the entire path submitted by the player
bool isValidLadderPath(const vector<string>& path,
const unordered_set<string>& dictionary,
const string& startWord,
const string& endWord) {
if (path.empty() || path.front() != startWord || path.back() != endWord)
return false;
for (const string& word : path) {
if (!dictionary.count(word)) {
cout << "❌ Word not in dictionary: " << word << endl;
return false;
}
}
for (int i = 1; i < path.size(); ++i) {
if (!isOneLetterDiff(path[i - 1], path[i])) {
cout << "❌ Invalid step: " << path[i - 1] << " -> " << path[i] << endl;
return false;
}
}
return true;
}
// ✅ Loads dictionary of given length from file
unordered_set<string> loadDictionary(const string& filename, int wordLength, vector<string>& wordListOut) {
unordered_set<string> dict;
ifstream file(filename);
string word;
while (file >> word) {
if (word.length() == wordLength) {
dict.insert(word);
wordListOut.push_back(word); // for ladderLength()
}
}
return dict;
}
// 🧩 Entry point
int main() {
string startWord = "cold";
string endWord = "warm";
// 🔽 Load dictionary and filtered word list
vector<string> wordList;
unordered_set<string> dictionary = loadDictionary("words.txt", startWord.length(), wordList);
// 🧠 Calculate the minimum steps required
int minSteps = ladderLength(startWord, endWord, wordList);
if (minSteps == 0) {
cout << "❌ No valid transformation from " << startWord << " to " << endWord << ".\n";
return 0;
}
cout << "🎮 Game Start! Transform '" << startWord << "' to '" << endWord << "'.\n";
cout << "📏 Minimum steps possible: " << minSteps << endl;
// 🧑💻 Simulate user path input (replace this with actual input from player)
vector<string> userPath = {"cold", "cord", "card", "ward", "warm"}; // <-- replace with user input logic
// ✅ Validate player path
if (isValidLadderPath(userPath, dictionary, startWord, endWord)) {
cout << "✅ Valid path submitted!\n";
int playerSteps = userPath.size();
cout << "📦 Player steps: " << playerSteps << endl;
// 🧮 Score computation
int score = 0;
if (playerSteps == minSteps) score = 100;
else if (playerSteps > minSteps) score = max(0, 100 - 10 * (playerSteps - minSteps));
else score = 0;
cout << "🏆 Score: " << score << "/100\n";
} else {
cout << "❌ Invalid path submitted.\n";
}
return 0;
}