Ad
Mathematics
Regular Expressions
Parsing

A quaternion contains 4 components; 1 Real Component and 3 Imaginary Components. The imaginary components are represented by the suffix i, j, k.

For example, 1 -2i + 3j - 4k is a quaternion with 1 being the real component and -2, 3, and -4 being the imaginary components.

In this kata you have to parse a string of a quaternion (ex. "1 + 2i - 3j - 4k") into a list/array of coefficients (ex. [1 2 -3 -4], with the real component first, then i, j, k). However, the quaternion string can be formatted in many different ways...

standard form: 1+2i-3j-4k
missing terms: 1-3k, 2i-4k
missing coefficients: i+j-k
It may not be in the right order: 2i-1+3k-4j
The coefficients may be integers or decimals: 7-2.4i+3.75j-4.0k

If you have missing terms, output 0 for those terms.

If you have missing coefficients, assume that the missing coefficient is 1.

There are some other things to note while parsing:

* There will always be a + or - between terms.
* You will always be passed valid input with at least 1 term, and without repeated components
* All numbers can be assumed to be valid
* You can change numbers into another form after parsing (ex. 3.0 => 3, 0.4 => .4, 7 => 7.0)
#include <array>
#include <string>
#include <regex>
#include <algorithm>

std::array<float, 4> ParseQuaternion(const std::string& t_quaternion)
{
    std::smatch matches;
    std::regex realCompPattern("(-?)([0-9.]+)*[^ijk]([+]|-|$)");
    std::regex_search(t_quaternion, matches, realCompPattern);

    float w = matches.empty() ? 0 : std::stof(matches[0]);

    auto g = [&](const std::string& t_letter) -> float {
        const std::regex pattern(R"((-?)([ (0-9).]+)?)" + t_letter);
        std::string result;
        if (std::regex_search(t_quaternion, matches, pattern))
        {
            if (matches[2].matched && matches[2] != " ")
            {
                auto matchStr = matches[2].str();
                matchStr.erase(std::remove(matchStr.begin(), matchStr.end(), ' '), matchStr.end());
                result = matches[1].str() + matchStr;
            }
            else
            {
                result = matches[1].str() + "1";
            }
        }
        else
        {
            result = "0";
        }
        return std::stof(result);
    };

    auto i = g("i");
    auto j = g("j");
    auto k = g("k");

    return { w, i, j, k };
}