S̶t̶r̶i̶k̶e̶t̶h̶r̶o̶u̶g̶h̶ the Word Search List

Introduction:

Every workday I read the newspaper in the morning while eating breakfast, and also do some of the puzzles at the back. When I do the word-search puzzles, I (almost) always go over the words in order, and strike them through one by one. The word-searches in the newspaper have two columns of words, and after I finished a column I will also put a vertical strike through it.

Challenge:

Let's do the same as a challenge. Given a list of lists of words and an integer $$\n\$$ for the amount of words I've already struck through, output the ASCII art representing that.
The words of each inner list will be placed in the same column, where the columns will have two spaces as delimiter (based on the longest word). All the letters in the words that are struck through are replaced with -, and if an entire column is struck through it's replaced with a vertical |.

Challenge rules:

• | rules:
• For the position of the |, we take the middle of the longest word in the column
• If the longest word has an even length, we take the left character of the two middle characters (e.g. -----|--)
• If a word in the column is shorter than the (left-focused) middle of the longest word, pad spaces between this shortest word and the vertical | line
• You can assume the list of words will only contain regular ASCII letters (in a casing of your choosing - e.g. all lowercase; all uppercase; or mixed casing)
• You can assume the list of words will all be of equal length, except for the last column which might potentially be shorter
• You can assume there is always at least one word in the list
• You can assume $$\0 \leq n \leq W\$$ (where $$\W\$$ is the total amount of words)
• Probably not really relevant, but you can assume the words are in alphabetical order
• Trailing spaces/newlines in the output are optional
• The input-list can be taken in any reasonable format. Could be a list/stream/array; could be taken from STDIN; could be a space-delimited string list; a matrix of characters; etc.
• You're allowed to take the words-input as a list of rows instead of columns. So input [["A","ABC","DEFGHIJ","FG","KLMN"],["QRSTUVW","QRSTUVWXYZ","ST","Y","YZ"],["Z","ZZZZZ"]] would be [["A","QRSTUVW","Z"],["ABC","QRSTUVWXYZ","ZZZZZ"],["DEFGHIJ","ST"],["FG","Y"],["KLMN","YZ"]] instead

Examples:

Input 1:

Words: [["A","ABC","DEFGHIJ","FG","KLMN"],["QRSTUVW","QRSTUVWXYZ","ST","Y","YZ"],["Z","ZZZZZ"]]
n:     0


Output 1:

A        QRSTUVW     Z
ABC      QRSTUVWXYZ  ZZZZZ
DEFGHIJ  ST
FG       Y
KLMN     YZ


Input 2:

Words: Same as the previous example
n:     11


Output 2:

-  |     ----|--     -
---|     ----|-----  ZZZZZ
---|---  --  |
-- |     -   |
---|     --  |


General rules:

• This is , so the shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

Test cases:

Input 1:

Words: [["A","ABC","DEFGHIJ","FG","KLMN"],["QRSTUVW","QRSTUVWXYZ","ST","Y","YZ"],["Z","ZZZZZ"]]
n:     0


Output 1:

A        QRSTUVW     Z
ABC      QRSTUVWXYZ  ZZZZZ
DEFGHIJ  ST
FG       Y
KLMN     YZ


Input 2:

Words: [["A","ABC","DEFGHIJ","FG","KLMN"],["QRSTUVW","QRSTUVWXYZ","ST","Y","YZ"],["Z","ZZZZZ"]]
n:     11


Output 2:

-  |     ----|--     -
---|     ----|-----  ZZZZZ
---|---  --  |
-- |     -   |
---|     --  |


Input 3:

Words: [["A","ABC","DEFGHIJ","FG","KLMN"],["QRSTUVW","QRSTUVWXYZ","ST","Y","YZ"],["Z","ZZZZZ"]]
n:     12


Output 3:

-  |     ----|--     - |
---|     ----|-----  --|--
---|---  --  |
-- |     -   |
---|     --  |


Input 4:

Words: [["BACKWARD","DIAGONAL","FIND","HORIZONTAL"],["RANDOM","SEEK","SLEUTH","VERTICAL"],["WIKIPEDIA","WORDSEARCH"]]
n:     0


Output 4:

BACKWARD    RANDOM    WIKIPEDIA
DIAGONAL    SEEK      WORDSEARCH
FIND        SLEUTH
HORIZONTAL  VERTICAL


Input 5:

Words: [["BACKWARD","DIAGONAL","FIND","HORIZONTAL"],["RANDOM","SEEK","SLEUTH","VERTICAL"],["WIKIPEDIA","WORDSEARCH"]]
n:     6


Output 5:

----|---    ------    WIKIPEDIA
----|---    ----      WORDSEARCH
----|       SLEUTH
----|-----  VERTICAL


Input 6:

Words: [["TEST"]]
n:     1


Output 6:

-|--

• You've got two examples 3's Mar 9 at 0:17
• @jezza_99 Woops.. Thanks for noticing. Should be fixed now. :) Mar 10 at 7:17

Jelly, 35 bytes

z⁶Z)µẎ«”-$⁹R¤¦Fṁ”|LHĊƊ¦€ḟƑ¡"⁸Zj€⁾  A dyadic Link that accepts the list of lists of words on the left and the number done on the right and yields a list of lines. Try it online! How? z⁶Z)µẎ«”-$⁹R¤¦Fṁ”|LHĊƊ¦€ḟƑ¡"⁸Zj€⁾   - Link: W, N
)                                - for each list in W:
z⁶                                  -   transpose with space filler
Z                                 -   transpose
Ẏ                              - tighten (to a list of padded words)
\$⁹R¤¦                      - apply to indices [1..N]:
”-                           -   a '-' character
«                             -   minimum (vectorises) -> '-' if not ' '
F                     - flatten
ṁ                    - mould like X
"⁸       - zip with X applying:
ḟƑ¡         -   if invariant under filter-discard:
Ɗ¦€            -     for each apply to indices...
L                 -     ...length
H                -        halved
Ċ               -        ceiling
”|                  -     ...a '|' character
Z      - transpose
j€⁾.. - join each with "  "


Python3, 321 bytes:

L=len
Y=lambda x:max(map(L,x))
g=lambda x:[[i+' '*((M:=Y(x))-L(i))for i in x],[i[:(T:=(J:=M//2)--~M%2)]+' '*(H:=max(T-L(i),0))+'|'+i[J+M%2:]+' '*(M-L(i)-H-(L(i)<=T))for i in x]][{i[0]for i in x}=={'-'}]
f=lambda w,n,c=0:'\n'.join(map('  '.join,zip(*[g([[j,'-'*L(j)][(c:=c+1)<=n]for j in i])+['']*(Y(w)-L(i))for i in w])))


Try it online!

• Nice answer. :) -1*(M%2==0) can be --~M%2 to save a couple of bytes. Mar 8 at 20:18
• @KevinCruijssen Thank you, please see my edited post. Mar 8 at 21:35

Charcoal, 47 bytes

Ｆθ«Ｅι⎇‹ληＬκκ≔⌈ＥιＬκζＭ⊘⊖ζ±ＬιＦ¬‹ηＬιＰ↓ＬιＭ⊘ζ→→→≧⁻Ｌιη


Try it online! Link is to verbose version of code. Very forgiving as to the input words. Explanation:

Ｆθ«


Loop over the list of columns of words.

Ｅι⎇‹ληＬκκ


Replace each word that has already been struck through with its length and print the result. This outputs a line of -s of that length for those words and the words unchanged for the remaining words.

≔⌈ＥιＬκζ


Get the length of the longest word.

Ｍ⊘⊖ζ±Ｌι


Move horizontally to the middle of the longest word (but vertically to the first word).

Ｆ¬‹ηＬιＰ↓Ｌι


If all of the words in this column have been struck through then vertically output a | for each word without moving the cursor.

Ｍ⊘ζ→


Move to the end of the longest word.

→→


Move to where the next block of words belongs.

≧⁻Ｌιη


Adjust the number of remaining words that have been struck through.

Ruby,152 155 153 bytes

->l,n{l.map!{|c|c.map!{|w|w.tr((0>n-=1)?'':'^ ',?-).ljust X=c.map(&:size).max}
n<0?c:c.each{|w|w[~-X/2]=?|}}
(0...l[0].size).map{|y|l.map{|c|c[y]}*"  "}}


Try it online!

• Added 3 Bytes to fix vertical lines position as spotted by @Kevin Cruijssen, whom then saved 2 suggesting the use of (bitwise x negated) trick, e.g. (x-1)/n => ~-x/n

Lambda taking l list and n that outputs an Array of lines.

The first adversity was to draw the vertical line, which can be done after padding, because it's not possible to access a string out of its bounds.

l.map!{|c|c.map!{|w|..
First we deep map(columns x words) each word by:

• tr((0>n-=1)?'':'^ ',?-
Substitute not-spaces '^ ' with ?- if n decreased is still >=0
• ljust X=c.map(&:size).max
Pad to max length of column, which is saved in constant X for later.

Before we continue to the next column:
n<0?c:c.each{|w|w[~-X/2]=?|}
we overwrite each word at X/2 with ?| if n is still >=0

The second adversity was obtaining rows, transpose wouldn't work because the last column is shorter.

(0...l[0].size).map{|y|
We build the rows by mapping the range [0..column size) and
l.map{|c|c[y]}*" "}
taking ith rows at each column.

• Thanks @Kevin Cruijssen , should be fixed now Mar 9 at 8:46
• Great, +1 from me. :) Btw, I don't know Ruby so I'm not entirely sure, but I think (X-1)/2 can be ~-X/2, right? (And your explanation still uses the old [X/2].) Mar 9 at 8:57
• Thanks @Kevin Cruijssen , of course it works, good catch! I was very tired so I just fixed the answer in some ways. Explanation should be fixed too Mar 9 at 15:36

Python 3.8 (pre-release), 276 258 bytes

L=len
def f(T,s,j=0):
h=L(T[0])
r=[""]*h
for C,u in zip(T,[s-i*h<L(T[i])for i in range(L(T))]):
a=L(max(C,key=L))
for i,w in enumerate(C):r[i]+=((j<s and(c:=L(w)*"-"+a*" ")[:(b:=a//2+a%2-1)]+["|",""][u]+u*c[b]+c[b+1:a]or w)+a*" ")[:a+1];j+=1
return r


Yields a list of lines

Try it online!

• 0 if s-i*h>=L(T[i])else 1 for can be s-i*h<L(T[i])for to save 13 bytes. Mar 9 at 8:16
• You can also make your enumerate loop + body a single line to save 5 more bytes: 258 bytes Mar 9 at 8:26
• Cheers for the additional golfing Mar 9 at 19:42

Julia 1.0, 165 166 bytes

! =length
f(N;n)=""
f(N,l,L...;n=!l,m=~-max(.!l...))=(1:n.|>i->i>!l ? "" : rpad(i>N ? l[i] : '-'^!l[i],m+3)|>x->N<!l ? x : x[1:m÷2]*'|'x[m÷2+2:!x]).*f(N-n,L...;n=n)


Try it online!

A recursive solution, using multiple dispatch. N and the lists are taken as arguments of the function f. Returns a list of strings

+1 to fix a bug pointed out by Kevin Cruijssen

JavaScript (Node.js), 205 204 bytes

-1 byte thanks to @Kevin Cruijssen.

w=>n=>(R=Array(N=w[0][L='length']).fill,w.map((C,x)=>C.map((c,y)=>R[y]+=c.replace(a=/./g,s=>j=n>y+N*x?'-':s).padEnd(l=Math.max(...C.map(s=>s[L]))+2).replace(a,(s,i)=>j&&n>=N*x+C[L]&i==l-3>>1?'|':s))),R)


Try it online!

Written using currying syntax, call as S(w)(n). Outputs an array of lines containing the ASCII art.

• Nice answer. +1 from me. :) You can golf a byte by changing the last && to &. Mar 15 at 20:13