secret_handshake.h
#ifndef SECRET_HANDSHAKE_H
#define SECRET_HANDSHAKE_H
#include <stddef.h>
const char **commands(size_t number);
#endif
secret_handshake.c
#include "secret_handshake.h"
#include <malloc.h>
static const char * signals[] = { "wink", "double blink", "close your eyes", "jump" };
const char **commands(size_t n) {
const char **output = calloc(4, sizeof(char *));
int signal = 0, signal_incr = 1, output_idx = 0, end = 4;
if (n & 16) {signal = 3; signal_incr = -1; end = -1;}
for (; signal != end; signal+=signal_incr)
if (n & 1 << signal)
output[output_idx++] = signals[signal];
return output;
}
This approach starts by defining an array of pointers to const
char
strings.
The const
indicates that the content of the elements can't be changed.
The static
is to indicate that the array has internal linkage within the file, and is not declared in the header for external use.
The commands
function starts by using the calloc
function to allocate the memory for the output pointer to pointers of const
char
s,
which can be thought of as an array of strings.
It indicates that the array will have 4
elements, and each element will be the size of a pointer to char
.
Variables are defined that control iterating through the signals array, setting their values to iterate in the normal order.
Also, the index for the ouput array is set to start with 0
.
The bitwise AND operator is used to check if the input number contains the signal for reversing the order of the other signals,
given that the signal for reversing is decimal value 16
(10000
in binary).
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 number passed in contains the signal for reverse, then the iteration variables are set to iterate backwards through the array of signals.
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 index being iterated.
It uses the falsiness of 0
and the truthiness of any value other than 0
.
for (; signal != end; signal+=signal_incr)
if (n & 1 << signal)
output[output_idx++] = signals[signal];
For example, if the index 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 number 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 string at index 0
of the array of signals is set to the element of the output array
at the current output index.
output_idx++
means that the value of output_idx
is incremented after it is used for indexing into the output array.
If the index being iterated is 1
, then 1
is shifted left 1
time, and the signal passed in is ANDed with 00010
.
If the number 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 string at index 1
of the array of signals is added to the output array
at the current output index.
If the number passed in, ANDed with 1
shifted left for the value of the index, is equal to 0
, then the signal in the array for that index is not set in the output array.
After iterating through the array of signals is done, the output array is returned from the function.