Skip to content

Commit f99f0d6

Browse files
Add sliding window XOR implementation with tests in C++
1 parent ba0d3ff commit f99f0d6

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/**
2+
* @file
3+
* @brief Implementation to [calculate XOR of sliding window of size k in an array of n integers]
4+
* (https://cses.fi/problemset/task/3426)
5+
*
6+
* @details
7+
* We are given an array of n integers. Our task is to calculate the bitwise XOR of each
8+
* window of k elements, from left to right, and cumulatively XOR the results into a single value.
9+
*
10+
* Worst Case Time Complexity: O(n)
11+
* Space Complexity: O(n)
12+
*
13+
* @author [Abhiraj Mandal](https://github.com/DataWorshipper)
14+
*/
15+
16+
#include <cassert> /// for assert
17+
#include <cstdint>
18+
#include <vector>
19+
#include <iostream> /// for IO operations
20+
21+
/**
22+
* @namespace bit_manipulation
23+
* @brief Bit manipulation algorithms
24+
*/
25+
namespace bit_manipulation {
26+
/**
27+
* @namespace sliding_window_xor
28+
* @brief Functions for cumulative XOR of sliding windows in arrays
29+
*/
30+
namespace sliding_window_xor {
31+
32+
/**
33+
* @brief Computes cumulative XOR of all windows of size k
34+
*
35+
* @param n Size of the array
36+
* @param k Window size
37+
* @param x Initial value to generate the array
38+
* @param a Multiplier in array generation
39+
* @param b Increment in array generation
40+
* @param c Modulo in array generation
41+
* @returns std::uint64_t The cumulative XOR of all windows of size k
42+
*
43+
* @details
44+
* This function generates the array using the recurrence:
45+
* arr[0] = x
46+
* arr[i] = (a * arr[i-1] + b) % c
47+
*
48+
* It maintains a sliding window of size k using two pointers l and r:
49+
* - x1 stores the XOR of the current window
50+
* - x2 stores the cumulative XOR of all valid windows
51+
*
52+
* This approach ensures that the algorithm runs in O(n) time.
53+
*/
54+
std::uint64_t compute(
55+
std::uint64_t n,
56+
std::uint64_t k,
57+
std::uint64_t x,
58+
std::uint64_t a,
59+
std::uint64_t b,
60+
std::uint64_t c) {
61+
62+
// Generate the array of n elements
63+
std::vector<std::uint64_t> arr(n);
64+
arr[0] = x; // First element of the array
65+
66+
for (std::uint64_t i = 1; i < n; ++i) {
67+
arr[i] = (a * arr[i - 1] + b) % c; // recurrence relation
68+
}
69+
70+
std::uint64_t x1 = 0; // XOR of the current window
71+
std::uint64_t x2 = 0; // Cumulative XOR of all windows of size k
72+
std::uint64_t l = 0; // Left pointer of sliding window
73+
std::uint64_t r = 0; // Right pointer of sliding window
74+
75+
// Slide the window over the array
76+
while (r < n) {
77+
x1 ^= arr[r]; // include current element in window XOR
78+
79+
// Shrink window from left if size exceeds k
80+
while (r - l + 1 > k) {
81+
x1 ^= arr[l]; // remove leftmost element from window XOR
82+
++l;
83+
}
84+
85+
// If window size equals k, add it to cumulative XOR
86+
if (r - l + 1 == k) {
87+
x2 ^= x1;
88+
}
89+
90+
++r; // Move right pointer
91+
}
92+
93+
return x2; // Return cumulative XOR of all windows
94+
}
95+
96+
} // namespace sliding_window_xor
97+
} // namespace bit_manipulation
98+
99+
/**
100+
* @brief Self-test implementation
101+
*/
102+
static void test() {
103+
using bit_manipulation::sliding_window_xor::compute;
104+
105+
// Testcase 1: n = 100, k = 20, expected = 1019
106+
assert(compute(100, 20, 3, 7, 1, 997) == 1019);
107+
108+
// Testcase 2: n = 2, k = 1, expected = 2
109+
assert(compute(2, 1, 2, 3, 4, 5) == 2);
110+
111+
// Testcase 3: n = 5, k = 2
112+
assert(compute(5, 2, 1, 1, 1, 100) == 0 ^ 3 ^ 1 ^ 7);
113+
114+
// Testcase 4: n = 3, k = 5, expected = 0
115+
assert(compute(3, 5, 5, 2, 1, 100) == 0);
116+
117+
// Testcase 5: n = 4, k = 4, expected = 0
118+
assert(compute(4, 4, 3, 1, 0, 10) == 0);
119+
120+
std::cout << "All test cases successfully passed!" << std::endl;
121+
}
122+
123+
/**
124+
* @brief Main function
125+
* @returns 0 on exit
126+
*/
127+
int main() {
128+
test(); // run self-test implementations
129+
return 0;
130+
}

0 commit comments

Comments
 (0)