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.