Find my word(s)!

27

4

The idea of this challenge is to find all the words from a dictionary on a grid of letters. Your input should come from stdin or function arg and will come in the following format:

[your dictionary as a list of space sep words]
[a grid of letters]

Example:

The cool car
looc
thea
jopr

Rules for finding a match

A match is valid if it is found diagonally, horizontally, or vertically on the board (case insensitive). The direction doesn't matter (e.g. look matches kool). If there are multiple matches of the same word, mark all of them.

Output:

Your output will be the grid you were given - with the minor change that the letters will be space separated and the lines will be double spaced. Example:

Input:
looc
thea
jopr

Output:
l o o c

t h e a

j o p r

To represent a match you will put an arrow between letters that go together. The arrows (/\-|X) will point to each pair of letters that are grouped in a match. X is used if /\ intersect.

Examples:

Input:
The cool car
looc
thea
jopr

Output:
l-o-o-c
      |
t-h-e a
      |
j o p r

Input:
Atomic chess is cool
achess
btoikm
bloosi
nowmlp
hewiir
asdfec

Output:
a c-h-e-s-s
 \ \   /   
b t o i k m
   \ \ \   
b l o o s-i
     \ \   
n o w m l p
       \   
h e w i i r
         \ 
a s d f e c

Input:
This is very neat words var are fun rob bot robot
wotsdsearn
siiewfvery
chheruoawd
tetoennore
asbdrgrehe
aobyedycab
tweosttgwt

Output:
w o t s d s e a r n
     /             
s-i i e w f v-e-r-y
   /      |  \     
c h h e r u o a w d
 /     /  |    X   
t e t o e n n o r e
     /       X   \ 
a s b d r g r e h e
   /       /   \   
a o b y e d y c a b
 /       /       \ 
t w e o s t t g w t

J Atkin

Posted 2015-12-22T19:15:59.810

Reputation: 4 846

Related: http://codegolf.stackexchange.com/q/37940/42963

– AdmBorkBork – 2015-12-22T19:25:07.340

5I can't imagine this going under 30 bytes. – Martijn – 2015-12-23T15:10:30.073

how much time did you spend writing the test inputs? it seems like a lot of work – cat – 2015-12-24T17:57:39.740

About 10-15 min. It wasn't to hard, even by hand (though is is quite error prone). – J Atkin – 2015-12-24T18:25:28.237

This seems actually very challenging to program, even without golfing it. – Codefun64 – 2015-12-31T07:55:41.467

I don't know if it's worth changing with two answers already on the board, but we usually allow a more flexible input format here. – lirtosiast – 2016-01-02T21:43:55.897

Drat, I didn't think about that. I forgot to include that you could write a function that takes a string... – J Atkin – 2016-01-02T21:53:15.137

@ThomasKwa What other formats would be considered common? – J Atkin – 2016-01-02T21:55:05.270

1I'm still waiting for that Pyth or CJam answer that will be under 40 bytes... – J Atkin – 2016-01-03T14:57:25.520

Uh, reviewing the text of the challenge I see that I should get a single string as input, my fuction has 2 parameters instead. I'll fix it later – edc65 – 2016-01-03T15:32:24.647

Some questions ... is the grid always lowercase as in the example? And if not, the casing should be kept in output? – edc65 – 2016-01-03T15:56:50.877

... and (case intensive) should be read (case insensitive) or plainly the contrary? – edc65 – 2016-01-03T15:59:30.490

Darn, I didn't think of that. Well its a little late to change it so I just go ahead and ignore casing. – J Atkin – 2016-01-03T16:00:12.920

Answers

4

JavaScript (ES6), 303 315

Mostly based on this answer

Edit 1

  • Following OP comment, ignoring casing and forcing all to lowercase.
  • Fixed the arguments, now just a single string argument that get splitted

Note: using template strings, there are 3 newlines in the code that are significant and incuded in the byte count

l=>(l=l.toLowerCase().split`
`).shift(r=l[1].length*4).split` `.map(v=>[2,-2,r,-r,r+2,-r-2,r-2,2-r].map((d,k)=>o.map((t,p)=>[...v].some((c,i)=>z[i?(z[i=t+d/2]=z[i]>' '?'X':'-|\\/'[k>>1],t+=d):t=p]!=c,z=[...o])?0:o=z)),o=[...l.map(s=>' '.repeat(r/2-1)+`
${[...s].join` `}
`).join``.slice(r/2)])&&o.join``

Explained (outdated)

// Note a pattern : in golfed code (but not in the following explanation),
//                  simple operations that have to done before calling .map or .every
//                  are inserted as parameter 2,3,etc... to the same function
//                  as each parameter is evaluated before calling a function
// 
F=( l, // word list as a space separated string
    o, // character grid as a newline separated string - each row is the same length
    // default parameters used as local variables
    r = 4 * o.search`\n` // offset from a line to next nonblank line in resulting output
  )=>(
    w = ' ', // shortcut for blank
    // given the input string in o, build the result as a single dimension array filled with blanks
    // between characters and runs of blank chars betweem each row 
    // .map used as a shorter .forEach
    z = w, // init z to a single blank
    [...o].map( c=> // for each char of o execute the following
                c > w // check if c is a letter (>' ') or a newline
                 ? z+=w+c // if c is a letter, add ' '+c to z
                 : ( // if c is a newline add chars to array o
                     z = z.slice(2), // remove the first 2 char of z ('  ' or '\n ')
                     z = [...z], // convert to array
                     o.push(...z, // push one by one the chars of z
                            c, // then c (a newline)
                            ...z.fill(w), // the same number of char as z, but all blanks
                            z = c // a newline again, meanwhile reset z
                           )
                   )
            , o=[] // o is reset to an empty array just in the map call 
                   // reusing o just to avoid another global variable (no real need in fact)
    ), // end of .map call 
    l.split` `.map( // split l into words and exec the following for each word
      v => [2,-2,r,-r,r+2,-r-2,r-2,2-r].map( // for each scan direction
        (d,k) => // d is the move offset , k is the index 0 to 7
        o.map( // for each char in (including fill blanks and newlines, the scan will fail for them) 
          (t,p) => // t is the first character but NOT USED (var t reused), p is the start position
          (
            z=[...o], // make a copy of o in z
            t = p-d, // current position-d goes in t, it will be incremented before using
            [...v].every( // check the following conditions for every char of word v
            (c,i) => // c: current char of word, i: index used to differentiate the first check when i==0
              (
                // while scanning I already modify the result working copy in z
                i ? // if i != 0 
                  // fill the intermediate position with the right fiil character
                  // based on direction index in k, or X if the position is already full
                  z[i = t+d/2] = z[i] > w ? 'X' : '--||\\\\//'[k]
                : 0, // else do nothing
                // case insensitive comparison, if not a letter parseInt returns NaN that is != from any value
                // this is the condition retured to the .every function
                parseInt(c,36)==parseInt(o[t+=d],36) // meanwhile increment position in T
              )  
            ) ? // check the result of .every
            o = z // if true, update o from the working copy
            : 0 // if false do nothing
          ) // end of o.map operations
        ) // end of o.map function call
      ) // end of direction list map function call
    ) // end of l.split.map function call
    , o.join``
  )

TEST

console.log=(...x)=>O.textContent+=x.join` `+`\n`;

F=l=>
  (l=l.toLowerCase().split`\n`)
  .shift(r=l[1].length*4).split` `.map(v=>[2,-2,r,-r,r+2,-r-2,r-2,2-r].map((d,k)=>o.map((t,p)=>
    [...v].some((c,i)=>z[i?(z[i=t+d/2]=z[i]>' '?'X':'-|\\/'[k>>1],t+=d):t=p]!=c
    ,z=[...o])?0:o=z)
  ),o=[...l.map(s=>' '.repeat(r/2-1)+`\n${[...s].join` `}\n`).join``.slice(r/2)])
  &&o.join``
  


console.log(F('Atomic chess is cool\nachess\nbtoikm\nbloosi\nnowmlp\nhewiir\nasdfec'))


console.log(F("RANDOM VERTICAL HORIZONTAL WIKIPEDIA Tail WordSearch CODEGOLF UNICORN\nWVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH"))
<pre id=O></pre>

edc65

Posted 2015-12-22T19:15:59.810

Reputation: 31 086

Very very impressive – J Atkin – 2016-01-03T14:56:34.513

Did not see that. You destroyed my answer. :( +1 – usandfriends – 2016-01-03T18:03:33.160

4

Javascript (ES6), 908 901 609 603 556 552 bytes

a=>(a=a.toLowerCase().replace(/\n/g,`

`).split`
`,b=a.slice(2).map(r=>r.length?r.replace(/./g,i=>i+` `).trim().split``:Array(a[2].length*2-1).fill(` `)),a[0].split` `.forEach(c=>{for(y=0;y<b.length;y+=2){for(x=0;x<b[y].length;x+=2){c[0]==b[y][x]&&(d=[-2,0,2]).map(l=>{d.map(k=>{e=`\\|/
-o-
/|\\`.split(`
`)[l/2+1][k/2+1];try{(f=(g,h,j)=>g>=c.length?1:(ch=c[g],((k||l)&&b[j+l][h+k]==ch&&f(g+1,h+k,j+l))?(b[j+l/2][h+k/2]=((b[j+l/2][h+k/2]=='\\'&&e=='/')||(b[j+l/2][h+k/2]=='/'&&e=='\\'))?'x':e):0))(1,x,y);}catch(e){}})})}}}),b.map(r=>r.join``).join`
`)

Ungolfed:

inp => (
    inp = inp.toLowerCase().replace(/\n/g, `

`).split `
`,
    puzzle = inp.slice(2).map(r => r.length ? r.replace(/./g, i => i + ` `).trim().split `` : Array(inp[2].length * 2 - 1).fill(` `)),

    inp[0].split ` `.forEach(word => {
        for (y = 0; y < puzzle.length; y += 2) {
            for (x = 0; x < puzzle[y].length; x += 2) {
                word[0] == puzzle[y][x] &&
                    (dirs = [-2, 0, 2]).map(ydir => {
                        dirs.map(xdir => {
                            symb = `\\|/
-o-
/|\\`.split(`
`)[ydir / 2 + 1][xdir / 2 + 1];

                            try {
                                (findWord = (chnum, xcoord, ycoord) =>
                                    chnum >= word.length ? 1 : (
                                        ch = word[chnum],
                                        ((xdir || ydir) && puzzle[ycoord + ydir][xcoord + xdir] == ch && findWord(chnum + 1, xcoord + xdir, ycoord + ydir)) ?
                                            (puzzle[ycoord + ydir / 2][xcoord + xdir / 2] = ((puzzle[ycoord + ydir / 2][xcoord + xdir / 2] == '\\' && symb == '/') || (puzzle[ycoord + ydir / 2][xcoord + xdir / 2] == '/' && symb == '\\')) ? 'x' : symb)
                                            : 0
                                    )
                                )(1, x, y);
                            } catch (e) {}
                        })
                    })
            }
        }
    }),

    puzzle.map(r => r.join ``).join `
`
)

Test (should work with modern browsers that have some ES6 support):

func=a=>(a=a.toLowerCase().replace(/\n/g,`

`).split`
`,b=a.slice(2).map(r=>r.length?r.replace(/./g,i=>i+` `).trim().split``:Array(a[2].length*2-1).fill(` `)),a[0].split` `.forEach(c=>{for(y=0;y<b.length;y+=2){for(x=0;x<b[y].length;x+=2){c[0]==b[y][x]&&(d=[-2,0,2]).map(l=>{d.map(k=>{e=`\\|/
-o-
/|\\`.split(`
`)[l/2+1][k/2+1];try{(f=(g,h,j)=>g>=c.length?1:(ch=c[g],((k||l)&&b[j+l][h+k]==ch&&f(g+1,h+k,j+l))?(b[j+l/2][h+k/2]=((b[j+l/2][h+k/2]=='\\'&&e=='/')||(b[j+l/2][h+k/2]=='/'&&e=='\\'))?'x':e):0))(1,x,y);}catch(e){}})})}}}),b.map(r=>r.join``).join`
`);
<textarea id="_input">Atomic chess is cool
achess
btoikm
bloosi
nowmlp
hewiir
asdfec</textarea>
<br />
<button onclick="document.getElementById('_output').innerHTML = func(document.getElementById('_input').value)">Run!</button>
<br />
<pre id="_output"></pre>

usandfriends

Posted 2015-12-22T19:15:59.810

Reputation: 687

2

Python 3, 1387

k=input().lower().split(" ")
a=[]
while 1:
 a.append(input())
 if not a[-1]:a.pop();break
b=sum([[list(' '.join(list(i))),[' ']*(len(i)*2-1)]for i in a],[])[:-1]
w,h=len(a[0]),len(a)
for l in range(h):
 r=a[l];c=list([1 if w in r else 2 if w in r[::-1] else 0, w] for w in k)
 for t,v in c:
  if not t:continue
  if t==2:v=v[::-1]
  i=r.index(v)
  for m in range(i,i+len(v)-1):b[l*2][m*2+1]="-"
for l in range(w):
 u=''.join(x[l]for x in a);_=list([1 if w in u else 2 if w in u[::-1]else 0,w]for w in k)
 for t,v in _:
  if not t:continue
  if t==2:v=v[::-1]
  i=u.index(v)
  for m in range(i,i+len(v)-1):b[m*2+1][l*2]="|"
def d(g,r=1,o=0):
 if g>=len(a[0]):o=g-w+1;g=w-1
 f=range(0,min(g+1,h-o));return[a[i+o][w-1-(g-i)if r else g-i]for i in f],[(i+o,w-1-(g-i)if r else g-i)for i in f]
for l in range(w+h-1):
 x,c=d(l);_=''.join(x);z=list([1 if w in _ else 2 if w in _[::-1]else 0,w]for w in k) 
 for t,v in z:
  if not t:continue
  if t==2:v=v[::-1]
  i=_.index(v)
  for m in range(i,i+len(v)-1):b[c[m][0]*2+1][c[m][1]*2+1]="\\"
for l in range(w+h-1):
 x,c=d(l,0);_=''.join(x);z=list([1 if w in _ else 2 if w in _[::-1]else 0,w]for w in k)
 for t,v in z:
  if not t:continue
  if t==2:v=v[::-1]
  i=_.index(v)
  for m in range(i,i+len(v)-1):y=c[m][0]*2+1;x=c[m][1]*2-1;j=b[y][x];b[y][x]="x"if j=="\\"else"/"
print('\n'.join(''.join(x) for x in b))

An "is" was missed in the second example

Atomic chess is cool
achess
btoikm
bloosi
nowmlp
hewiir
asdfec

a c-h-e-s-s
 \ \   /
b t o i k m
   \ \ \
b l o o s-i
     \ \
n o w m l p
       \
h e w i i r
         \
a s d f e c

Sorta ungolfed

words = input().lower().split(" ")
square = []
while 1:
 square.append(input())
 if not square[-1]:square.pop();break

solved = sum([[list(' '.join(list(i))),[' ']*(len(i)*2-1)]for i in square], [])[:-1]
w,h = len(square[0]), len(square)


for l in range(h):
 r = square[l]
 rm = list([1 if w in r else 2 if w in r[::-1] else 0, w] for w in words)
 for t,v in rm:
  if not t:continue
  v = v[::-1] if t==2 else v
  i = r.index(v)

  for m in range(i,i+len(v)-1):solved[l*2][m*2+1]="-"

for l in range(w):
 u = ''.join(x[l] for x in square)
 um = list([1 if w in u else 2 if w in u[::-1] else 0, w] for w in words)
 for t,v in um:
  if not t:continue
  v = v[::-1] if t==2 else v
  i = u.index(v)

  for m in range(i,i+len(v)-1):solved[m*2+1][l*2]="|"

def d(m,ind,r=1,o=0):
 if ind>=len(m[0]):o=ind-len(m[0])+1;ind=len(m[0])-1
 f=range(0,min(ind+1,len(m)-o));return[m[i+o][len(m[0])-1-(ind-i)if r else ind-i]for i in f],[(i+o,len(m[0])-1-(ind-i)if r else ind-i)for i in f]

for l in range(w+h-1):
 x,c = d(square,l)
 dl = ''.join(x)
 dlm = list([1 if w in dl else 2 if w in dl[::-1] else 0, w] for w in words)
 for t,v in dlm:
  if not t:continue
  v = v[::-1] if t==2 else v
  i = dl.index(v)
  for m in range(i,i+len(v)-1):solved[c[m][0]*2+1][c[m][1]*2+1]="\\"

for l in range(w+h-1):
 x,c = d(square,l,0)
 dr = ''.join(x)
 drm = list([1 if w in dr else 2 if w in dr[::-1] else 0, w] for w in words)
 for t,v in drm:
  if not t:continue
  v = v[::-1] if 

t==2 else v
  i = dr.index(v)
  for m in range(i,i+len(v)-1):y=c[m][0]*2+1;x=c[m][1]*2-1;j=solved[y][x];solved[y][x]="x"if j=="\\"else"/"

print('\n'.join(''.join(x) for x in solved))

JuanPotato

Posted 2015-12-22T19:15:59.810

Reputation: 399

2looks at other answers, weeps – JuanPotato – 2016-01-03T14:01:10.117

LoL, this vs this...

– J Atkin – 2016-01-03T14:53:10.080

If I could understand the python answer for the word search puzzle question, this may have been shorter.

– JuanPotato – 2016-01-03T14:57:06.643

1

Mathematica, 478 bytes

f[j_,k_]:=({m,p}=ToCharacterCode@*StringSplit/@{j,ToLowerCase@k};
    t=Transpose;v=Length@m[[1]];i=MapIndexed;r=RotateLeft;
    y@d_:=t@i[r[PadLeft[#,2v d],#2 d]&,m];z[m_,d_,p_]:=i[r[#,#2d]&,t@m][[All,p]];
    c[m_,s_]:=(a=0~Table~{v};a[[Join@@(Range[#,#2-1]&@@@SequencePosition[#,s|Reverse@s])]]=1;a)&/@m;
    FromCharacterCode@Flatten@Riffle[#,10]&@
        Flatten[BitOr@@({{m,8m~c~#},{4t@c[t@m,#],2z[y@1~c~#,-1,-v;;-1]+z[c[y@-1,#],1,2;;v+1]}}&/@p)
            /.{0->32,1->47,2->92,3->88,4->124,8->45},{{3,1},{4,2}}])

Test case:

f["wotsdsearn\nsiiewfvery\nchheruoawd\ntetoennore\nasbdrgrehe\naobyedycab\ntweosttgwt",
    "This is very neat words var are fun rob bot robot"]
(*
w o t s d s e a r n 
     /              
s-i i e w f v-e-r-y 
   /      |  \      
c h h e r u o a w d 
 /     /  |    X    
t e t o e n n o r e 
     /       X   \  
a s b d r g r e h e 
   /       /   \    
a o b y e d y c a b 
 /       /       \  
t w e o s t t g w t 
*)

njpipeorgan

Posted 2015-12-22T19:15:59.810

Reputation: 2 992