OK, so this is the cpp file.
#include "QuineMcCluskeyandPetrick.h"
// Solver universel
static void clearArrays() {
for (int i = 0; i < 26; i++) {
//processed[i] = ""; // Clear each string in the array
letterCounts[i] = 0; // Reset each integer to 0
}
}
String QuineMcCluskeyandPetrick(String input) {
String result;
clearArrays();
// Check the length of the input string
if (input.length() == 4) {
result = solve2x2(input);
}
else if (input.length() == 8) {
result = solve2x4(input);
}
else if (input.length() == 16) {
result = solve4x4(input);
}
else {
result = "Invalid length";
}
return result;
}
//Solver 4 par 4
// Define a 2D array stored in program memory
static const char data[18][2][17] PROGMEM = {
{"1111111111111111", "1"},
{"0111111111111111", "A+B+C+D"},
{"1011111111111111", "A+B+C+D'"},
{"1101111111111111", "A+B+C'+D"},
{"1110111111111111", "A+B+C'+D'"},
{"1111011111111111", "A+B'+C+D"},
{"1111101111111111", "A+B'+C+D'"},
{"1111110111111111", "A+B'+C'+D"},
{"1111111011111111", "A+B'+C'+D'"},
{"1111111101111111", "A'+B+C+D"},
{"1111111110111111", "A'+B+C+D'"},
{"1111111111011111", "A'+B+C'+D"},
{"1111111111101111", "A'+B+C'+D'"},
{"1111111111110111", "A'+B'+C+D"},
{"1111111111111011", "A'+B'+C+D'"},
{"1111111111111101", "A'+B'+C'+D"},
{"1111111111111110", "A'+B'+C'+D'"},
{"0000000000000000", "0"}
};
static String findValue(String searchStr) {
char buffer[17]; // Temporary buffer to store retrieved strings (16 characters + null terminator)
for (int i = 0; i < 18; i++) {
// Retrieve the binary string from the first column of the current row
strcpy_P(buffer, data[i][0]);
if (searchStr == String(buffer)) { // Compare the search string with the retrieved string
// Retrieve the value from the second column
strcpy_P(buffer, data[i][1]);
return String(buffer); // Return the corresponding value as a String
}
}
return "Not found"; // Return "Not found" if the search string isn't found
}
static String processBinaryInput(String binaryInput) {
// Array to store positions of '1's
int positions[16];
size_t size = 0;
// Convert binary string to positions of '1's
for (int i = 0; i < 16; i++) {
if (binaryInput.charAt(i) == '1') {
positions[size] = i; // Store the index of '1'
size++; // Increase the size of positions array
}
}
// Print the positions array for debugging
Serial.print("Positions: ");
for (int i = 0; i < size; i++) {
Serial.print(positions[i]);
Serial.print(" ");
}
Serial.println();
// Call the function to process values and get the result
return processValues(positions, size);
}
static String solve4x4(String input) {
// Ensure the input length is 16
if (input.length() != 16) {
return "Error: Input must be a 16-character string.";
}
// Count the number of '1's in the input
int countOnes = 0;
for (int i = 0; i < input.length(); i++) {
if (input[i] == '1') {
countOnes++;
}
}
// Apply Function A if count is 0, 16, or 1
if (countOnes == 0 || countOnes == 16 || countOnes == 15) {
return findValue(input); // Pass the input to the function
} else {
return processBinaryInput(input); // Pass the input to the function
}
}
//Solveur 2 par 2
// Define the 2D array stored in program memory
static const char data2x2[18][2][10] PROGMEM = {
{"0000", "0"},
{"0001", "AB"},
{"0010", "AB'"},
{"0011", "A"},
{"0100", "A'B"},
{"0101", "B"},
{"0110", "AB'+A'B"},
{"0111", "A+B"},
{"1000", "A'B'"},
{"1001", "A'B'+AB"},
{"1010", "B'"},
{"1011", "B'+A"},
{"1100", "A'"},
{"1101", "A'+B"},
{"1110", "A'+B'"},
{"1111", "1"}
};
// Function to find the string and return the value from the second column
static String solve2x2(String searchStr) {
char buffer[20]; // Temporary buffer for data retrieval (max 7 characters + null terminator)
for (int i = 0; i < 16; i++) {
// Retrieve the binary string (first column) from `PROGMEM`
strcpy_P(buffer, data2x2[i][0]);
if (searchStr == String(buffer)) { // Compare search string with retrieved string
// Retrieve the corresponding value (second column) from `PROGMEM`
strcpy_P(buffer, data2x2[i][1]);
return String(buffer); // Return the corresponding value as a String
}
}
return "Not found"; // Return "Not found" if the search string isn't found
}
//Solver 2 par 4
// Function to expand the 8-bit input binary string to a 16-bit binary string
static String expandTo16Bit(String input) {
String expanded = "";
// Loop through each bit of the input string and repeat it
for (int i = 0; i < input.length(); i++) {
// Add the bit twice to the expanded string
expanded += input.charAt(i);
expanded += input.charAt(i);
}
return expanded;
}
// solve2x4 function that applies two transformations and outputs the result
static String solve2x4(String inputBinary) {
// Apply functionA to the input binary
String resultA = expandTo16Bit(inputBinary);
// Apply functionB to the result of functionA
String resultB = solve4x4(resultA);
// Return the final result
return resultB;
}
static String processValues(int values[], size_t size) {
// Groups to hold the binary strings
String groups[5][10]; // 5 groups (0 to 4 ones), each can hold up to 10 items
int decimalGroups[5][10]; // 5 groups (0 to 4 ones), each can hold up to 10 items
int groupSizes[5]; // To track the size of each group
// Call the function with the input list
processValuesWithTracking(values, size, groups, decimalGroups, groupSizes);
// Print all groups with decimal values and the corresponding binary string
Serial.println("Groups and corresponding binary strings:");
printGroupsWithDecimalAndTracking(groups, decimalGroups, groupSizes);
createPairsAcrossGroups(groups, decimalGroups, groupSizes);
createPairsAcrossGroups(groups, decimalGroups, groupSizes);
processTranslatedGroups(groups, groupSizes);
String sortedTerms = sortTranslatedTerms(groups, groupSizes);
// Print the sorted terms
Serial.println("Sorted Translated Terms:");
Serial.println(sortedTerms);
processSortedTerms(sortedTerms);
String result = "";
String implicantCoverage[16]; // Array to store implicants
int mintermsCovered[16][16]; // 2D array to store minterms covered by each implicant
int implicantCount = 0; // Counter for implicants
String mintermImplicants[16];
// Call the function with all required arguments
findCoveredMinterms(sortedTerms, result, implicantCoverage, mintermsCovered, implicantCount);
// Print the results
Serial.println("Result:");
Serial.println(result);
Serial.println("Implicants and their covered minterms:");
for (int i = 0; i < implicantCount; i++) {
Serial.print(implicantCoverage[i] + ": ");
for (int j = 0; j < 16; j++) {
if (mintermsCovered[i][j] == -1) break; // Stop if no more minterms
Serial.print(mintermsCovered[i][j]);
Serial.print(" ");
}
Serial.println();
}
// Output the result to the Serial Monitor
Serial.println("The expressions that uniquely cover minterms are:");
Serial.println(result);
// Step 3: Call findImplicantsForMinterms
findImplicantsForMinterms(implicantCoverage, mintermsCovered, implicantCount, mintermImplicants);
// Step 4: Print the result
for (int i = 0; i < 16; i++) {
if (mintermImplicants[i].length() > 0) {
Serial.print("Minterm ");
Serial.print(i);
Serial.print(": ");
Serial.println(mintermImplicants[i]);
}
}
String formattedImplicants[16];
formatMintermImplicants(mintermImplicants, formattedImplicants);
// Print the result
for (int i = 0; i < 16; i++) {
if (formattedImplicants[i].length() > 0) {
Serial.print("Minterm ");
Serial.print(i);
Serial.print(": ");
Serial.println(formattedImplicants[i]);
}
}
String combined = combineFormattedImplicants(formattedImplicants);
Serial.print("Combined implicants: ");
Serial.println(combined);
String output = addQuotesBetweenPlusAndParentheses(combined);
Serial.println("Output: " + output);
// Declare variables with exotic names to hold the results
String chimericOutput = "";
String crypticMappings = "";
// Call the function with the input string
replaceTerms(output, chimericOutput, crypticMappings);
// Define a POS input string
String posInput = chimericOutput;
String sopOutput = "";
// Initial Sum of Product (SoP) expression
String sop = posInput;
Serial.println("Initial Expression: ");
Serial.println(sop);
while (true) {
// Locate the first two sets of parentheses
int firstOpen = sop.indexOf('(');
int firstClose = sop.indexOf(')', firstOpen);
int secondOpen = sop.indexOf('(', firstClose);
int secondClose = sop.indexOf(')', secondOpen);
// Break if there are no two pairs of parentheses left
if (firstOpen == -1 || firstClose == -1 || secondOpen == -1 || secondClose == -1) {
Serial.println("Final Expanded Expression: ");
Serial.println(sop);
break;
}
// Extract parts
String firstPart = sop.substring(firstOpen + 1, firstClose);
String secondPart = sop.substring(secondOpen + 1, secondClose);
// Multiply, simplify, and retain one of each duplicate
String expanded = multiplyAndSimplify(firstPart, secondPart);
// Replace the first two sets of parentheses with the expanded result
sop = sop.substring(0, firstOpen) + "(" + expanded + ")" + sop.substring(secondClose + 1);
// Debug: Print updated expression
Serial.println("Updated Expression:");
Serial.println(sop);
}
// Example input
String RA = sop;
// Call the groupLetters function
groupLetters10(RA);
Serial.println(crypticMappings);
String singleString = convertCrypticMappingToString(crypticMappings);
Serial.println(singleString); // Print the result to the serial monitor
RA.replace("(", ""); // Replace all '(' with an empty string
RA.replace(")", ""); // Replace all ')' with an empty string
// Process the input string and count occurrences for each term
processInput(singleString);
String encodedMessage = ""; // String to hold the final output
bool first = true; // Flag to track if it's the first result
for (char letter = 'A'; letter <= 'Z'; letter++) {
int index = letter - 'A'; // Convert 'A' to index 0, 'B' to index 1, etc.
if (letterCounts[index] > 0) {
if (!first) {
encodedMessage += ", "; // Add a comma before subsequent results
}
first = false; // After the first result, set the flag to false
encodedMessage += letter; // Add the letter to the string
encodedMessage += letterCounts[index]; // Add the count for the letter
}
}
// Now you can print the result string to the serial monitor
Serial.println(encodedMessage);
Serial.println();
Serial.println(RA);
// Example usage
String words = RA;
String binomes = encodedMessage;
String leastPointsWord = calculateWordPoints(words, binomes);
// Now you can use the result in your code, here we're printing it to the serial monitor
Serial.print("Word with least points: ");
Serial.println(leastPointsWord);
String inputWord = leastPointsWord;
String description = singleString;
// Get the replaced term result
String nt = replaceLettersWithTerms(inputWord, description);
// Return the final result (nt)
return nt;
}
static void processValuesWithTracking(const int* values, size_t size, String groups[5][10], int decimalGroups[5][10], int groupSizes[5]) {
// Initialize group sizes
for (int i = 0; i < 5; i++) {
groupSizes[i] = 0;
}
// Process each value in the input list
for (size_t k = 0; k < size; k++) {
int num = values[k];
// Convert the number to a 4-bit binary string
String binary = "";
for (int i = 3; i >= 0; i--) {
binary += String((num >> i) & 1);
}
// Count the number of 1s in the binary string
int oneCount = 0;
for (size_t j = 0; j < binary.length(); j++) {
if (binary[j] == '1') {
oneCount++;
}
}
// Add to the corresponding group
if (oneCount >= 0 && oneCount <= 4) {
int index = groupSizes[oneCount]; // Current size of the group
groups[oneCount][index] = binary; // Add binary string to the group
decimalGroups[oneCount][index] = num; // Add decimal value to the group
groupSizes[oneCount]++; // Increment the size of the group
}
}
}
static void printGroupsWithDecimalAndTracking(String groups[5][10], int decimalGroups[5][10], int groupSizes[5]) {
String allGroupsOutput = "";
// Iterate over each group and add the group information to the output string
for (int i = 0; i < 5; i++) {
allGroupsOutput += "Group with " + String(i) + " ones:\n";
if (groupSizes[i] > 0) {
for (int j = 0; j < groupSizes[i]; j++) {
allGroupsOutput += String(decimalGroups[i][j]) + ": " + groups[i][j] + "\n";
}
} else {
allGroupsOutput += "No entries in this group.\n";
}
}
// Print all groups at once
Serial.println(allGroupsOutput);
}
static void createPairsAcrossGroups(String groups[5][10], int decimalGroups[5][10], int groupSizes[5]) {
String newGroups[5][10]; // Temporary storage for new groups
int newGroupSizes[5] = {0}; // Sizes of temporary groups
bool madeChange; // Tracks if any new term was created
do {
madeChange = false;
bool used[5][10] = {{false}}; // Tracks whether terms were used in the current iteration
// Iterate through all pairs of groups (not just adjacent)
for (int i = 0; i < 5; i++) {
for (int j = i + 1; j < 5; j++) { // Compare group i with group j (i < j)
for (int k = 0; k < groupSizes[i]; k++) {
for (int l = 0; l < groupSizes[j]; l++) {
String bin1 = groups[i][k];
String bin2 = groups[j][l];
// Find the difference between the two binary terms
int diffCount = 0, diffIndex = -1;
for (int bit = 0; bit < bin1.length(); bit++) {
if (bin1[bit] != bin2[bit]) {
diffCount++;
diffIndex = bit;
}
}
if (diffCount == 1) { // Terms differ by exactly one bit
String newTerm = bin1;
newTerm[diffIndex] = '-'; // Replace differing bit with '-'
// Check if the new term already exists in the new group
bool isDuplicate = false;
for (int m = 0; m < newGroupSizes[i]; m++) {
if (newGroups[i][m] == newTerm) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
newGroups[i][newGroupSizes[i]] = newTerm; // Add new term
newGroupSizes[i]++;
madeChange = true;
// Debugging: Log the new term and which terms created it
Serial.print("New group formed by: ");
Serial.print(bin1);
Serial.print(" and ");
Serial.print(bin2);
Serial.print(" -> New term: ");
Serial.println(newTerm);
}
used[i][k] = true; // Mark original terms as used
used[j][l] = true; // Mark original terms as used
}
}
}
}
}
// Debugging: Print the current state of the groups and used array
Serial.println("Current groups after comparison:");
for (int i = 0; i < 5; i++) {
Serial.print("Group ");
Serial.print(i);
Serial.print(" (size ");
Serial.print(groupSizes[i]);
Serial.println("):");
for (int j = 0; j < groupSizes[i]; j++) {
Serial.println(groups[i][j]);
}
}
// Update groups: retain unused terms and add new terms
for (int i = 0; i < 5; i++) {
int newIndex = 0;
// Retain unused terms
for (int j = 0; j < groupSizes[i]; j++) {
if (!used[i][j]) {
groups[i][newIndex] = groups[i][j];
decimalGroups[i][newIndex] = decimalGroups[i][j];
newIndex++;
}
}
// Add new terms from this iteration
for (int j = 0; j < newGroupSizes[i]; j++) {
groups[i][newIndex] = newGroups[i][j];
newIndex++;
}
// Update group size
groupSizes[i] = newIndex;
}
// Clear new groups for the next iteration
for (int i = 0; i < 5; i++) {
newGroupSizes[i] = 0;
}
// Debugging: Print the groups after adding new terms and updating sizes
Serial.println("Groups after adding new terms:");
for (int i = 0; i < 5; i++) {
Serial.print("Group ");
Serial.print(i);
Serial.print(" (size ");
Serial.print(groupSizes[i]);
Serial.println("):");
for (int j = 0; j < groupSizes[i]; j++) {
Serial.println(groups[i][j]);
}
}
} while (madeChange); // Repeat until no changes are made
// Debugging: Print final groups before removing duplicates
Serial.println("Final groups before duplicates removal:");
for (int i = 0; i < 5; i++) {
if (groupSizes[i] > 0) {
Serial.print("Group with ");
Serial.print(i);
Serial.println(" ones:");
for (int j = 0; j < groupSizes[i]; j++) {
Serial.println(groups[i][j]);
}
}
}
// Remove duplicates from the final groups
for (int i = 0; i < 5; i++) {
removeDuplicates(groups[i], groupSizes[i]);
}
// Debugging: Print final groups after duplicates removal
Serial.println("Final groups after duplicates removal:");
for (int i = 0; i < 5; i++) {
if (groupSizes[i] > 0) {
Serial.print("Group with ");
Serial.print(i);
Serial.println(" ones:");
for (int j = 0; j < groupSizes[i]; j++) {
Serial.println(groups[i][j]);
}
}
}
}
// Helper function to remove duplicates from a group
static void removeDuplicates(String group[10], int &size) {
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (group[i] == group[j]) {
// Shift elements to remove duplicate
for (int k = j; k < size - 1; k++) {
group[k] = group[k + 1];
}
size--; // Decrease the size of the group
j--; // Recheck the new element at index j
}
}
}
}
static String translateTerm(String binTerm) {
String translatedTerm = "";
// Iterate over each bit in the binary term (4 bits)
for (int i = 0; i < 4; i++) {
char bit = binTerm[i];
if (bit == '1') {
// '1' translates to 'A', 'B', 'C', or 'D'
if (i == 0) translatedTerm += "A";
else if (i == 1) translatedTerm += "B";
else if (i == 2) translatedTerm += "C";
else if (i == 3) translatedTerm += "D";
}
else if (bit == '0') {
// '0' translates to 'A', 'B', 'C', or 'D' with a '
if (i == 0) translatedTerm += "A'";
else if (i == 1) translatedTerm += "B'";
else if (i == 2) translatedTerm += "C'";
else if (i == 3) translatedTerm += "D'";
}
else if (bit == '-') {
// If there's a '-', suppress the letter at that position
// Don't append anything for this position
continue;
}
}
return translatedTerm;
}
static void processTranslatedGroups(String groups[5][10], int groupSizes[5]) {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < groupSizes[i]; j++) {
// Translate each binary term in the group
String translatedTerm = translateTerm(groups[i][j]);
Serial.print("Original: ");
Serial.print(groups[i][j]);
Serial.print(" -> Translated: ");
Serial.println(translatedTerm);
}
}
}
static String sortTranslatedTerms(String groups[5][10], int groupSizes[5]) {
// Create an array to store the translated terms
String allTranslatedTerms[50];
int index = 0;
// Collect all translated terms into one array
for (int i = 0; i < 5; i++) {
for (int j = 0; j < groupSizes[i]; j++) {
String translatedTerm = translateTerm(groups[i][j]);
allTranslatedTerms[index++] = translatedTerm;
}
}
// Sort all translated terms alphabetically, taking apostrophes into account
for (int i = 0; i < index - 1; i++) {
for (int j = i + 1; j < index; j++) {
if (compareTerms(allTranslatedTerms[i], allTranslatedTerms[j])) {
String temp = allTranslatedTerms[i];
allTranslatedTerms[i] = allTranslatedTerms[j];
allTranslatedTerms[j] = temp;
}
}
}
// Join the sorted translated terms into a single string for easy display
String sortedTerms = "";
for (int i = 0; i < index; i++) {
sortedTerms += allTranslatedTerms[i] + " ";
}
return sortedTerms;
}
static bool compareTerms(String term1, String term2) {
int len1 = term1.length();
int len2 = term2.length();
int minLength = min(len1, len2);
for (int i = 0; i < minLength; i++) {
char char1 = term1[i];
char char2 = term2[i];
if (char1 == '\'') char1 = term1[i + 1]; // Skip the apostrophe
if (char2 == '\'') char2 = term2[i + 1]; // Skip the apostrophe
if (char1 != char2) {
return char1 < char2; // Alphabetically compare letters
}
}
return len1 < len2; // If they are the same up to the shortest length, consider their lengths
}
static void getMinterms(String term, int minterms[], int &mintermCount) {
mintermCount = 0;
// We assume there are four variables: A, B, C, D
// A -> bit 3, B -> bit 2, C -> bit 1, D -> bit 0
int totalMinterms = 16;
// Array to store which variables are fixed by the term
bool variableStates[4] = {false, false, false, false}; // A, B, C, D
bool isNegated[4] = {false, false, false, false}; // A', B', C', D'
// Check each character of the term to determine the state of each variable
for (int i = 0; i < term.length(); i++) {
char ch = term[i];
int varIndex = -1;
// Identify which variable the character corresponds to (A, B, C, D)
if (ch == 'A') varIndex = 0;
else if (ch == 'B') varIndex = 1;
else if (ch == 'C') varIndex = 2;
else if (ch == 'D') varIndex = 3;
if (varIndex != -1) {
// If the next character is a `'`, it's negated
if (i + 1 < term.length() && term[i + 1] == '\'') {
isNegated[varIndex] = true; // Negated variable
i++; // Skip the `'`
} else {
isNegated[varIndex] = false; // Non-negated variable
}
variableStates[varIndex] = true; // The variable is now fixed
}
}
// Iterate over all 16 possible minterms
for (int i = 0; i < totalMinterms; i++) {
bool match = true;
// Check for each variable (A, B, C, D)
for (int j = 0; j < 4; j++) {
if (variableStates[j]) { // This variable is fixed by the term
bool bitSet = (i >> (3 - j)) & 1; // Get the bit for the variable
// If it's negated, it must be 0
if (isNegated[j] && bitSet) {
match = false;
break;
}
// If it's not negated, it must be 1
if (!isNegated[j] && !bitSet) {
match = false;
break;
}
}
}
// If the minterm matches, add it to the list
if (match) {
minterms[mintermCount] = i;
mintermCount++;
}
}
}
// Function to process sorted terms and print their corresponding minterms
static void processSortedTerms(String sortedTerms) {
String term = "";
// Array to store minterms
int minterms[16]; // There are 16 possible minterms (for 4 variables)
int mintermCount = 0; // Counter for the number of minterms
// Trim leading/trailing spaces to avoid issues with empty terms
sortedTerms.trim();
// Split the sortedTerms into individual terms by space
for (int i = 0; i < sortedTerms.length(); i++) {
char ch = sortedTerms[i];
// If we reach a space, process the current term
if (ch == ' ') {
if (term.length() > 0) {
// Get the minterms for the current term
getMinterms(term, minterms, mintermCount);
// Print the term and the corresponding minterms
Serial.print("Term: ");
Serial.print(term);
Serial.print(" -> Minterms: ");
for (int j = 0; j < mintermCount; j++) {
Serial.print(minterms[j]);
if (j < mintermCount - 1) {
Serial.print(", ");
}
}
Serial.println();
// Reset term for the next iteration
term = "";
mintermCount = 0; // Reset minterm count for the next term
}
} else {
term += ch; // Add the character to the current term
}
}
// Process the last term if any (after the final space)
if (term.length() > 0) {
getMinterms(term, minterms, mintermCount);
Serial.print("Term: ");
Serial.print(term);
Serial.print(" -> Minterms: ");
for (int j = 0; j < mintermCount; j++) {
Serial.print(minterms[j]);
if (j < mintermCount - 1) {
Serial.print(", ");
}
}
Serial.println();
}
}
static void findCoveredMinterms(String sortedTerms, String &result, String (&implicantCoverage)[16], int (&mintermsCovered)[16][16], int &implicantCount) {
int mintermCount[16] = {0}; // To store the count of terms covering each minterm
String uniqueTermForMinterm[16]; // To store the term uniquely covering each minterm
String terms[16]; // To store all unique terms parsed from sortedTerms
int termCount = 0;
// Initialize the result string
result = "";
// Parse the sortedTerms into individual terms
for (int i = 0; i < sortedTerms.length(); i++) {
String term = "";
// Collect each term
while (i < sortedTerms.length() && sortedTerms[i] != ' ') {
term += sortedTerms[i];
i++;
}
// Avoid adding duplicate terms
bool isDuplicate = false;
for (int j = 0; j < termCount; j++) {
if (terms[j] == term) {
isDuplicate = true;
break;
}
}
if (!isDuplicate && term.length() > 0) {
terms[termCount++] = term;
}
}
// Map minterms to terms and track coverage
implicantCount = 0; // Reset implicant count
for (int i = 0; i < termCount; i++) {
int termMinterms[16];
int termMintermCount = 0;
// Get the minterms for the current term
getMinterms(terms[i], termMinterms, termMintermCount);
// Store the implicant in the implicantCoverage array
implicantCoverage[implicantCount] = terms[i];
// Reset the minterms covered by this implicant
for (int j = 0; j < 16; j++) {
mintermsCovered[implicantCount][j] = -1; // -1 indicates no coverage
}
// Update minterm coverage and record the term
for (int j = 0; j < termMintermCount; j++) {
int minterm = termMinterms[j];
// Track minterms covered by this term
mintermsCovered[implicantCount][j] = minterm;
if (mintermCount[minterm] == 0) {
// If no other term covers this minterm yet, record this term
uniqueTermForMinterm[minterm] = terms[i];
} else {
// If the minterm is already covered by another term, clear unique record
uniqueTermForMinterm[minterm] = "";
}
// Increment coverage count for this minterm
mintermCount[minterm]++;
}
// Increment the implicant count
implicantCount++;
}
// Add terms to the result where minterms are uniquely covered
for (int i = 0; i < 16; i++) {
if (mintermCount[i] == 1 && uniqueTermForMinterm[i].length() > 0) {
if (result.indexOf(uniqueTermForMinterm[i]) == -1) { // Avoid duplicate terms in the result
result += uniqueTermForMinterm[i];
result += " ";
}
}
}
}
// Function to find implicants for minterms
static void findImplicantsForMinterms(String implicantCoverage[],
int mintermsCovered[][16],
int implicantCount,
String mintermImplicants[]) {
// Initialize the result array with empty strings
for (int i = 0; i < 16; i++) {
mintermImplicants[i] = "";
}
// Loop over all implicants
for (int i = 0; i < implicantCount; i++) {
Serial.print("Processing implicant: ");
Serial.println(implicantCoverage[i]);
for (int j = 0; j < 16; j++) {
int minterm = mintermsCovered[i][j];
if (minterm == -1) {
// No more minterms covered by this implicant
break;
}
// Append the implicant to the list of the corresponding minterm, if not already added
if (mintermImplicants[minterm].length() > 0) {
// Check if the implicant is already added to the minterm
if (mintermImplicants[minterm].indexOf(implicantCoverage[i]) == -1) {
mintermImplicants[minterm] += ":"; // Add separator if it's not the first implicant
mintermImplicants[minterm] += implicantCoverage[i];
}
} else {
// First implicant for this minterm
mintermImplicants[minterm] += implicantCoverage[i];
}
Serial.print("Minterm ");
Serial.print(minterm);
Serial.print(" covered by implicant: ");
Serial.println(implicantCoverage[i]);
}
}
}
// Function to format minterm implicants into readable format
static void formatMintermImplicants(String mintermImplicants[], String formattedImplicants[]) {
// Iterate through each minterm
for (int i = 0; i < 16; i++) {
Serial.print("Formatting minterm ");
Serial.println(i);
// Check if the minterm has any implicants
if (mintermImplicants[i].length() > 0) {
String formatted = "(";
bool firstImplicant = true;
// Iterate through each character in the implicant string
for (int j = 0; j < mintermImplicants[i].length(); j++) {
// Find the end of the current implicant (until the colon or end of the string)
int start = j;
while (j < mintermImplicants[i].length() && mintermImplicants[i][j] != ':') {
j++;
}
// Extract the implicant substring
String implicant = mintermImplicants[i].substring(start, j);
// Add to the formatted result
if (!firstImplicant) {
formatted += "+";
}
formatted += implicant;
firstImplicant = false; // Ensure "+" is added between implicants
}
formatted += ")";
formattedImplicants[i] = formatted;
Serial.print("Formatted implicants for minterm ");
Serial.print(i);
Serial.print(": ");
Serial.println(formattedImplicants[i]);
} else {
formattedImplicants[i] = ""; // No implicants for this minterm
Serial.print("No implicants for minterm ");
Serial.println(i);
}
}
}
// Function to combine all formatted implicants into one string
static String combineFormattedImplicants(String formattedImplicants[]) {
String combined = ""; // Initialize an empty string to store the result
// Loop through each minterm
for (int i = 0; i < 16; i++) {
if (formattedImplicants[i].length() > 0) {
// Add the formatted implicant enclosed in parentheses to the combined string
combined += formattedImplicants[i];
}
}
// Return the combined string
return combined;
}
static String addQuotesBetweenPlusAndParentheses(String input) {
String result = "";
bool insideParentheses = false;
bool quotingRequired = false;
String temp = "";
for (int i = 0; i < input.length(); i++) {
char currentChar = input[i];
if (currentChar == '(') {
// Start of parentheses block
if (temp.length() > 0) {
// Add any collected content into quotes before starting new block
result += "\"" + temp + "\"";
temp = "";
}
result += "(";
insideParentheses = true;
quotingRequired = true;
} else if (currentChar == ')') {
// End of parentheses block
if (temp.length() > 0) {
result += "\"" + temp + "\"";
temp = "";
}
result += ")";
insideParentheses = false;
quotingRequired = false;
} else if (currentChar == '+') {
// Plus symbol
if (temp.length() > 0) {
result += "\"" + temp + "\"";
temp = "";
}
result += "+";
quotingRequired = true;
} else if (quotingRequired && !isspace(currentChar)) {
// Collect content to be quoted
temp += currentChar;
} else {
// Add non-quoted content (e.g., spaces)
if (temp.length() > 0) {
result += "\"" + temp + "\"";
temp = "";
}
result += currentChar;
}
}
// Add any leftover content
if (temp.length() > 0) {
result += "\"" + temp + "\"";
}
return result;
}
// Helper function to generate a random unique letter
static char generateRandomUniqueLetter(bool usedLetters[]) {
char letter;
do {
letter = 'A' + random(0, 26); // Pick a random letter between A and Z
} while (usedLetters[letter - 'A']); // Ensure the letter hasn't been used already
usedLetters[letter - 'A'] = true; // Mark the letter as used
return letter;
}
static void replaceTerms(String input, String &arcaneOutput, String &mysticMappings) {
bool usedLetters[26] = {false}; // Array to keep track of used letters
String terms[50]; // Array to store the unique terms (can store up to 50 terms)
char letters[50]; // Array to store the corresponding letters for the terms
int termCount = 0; // Counter for the number of terms encountered
// Split the input string based on the quote symbols
int startIndex = -1; // To store the starting index of the quoted term
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == '"') {
if (startIndex == -1) {
startIndex = i; // Found the start of a quoted term
} else {
String term = input.substring(startIndex + 1, i); // Extract the term between quotes
char randomLetter;
// Check if the term already exists
int foundIndex = -1;
for (int j = 0; j < termCount; j++) {
if (terms[j] == term) {
foundIndex = j;
break;
}
}
// If the term already has a letter, use that letter, else assign a new letter
if (foundIndex == -1) {
randomLetter = generateRandomUniqueLetter(usedLetters); // Get a random unique letter
// Ensure we don't reuse the same letter
if (randomLetter == '\0') {
Serial.println("Error: No available letters left!"); // If we get '\0', we ran out of available letters
return; // Exit if no letters are available
}
// Store the new term and its corresponding letter
terms[termCount] = term;
letters[termCount] = randomLetter;
termCount++;
// Mark the letter as used
usedLetters[randomLetter - 'A'] = true;
// Debugging: Log the assigned letter
Serial.print("Assigned letter: ");
Serial.println(randomLetter);
// Append the mapping to mysticMappings only the first time
mysticMappings += String(randomLetter) + " -> \"" + term + "\"\n";
} else {
randomLetter = letters[foundIndex]; // Use the existing letter for the term
}
// Append the random letter to the output (only once per term)
arcaneOutput += randomLetter;
startIndex = -1; // Reset for the next quote
}
} else if (startIndex == -1) {
arcaneOutput += input.charAt(i); // Append non-quoted characters to the result string
}
}
// Print final outputs directly for inspection
Serial.println("arcaneOutput: " + arcaneOutput);
Serial.println("mysticMappings: " + mysticMappings);
}
static void groupLetters10(String input) {
String currentGroup = ""; // To store the current group of letters
String groups[50]; // Array to store the resulting groups
int groupCount = 0; // Counter for the number of groups
// Loop through the string and create groups
for (int i = 0; i < input.length(); i++) {
char currentChar = input.charAt(i);
// Check if the current character is a letter (A-Z, a-z)
if (isAlpha(currentChar)) {
// Add to the current group if it's a letter
currentGroup += currentChar;
} else {
// If we encounter a non-letter, store the current group (if it's not empty)
if (currentGroup.length() > 0) {
groups[groupCount++] = currentGroup; // Store the group
currentGroup = ""; // Reset the current group
}
}
}
// If there is a group left at the end of the string, add it
if (currentGroup.length() > 0) {
groups[groupCount++] = currentGroup;
}
// Find the group(s) with the smallest length
int minLength = input.length(); // Start with a large number
for (int i = 0; i < groupCount; i++) {
int groupLength = groups[i].length();
if (groupLength < minLength) {
minLength = groupLength; // Update minimum length
}
}
// Output the groups with the smallest length
Serial.println("Groups with smallest length:");
for (int i = 0; i < groupCount; i++) {
if (groups[i].length() == minLength) {
Serial.println(groups[i]); // Print the group
}
}
}
// Function to convert crypticMappings to a single string
static String convertCrypticMappingToString(String mysticMappings) {
String result = ""; // Initialize an empty string to store the final output
int startIndex = 0;
while (startIndex < mysticMappings.length()) {
int newlineIndex = mysticMappings.indexOf('\n', startIndex); // Find the next newline
if (newlineIndex == -1) break;
String line = mysticMappings.substring(startIndex, newlineIndex); // Extract each line
result += line + " "; // Add the line followed by a space (or any separator you prefer)
startIndex = newlineIndex + 1; // Move to the next line
}
// Remove any extra space at the end of the result string
if (result.length() > 0 && result[result.length() - 1] == ' ') {
result.remove(result.length() - 1);
}
return result; // Return the final concatenated string
}
static String processInput(String input) {
String processed[26]; // Tracks processed (letter-term) combinations
String result = ""; // Initialize the result string
int startIndex = 0;
while (startIndex < input.length()) {
// A map to store counts for each letter
int arrowIndex = input.indexOf("->", startIndex);
if (arrowIndex == -1) break; // No more mappings
int letterIndex = arrowIndex - 2; // Position of the letter
char letter = input.charAt(letterIndex); // Get the letter (L, R, etc.)
// Ensure that the letter is a valid alphabet character (A-Z)
if (letter >= 'A' && letter <= 'Z') {
// Find the start and end of the term inside the quotes
int quoteStartIndex = input.indexOf('\"', arrowIndex);
int quoteEndIndex = input.indexOf('\"', quoteStartIndex + 1); // Initialize quoteEndIndex here
// Extract the term inside the quotes
String term = input.substring(quoteStartIndex + 1, quoteEndIndex);
// Create a unique string representing the letter-term combination
String letterTerm = String(letter) + "-" + term;
// Check if this (letter, term) combination has already been processed
int letterIndex = letter - 'A'; // Convert 'A' to index 0, 'B' to index 1, etc.
bool isProcessed = false;
// Check if we've processed this letter-term combination
for (int i = 0; i < processed[letterIndex].length(); i++) {
if (processed[letterIndex].substring(i, i + letterTerm.length()) == letterTerm) {
isProcessed = true;
break;
}
}
if (isProcessed) {
// If the term has already been processed for this letter, skip
startIndex = quoteEndIndex + 1;
continue;
}
// Count the number of characters in the term
int termLength = term.length();
// Update the count for the corresponding letter
letterCounts[letterIndex] += termLength;
// Add this (letter, term) combination to the processed list
processed[letterIndex] += letterTerm + ","; // Append this combination
// Append the result to the string
result += String(letter) + "->" + term + " (Length: " + String(termLength) + ")\n";
}
// Move the start index forward to continue searching
startIndex = arrowIndex + 2; // Move past the "->"
}
return result;
}
static String calculateWordPoints(String words, String binomes) {
// Remove any whitespace from the input strings
words.replace(" ", "");
binomes.replace(" ", "");
// Split the binomes into an array of letter-number pairs
String binomesArr[10]; // Adjust size according to the expected number of binomes
int numBinomes = 0;
int startIdx = 0;
for (int i = 0; i < binomes.length(); i++) {
if (binomes.charAt(i) == ',') {
binomesArr[numBinomes++] = binomes.substring(startIdx, i);
startIdx = i + 1;
}
}
binomesArr[numBinomes++] = binomes.substring(startIdx); // Add the last binome
// Create a map (array) to store points for each letter
int letterPoints[26] = {0}; // For A-Z letters
// Populate the letter points based on the binomes
for (int i = 0; i < numBinomes; i++) {
String binome = binomesArr[i];
char letter = binome.charAt(0); // Letter is the first character
int points = binome.substring(1).toInt(); // Get the number after the letter
letterPoints[letter - 'A'] = points; // Store the points corresponding to the letter
}
// Split the words into an array
String wordsArr[10]; // Adjust size according to the expected number of words
int numWords = 0;
startIdx = 0;
for (int i = 0; i < words.length(); i++) {
if (words.charAt(i) == '+') {
wordsArr[numWords++] = words.substring(startIdx, i);
startIdx = i + 1;
}
}
wordsArr[numWords++] = words.substring(startIdx); // Add the last word
// Variables to track the least points and the words with the least points
int minPointValue = 9999; // Use a reasonably large number as initial value
String wordsWithMinPoints[10]; // Array to store words with the least points
int numMinWords = 0;
// Process each word and calculate the points
for (int i = 0; i < numWords; i++) {
String word = wordsArr[i];
int wordPoints = 0;
// Calculate the total points for the word
for (int j = 0; j < word.length(); j++) {
char letter = word.charAt(j);
if (letter >= 'A' && letter <= 'Z') {
wordPoints += letterPoints[letter - 'A'];
}
}
// Print the word and its total points
Serial.print(word);
Serial.print(": ");
Serial.println(wordPoints);
// Track the least points and the words with the least points
if (wordPoints < minPointValue) {
minPointValue = wordPoints;
wordsWithMinPoints[0] = word; // Reset the array with the new least point word
numMinWords = 1;
} else if (wordPoints == minPointValue) {
wordsWithMinPoints[numMinWords++] = word; // Add to the array if it has the same least points
}
}
// Print the minimum points value
Serial.print("Minimum points value: ");
Serial.println(minPointValue);
// If there are multiple words with the least points, select one randomly
String selectedWord = wordsWithMinPoints[random(numMinWords)];
// Return the word with the least points
return selectedWord;
}
static String replaceLettersWithTerms(String inputWord, String description) {
// Remove spaces from the description string
description.replace(" ", "");
// Create a map for letter -> term mapping
String result = "";
// Loop through each character in the inputWord
for (int i = 0; i < inputWord.length(); i++) {
char letter = inputWord.charAt(i);
String term = extractTermForLetter(letter, description);
if (i > 0) {
result += "+";
}
result += term;
}
return result;
}
static String extractTermForLetter(char letter, String description) {
// Find the position of the letter in the description string
String pattern = String(letter) + "->\"";
int startPos = description.indexOf(pattern);
if (startPos == -1) {
return ""; // If no match found, return an empty string
}
// Extract the term associated with the letter
startPos += pattern.length(); // Move position after "letter->"
int endPos = description.indexOf("\"", startPos); // Find the end of the term
String term = description.substring(startPos, endPos);
return term;
}
// Function to multiply terms and apply simplifications
static String multiplyAndSimplify(String part1, String part2) {
String terms[MAX_TERMS];
int termCount = 0;
// Split part1 into terms
int i = 0;
while (i < part1.length()) {
int endFirst = part1.indexOf('+', i);
if (endFirst == -1) endFirst = part1.length();
String term1 = part1.substring(i, endFirst);
// Split part2 into terms
int j = 0;
while (j < part2.length()) {
int endSecond = part2.indexOf('+', j);
if (endSecond == -1) endSecond = part2.length();
String term2 = part2.substring(j, endSecond);
// Combine terms and remove duplicates within each term
String newTerm = removeDuplicateLetters(term1 + term2);
// Add to list if not already present
bool isDuplicate = false;
for (int k = 0; k < termCount; k++) {
if (terms[k] == newTerm) {
isDuplicate = true;
break;
}
}
if (!isDuplicate && termCount < MAX_TERMS) {
terms[termCount++] = newTerm;
}
j = endSecond + 1;
}
i = endFirst + 1;
}
// Apply redundancy elimination (retain one instance of each term, remove redundant bigger terms)
String simplified = removeRedundantTerms(terms, termCount);
return simplified;
}
// Function to remove duplicate letters within a term
static String removeDuplicateLetters(String term) {
String result = "";
for (int i = 0; i < term.length(); i++) {
char c = term[i];
if (result.indexOf(c) == -1) {
result += c;
}
}
return result;
}
// Function to remove redundant terms (retain one instance of each unique term)
static String removeRedundantTerms(String terms[], int termCount) {
String result = "";
for (int i = 0; i < termCount; i++) {
bool isRedundant = false;
for (int j = 0; j < termCount; j++) {
if (i != j && isSubset(terms[j], terms[i])) {
// If the current term (i) is a superset of another term (j), mark it redundant
isRedundant = true;
break;
}
}
// Retain non-redundant terms
if (!isRedundant) {
result += terms[i] + "+";
}
}
// Remove trailing '+' if present
if (result.endsWith("+")) {
result = result.substring(0, result.length() - 1);
}
return result;
}
// Function to check if term1 is a subset of term2
static bool isSubset(String term1, String term2) {
for (int i = 0; i < term1.length(); i++) {
if (term2.indexOf(term1[i]) == -1) {
return false; // A letter in term1 is not in term2
}
}
return true;
}