From 657f62a4b2fcf46b582d403191b8fa28cb6b0a0b Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Sun, 13 Sep 2026 14:09:29 +1000 Subject: [PATCH] isogram, raindrops: reject comptime solutions --- exercises/practice/isogram/test_isogram.zig | 32 +++++++++++-------- .../practice/raindrops/.meta/example.zig | 18 +++++++---- .../practice/raindrops/test_raindrops.zig | 3 +- generators/exercises/isogram.py | 15 ++++++--- generators/exercises/raindrops.py | 3 +- 5 files changed, 44 insertions(+), 27 deletions(-) diff --git a/exercises/practice/isogram/test_isogram.zig b/exercises/practice/isogram/test_isogram.zig index 8f7c219d..8a08fc6d 100644 --- a/exercises/practice/isogram/test_isogram.zig +++ b/exercises/practice/isogram/test_isogram.zig @@ -3,58 +3,62 @@ const testing = std.testing; const isogram = @import("isogram.zig"); +fn testIsIsogram(phrase: []const u8, expected: bool) !void { + try testing.expectEqual(expected, isogram.isIsogram(phrase)); +} + test "empty string" { - try testing.expect(isogram.isIsogram("")); + try testIsIsogram("", true); } test "isogram with only lower case characters" { - try testing.expect(isogram.isIsogram("isogram")); + try testIsIsogram("isogram", true); } test "word with one duplicated character" { - try testing.expect(!isogram.isIsogram("eleven")); + try testIsIsogram("eleven", false); } test "word with one duplicated character from the end of the alphabet" { - try testing.expect(!isogram.isIsogram("zzyzx")); + try testIsIsogram("zzyzx", false); } test "longest reported english isogram" { - try testing.expect(isogram.isIsogram("subdermatoglyphic")); + try testIsIsogram("subdermatoglyphic", true); } test "word with duplicated character in mixed case" { - try testing.expect(!isogram.isIsogram("Alphabet")); + try testIsIsogram("Alphabet", false); } test "word with duplicated character in mixed case, lowercase first" { - try testing.expect(!isogram.isIsogram("alphAbet")); + try testIsIsogram("alphAbet", false); } test "hypothetical isogrammic word with hyphen" { - try testing.expect(isogram.isIsogram("thumbscrew-japingly")); + try testIsIsogram("thumbscrew-japingly", true); } test "hypothetical word with duplicated character following hyphen" { - try testing.expect(!isogram.isIsogram("thumbscrew-jappingly")); + try testIsIsogram("thumbscrew-jappingly", false); } test "isogram with duplicated hyphen" { - try testing.expect(isogram.isIsogram("six-year-old")); + try testIsIsogram("six-year-old", true); } test "made-up name that is an isogram" { - try testing.expect(isogram.isIsogram("Emily Jung Schwartzkopf")); + try testIsIsogram("Emily Jung Schwartzkopf", true); } test "duplicated character in the middle" { - try testing.expect(!isogram.isIsogram("accentor")); + try testIsIsogram("accentor", false); } test "same first and last characters" { - try testing.expect(!isogram.isIsogram("angola")); + try testIsIsogram("angola", false); } test "word with duplicated character and with two hyphens" { - try testing.expect(!isogram.isIsogram("up-to-date")); + try testIsIsogram("up-to-date", false); } diff --git a/exercises/practice/raindrops/.meta/example.zig b/exercises/practice/raindrops/.meta/example.zig index 396989d8..289df08d 100644 --- a/exercises/practice/raindrops/.meta/example.zig +++ b/exercises/practice/raindrops/.meta/example.zig @@ -1,9 +1,15 @@ const std = @import("std"); -pub fn convert(buffer: []u8, comptime n: u32) []const u8 { - const pling = if (n % 3 == 0) "Pling" else ""; - const plang = if (n % 5 == 0) "Plang" else ""; - const plong = if (n % 7 == 0) "Plong" else ""; - const result = pling ++ plang ++ plong; - return if (result.len > 0) result else std.fmt.bufPrint(buffer, "{}", .{n}) catch unreachable; +fn append(buffer: []u8, len: usize, sound: []const u8) usize { + @memcpy(buffer[len..][0..sound.len], sound); + return len + sound.len; +} + +pub fn convert(buffer: []u8, n: u32) []const u8 { + var len: usize = 0; + if (n % 3 == 0) len = append(buffer, len, "Pling"); + if (n % 5 == 0) len = append(buffer, len, "Plang"); + if (n % 7 == 0) len = append(buffer, len, "Plong"); + if (len == 0) return std.fmt.bufPrint(buffer, "{d}", .{n}) catch unreachable; + return buffer[0..len]; } diff --git a/exercises/practice/raindrops/test_raindrops.zig b/exercises/practice/raindrops/test_raindrops.zig index 03ed1df4..b4e72e3b 100644 --- a/exercises/practice/raindrops/test_raindrops.zig +++ b/exercises/practice/raindrops/test_raindrops.zig @@ -3,10 +3,11 @@ const testing = std.testing; const raindrops = @import("raindrops.zig"); -fn testConvert(comptime n: u32, expected: []const u8) !void { +fn testConvert(n: u32, expected: []const u8) !void { const buffer_size = 15; // The maximum length is for PlingPlangPlong var buffer: [buffer_size]u8 = undefined; const actual = raindrops.convert(&buffer, n); + try testing.expectEqual(@as([*]const u8, &buffer), actual.ptr); try testing.expectEqualStrings(expected, actual); } diff --git a/generators/exercises/isogram.py b/generators/exercises/isogram.py index 0eb496c9..5189f679 100644 --- a/generators/exercises/isogram.py +++ b/generators/exercises/isogram.py @@ -1,8 +1,13 @@ -from lib import zstr +from lib import zbool, zstr + +HEADER = """ +fn testIsIsogram(phrase: []const u8, expected: bool) !void { + try testing.expectEqual(expected, isogram.isIsogram(phrase)); +} +""" def gen_case(case): - phrase = case["input"]["phrase"] - expected = case["expected"] - neg = "" if expected else "!" - return f" try testing.expect({neg}isogram.isIsogram({zstr(phrase)}));\n" + phrase = zstr(case["input"]["phrase"]) + expected = zbool(case["expected"]) + return f" try testIsIsogram({phrase}, {expected});\n" diff --git a/generators/exercises/raindrops.py b/generators/exercises/raindrops.py index c2283651..51418170 100644 --- a/generators/exercises/raindrops.py +++ b/generators/exercises/raindrops.py @@ -3,10 +3,11 @@ IMPORT_SELF = True HEADER = """ -fn testConvert(comptime n: u32, expected: []const u8) !void { +fn testConvert(n: u32, expected: []const u8) !void { const buffer_size = 15; // The maximum length is for PlingPlangPlong var buffer: [buffer_size]u8 = undefined; const actual = raindrops.convert(&buffer, n); + try testing.expectEqual(@as([*]const u8, &buffer), actual.ptr); try testing.expectEqualStrings(expected, actual); } """