27
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Related: codegolf.stackexchange.com/q/37940/42963 \$\endgroup\$ – AdmBorkBork Dec 22 '15 at 19:25
  • 5
    \$\begingroup\$ I can't imagine this going under 30 bytes. \$\endgroup\$ – Martijn Dec 23 '15 at 15:10
  • \$\begingroup\$ how much time did you spend writing the test inputs? it seems like a lot of work \$\endgroup\$ – cat Dec 24 '15 at 17:57
  • \$\begingroup\$ About 10-15 min. It wasn't to hard, even by hand (though is is quite error prone). \$\endgroup\$ – J Atkin Dec 24 '15 at 18:25
  • 1
    \$\begingroup\$ I'm still waiting for that Pyth or CJam answer that will be under 40 bytes... \$\endgroup\$ – J Atkin Jan 3 '16 at 14:57
4
+100
\$\begingroup\$

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>

\$\endgroup\$
  • \$\begingroup\$ Very very impressive \$\endgroup\$ – J Atkin Jan 3 '16 at 14:56
  • \$\begingroup\$ Did not see that. You destroyed my answer. :( +1 \$\endgroup\$ – usandfriends Jan 3 '16 at 18:03
4
\$\begingroup\$

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>

\$\endgroup\$
2
\$\begingroup\$

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))
\$\endgroup\$
  • 2
    \$\begingroup\$ looks at other answers, weeps \$\endgroup\$ – JuanPotato Jan 3 '16 at 14:01
  • \$\begingroup\$ LoL, this vs this... \$\endgroup\$ – J Atkin Jan 3 '16 at 14:53
  • \$\begingroup\$ If I could understand the python answer for the word search puzzle question, this may have been shorter. \$\endgroup\$ – JuanPotato Jan 3 '16 at 14:57
1
\$\begingroup\$

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 
*)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.