 # JaeHyoLee's solution

## to Word Search in the Lua Track

Published at Jul 13 2018 · 0 comments
Instructions
Test suite
Solution

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

For example:

``````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.

## Running the tests

To run the tests, run the command `busted` from within the exercise directory.

## Further information

For more detailed information about the Lua track, including how to get help if you're having trouble, please visit the exercism.io Lua language page.

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### word-search_spec.lua

``````local WordSearch = require('word-search')

describe('word-search', function()
local puzzle = {
'jefblpepre',
'camdcimgtc',
'oivokprjsm',
'pbwasqroua',
'rixilelhrs',
'wolcqlirpc',
'screeaumgr',
'alxhpburyi',
'jalaycalmp',
'clojurermt',
}

it('should find horizontal words written left-to-right', function()
local first, last = WordSearch(puzzle).find('clojure')
assert.same({ 1, 10 }, first)
assert.same({ 7, 10 }, last)
end)

it('should find horizontal words written right-to-left', function()
local first, last = WordSearch(puzzle).find('elixir')
assert.same({ 6, 5 }, first)
assert.same({ 1, 5 }, last)
end)

it('should find vertical words written top-to-bottom', function()
local first, last = WordSearch(puzzle).find('ecmascript')
assert.same({ 10, 1 }, first)
assert.same({ 10, 10 }, last)
end)

it('should find vertical words written bottom-to-top', function()
local first, last = WordSearch(puzzle).find('rust')
assert.same({ 9, 5 }, first)
assert.same({ 9, 2 }, last)
end)

it('should find diagonal words written top-left-to-bottom-right', function()
local first, last = WordSearch(puzzle).find('java')
assert.same({ 1, 1 }, first)
assert.same({ 4, 4 }, last)
end)

it('should find diagonal upper written bottom-right-to-top-left', function()
local first, last = WordSearch(puzzle).find('lua')
assert.same({ 8, 9 }, first)
assert.same({ 6, 7 }, last)
end)

it('should find diagonal upper written bottom-left-to-top-right', function()
local first, last = WordSearch(puzzle).find('lisp')
assert.same({ 3, 6 }, first)
assert.same({ 6, 3 }, last)
end)

it('should find diagonal upper written top-right-to-bottom-left', function()
local first, last = WordSearch(puzzle).find('ruby')
assert.same({ 8, 6 }, first)
assert.same({ 5, 9 }, last)
end)

it('should not find words that are not in the puzzle', function()
assert.same(nil, first)
assert.same(nil, last)
end)

it('should be able to search differently-sized puzzles', function()
local puzzle = {
'qwertyuiopz',
'luamsicrexe',
'abcdefghijk'
}
local first, last = WordSearch(puzzle).find('exercism')
assert.same({ 11, 2 }, first)
assert.same({ 4, 2 }, last)
end)
end)``````
``````local function search_neighbors(puzzle, word, s)
local x = s
local y = s
local l = word:len() - 1
local width = #puzzle

local direction = {
N = y-l>0,
NE = y-l>0 and x+l<=width,
E = x+l<=width,
SE = y+l<=width and x+l<=width,
S = y+l<=width,
SW = y+l<=width and x-l>0,
W = x-l>0,
NW = y+l>width and x-l>0,
}

for i=1, l do
direction.N = direction.N and puzzle[y-i]:sub(x, x) == word:sub(i+1, i+1) and {x, y-i}
direction.NE = direction.NE and puzzle[y-i]:sub(x+i, x+i) == word:sub(i+1, i+1) and {x+i, y-i}
direction.E = direction.E and puzzle[y]:sub(x+i, x+i) == word:sub(i+1, i+1) and {x+i, y}
direction.SE = direction.SE and puzzle[y+i]:sub(x+i, x+i) == word:sub(i+1, i+1) and {x+i, y+i}
direction.S = direction.S and puzzle[y+i]:sub(x, x) == word:sub(i+1, i+1) and {x, y+i}
direction.SW = direction.SW and puzzle[y+i]:sub(x-i, x-i) == word:sub(i+1, i+1) and {x-i, y+i}
direction.W = direction.W and puzzle[y]:sub(x-i, x-i) == word:sub(i+1, i+1) and {x-i, y}
direction.NW = direction.NW and puzzle[y-i]:sub(x-i, x-i) == word:sub(i+1, i+1) and {x-i, y-i}
end

for k, v in pairs(direction) do
if v then return s, v end
end
return nil
end

return function(puzzle)
return {
find = function(word)
local c = word:sub(1,1)
local s
local e
for k, v in ipairs(puzzle) do
local index = 1
repeat
index = v:find(c, index)
if index ~= nil then
s, e = search_neighbors(puzzle, word, {index, k})
if e ~= nil then return s, e end
index = index + 1
end
until index == nil
end
return s, e
end
}
end``````