Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3388bb6
* add practice exercise: word-search
jimmytty Sep 15, 2025
93ab471
* irreproducible error: debbug - try 001
jimmytty Sep 15, 2025
aeb98d0
* irreproducible error: debbug - try 002
jimmytty Sep 15, 2025
ebdd42f
* irreproducible error: debbug - try 003
jimmytty Sep 15, 2025
01c0146
* irreproducible error: debbug - try 004
jimmytty Sep 15, 2025
49782c7
* irreproducible error: debbug - try 005
jimmytty Sep 15, 2025
b50c876
* irreproducible error: debbug - try 006
jimmytty Sep 15, 2025
91a414e
* irreproducible error: debbug - try 007
jimmytty Sep 15, 2025
c2dcdc8
* irreproducible error: debbug - try 008
jimmytty Sep 15, 2025
2dc0813
* irreproducible error: debbug - try 009
jimmytty Sep 15, 2025
1f58187
* irreproducible error: debbug - try 010
jimmytty Sep 15, 2025
fe13bdc
* irreproducible error: debbug - try 011
jimmytty Sep 15, 2025
71f4d2d
* irreproducible error: debbug - try 012
jimmytty Sep 16, 2025
4c71652
* fix typo
jimmytty Sep 16, 2025
78c0a56
* irreproducible error: debbug - try 013
jimmytty Sep 17, 2025
782dca5
* irreproducible error: debbug - try 014
jimmytty Sep 17, 2025
a5142f7
* irreproducible error: debbug - try 015
jimmytty Sep 17, 2025
f5358bf
* irreproducible error: debbug - try 016
jimmytty Sep 17, 2025
53e3164
* irreproducible error: debbug - try 017
jimmytty Sep 17, 2025
a58b7e7
* irreproducible error: debbug - try 018
jimmytty Sep 17, 2025
7030605
* irreproducible error: debbug - try 019
jimmytty Sep 17, 2025
a95b450
* irreproducible error: debbug - try 020
jimmytty Sep 17, 2025
f3f023f
* irreproducible error: debbug - try 021
jimmytty Sep 17, 2025
edf9339
* irreproducible error: debbug - try 022
jimmytty Sep 18, 2025
507a03b
* irreproducible error: debbug - try 023
jimmytty Sep 18, 2025
84ecc76
* irreproducible error: debbug - try 024
jimmytty Sep 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,14 @@
"prerequisites": [],
"difficulty": 8
},
{
"slug": "word-search",
"name": "Word Search",
"uuid": "3d82c7c8-0988-438b-b9db-345c9eb61250",
"practices": [],
"prerequisites": [],
"difficulty": 8
},
{
"slug": "wordy",
"name": "Wordy",
Expand Down
24 changes: 24 additions & 0 deletions exercises/practice/word-search/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Instructions

In word search puzzles you get a square of letters and have to find specific words in them.

For example:

```text
jefblpepre
camdcimgtc
oivokprjsm
pbwasqroua
rixilelhrs
wolcqlirpc
screeaumgr
alxhpburyi
jalaycalmp
clojurermt
```

There are several programming languages hidden in the above square.

Words can be hidden in all kinds of directions: left-to-right, right-to-left, vertical and diagonal.

Given a puzzle and a list of words return the location of the first and last letter of each word.
17 changes: 17 additions & 0 deletions exercises/practice/word-search/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"authors": [
"jimmytty"
],
"files": {
"solution": [
"word-search.sql"
],
"test": [
"word-search_test.sql"
],
"example": [
".meta/example.sql"
]
},
"blurb": "Create a program to solve a word search puzzle."
}
216 changes: 216 additions & 0 deletions exercises/practice/word-search/.meta/example.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
DROP TABLE IF EXISTS letters;
CREATE TEMPORARY TABLE letters (
grid TEXT NOT NULL,
chr TEXT NOT NULL,
row INTEGER NOT NULL,
col INTEGER NOT NULL
);
WITH
to_lines AS (
SELECT grid,
j.value AS line,
LENGTH(j.value) AS len,
j.key AS row
FROM (SELECT DISTINCT JSON_EXTRACT(input, '$.grid') AS grid
FROM "word-SEARCH"),
JSON_EACH(grid) j
),
to_chars AS (
SELECT grid, SUBSTR(line, g.value, 1) AS chr, row, g.value - 1 col
FROM to_lines, GENERATE_SERIES(1, to_lines.len) g
)
INSERT INTO letters
(grid, chr, row, col)
SELECT grid, chr, row, col
FROM to_chars
;

DROP TABLE IF EXISTS strings;
CREATE TEMPORARY TABLE strings (
grid TEXT NOT NULL,
string TEXT NOT NULL,
array TEXT NOT NULL
);
INSERT INTO strings (grid, string, array)
SELECT grid,
GROUP_CONCAT(chr, ''),
JSON_GROUP_ARRAY(JSON_ARRAY(chr, JSON_ARRAY(row, col)))
FROM (
SELECT grid, chr, row, col
FROM letters
ORDER BY row ASC, col ASC
)
GROUP BY grid, row
HAVING LENGTH(GROUP_CONCAT(chr, '')) > 1
;
INSERT INTO strings (grid, string, array)
SELECT grid,
GROUP_CONCAT(chr, ''),
JSON_GROUP_ARRAY(JSON_ARRAY(chr, JSON_ARRAY(row, col)))
FROM (
SELECT grid, chr, row, col
FROM letters
ORDER BY row DESC, col DESC
)
GROUP BY grid, row
HAVING LENGTH(GROUP_CONCAT(chr, '')) > 1
;
INSERT INTO strings (grid, string, array)
SELECT grid,
GROUP_CONCAT(chr, ''),
JSON_GROUP_ARRAY(JSON_ARRAY(chr, JSON_ARRAY(row, col)))
FROM (
SELECT grid, chr, row, col
FROM letters
ORDER BY col ASC, row ASC
)
GROUP BY grid, col
HAVING LENGTH(GROUP_CONCAT(chr, '')) > 1
;
INSERT INTO strings (grid, string, array)
SELECT grid,
GROUP_CONCAT(chr, ''),
JSON_GROUP_ARRAY(JSON_ARRAY(chr, JSON_ARRAY(row, col)))
FROM (
SELECT grid, chr, row, col
FROM letters
ORDER BY col DESC, row DESC
)
GROUP BY grid, col
HAVING LENGTH(GROUP_CONCAT(chr, '')) > 1
;

WITH
bounds (grid, mrow, mcol) AS (
SELECT grid, MAX(row), MAX(col)
FROM letters
GROUP BY grid
),
starts AS (
SELECT grid,
gr.value row,
gc.value col
FROM bounds, GENERATE_SERIES(0, mrow) gr, GENERATE_SERIES(0, mcol) gc
),
r2l_coords AS (
SELECT grid,
JSON_GROUP_ARRAY(JSON(coord)) AS coords
FROM (
SELECT DISTINCT
starts.grid,
row,
col,
JSON_ARRAY(row + g.value, col + g.value) coord
FROM bounds, starts, GENERATE_SERIES(0, mrow) g
WHERE bounds.grid = starts.grid
AND row + g.value <= mrow
AND col + g.value <= mcol
)
GROUP BY grid, row, col
HAVING JSON_ARRAY_LENGTH(coords) > 1
),
l2r_coords AS (
SELECT grid,
JSON_GROUP_ARRAY(JSON(coord)) AS coords
FROM (
SELECT DISTINCT
starts.grid,
row,
col,
g.value,
JSON_ARRAY(row + g.value, col - g.value) coord
FROM bounds, starts, GENERATE_SERIES(0, mrow) g
WHERE bounds.grid = starts.grid
AND row + g.value <= mrow
AND col - g.value >= 0
)
GROUP BY grid, row, col
HAVING JSON_ARRAY_LENGTH(coords) > 1
),
chrs AS (
SELECT letters.*,
JSON_ARRAY(letters.row, letters.col) AS row_col,
r2l_coords.coords
FROM letters, r2l_coords
WHERE letters.grid = r2l_coords.grid
AND row_col IN ((SELECT j.value FROM JSON_EACH(coords) j))
UNION ALL
SELECT letters.*,
JSON_ARRAY(letters.row, letters.col) AS row_col,
l2r_coords.coords
FROM letters, l2r_coords
WHERE letters.grid = l2r_coords.grid
AND row_col IN ((SELECT j.value FROM JSON_EACH(coords) j))
),
straight AS (
SELECT grid,
GROUP_CONCAT(chr, '') AS string,
JSON_GROUP_ARRAY(JSON_ARRAY(chr, JSON_ARRAY(row, col))) array
FROM (SELECT * FROM chrs ORDER BY grid, row_col ASC)
GROUP BY grid, coords
),
reversed AS (
SELECT grid,
GROUP_CONCAT(chr, '') AS string,
JSON_GROUP_ARRAY(JSON_ARRAY(chr, JSON_ARRAY(row, col))) array
FROM (SELECT * FROM chrs ORDER BY grid, row_col DESC)
GROUP BY grid, coords
)
INSERT INTO strings (grid, string, array)
SELECT * FROM straight
UNION ALL
SELECT * FROM reversed
;

WITH
find AS (
SELECT input,
j.value AS word,
(SELECT
JSON_EXTRACT(
array,
PRINTF('$[%d][1]', INSTR(string, j.value) - 1),
PRINTF('$[%d][1]', INSTR(string, j.value) +
LENGTH(j.value) - 2
)
)
FROM strings
WHERE JSON_EXTRACT(input, '$.grid') = grid
AND INSTR(string, j.value)
) AS bounds
FROM "word-search",
JSON_EACH(JSON_EXTRACT(input, '$.wordsToSearchFor')) j
),
results AS (
SELECT input,
JSON_GROUP_OBJECT(word, JSON(object)) result
FROM (
SELECT
input,
word,
IIF(
bounds ISNULL,
bounds,
JSON_OBJECT(
'start',
JSON_OBJECT(
'column', JSON_EXTRACT(bounds, '$[0][1]') + 1,
'row', JSON_EXTRACT(bounds, '$[0][0]') + 1
),
'end',
JSON_OBJECT(
'column', JSON_EXTRACT(bounds, '$[1][1]') + 1,
'row', JSON_EXTRACT(bounds, '$[1][0]') + 1
)
)
) object
FROM find
ORDER BY input, word
)
GROUP BY input
)
UPDATE "word-search"
SET result = results.result
FROM results
WHERE "word-search".input = results.input
;
82 changes: 82 additions & 0 deletions exercises/practice/word-search/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# 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.

[b4057815-0d01-41f0-9119-6a91f54b2a0a]
description = "Should accept an initial game grid and a target search word"

[6b22bcc5-6cbf-4674-931b-d2edbff73132]
description = "Should locate one word written left to right"

[ff462410-434b-442d-9bc3-3360c75f34a8]
description = "Should locate the same word written left to right in a different position"

[a02febae-6347-443e-b99c-ab0afb0b8fca]
description = "Should locate a different left to right word"

[e42e9987-6304-4e13-8232-fa07d5280130]
description = "Should locate that different left to right word in a different position"

[9bff3cee-49b9-4775-bdfb-d55b43a70b2f]
description = "Should locate a left to right word in two line grid"

[851a35fb-f499-4ec1-9581-395a87903a22]
description = "Should locate a left to right word in three line grid"

[2f3dcf84-ba7d-4b75-8b8d-a3672b32c035]
description = "Should locate a left to right word in ten line grid"

[006d4856-f365-4e84-a18c-7d129ce9eefb]
description = "Should locate that left to right word in a different position in a ten line grid"

[eff7ac9f-ff11-443e-9747-40850c12ab60]
description = "Should locate a different left to right word in a ten line grid"

[dea39f86-8c67-4164-8884-13bfc48bd13b]
description = "Should locate multiple words"

[29e6a6a5-f80c-48a6-8e68-05bbbe187a09]
description = "Should locate a single word written right to left"

[3cf34428-b43f-48b6-b332-ea0b8836011d]
description = "Should locate multiple words written in different horizontal directions"

[2c8cd344-a02f-464b-93b6-8bf1bd890003]
description = "Should locate words written top to bottom"

[9ee1e43d-e59d-4c32-9a5f-6a22d4a1550f]
description = "Should locate words written bottom to top"

[6a21a676-f59e-4238-8e88-9f81015afae9]
description = "Should locate words written top left to bottom right"

[c9125189-1861-4b0d-a14e-ba5dab29ca7c]
description = "Should locate words written bottom right to top left"

[b19e2149-7fc5-41ec-a8a9-9bc6c6c38c40]
description = "Should locate words written bottom left to top right"

[69e1d994-a6d7-4e24-9b5a-db76751c2ef8]
description = "Should locate words written top right to bottom left"

[695531db-69eb-463f-8bad-8de3bf5ef198]
description = "Should fail to locate a word that is not in the puzzle"

[fda5b937-6774-4a52-8f89-f64ed833b175]
description = "Should fail to locate words that are not on horizontal, vertical, or diagonal lines"

[5b6198eb-2847-4e2f-8efe-65045df16bd3]
description = "Should not concatenate different lines to find a horizontal word"

[eba44139-a34f-4a92-98e1-bd5f259e5769]
description = "Should not wrap around horizontally to find a word"

[cd1f0fa8-76af-4167-b105-935f78364dac]
description = "Should not wrap around vertically to find a word"
10 changes: 10 additions & 0 deletions exercises/practice/word-search/create_fixture.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DROP TABLE IF EXISTS "word-search";
CREATE TABLE "word-search" (
input TEXT NOT NULL, -- json object
result TEXT -- json object
);

.mode csv
.import ./data.csv "word-search"

UPDATE "word-search" SET result = NULL;
Loading
Loading