- Non-pangram count: 429819
- Imperfect pangram count: 488132
- Perfect pangram count: 8349
- Total pangram count: 571181 (perfect + imperfect)
#include <iostream>
#include <fstream>
#include <print>
#include <chrono>
#include <algorithm>
#include <string>
#include <cassert>
const char* defaultFileName = "List of 1000 strings.json";
enum class PangramType
{
NotAPangram,
ImperfectPangram,
PerfectPangram,
};
char const* PangramTypeNames[3] = {"Not a pangram", "Pangram", "Perfect pangram"};
std::string ReadTextFile(const char* fileName);
std::string ReadTextFile(std::basic_istream<char, std::char_traits<char>>& inputStream);
std::string_view GetNextString(std::string_view text);
PangramType DeterminePangramType(std::string_view text);
int main()
{
int pangramCounts[3 /*PangramType total*/] = {};
std::string fileText = ReadTextFile(defaultFileName);
std::string_view fileTextRange = fileText;
auto fileTextRangeEnd = fileTextRange.data() + fileTextRange.size(); // Can't use end() because of debug iterator bogus warning.
while (true)
{
std::string_view stringRange = GetNextString(fileTextRange);
if (stringRange.empty())
break;
PangramType pangramType = DeterminePangramType(stringRange);
++pangramCounts[size_t(pangramType)];
std::println("{} - {}", stringRange, PangramTypeNames[size_t(pangramType)]);
auto stringRangeEnd = stringRange.data() + stringRange.size() + 1;
fileTextRange = std::string_view{stringRangeEnd, fileTextRangeEnd};
}
std::println();
std::println("Non-pangram count: {}", pangramCounts[size_t(PangramType::NotAPangram)]);
std::println("Imperfect pangram count: {}", pangramCounts[size_t(PangramType::ImperfectPangram)]);
std::println("Perfect pangram count: {}", pangramCounts[size_t(PangramType::PerfectPangram)]);
std::println("Total pangram count: {} (perfect + imperfect)", pangramCounts[size_t(PangramType::ImperfectPangram)] + pangramCounts[size_t(PangramType::PerfectPangram)]);
return EXIT_SUCCESS;
}
std::string_view GetNextString(std::string_view text)
{
auto startPosition = text.find('"');
if (startPosition == std::string::npos)
return {};
auto endPosition = text.find('"', startPosition + 1);
if (endPosition == std::string::npos)
return {};
auto range = std::string_view(text).substr(startPosition + 1, endPosition - startPosition - 1);
return range;
}
std::string ReadTextFile(std::basic_istream<char, std::char_traits<char>>& inputStream)
{
std::string dataBuffer;
// Avoid unnecessary zeroing of the buffer which will just be overwritten anyway.
// The transient indeterminate values between resize_and_overwrite and read are irrelevant.
inputStream.seekg(0, std::ios_base::end);
std::size_t fileSize = inputStream.tellg();
inputStream.seekg(0, std::ios_base::beg);
auto dummyResize = [](char* buffer, std::size_t fileSize) noexcept -> size_t { return fileSize;};
dataBuffer.resize_and_overwrite(fileSize, dummyResize);
inputStream.read(dataBuffer.data(), fileSize);
return dataBuffer;
}
std::string ReadTextFile(const char* fileName)
{
std::ifstream inputStream(fileName, std::ios::binary);
if (!inputStream.is_open())
{
std::cerr << "Could not open the file - '" << fileName << "'" << std::endl;
return {};
}
std::string dataBuffer = ReadTextFile(inputStream);
inputStream.close();
return dataBuffer;
}
PangramType DeterminePangramType(std::string_view text)
{
bool lettersSeen[26] = {};
int letterCount = 0;
int uniqueLetterCount = 0;
for (char c : text)
{
c &= ~0x20; // Convert to uppercase.
if (c >= 'A' && c <= 'Z')
{
if (!lettersSeen[c - 'A'])++letterCount;
{
int letterIndex = c - 'A';
++uniqueLetterCount;
uniqueLetterCount += !lettersSeen[letterIndex];
lettersSeen[c]lettersSeen[letterIndex] = true;
}
}
}
if (uniqueLetterCount ==< sizeof(lettersSeen))
{
return PangramType::PerfectPangram;NotAPangram;
}
else if (uniqueLetterCountletterCount <== sizeof(lettersSeen))
{
return PangramType::NotAPangram;PerfectPangram;
}
else
{
return PangramType::ImperfectPangram;
}
}