Thế hệ câu đố tìm kiếm từ


13

Đưa ra một danh sách các chuỗi, tìm ma trận vuông nhỏ nhất chứa mỗi chuỗi ban đầu. Các chuỗi có thể xuất hiện theo chiều ngang, chiều dọc hoặc đường chéo và chuyển tiếp hoặc ngược lại như trong câu hỏi này Word Search Puzzle .

Các từ nên được đặt trong hình vuông, với ít nhất một từ theo mỗi hướng (ngang, dọc và chéo). Từ ngữ chỉ nên xuất hiện một lần.

Vì vậy, đầu vào chỉ là một danh sách các từ. Ví dụ : CAT, TRAIN, CUBE, BICYCLE. Một giải pháp có thể là:

B N * * * * *
* I * * C A T
* A C * * * *
* R * Y * * C
* T * * C * U
* * * * * L B
* * * * * * E

Tôi thay thế điền chữ cái bằng dấu hoa thị chỉ cho rõ ràng. Đầu ra mong muốn nên bao gồm các chữ cái điền ngẫu nhiên.


Phải tìm thấy mỗi từ chỉ trong một vị trí (như tìm kiếm từ điển hình)? Ví dụ, chữ cái còn lại ACtrong ví dụ của bạn sẽ tạo một chữ cái khác CATnếu nó T.
Geobits

Tôi không rõ chính xác ý bạn là gì bởi "Các từ nên được đặt ngẫu nhiên theo mọi hướng ". Liệu một câu trả lời có đáp ứng tiêu chí này không, nếu đặt các từ một cách xác định, nó sẽ chọn ngẫu nhiên một trong tám đối xứng của hình vuông? Hoặc, ở một thái cực khác, đầu ra có nên được chọn thống nhất từ ​​tất cả các ô vuông nhỏ nhất có thể có chứa các từ không? Hay là đường vẽ ở đâu đó ở giữa những thái cực đó?
Peter Taylor

Vâng, nó chỉ nên được tìm thấy ở một vị trí.
Di chuyển

1
Không thực sự, không. Tôi vẫn chưa rõ không gian mà một câu trả lời nên lấy mẫu ngẫu nhiên là gì, cũng như mức độ linh hoạt được phép trong việc cân các yếu tố của không gian đó.
Peter Taylor

1
Đến bây giờ, câu hỏi có những đầu vào không thể giải quyết được, nhưng không có đề cập nào được đưa ra về cách bạn phải giải quyết vấn đề đó. Ví dụ bộ A B C D E F G H I J K L M N O P Q R S T U V W X Y Zkhông có giải pháp.
orlp

Câu trả lời:


6

JavaScript (ES6), 595 628 680

Chỉnh sửa Một số dọn dẹp và hợp nhất:
- hàm P được hợp nhất bên trong hàm R
- calc x và z trong cùng một .map
- khi tìm thấy giải pháp, đặt x thành 0 để thoát khỏi vòng lặp bên ngoài
- sáp nhập definiton và cuộc gọi của W

Chỉnh sửa thêm 2 lần chơi gôn, rút ​​ngắn điền ngẫu nhiên, sửa vòng lặp ngoài ... xem lịch sử để biết thêm điều gì dễ đọc hơn

Không giống như câu trả lời được chấp nhận, điều này sẽ làm việc cho hầu hết các đầu vào. Chỉ cần tránh các từ đơn. Nếu một đầu ra được tìm thấy, nó tối ưu và sử dụng cả 3 hướng.

Hạn chế của việc tránh lặp lại các từ là rất khó. Tôi đã phải tìm kiếm từ lặp lại ở mỗi bước thêm từ vào lưới và ở mỗi ký tự điền ngẫu nhiên.

Các chức năng con chính:

  • P (w) đúng nếu từ palindrom. Một từ palindrom sẽ được tìm thấy hai lần khi kiểm tra các từ lặp lại.

  • R (s) kiểm tra các từ lặp lại trên lưới s

  • Q (s) điền vào lưới s bằng các ký tự ngẫu nhiên - đó là đệ quy và quay lại trong trường hợp lặp lại từ - và có thể thất bại.

  • W () đệ quy, cố gắng điền vào một lưới có kích thước nhất định, nếu có khả năng.

Hàm chính sử dụng W () để tìm lưới đầu ra, thử từ kích thước của từ dài nhất trong đầu vào cho đến tổng độ dài của tất cả các từ.

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
}

Ung dung và giải thích (không đầy đủ, xin lỗi các bạn đó là rất nhiều công việc)

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)
  }    
}

Kiểm tra trong bảng điều khiển Firefox / FireBug

F (['TRAIN', 'CUBE', 'HỘP', '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,  

Chưa được điên

,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', 'AD', 'AE', 'AF', 'AG'])

,A,U,B,C,
,T,A,E,Z,
,C,D,O,F,
,Q,C,G,A,

F (['AA', 'AB', 'AC', 'AD', 'AE', 'AF'])

đầu ra không được điền - @nathan: bây giờ bạn không thể thêm A x khác mà không lặp lại. Bạn sẽ cần một lưới lớn hơn.

,A, ,C,
, ,A,F,
,D,E,B,

Trong trường hợp thử nghiệm cuối cùng của bạn, không thể có trong lưới 3x3?
Nathan Merrill

@NathanMerrill không. Chi tiết hơn trong văn bản trả lời
edc65

mã hoàn toàn không thể đọc được :) nhưng thật tuyệt đó là nhược điểm của "giải thưởng" byte / điểm không phải là trình biên dịch của con người
firephil

1
@firephil cố gắng thêm một lời giải thích, thật không dễ dàng ...
edc65

1

C #

Đây là một cách thực hiện đơn giản với công việc vẫn phải hoàn thành. Có rất nhiều kết hợp để có được kích thước nhỏ nhất. Vì vậy, chỉ cần sử dụng thuật toán đơn giản nhất có thể nghĩ ra.

class Tile
{
    public char C;
    public int X, Y;
}

class Grid
{
    List<Tile> tiles;

    public Grid()
    {
        tiles = new List<Tile>();
    }
    public int MaxX()
    {
        return tiles.Max(x => x.X);
    }
    public int MaxY()
    {
        return tiles.Max(x => x.Y);
    }
    public void AddWords(List<string> list)
    {
        int n = list.Count;
        for (int i = 0; i < n; i++)
        {
            string s = list[i];
            if(i==0)
            {
                Vert(s, 0, 0);
            }
            else if(i==n-1)
            {
                int my = MaxY();
                Diag(s, 0, my+1);
            }
            else
            {
                Horiz(s, 0, i);
            }
        }

    }
    private void Vert(string s, int x, int y)
    {
        for (int i = 0; i < s.Length; i++)
        {
            Tile t = new Tile();
            t.C = s[i];
            t.X = x+i;
            t.Y = y;
            tiles.Add(t);
        }
    }
    private void Horiz(string s, int x, int y)
    {
        for (int i = 0; i < s.Length; i++)
        {
            Tile t = new Tile();
            t.C = s[i];
            t.X = x+i;
            t.Y = y;
            tiles.Add(t);
        }
    }
    private void Diag(string s, int x, int y)
    {
        for (int i = 0; i < s.Length; i++)
        {
            Tile t = new Tile();
            t.C = s[i];
            t.X = x++;
            t.Y = y++;
            tiles.Add(t);
        }
    }
    public void Print()
    {
        int mx = this.MaxX();
        int my = this.MaxY();
        int S = Math.Max(mx, my) + 1;
        char[,] grid = new char[S, S];
        Random r = new Random(DateTime.Now.Millisecond);
        //fill random chars
        for (int i = 0; i < S; i++)
        {
            for (int j = 0; j < S; j++)
            {
                grid[i, j] = (char)(r.Next() % 26 + 'A');
            }
        }
        //fill words
        tiles.ForEach(t => grid[t.X, t.Y] = t.C);
        //print
        for (int i = 0; i < S; i++)
        {
            for (int j = 0; j < S; j++)
            {
                Console.Write("{0} ", grid[i,j]);
            }
            Console.WriteLine();
        }
    }
}

class WordSearch
{
    public static void Generate(List<string>list)
    {
        list.Sort((x, y) =>
        { int s = 0; if (x.Length < y.Length)s = -1; else if (y.Length < x.Length)s = 1; return s; });
        list.Reverse();
        Grid g = new Grid();
        g.AddWords(list);
        g.Print();
    }

}

Kiểm tra

class Program
{
    static void Main(string[] args)
    {
        string words = "CAT, TRAIN, CUBE, BICYCLE";
        string comma=",";
        List<string> w = words.Split(comma.ToArray()).ToList();
        List<string> t = new List<string>();
        foreach(string s in w)
        {
           t.Add(s.Trim());
        }
        WordSearch.Generate(t);

        Console.ReadKey();
    }
}

nó hoạt động nhưng không tối ưu: chuỗi từ mẫu = "CAT, DOG, HR, RUN, CMD";
hỏa hoạn

Bạn có kiểm tra xem các ký tự điền ngẫu nhiên có gây ra sự lặp lại của một từ trong lưới không?
edc65

-1 Đã thử nó. Không theo thông số kỹ thuật at least one word in each direction (horizontal, vertical and diagonal). Chạy chương trình thử nghiệm, không có từ ngang (3 dọc, 1 diag)
edc65

3
Câu hỏi này là code-golf , vì vậy bạn nên đăng bao nhiêu byte trong tiêu đề và có thể rút ngắn một bó chương trình của bạn. Cảm ơn.
mbomb007

@ edc65 Nó thực hiện một chiều dọc, một đường chéo và tất cả các đường chéo khác. Như tôi đã nhận xét để có được giải pháp hoàn hảo sẽ đòi hỏi số lượng lớn kết hợp để kiểm tra cũng như các thông số kỹ thuật của câu hỏi.
bacchusbeale
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.