g | x | w | all
Bytes Lang Time Link
081Uiua250703T235210ZErikDaPa
065Vyxal j250627T195452Zpacman25
114BQN220128T164747Zovs
878305AB1E220128T155403ZKevin Cr
166Ruby 1.9110810T203837ZLowjacke
649Scala110811T070344Zuser unk
342JavaScript110809T181701ZBriguy37
230Perl110810T154400ZDCharnes

Uiua, 81 bytes

≡₀⨬⋅@ ∘↥⤚⊃(/↥⊂≡⍉∩⌟˜≡◇⦷⊸⍉□|↥∩≡↘₁∩⌟₂⍜(⍉≡↻|/↥˜≡◇⦷□)⊸¯°⊏≡(⊂@ )):⊂⊸⍚⇌∩°□°⊟⊜(□⍣⊜∘⊜□¬⊸⦷@\n)¬⊸⦷˙⊂@\n

Explanation:

≡₀⨬⋅@ ∘↥⤚⊃(RC|DA):⊂⊸⍚⇌GD
                      GD => (get data), splits data into grid and list of words
                 :⊂⊸⍚⇌   => reverse each word and include it in the list of words
        ⤚⊃(RC|DA)        => (word search)
≡₀⨬⋅@ ∘↥                 => OR all searches, and keep letters at truthy indices
                               otherwise fill with spaces

GD: (get data)
∩°□°⊟⊜(□⍣⊜∘⊜□¬⊸⦷@\n)¬⊸⦷˙⊂@\n
     ⊜(            )¬⊸⦷˙⊂@\n  => splits by double newline (word list & grid)
       □⍣⊜∘⊜□¬⊸⦷@\n           => for each result split by newline and box each row if needed
∩°□°⊟                         => put elements of the list onto the stack and unbox both elements

RC: (row & col search)
/↥⊂≡⍉∩⌟˜≡◇⦷⊸⍉□
     ∩⌟˜≡◇⦷⊸⍉□ => generate bool masks for all matches in rows and cols
/↥⊂≡⍉          => transpose back col bool masks, then OR them

DA: (diag & anti-diag search)
↥∩≡↘₁∩⌟₂⍜(⍉≡↻|/↥˜≡◇⦷□)⊸¯°⊏≡(⊂@ )
        ⍜(⍉≡↻|       )⊸¯°⊏≡(⊂@ ) => rotate each row prepended with spaces by its idx in both directions 
                                    & transpose (gives both diag & anti-diag)
     ∩⌟₂      /↥˜≡◇⦷□            => search (basically the same logic as RC)
↥∩≡↘₁                            => drop prepended space and OR both bool masks

Try this online!

Vyxal j, 73 69 68 65 bytes

¤€÷$:RJ£D₍Þ√Þ`ṅ∇∩"Jvƛ¥ve:[¨vƒrꜝfUsn$⁽ɽ¢]ƛaßð;ṅ;ɾ÷∩^Þ„‟Þ‟W∩4/ƛ∩vGṅ

Try it Online!

this took me several hours and a lot of annoyances with regex but I did it will explain later today

-8 from basic optimization

explanation (old):

¤€÷$:RJ£D₍Þ√Þ`ṅ∇∩"Jvƛ¥ve:a[¨vƒrꜝfUsn$⁽ɽ¢|n]ƛaßð;ṅ;ɾ÷∩^Þ„‟Þ‟W∩4/ƛ∩vG;ṅ­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏⁠‎⁡⁠⁤‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁣⁡‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏⁠‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏⁠‎⁡⁠⁤⁤‏⁠‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏⁠‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁢⁡⁤‏⁠‎⁡⁠⁢⁢⁡‏⁠‎⁡⁠⁤⁡⁡‏⁠‎⁡⁠⁤⁡⁢‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢⁢⁢‏⁠‎⁡⁠⁢⁢⁣‏⁠‎⁡⁠⁢⁢⁤‏‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁢⁣⁡‏⁠‎⁡⁠⁢⁣⁢‏⁠‎⁡⁠⁢⁣⁣‏⁠‎⁡⁠⁣⁣⁡‏⁠‎⁡⁠⁣⁣⁣‏‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁢⁣⁤‏⁠‎⁡⁠⁢⁤⁡‏⁠‎⁡⁠⁢⁤⁢‏⁠‎⁡⁠⁢⁤⁣‏⁠‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁢⁤⁤‏⁠‎⁡⁠⁣⁡⁡‏⁠‎⁡⁠⁣⁡⁢‏⁠‎⁡⁠⁣⁡⁣‏⁠‏​⁡⁠⁡‌⁣⁢​‎‎⁡⁠⁣⁡⁤‏⁠‎⁡⁠⁣⁢⁡‏⁠‎⁡⁠⁣⁢⁢‏⁠‎⁡⁠⁣⁢⁣‏⁠‎⁡⁠⁣⁢⁤‏⁠⁠‏​⁡⁠⁡‌⁣⁣​‎‏​⁢⁠⁡‌⁣⁤​‎‎⁡⁠⁣⁣⁢‏⁠‏​⁡⁠⁡‌⁤⁡​‎‎⁡⁠⁣⁣⁤‏⁠‎⁡⁠⁣⁤⁡‏⁠‎⁡⁠⁣⁤⁢‏⁠‎⁡⁠⁣⁤⁣‏⁠‎⁡⁠⁣⁤⁤‏‏​⁡⁠⁡‌⁤⁢​‎‎⁡⁠⁤⁡⁣‏⁠⁠‏​⁡⁠⁡‌⁤⁣​‎‎⁡⁠⁤⁡⁤‏‏​⁡⁠⁡‌⁤⁤​‎‎⁡⁠⁤⁢⁡‏⁠‎⁡⁠⁤⁢⁢‏‏​⁡⁠⁡‌⁢⁡⁡​‎‎⁡⁠⁤⁢⁣‏⁠‎⁡⁠⁤⁢⁤‏⁠‎⁡⁠⁤⁣⁡‏⁠‎⁡⁠⁤⁣⁢‏⁠‎⁡⁠⁤⁣⁣‏‏​⁡⁠⁡‌⁢⁡⁢​‎‎⁡⁠⁤⁣⁤‏⁠‎⁡⁠⁤⁤⁡‏⁠‎⁡⁠⁤⁤⁢‏⁠‎⁡⁠⁤⁤⁣‏‏​⁡⁠⁡‌⁢⁡⁣​‎‏​⁢⁠⁡‌⁢⁡⁤​‎‎⁡⁠⁤⁤⁤‏⁠‎⁡⁠⁢⁡⁡⁡‏⁠‎⁡⁠⁢⁡⁡⁢‏⁠‎⁡⁠⁢⁡⁡⁣‏⁠‎⁡⁠⁢⁡⁡⁤‏⁠‎⁡⁠⁢⁡⁢⁡‏‏​⁡⁠⁡‌­
¤€÷$                                                                   # ‎⁡parse input
    :RJ£                                                               # ‎⁢set register to the wordlist plus all words reversed
        D                                                              # ‎⁣push the grid 3x
         ₍Þ√Þ`ṅ∇∩"J                                                    # ‎⁤list of diagonals, antidiagonals, rows and columns
                   vƛ                           ṅ;                     # ‎⁢⁡map over each slice and concat
                     ¥ve                                               # ‎⁢⁢first and last index for all regex matches for words
                        :a[             | ]                            # ‎⁢⁣if any has a match
                           ¨vƒr                                        # ‎⁢⁤convert those indices to a range
                               ꜝfUs                                    # ‎⁣⁡sort all unique values across all ranges
                                   n$⁽ɽ¢                               # ‎⁣⁢apply lowercase to items at those indices
# ‎⁣⁣This now has the words all lowercased in each slice of uppercase
                                         n                             # ‎⁣⁤otherwise just push the slice
                                           ƛaßð;                       # ‎⁤⁡convert any uppercase letters to spaces
                                                  ɾ                    # ‎⁤⁢uppercase everything
                                                   ÷                   # ‎⁤⁣push all the slice lists
                                                    ∩^                 # ‎⁤⁤transpose the first one to get columns, then reverse the stack
                                                      Þ„‟Þ‟            # ‎⁢⁡⁡list from diagonals and antidiagonals with a stack rotate in between
                                                           W∩4/        # ‎⁢⁡⁢wrap the stack, transpose it and split into four equal parts
# ‎⁢⁡⁣this gives each row in a solved grid for rows columns diags and antidiags
                                                               ƛ∩vG;ṅ  # ‎⁢⁡⁤get any uppercase letters in any row, spaces for the rest
💎

Created with the help of Luminespire.

BQN, 126 114 bytesSBCS

{S←-++`׬⋄{w𝕊g:g⊑∘↑˜¨¯2+∨´⥊w{H←⊒˜∊·⥊(↕≠𝕨)+⌜·/𝕨⊸⍷⋄(H˘∨1↓˘⊒˜⌽⁼˘·H˘⌾⍉⊒˜⌽˘' '⊸∾˘)⌾(⌽∘⍉⍟𝕩)g}⌜↕4}⟜>´(S⟨⟩⊸≡¨)⊸⊔𝕩⊔˜S𝕩='
'}

Run online!

One third of the code is parsing the input, the more interesting parts are outlined below:

{w𝕊g:g⊑∘↑˜¨¯2+∨´⥊w{H←⊒˜∊·⥊(↕≠𝕨)+⌜·/𝕨⊸⍷⋄(H˘∨1↓˘⊒˜⌽⁼˘·H˘⌾⍉⊒˜⌽˘' '⊸∾˘)⌾(⌽∘⍉⍟𝕩)g}⌜↕4}

Run online!

{w𝕊g:g⊑∘↑˜¨¯2+∨´⥊w{ ... }⌜↕4}
 w𝕊g:                          # A dyadic function taking:
                               #  - left argument w: word list
                               #  - right argument g: grid
                          ↕4   # 0 1 2 3
                  { ... }⌜     # For each of those numbers on the right (specifying rotation) and ...
                 w             # each word on the left, call the inner function.
                               # The inner function returns boolean matrices of the same shape of the input
              ∨´⥊              # Boolean OR of all the matrices
     g⊑∘↑˜¨¯2+                 # For 1's in the matrix take a character from the grid, for 0's take a space.

The inner function rotates the grid (as many times as its right argument specifies: ⌽∘⍉⍟𝕩), checks for words from left to right and on diagonals and then rotates the result back.

How to get get diagonals:

This method is mostly taken from BQNcrate. First a space is prepended to each row. Then each row is rotated by its index. Now words previously in the diagonals are in the columns, by transposing we get them in the rows. After marking the words, all the steps can be reversed: Try with step-by-step results!

05AB1E, 87 (or 83?) bytes

||UεVX8FD»YåiY1:AuSð:1Y:}D€g©ËiεSÐ0:«NFÁ}}øíJ0δKõKë®à©FD®£€нJRsεN®‹i¦}}¦}\)]€Søε{θ}J®ä»

With the actual I/O as mentioned in the challenge description.

Try it online. (For some reason, the Á is very slow on an inner list of characters instead of a string in this program, so εSÐ0:«NFÁ}} has been replaced with εÐS0:«NFÁ}S} (rotate first; then convert it to a list of characters) to speed things up substantially - it'll now output on TIO in roughly a second, instead of timing out without any output after 60 seconds.)

With less strict I/O (first words-input as a list, second grid-input as a list of lines; output-grid as a list of lines as well), this would be 83 bytes instead:

εVI8FD»YåiY1:AuSð:1Y:}D€g©ËiεSÐ0:«NFÁ}}øíJ0δKõKë®à©FD®£€нJRsεN®‹i¦}}¦}\)]€Søε{θ}J®ä

Try it online (with the same modification as above so it won't time out).

Explanation:

In pseudo-code, I do the following steps:

Map over the list of words:
 Push the input-grid
 Loop 8 times:
  If the word is present horizontally left-to-right:
   Replace everything else with a space
  Rotate the grid 45 degrees counterclockwise
Reduce/combine all grids of spaces and words

As for the actual code, of which most (50 bytes) is used to rotate the grid 45 degrees:

|                      # Get all inputs until an empty line is encountered,
                       # resulting in the list of words
 |                     # Do it again, resulting in the grid
  U                    # Pop and store the grid in variable `X`
 ε                     # Map over each of the words:
  V                    #  Pop and store the word in variable `Y`
  X                    #  Push grid `X`
   8F                  #  Loop 8 times:
     D»Yå              #   Check if the word is in the grid:
     D                 #    Duplicate the grid
      »                #    Join the lines with newline delimiter
       Yå              #    Check that this contains the word `Y`
         i             #   If this is truthy:
          Y1:          #    Replace the word temporarily with a 1
          AuSð:        #    Replace all uppercase letters with a space
          1Y:          #    Replace the 1 back to the word
         }             #   Close the if-statement
     D€g©ËiεSÐ0:«NFÁ}}øíJ0δKõKë®à©FD®£€нJRsεN®‹i¦}}¦}\)
                       #   Rotate the grid 45 degrees counterclockwise:
     D€g©Ë             #    Check if the grid is a rectangle:
     D                 #     Duplicate the grid
      €g               #     Get the length of each row
        ©              #     Save this list of lengths in variable `®` (without popping)
         Ë             #     Check whether these lengths are all equal
          i            #    If this is truthy:
           ε           #     Map over each row:
            S          #      Convert it to a list of characters
             Ð0:«      #      Append the row-length amount of 0s to the row
             Ð         #       Triplicate the row
              0:       #       Pop two, and replace all characters to 0s
                «      #       Merge this list of 0s to the row
             NF        #      Loop the 0-based map-index amount of times:
               Á       #       Rotate the row once towards the right
             }         #      Close the loop
           }           #     Close the map
            øí         #     Now rotate 90 degrees clockwise:
            ø          #      Zip/transpose; swapping rows/columns
             í         #      Reverse each row
              J        #     Join the inner list of characters back to a string
                δ      #     Map over each row:
               0 K     #      Remove all 0s from the row
                  õK   #     Remove any empty rows
          ë            #    Else (it's a diamond-shape instead):
           ®           #     Push the list of lengths
            à          #     Pop and push its maximum
             ©         #     Store this maximum as new variable `®` (without popping)
              F        #     Loop this maximum amount of times:
               D       #      Duplicate the list
                ®£     #      Only leave the first max amount of values
                  €н   #      Only leave the first character of each row
                    J  #      Join these characters together to a string
                     R #      Reverse it
               s       #      Swap so the list is at the top again
                ε      #      Map over each row:
                 N®‹i  #       If the map-index is smaller than max `®`:
                     ¦ #        Remove the first character
                    }  #       Close the if-statement
                }      #      Close the map
                 ¦     #      Remove the first (now empty) row
              }        #     Close the loop
               \       #     Discard the now empty list
                )      #     Wrap all rows on the stack into a list
 ]                     # Close the open if-statement; loop; and map
                       # (we now have a list space-grids, except for the found words)
  €S                   # Convert each inner grid to a flattened list of characters
    ø                  # Zip/transpose; swapping rows/columns
     ε                 # Map over each inner list:
      {                #  Sort; spaces at the front, potential letter(s) at the end
       θ               #  Pop and leave the last character
     }                 # Close the map
      J                # Join everything together to one huge string
       ®               # Push the last maximum `®`
        ä              # Split the string into that many equal-sized parts
         »             # Join the list of rows with newline delimiter
                       # (after which it is output implicitly as result)

Ruby 1.9, 214 210 206 182 177 173 172 166

s,G=$<.read.split$/*2
O=G.tr'^
',' '
(s+$/+s.reverse).split.map{|w|[0,l=G=~/$/,l+1,l-1].map{|d|(k=G=~/#{[*w.chars].*?.*d}/m)&&w.size.times{|i|O[k+d*i+i]=w[i]}}}
$><<O

Scala 697, 666 649

val(z,n)=io.Source.fromFile("F").getLines.toList.span(_.length>0)
val m=n.tail
val(w,h)=(m.head.length,m.size)
def g(d:Int,e:Int,k:Int,g:Int,h:Int,i:Int,s:String)={
def f(x:Int,y:Int):Seq[(Int,Int)]={
val q=for(c<-(0 to s.size-1))
yield (y+c*i,x+c*k)
if((q.map(p=>m(p._1)(p._2))).mkString==s)q else Nil}
val t=for(x<-(d to e);
y<-(g to h))yield f(x,y)
t.flatten}
def i(s:String)={val l=s.size
g(0,w-l,1,0,h-1,0,s)++ g(0,w-1,0,0,h-l,1,s)++ g(0,w-l,1,l-1,h-1,-1,s)++ g(0,w-l,1,0,h-l,1,s)}
def j(s: String)=i(s)++ i(s.reverse)
val k=z.map(j).flatten
(0 to h-1).map(r=>{(0 to w-1).map(c=>if(k.contains(r,c))print(""+m(r)(c))else print(" "));println()})

degolfed:

object Golf {

def main (args: Array[String]) = {
  val (words, matrix) = io.Source.fromFile ("./wordsearch.data").getLines.toList.span (_.length > 0)
  val m = matrix.tail
  val (w,h) = (m.head.length, m.size)

  // xi: x-increment, yi: y-increment
  def find (x: Int, y: Int, xi: Int, yi: Int, s: String): Seq [(Int, Int)] = {
    val points = for (c <- (0 to s.length-1))
       yield (y + c*yi, x + c * xi)
    if ((points.map (p => m (p._1)(p._2))).mkString == s) points else Nil
  }

  def findInScope (xS: Int, xD: Int, xi: Int, yS: Int, yD: Int, yi: Int, s: String): Seq [(Int, Int)] = {
    val ppoints = for (x <- (xS to xD);
          y <- (yS to yD)) yield find (x, y, xi, yi, s)
    ppoints.flatten 
  }

  def findRowColFallingClimbing (s: String) = {
    val l=s.length

    // horizontal:
      findInScope (0,   w-l,  1,   0, h-1,  0, s) ++
    // vertical: 
      findInScope (0,   w-1,  0,   0, h-l,  1, s) ++
    // climbing /:
      findInScope (0,   w-l,  1, l-1, h-1, -1, s) ++
    // falling \:
      findInScope (0,   w-l,  1,   0, h-l,  1, s)
  }

  def findBoth (s: String) = findRowColFallingClimbing (s) ++ findRowColFallingClimbing (s.reverse)
  val coords = words.map (findBoth).flatten

  (0 to h-1).map ( r => {
    (0 to w-1).map (c =>
      if (coords.contains (r, c))
       print ("" + m(r)(c)) 
      else print (" ")
     )
     println ()
   })
  }
}

JavaScript: 342 characters

Code-Golfed version:

function a(b){c='\n';d=b.split(c+c);e=d[1].split(c);for(f=-1,g=[];h=e[++f];)for(i=-1,g[f]=[];h[++i];)for(j=-2,g[f][i]=' ';2>++j;)for(l=-2;2>++l;)for(k=0;m=d[0].split(c)[k++];)for(n=-1;o=m[++n];)for(p=f-n*j-j,q=i-n*l-l,r=0;(s=m[r++])&&(t=e[p+=j])&&(u=t[q+=l])&&s==u;)if(r==m.length)g[f][i]=o;for(i=0;v=g[i];)g[i++]=v.join('');return g.join(c)}

Formatted version:

function solveWordsearch(input){
    var lineBreak = '\n';
    var solver = input.split(lineBreak+lineBreak);
    var board = solver[1].split(lineBreak);

    for(row=-1,output=[]; line=board[++row];){
        for(col=-1,output[row]=[]; line[++col];){
            for(rowIncrement=-2,output[row][col]=' ';2>++rowIncrement;){
                for(colIncrement=-2;2>++colIncrement;){
                    for(k=0; word=solver[0].split(lineBreak)[k++];){
                        for(charPosition=-1; wordChar=word[++charPosition];){
                            var startRowIndex=row-charPosition*rowIncrement-rowIncrement;
                            var startColIndex=col-charPosition*colIncrement-colIncrement;
                            for(wordIndex=0;(compareWordChar=word[wordIndex++])&&(compareBoardRow=board[startRowIndex+=rowIncrement])&&(compareBoardChar=compareBoardRow[startColIndex+=colIncrement])&&compareWordChar==compareBoardChar;){
                                if(wordIndex == word.length){
                                    output[row][col]=wordChar;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    for(i=0;outLine=output[i];){
        output[i++]=outLine.join('');
    }

    return output.join('\n');
}

The concept behind this solution is to iterate over all positions on the board, initialize a 2D-array's values to ' ' for each position, and then consider all potential word directions and word offsets. If a matching word is found, the array's value for that position is updated to the correct letter. Finally, the array is converted to a string and returned.

Perl - 230 chars

Count includes 4 for "-ln " command-line options.

if(1../^$/){push@w,$_,''.reverse if$_}else{$a.="$_\n"}END{$_=$a;/.+/;$W=$+[0];y/A-Z/ /;chomp;for$w(@w){for$n(0,$W-1..$W+1){$r=join".{$n}",map"($_)",(@l=split//,$w);if($i=$a=~/$r/s){substr($_,$-[$i++],1,shift@l)while@l}}}print}

Ungolfed:

# -n: implicitly loop over input lines
# -l: strip the newlines
if ( 1 .. /^$/ ) {              # from first line to empty line
  push @w,                      # record in @w
    $_,                         #   the word
      ''.reverse                #   and its reverse
        if $_                   #   if it's not the empty line
}
else {
  $a .= "$_\n"                  # otherwise, add to the search array
}

END {
  $_ = $a;                      # make a copy for the output
  /.+/; $W = $+[0];             # compute array width
  y/A-Z/ /;                     # blank the output board
  chomp;                        # and remove the trailing newline,
                                #  because -l will add it back for us
  for $w (@w) {                 # for each word
    for $n (0, $W-1 .. $W+1) {  # for each direction in E, SW, S, SE
      $r = join ".{$n}",        # form a regexp with an appropriate
                                #  number of characters skipped between letters
                                #  (0 -> adjacent, so E; $W -> next line, so S;
                                #   off by one from $W for the diagonals),
        map "($_)",             #  capturing the letters of the word (for their offsets),
          (@l=split//,$w);      #  which we split up here
      if ( $i = $a =~ /$r/s ) { # if the word matches in this orientation
        substr( $_,             # set the substring of the output
                $-[$i++],       #  at the offset this letter matched
                1,              #  length 1
                shift @l )      #  to the corresponding letter
          while @l              #  (for each letter)
      }
    }
  }
  print                         # and print the output
}