| ... | ... | @@ -0,0 +1,142 @@ |
| 1 | const std = @import("std"); |
| 2 | const string = []const u8; |
| 3 | const extras = @import("./lib.zig"); |
| 4 | |
| 5 | /// Swap subregions slice[a..][0..an] and slice[b..][0..bn]. |
| 6 | /// Subregions may not overlap. |
| 7 | pub fn swapMany(T: type, slice: []T, a: usize, an: usize, b: usize, bn: usize) void { |
| 8 | if (a == b) return; |
| 9 | if (a < b) return swapManyLR(T, slice, a, an, b, bn); |
| 10 | if (a > b) return swapManyLR(T, slice, b, bn, a, an); |
| 11 | unreachable; |
| 12 | } |
| 13 | pub fn swapManyLR(T: type, slice: []T, a: usize, an: usize, b: usize, bn: usize) void { |
| 14 | std.debug.assert(a + an <= b); |
| 15 | std.debug.assert(b + bn <= slice.len); |
| 16 | |
| 17 | if (an == bn) { |
| 18 | for (0..an, 0..bn) |i, j| { |
| 19 | std.mem.swap(T, &slice[a + i], &slice[b + j]); |
| 20 | } |
| 21 | return; |
| 22 | } |
| 23 | |
| 24 | const m = @min(an, bn); |
| 25 | |
| 26 | if (an < bn) { |
| 27 | for (0..m) |i| { |
| 28 | std.mem.swap(T, &slice[a + i], &slice[b + i]); |
| 29 | } |
| 30 | for (m..bn) |i| { |
| 31 | const temp = slice[b + i]; |
| 32 | std.mem.copyBackwards( |
| 33 | T, |
| 34 | slice[a + i + 1 .. b + i + 1], |
| 35 | slice[a + i .. b + i], |
| 36 | ); |
| 37 | slice[a + i] = temp; |
| 38 | } |
| 39 | return; |
| 40 | } |
| 41 | if (an > bn) { |
| 42 | for (0..m) |i| { |
| 43 | std.mem.swap(T, &slice[a + i], &slice[b + i]); |
| 44 | } |
| 45 | for (m..an) |_| { |
| 46 | const temp = slice[a + m]; |
| 47 | for (a + m..b + m - 1) |w| slice[w] = slice[w + 1]; |
| 48 | slice[b + m - 1] = temp; |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | test { |
| 54 | var buf = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
| 55 | swapMany(u8, &buf, 2, 3, 6, 3); |
| 56 | try std.testing.expectEqualSlices(u8, &.{ 0, 1, 6, 7, 8, 5, 2, 3, 4, 9 }, &buf); |
| 57 | } |
| 58 | test { |
| 59 | var buf = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
| 60 | swapMany(u8, &buf, 2, 2, 6, 4); |
| 61 | try std.testing.expectEqualSlices(u8, &.{ 0, 1, 6, 7, 8, 9, 4, 5, 2, 3 }, &buf); |
| 62 | } |
| 63 | test { |
| 64 | var buf = [_]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
| 65 | swapMany(u8, &buf, 6, 4, 2, 2); |
| 66 | try std.testing.expectEqualSlices(u8, &.{ 0, 1, 6, 7, 8, 9, 4, 5, 2, 3 }, &buf); |
| 67 | } |
| 68 | |
| 69 | test { |
| 70 | // 43111_ABCDIHEFGJ |
| 71 | var actual = "ABCDEFGHIJ".*; |
| 72 | swapMany(u8, &actual, 4, 3, 8, 1); |
| 73 | try std.testing.expectEqualSlices(u8, "ABCDIHEFGJ", &actual); |
| 74 | } |
| 75 | test { |
| 76 | // 33121_ABCHIGDEFJ |
| 77 | var actual = "ABCDEFGHIJ".*; |
| 78 | swapMany(u8, &actual, 3, 3, 7, 2); |
| 79 | try std.testing.expectEqualSlices(u8, "ABCHIGDEFJ", &actual); |
| 80 | } |
| 81 | test { |
| 82 | // 14131_AGHIFBCDEJ |
| 83 | var actual = "ABCDEFGHIJ".*; |
| 84 | swapMany(u8, &actual, 1, 4, 6, 3); |
| 85 | try std.testing.expectEqualSlices(u8, "AGHIFBCDEJ", &actual); |
| 86 | } |
| 87 | |
| 88 | comptime { |
| 89 | @setEvalBranchQuota(20_000); |
| 90 | for (1..5) |an| { |
| 91 | for (1..5) |bn| { |
| 92 | for (1..5) |cn| { |
| 93 | for (1..5) |dn| { |
| 94 | for (1..5) |en| { |
| 95 | _ = struct { |
| 96 | test { |
| 97 | // | a | b | c | d | e | |
| 98 | const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
| 99 | const digits = "0123456789"; |
| 100 | var i: usize = 0; |
| 101 | var j: usize = 0; |
| 102 | var a: [an]u8 = undefined; |
| 103 | j = 0; |
| 104 | while (j < an) : (j += 1) a[j] = letters[i + j]; |
| 105 | i += an; |
| 106 | var b: [bn]u8 = undefined; |
| 107 | j = 0; |
| 108 | while (j < bn) : (j += 1) b[j] = letters[i + j]; |
| 109 | i += bn; |
| 110 | var c: [cn]u8 = undefined; |
| 111 | j = 0; |
| 112 | while (j < cn) : (j += 1) c[j] = letters[i + j]; |
| 113 | i += cn; |
| 114 | var d: [dn]u8 = undefined; |
| 115 | j = 0; |
| 116 | while (j < dn) : (j += 1) d[j] = letters[i + j]; |
| 117 | i += dn; |
| 118 | var e: [en]u8 = undefined; |
| 119 | j = 0; |
| 120 | while (j < en) : (j += 1) e[j] = letters[i + j]; |
| 121 | i += en; |
| 122 | const key = [_]u8{ digits[an], digits[bn], digits[cn], digits[dn], digits[en], '_' }; |
| 123 | var actual = key ++ a ++ b ++ c ++ d ++ e; |
| 124 | // | a | b | c | d | e | |
| 125 | swapMany( |
| 126 | u8, |
| 127 | &actual, |
| 128 | key.len + a.len, |
| 129 | b.len, |
| 130 | key.len + a.len + b.len + c.len, |
| 131 | d.len, |
| 132 | ); |
| 133 | const expected = key ++ a ++ d ++ c ++ b ++ e; |
| 134 | try std.testing.expectEqualStrings(&expected, &actual); |
| 135 | } |
| 136 | }; |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | } |
| 141 | } |
| 142 | } |