Iterate once

Secret Handshake
Secret Handshake in C++

secret_handshake.h

#if !defined(SECRET_HANDSHAKE_H)
#define SECRET_HANDSHAKE_H
#include <vector>
#include <string>

namespace secret_handshake {
    std::vector<std::string> commands (unsigned int signal);
}  // namespace secret_handshake

#endif // SECRET_HANDSHAKE_H

secret_handshake.cpp

#include "secret_handshake.h"

namespace {
    const std::vector<std::string> actions = {
        "wink",
        "double blink",
        "close your eyes",
        "jump",
    };
    const unsigned int reverse = 16;
}

namespace secret_handshake {
    std::vector<std::string> commands (unsigned int signal) {
        std::vector<std::string> output;
        int action = 0, action_incr = 1, end = actions.size();
        if (signal & reverse) {action = actions.size() - 1; action_incr = -1; end = -1;}        
            
        for (; action != end; action += action_incr)
            if (signal & (1 << action))
                output.emplace_back(actions[action]);
        return output;
    }
}  // namespace secret_handshake

This approach starts by defining a const vector to hold the action values in their normal order. The value of 16 is defined as a const with a meaningful name so it won't be used as a magic number. The values are defined within an unnamed namespace. The static keyword used to be used for this, but it was deprecated for this purpose in former versions (and then was later undeprecated.) Many coders still prefer using the unnamed namespace.

The output vector is defined, and then variables are defined that control iterating through the actions vector, setting their values to iterate in the normal order.

The bitwise AND operator is used to check if the input signal contains the action for reversing the order of the other actions.

For example, if the number passed in is 19, which is 10011 in binary, then it is ANDed with 16, which is 10000 in binary. The 1 in 10000 is also at the same position in 10011, so the two values ANDed will not be 0.

  • 10011 AND
  • 10000 =
  • 10000

If the number passed in is 3, which is 00011 in binary, then it is ANDed with 16, which is 10000 in binary. The 1 in 10000 is not at the same position in 00011, so the two values ANDed will be 0.

  • 00011 AND
  • 10000 =
  • 00000

If the signal passed in contains the action for reverse, then the iteration variables are set to iterate backwards through the vector of actions.

The for loop begins.

Normal iteration will start at index 0. Reverse iteration will start at index 3.

Normal iteration will terminate when the index equals 4. Reverse iteration will terminate when the index equals -1.

Normal iteration will increase the index by 1 for each iteration. Reverse iteration will decrease the index by 1 for each iteration.

For each iteration of the for loop, the AND operator is used to check if the number passed in contains 1 shifted left (<<) for the number of positions as the value being iterated. It uses the falsiness of 0 and the truthiness of any value other than 0.

for (; action != end; action += action_incr)
    if (signal & (1 << action))
        output.emplace_back(actions[action]);

For example, if the number being iterated is 0, then 1 is shifted left 0 times (so not shifted at all), and the signal passed in is ANDed with 00001. If the signal passed in is 3, which is 00011 in binary, then it is ANDed with 00001. 00011 ANDed with 00001 is not equal to 0 (so not false), so the action at the index of the vector of actions is added to the output vector. The index used is the number being iterated, which is 0, so the element at index 0 ("wink") would be added to the output vector using the emplace_back function.

If the number being iterated is 1, then 1 is shifted left 1 time, and the signal passed in is ANDed with 00010. If the signal passed in is 3, which is 00011 in binary, then it is ANDed with 00010. 00011 ANDed with 00010 is not equal to 0 (so not false), so the action at the index of the vector of actions is added to the output vector. The index used is the number being iterated, which is 1, so the element at index 1 ("double blink") would be added to the output vector.

If the signal passed in ANDed with the number being iterated is equal to 0, then the action in the vector for that index is not added to the output vector.

After iterating through the vector of actions is done, the output vector is returned from the function.

21st Aug 2024 · Found it useful?