From a75f76dbefa4c3dce61b02dbfd4b3c27eb772515 Mon Sep 17 00:00:00 2001 From: Ryan Hartlage <2488333+ryanplusplus@users.noreply.github.com> Date: Thu, 7 Aug 2025 21:19:10 -0400 Subject: [PATCH] Update word-count tests --- .../practice/word-count/.meta/example.lua | 11 ++- .../word-count/.meta/spec_generator.lua | 32 ++++++ .../practice/word-count/.meta/tests.toml | 21 +++- exercises/practice/word-count/word-count.lua | 4 +- .../practice/word-count/word-count_spec.lua | 99 ++++++++++++------- 5 files changed, 119 insertions(+), 48 deletions(-) create mode 100644 exercises/practice/word-count/.meta/spec_generator.lua diff --git a/exercises/practice/word-count/.meta/example.lua b/exercises/practice/word-count/.meta/example.lua index 5d460b89..3bfd9693 100644 --- a/exercises/practice/word-count/.meta/example.lua +++ b/exercises/practice/word-count/.meta/example.lua @@ -1,11 +1,12 @@ -local function word_count(s) +local function count_words(s) local counts = {} - s = s:gsub("'([%w%d']+)'", "%1") for w in s:gmatch('[%w%d\']+') do - local normalized = w:lower() - counts[normalized] = (counts[normalized] or 0) + 1 + local w = w:lower():gsub("^'", ''):gsub("'$", '') + if #w > 0 then + counts[w] = (counts[w] or 0) + 1 + end end return counts end -return { word_count = word_count } +return { count_words = count_words } diff --git a/exercises/practice/word-count/.meta/spec_generator.lua b/exercises/practice/word-count/.meta/spec_generator.lua new file mode 100644 index 00000000..89a6e8f7 --- /dev/null +++ b/exercises/practice/word-count/.meta/spec_generator.lua @@ -0,0 +1,32 @@ +local function stringify(s) + s = s:gsub('\n', '\\n') + if s:match("'") and not s:match('"') then + return '"' .. s .. '"' + else + return "'" .. s:gsub("'", "\\'") .. "'" + end +end + +local function format_hash(t) + local key_value_pairs = {} + for key in pairs(t) do + table.insert(key_value_pairs, "[" .. stringify(key) .. "] = " .. t[key]) + end + + table.sort(key_value_pairs) + + return '{ ' .. table.concat(key_value_pairs, ', ') .. ' }' +end + +return { + module_name = 'word_count', + + generate_test = function(case) + local template = [[ + local result = word_count.count_words(%s) + local expected = %s + assert.are.same(expected, result)]] + + return template:format(stringify(case.input.sentence), format_hash(case.expected)) + end +} diff --git a/exercises/practice/word-count/.meta/tests.toml b/exercises/practice/word-count/.meta/tests.toml index b00c20ae..1be425b3 100644 --- a/exercises/practice/word-count/.meta/tests.toml +++ b/exercises/practice/word-count/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. [61559d5f-2cad-48fb-af53-d3973a9ee9ef] description = "count one word" @@ -28,6 +35,11 @@ description = "normalize case" [4185a902-bdb0-4074-864c-f416e42a0f19] description = "with apostrophes" +include = false + +[4ff6c7d7-fcfc-43ef-b8e7-34ff1837a2d3] +description = "with apostrophes" +reimplements = "4185a902-bdb0-4074-864c-f416e42a0f19" [be72af2b-8afe-4337-b151-b297202e4a7b] description = "with quotations" @@ -40,3 +52,6 @@ description = "multiple spaces not detected as a word" [50176e8a-fe8e-4f4c-b6b6-aa9cf8f20360] description = "alternating word separators not detected as a word" + +[6d00f1db-901c-4bec-9829-d20eb3044557] +description = "quotation for word with apostrophe" diff --git a/exercises/practice/word-count/word-count.lua b/exercises/practice/word-count/word-count.lua index 923ebf4f..94e09cd1 100644 --- a/exercises/practice/word-count/word-count.lua +++ b/exercises/practice/word-count/word-count.lua @@ -1,4 +1,4 @@ -local function word_count(s) +local function count_words(s) end -return { word_count = word_count } +return { count_words = count_words } diff --git a/exercises/practice/word-count/word-count_spec.lua b/exercises/practice/word-count/word-count_spec.lua index e8b412aa..14f59697 100644 --- a/exercises/practice/word-count/word-count_spec.lua +++ b/exercises/practice/word-count/word-count_spec.lua @@ -1,82 +1,105 @@ --- problem specification version 1.4.0 -local word_count = require('word-count').word_count +local word_count = require('word-count') describe('word-count', function() - it('counts one word', function() - local result = word_count('word') - local expected = { word = 1 } + it('count one word', function() + local result = word_count.count_words('word') + local expected = { ['word'] = 1 } assert.are.same(expected, result) end) - it('counts one of each', function() - local result = word_count('one of each') - local expected = { one = 1, of = 1, each = 1 } + it('count one of each word', function() + local result = word_count.count_words('one of each') + local expected = { ['each'] = 1, ['of'] = 1, ['one'] = 1 } assert.are.same(expected, result) end) - it('counts multiple occurrences', function() - local result = word_count('one fish two fish red fish blue fish') - local expected = { one = 1, fish = 4, two = 1, red = 1, blue = 1 } + it('multiple occurrences of a word', function() + local result = word_count.count_words('one fish two fish red fish blue fish') + local expected = { ['blue'] = 1, ['fish'] = 4, ['one'] = 1, ['red'] = 1, ['two'] = 1 } assert.are.same(expected, result) end) it('handles cramped lists', function() - local result = word_count('one,two,three') - local expected = { one = 1, two = 1, three = 1 } + local result = word_count.count_words('one,two,three') + local expected = { ['one'] = 1, ['three'] = 1, ['two'] = 1 } assert.are.same(expected, result) end) it('handles expanded lists', function() - local result = word_count('one,\ntwo,\nthree') - local expected = { one = 1, two = 1, three = 1 } + local result = word_count.count_words('one,\ntwo,\nthree') + local expected = { ['one'] = 1, ['three'] = 1, ['two'] = 1 } assert.are.same(expected, result) end) - it('ignores punctuation', function() - local result = word_count('car : carpet as java : javascript!!&@$%^&') - local expected = { car = 1, carpet = 1, as = 1, java = 1, javascript = 1 } + it('ignore punctuation', function() + local result = word_count.count_words('car: carpet as java: javascript!!&@$%^&') + local expected = { ['as'] = 1, ['car'] = 1, ['carpet'] = 1, ['java'] = 1, ['javascript'] = 1 } assert.are.same(expected, result) end) - it('includes numbers', function() - local result = word_count('testing, 1, 2 testing') - local expected = { testing = 2, ['1'] = 1, ['2'] = 1 } + it('include numbers', function() + local result = word_count.count_words('testing, 1, 2 testing') + local expected = { ['1'] = 1, ['2'] = 1, ['testing'] = 2 } assert.are.same(expected, result) end) - it('normalizes case', function() - local result = word_count('go Go GO Stop stop') - local expected = { go = 3, stop = 2 } + it('normalize case', function() + local result = word_count.count_words('go Go GO Stop stop') + local expected = { ['go'] = 3, ['stop'] = 2 } assert.are.same(expected, result) end) - it('counts with apostrophes', function() - local result = word_count("First: don't laugh. Then: don't cry.") - local expected = { first = 1, ["don't"] = 2, laugh = 1, ['then'] = 1, cry = 1 } + it('with apostrophes', function() + local result = word_count.count_words("'First: don't laugh. Then: don't cry. You're getting it.'") + local expected = { + ["don't"] = 2, + ["you're"] = 1, + ['cry'] = 1, + ['first'] = 1, + ['getting'] = 1, + ['it'] = 1, + ['laugh'] = 1, + ['then'] = 1 + } assert.are.same(expected, result) end) - it('counts with quotation', function() - local result = word_count("Joe can't tell between 'large' and large.") - local expected = { joe = 1, ["can't"] = 1, tell = 1, between = 1, large = 2, ["and"] = 1 } + it('with quotations', function() + local result = word_count.count_words("Joe can't tell between 'large' and large.") + local expected = { ["can't"] = 1, ['and'] = 1, ['between'] = 1, ['joe'] = 1, ['large'] = 2, ['tell'] = 1 } assert.are.same(expected, result) end) - it('counts with substrings from the beginning', function() - local result = word_count("Joe can't tell between app, apple and a.") - local expected = { joe = 1, ["can't"] = 1, tell = 1, between = 1, app = 1, apple = 1, ["and"] = 1, a = 1 } + it('substrings from the beginning', function() + local result = word_count.count_words("Joe can't tell between app, apple and a.") + local expected = { + ["can't"] = 1, + ['a'] = 1, + ['and'] = 1, + ['app'] = 1, + ['apple'] = 1, + ['between'] = 1, + ['joe'] = 1, + ['tell'] = 1 + } assert.are.same(expected, result) end) - it('does not count multiple spaces as a word', function() - local result = word_count(' multiple whitespaces') - local expected = { multiple = 1, whitespaces = 1 } + it('multiple spaces not detected as a word', function() + local result = word_count.count_words(' multiple whitespaces') + local expected = { ['multiple'] = 1, ['whitespaces'] = 1 } assert.are.same(expected, result) end) it('alternating word separators not detected as a word', function() - local result = word_count(",\n,one,\n ,two \n 'three'") - local expected = { one = 1, two = 1, three = 1 } + local result = word_count.count_words(",\n,one,\n ,two \n 'three'") + local expected = { ['one'] = 1, ['three'] = 1, ['two'] = 1 } + assert.are.same(expected, result) + end) + + it('quotation for word with apostrophe', function() + local result = word_count.count_words("can, can't, 'can't'") + local expected = { ["can't"] = 2, ['can'] = 1 } assert.are.same(expected, result) end) end)