Skip to content

Commit 35c6617

Browse files
Add series exercise
1 parent e503b12 commit 35c6617

File tree

7 files changed

+228
-0
lines changed

7 files changed

+228
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,14 @@
10271027
"prerequisites": [],
10281028
"difficulty": 5
10291029
},
1030+
{
1031+
"slug": "series",
1032+
"name": "Series",
1033+
"uuid": "fc7d90fa-0bb6-4560-8dee-ddf82adf412c",
1034+
"practices": [],
1035+
"prerequisites": [],
1036+
"difficulty": 5
1037+
},
10301038
{
10311039
"slug": "spiral-matrix",
10321040
"name": "Spiral Matrix",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Instructions
2+
3+
Given a string of digits, output all the contiguous substrings of length `n` in that string in the order that they appear.
4+
5+
For example, the string "49142" has the following 3-digit series:
6+
7+
- "491"
8+
- "914"
9+
- "142"
10+
11+
And the following 4-digit series:
12+
13+
- "4914"
14+
- "9142"
15+
16+
And if you ask for a 6-digit series from a 5-digit string, you deserve whatever you get.
17+
18+
Note that these series are only required to occupy _adjacent positions_ in the input;
19+
the digits need not be _numerically consecutive_.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"series.zig"
8+
],
9+
"test": [
10+
"test_series.zig"
11+
],
12+
"example": [
13+
".meta/example.zig"
14+
]
15+
},
16+
"blurb": "Given a string of digits, output all the contiguous substrings of length `n` in that string.",
17+
"source": "A subset of the Problem 8 at Project Euler",
18+
"source_url": "https://projecteuler.net/problem=8"
19+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const std = @import("std");
2+
const fmt = std.fmt;
3+
const mem = std.mem;
4+
5+
fn free(allocator: mem.Allocator, array_list: *std.ArrayList([]u8)) void {
6+
for (array_list.items) |item| {
7+
allocator.free(item);
8+
}
9+
array_list.deinit(allocator);
10+
}
11+
12+
pub fn slices(comptime slice_length: usize, allocator: mem.Allocator, series: []const u8) mem.Allocator.Error![][]u8 {
13+
comptime {
14+
std.debug.assert(slice_length > 0);
15+
}
16+
17+
var array_list = std.ArrayList([]u8).empty;
18+
errdefer free(allocator, &array_list);
19+
if (slice_length <= series.len) {
20+
for (slice_length..(series.len + 1)) |i| {
21+
try array_list.append(allocator, try fmt.allocPrint(allocator, "{s}", .{series[(i - slice_length)..i]}));
22+
}
23+
}
24+
return array_list.toOwnedSlice(allocator);
25+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[7ae7a46a-d992-4c2a-9c15-a112d125ebad]
13+
description = "slices of one from one"
14+
15+
[3143b71d-f6a5-4221-aeae-619f906244d2]
16+
description = "slices of one from two"
17+
18+
[dbb68ff5-76c5-4ccd-895a-93dbec6d5805]
19+
description = "slices of two"
20+
21+
[19bbea47-c987-4e11-a7d1-e103442adf86]
22+
description = "slices of two overlap"
23+
24+
[8e17148d-ba0a-4007-a07f-d7f87015d84c]
25+
description = "slices can include duplicates"
26+
27+
[bd5b085e-f612-4f81-97a8-6314258278b0]
28+
description = "slices of a long series"
29+
30+
[6d235d85-46cf-4fae-9955-14b6efef27cd]
31+
description = "slice length is too large"
32+
33+
[d7957455-346d-4e47-8e4b-87ed1564c6d7]
34+
description = "slice length is way too large"
35+
36+
[d34004ad-8765-4c09-8ba1-ada8ce776806]
37+
description = "slice length cannot be zero"
38+
include = false
39+
40+
[10ab822d-8410-470a-a85d-23fbeb549e54]
41+
description = "slice length cannot be negative"
42+
include = false
43+
44+
[c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2]
45+
description = "empty series is invalid"
46+
include = false
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const std = @import("std");
2+
const mem = std.mem;
3+
4+
pub fn slices(comptime slice_length: usize, allocator: mem.Allocator, series: []const u8) mem.Allocator.Error![][slice_length]u8 {
5+
comptime {
6+
std.debug.assert(slice_length > 0);
7+
}
8+
9+
_ = allocator;
10+
_ = series;
11+
@compileError("please implement the slices function");
12+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
const std = @import("std");
2+
const testing = std.testing;
3+
4+
const slices = @import("series.zig").slices;
5+
6+
fn free(arr: [][]u8) void {
7+
for (arr) |s| {
8+
testing.allocator.free(s);
9+
}
10+
testing.allocator.free(arr);
11+
}
12+
13+
test "slices of one from one" {
14+
const series = "1";
15+
const expected = [_][]const u8{"1"};
16+
const actual = try slices(1, testing.allocator, series);
17+
defer free(actual);
18+
try testing.expectEqual(expected.len, actual.len);
19+
for (expected, 0..) |expected_slice, i| {
20+
try testing.expectEqualStrings(expected_slice, actual[i]);
21+
}
22+
}
23+
24+
test "slices of one from two" {
25+
const series = "12";
26+
const expected = [_][]const u8{ "1", "2" };
27+
const actual = try slices(1, testing.allocator, series);
28+
defer free(actual);
29+
try testing.expectEqual(expected.len, actual.len);
30+
for (expected, 0..) |expected_slice, i| {
31+
try testing.expectEqualStrings(expected_slice, actual[i]);
32+
}
33+
}
34+
35+
test "slices of two" {
36+
const series = "35";
37+
const expected = [_][]const u8{"35"};
38+
const actual = try slices(2, testing.allocator, series);
39+
defer free(actual);
40+
try testing.expectEqual(expected.len, actual.len);
41+
for (expected, 0..) |expected_slice, i| {
42+
try testing.expectEqualStrings(expected_slice, actual[i]);
43+
}
44+
}
45+
46+
test "slices of two overlap" {
47+
const series = "9142";
48+
const expected = [_][]const u8{ "91", "14", "42" };
49+
const actual = try slices(2, testing.allocator, series);
50+
defer free(actual);
51+
try testing.expectEqual(expected.len, actual.len);
52+
for (expected, 0..) |expected_slice, i| {
53+
try testing.expectEqualStrings(expected_slice, actual[i]);
54+
}
55+
}
56+
57+
test "slices can include duplicates" {
58+
const series = "777777";
59+
const expected = [_][]const u8{ "777", "777", "777", "777" };
60+
const actual = try slices(3, testing.allocator, series);
61+
defer free(actual);
62+
try testing.expectEqual(expected.len, actual.len);
63+
for (expected, 0..) |expected_slice, i| {
64+
try testing.expectEqualStrings(expected_slice, actual[i]);
65+
}
66+
}
67+
68+
test "slices of a long series" {
69+
const series = "918493904243";
70+
const expected = [_][]const u8{ "91849", "18493", "84939", "49390", "93904", "39042", "90424", "04243" };
71+
const actual = try slices(5, testing.allocator, series);
72+
defer free(actual);
73+
try testing.expectEqual(expected.len, actual.len);
74+
for (expected, 0..) |expected_slice, i| {
75+
try testing.expectEqualStrings(expected_slice, actual[i]);
76+
}
77+
}
78+
79+
test "slice length is too large" {
80+
const series = "12345";
81+
const expected = [_][]const u8{};
82+
const actual = try slices(6, testing.allocator, series);
83+
defer free(actual);
84+
try testing.expectEqual(expected.len, actual.len);
85+
for (expected, 0..) |expected_slice, i| {
86+
try testing.expectEqualStrings(expected_slice, actual[i]);
87+
}
88+
}
89+
90+
test "slice length is way too large" {
91+
const series = "12345";
92+
const expected = [_][]const u8{};
93+
const actual = try slices(42, testing.allocator, series);
94+
defer free(actual);
95+
try testing.expectEqual(expected.len, actual.len);
96+
for (expected, 0..) |expected_slice, i| {
97+
try testing.expectEqualStrings(expected_slice, actual[i]);
98+
}
99+
}

0 commit comments

Comments
 (0)