JavaScript (ES6), 595 628 680
แก้ไขการล้างและผสานบางส่วน:
- ฟังก์ชัน P ที่ผสานภายในฟังก์ชัน R
- calc x และ z ใน. map เดียวกัน
- เมื่อพบวิธีแก้ปัญหาให้ตั้งค่า x เป็น 0 เพื่อออกจากวงรอบนอก
- นิยามที่รวมกันและการเรียก W
Edit2เพิ่มเติมการเล่นกอล์ฟการสุ่มเติมให้สั้นลงการวนรอบนอกแก้ไข ... ดูประวัติสำหรับสิ่งที่อ่านง่ายขึ้น
ต่างจากคำตอบที่ยอมรับได้ซึ่งควรใช้กับอินพุตส่วนใหญ่ เพียงหลีกเลี่ยงคำตัวอักษรเดียว หากพบผลลัพธ์จะเป็นการดีที่สุดและใช้ทั้ง 3 ทิศทาง
ข้อ จำกัด ในการหลีกเลี่ยงคำซ้ำ ๆ เป็นเรื่องยากมาก ฉันต้องมองหาคำที่ซ้ำกันในแต่ละขั้นตอนเพิ่มคำลงในตารางและที่ตัวละครเติมแต่ละแบบสุ่ม
ฟังก์ชั่นหลัก:
P (w) จริงถ้าคำ palindrome คำ palindrom จะพบสองครั้งเมื่อตรวจสอบคำที่ซ้ำกัน
R (s) ตรวจสอบคำที่ซ้ำกันในกริด s
Q เติม s กริดด้วยอักขระสุ่ม - มันวนซ้ำและย้อนกลับในกรณีที่มีคำซ้ำ - และอาจล้มเหลว
W () วนซ้ำพยายามเติมกริดที่มีขนาดที่กำหนดถ้าเป็นไปได้
ฟังก์ชั่นหลักใช้ W () เพื่อค้นหากริดเอาต์พุตโดยลองจากขนาดของคำที่ยาวที่สุดในอินพุตจนถึงผลรวมของความยาวของคำทั้งหมด
F=l=>{
for(z=Math.max(...l.map(w=>(w=w.length,x+=w,w),x=0));
++z<=x;
(W=(k,s,m,w=l[k])=>w?s.some((a,p)=>!!a&&
D.some((d,j,_,r=[...s],q=p-d)=>
[...w].every(c=>r[q+=d]==c?c:r[q]==1?r[q]=c:0)
&&R(r)&&W(k+1,r,m|1<<(j/2))
)
)
:m>12&&Q(s)&&(console.log(''+s),z=x)
)(0,[...Array(z*z-z)+99].map((c,i)=>i%z?1:'\n'))
)
D=[~z,-~z,1-z,z-1,z,-z,1,-1]
,R=u=>!l.some(w=>u.map((a,p)=>a==w[0]&&D.map(d=>n+=[...w].every(c=>u[q+=d]==c,q=p-d)),
n=~([...w]+''==[...w].reverse()))&&n>0)
,Q=(u,p=u.indexOf(1),r=[...'ABCDEFGHIJHLMNOPQRSTUVWXYZ'])=>
~p?r.some((v,c)=>(r[u[p]=r[j=0|c+Math.random()*(26-c)],j]=v,R(u)&&Q(u)))||(u[p]=1):1
//,Q=u=>u.map((c,i,u)=>u[i]=c!=1?c:' ') // uncomment to avoid random fill
}
Ungolfedและอธิบาย (ไม่สมบูรณ์ขอโทษพวกมันทำงานมาก)
F=l=>
{
var x, z, s, q, D, R, Q, W;
// length of longest word in z
z = Math.max( ... l.map(w => w.length))
// sum of all words length in x
x = 0;
l.forEach(w => x += w.length);
for(; ++z <= x; ) // test square size from z to x
{
// grid in s[], each row of len z + 1 newline as separator, plus leading and trailing newline
// given z==offset between rows, total length of s is z*(z-1)+1
// gridsize: 2, z:3, s.length: 7
// gridsize: 3, z:4, s.length: 13
// ...
// All empty, nonseparator cells, filled with 1, so
// - valid cells have a truthy value (1 or string)
// - invalid cells have falsy value ('\n' or undefined)
s = Array(z*z-z+1).fill(1)
s = s.map((v,i) => i % z != 0 ? 1 : '\n');
// offset for 8 directions
D = [z+1, -z-1, 1-z, z-1, z, -z, 1, -1]; // 4 diags, then 2 vertical, then 2 horizontal
// Function to check repeating words
R = u => // return true if no repetition
! l.some( w => // for each word (exit early when true)
{
n = -1 -([...w]+''==[...w].reverse()); // counter starts at -1 or -2 if palindrome word
u.forEach( (a, p) => // for each cell if grid
{
if (a == [0]) // do check if cell == first letter of word, else next word
D.forEach( d => // check all directions
n += // word counter
[...w].every( c => // for each char in word, exit early if not equal
u[q += d] == c, // if word char == cell, continue to next cell using current offset
q = p-d // starting position for cell
)
) // end for each direction
} ) // end for each cell
return n > 0 // if n>0 the word was found more than once
} ) // end for each word
// Recursive function to fill empty space with random chars
// each call add a single char
Q =
( u,
p = u.indexOf(1), // position of first remaining empty cell
r = [...'ABCDEFGHIJHLMNOPQRSTUVWXYZ'] // char array to be random shuffled
) => {
if (~p) // proceed if p >= 0
return r.some((v,c)=>(r[u[p]=r[j=0|c+Math.random()*(26-c)],j]=v,R(u)&&Q(u)))||(u[p]=1)
else
return 1; // when p < 0, no more empty cells, return 1 as true
}
// Main working function, recursive fill of grid
W =
( k, // current word position in list
s, // grid
m, // bitmask with all directions used so far (8 H, 4V, 2 or 1 diag)
w = l[k] // get current word
) => {
var res = false
if (w) { // if current word exists
res = s.some((a,p)=>!!a&&
D.some((d,j,_,r=[...s],q=p-d)=>
[...w].every(c=>r[q+=d]==c?c:r[q]==1?r[q]=c:0)
&&R(r)&&W(k+1,r,m|1<<(j/2))
)
)
}
else
{ // word list completed, check additional constraints
if (m > 12 // m == 13, 14 or 15, means all directions used
&& Q(s) ) // try to fill with random, proceed if ok
{ // solution found !!
console.log(''+s) // output grid
z = x // z = x to stop outer loop
res = x//return value non zero to stop recursion
}
}
return res
};
W(0,s)
}
}
ทดสอบในคอนโซล Firefox / FireBug
F (['TRAIN', 'CUBE', 'BOX', 'BICYCLE'])
,T,C,B,O,X,B,H,
,H,R,U,H,L,I,H,
,Y,A,A,B,E,C,B,
,D,H,S,I,E,Y,I,
,H,E,R,L,N,C,T,
,G,S,T,Y,F,L,U,
,H,U,Y,F,O,E,H,
ไม่เต็ม
,T,C,B,O,X,B, ,
, ,R,U, , ,I, ,
, , ,A,B, ,C, ,
, , , ,I,E,Y, ,
, , , , ,N,C, ,
, , , , , ,L, ,
, , , , , ,E, ,
F (['TRAIN', 'ARTS', 'RAT', 'CUBE', 'BOX', 'BICYCLE', 'STORM', 'BRAIN', 'DEPTH', 'MOUTH', 'SLAB'])
,T,A,R,C,S,T,H,
,S,R,R,L,U,D,T,
,T,B,A,T,N,B,P,
,O,B,O,I,S,A,E,
,R,B,A,X,N,H,D,
,M,R,M,O,U,T,H,
,B,I,C,Y,C,L,E,
F ([ 'AA', 'AB', 'AC', 'โฆษณา', 'AE', 'เอเอฟ', 'เอจี'])
,A,U,B,C,
,T,A,E,Z,
,C,D,O,F,
,Q,C,G,A,
F ([ 'AA', 'AB', 'AC', 'โฆษณา', 'AE', 'เอเอฟ'])
ไม่ได้กรอกข้อมูลเอาท์พุท - @nathan: ตอนนี้คุณไม่สามารถเพิ่ม A xอีกครั้งโดยไม่มีการทำซ้ำ คุณจะต้องมีกริดที่ใหญ่กว่า
,A, ,C,
, ,A,F,
,D,E,B,
AC
ในตัวอย่างของคุณจะทำให้คนอื่นถ้ามันCAT
T