单词搜索难题


29

给定一个矩形文本作为单词搜索难题和一个搜索字符串,请确定该文本是否包含搜索字符串。搜索字符串可能会出现:

  • 水平,垂直或对角线
  • 前进或后退

您可以编写一个函数或程序,并通过函数参数ARGV或STDIN接受两个字符串作为输入。输出应该是真实的或虚假的结果,可以从函数返回或写入STDOUT。

假定文本将包含任意可打印的ASCII字符(十六进制代码20至7E)和换行符。字母区分大小写。您可以假定输入文本为矩形,即所有行的长度均相同。您可以输入是否以尾随换行符结尾(如果对您的提交很重要)。

这是代码高尔夫球,最短的答案(以字节为单位)获胜。

例子

使用维基百科关于单词搜索的文章中的此网格作为第一个输入:

WVERTICALL
ROOAFFLSAB
ACRILIATOA
NDODKONWDC
DRKESOODDK
OEEPZEGLIW
MSIIHOAERA
ALRKRRIRER
KODIDEDRCD
HELWSLEUTH

以下搜索字符串应分别产生真实或虚假结果:

Truthy: RANDOM, VERTICAL, HORIZONTAL, WORDSEARCH, WIKIPEDIA, TAIL
Falsy:  WordSearch, CODEGOLF, UNICORN

或者,使用此输入文本

Lorem ipsum dolor sit amet consectetu
r adipisicing elit sed do eiusmod tem
por incididunt ut labore et dolore ma
gna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco lab
oris nisi ut aliquip ex ea commodo co
nsequat. Duis aute irure dolor in rep
rehenderit in voluptate velit esse ci
llum dolore eu fugiat nulla pariatur.

我们得到以下搜索结果(现在使用引号,因为某些搜索字符串中有空格):

Truthy: "Lorem", "mine", "uma bop", "tuetdod", "snol,a", "texas", "pii.d  v", "vexta"
Falsy:  "lorem", "wordsearch", "pii.d v", "mute"

Answers:


7

CJam,46 37字节

qN%{_zW%__,N**2$2$+,)/z\}4*]:+N*eas#)

从STDIN和单词中读取网格作为命令行参数。打印匹配的正整数,不匹配的则打印0。

可以从STDIN中读取两个字符串(单词,换行符和网格),但要多花两个字节:

qN%(\{_zW%__,N**2$2$+,)/z\}4*](\:+N*\#)

您可以使用CJam解释器在线尝试该版本。

运行示例

$ for W in Lorem mine uma\ bop tuetdod snol,a texas pii.d\ \ v vexta WordSearch CODEGOLF UNICORN; do echo -e "$(cjam wordsearch.cjam "$W" < grid)\t$W"; done
1       Lorem
3085    mine
2055    uma bop
5142    tuetdod
3878    snol,a
1426    texas
5371    pii.d  v
2536    vexta
0       WordSearch
0       CODEGOLF
0       UNICORN

背景

假设输入是以下网格:

ABCD
EFGH
IJKL

在换行符处拆分,我们获得以下数组:

A := [
         "ABCD"
         "EFGH"
         "IJKL"
     ]

涵盖了东方单词(单词从左到右)。

现在,我们结合A使用len(A)换行字符串作为分隔符的元素:

"ABCD⏎⏎⏎EFGH⏎⏎⏎IJKL"

然后,将生成的字符串切成一定长度的块len(A) + len(A[0]) + 1

[
    "ABCD⏎⏎⏎E"
    "FGH⏎⏎⏎IJ"
    "KL"
]

如果我们“压缩”数组(转置行和列),则可以获得:

[
    "AFK"
    "BGL"
    "CH"
    "D⏎"
    "⏎⏎"
    "⏎⏎"
    "I⏎"
    "EJ"
]

那涵盖了东南词。

如果我们压缩A并反转结果行的顺序,则可以获得:

[
    "DHL"
    "CGK"
    "BFJ"
    "AEI"
]

它涵盖了南方,以及-在重复对角线的过程之后-西南单词。

再次压缩和反转,我们获得:

[
    "LKJI"
    "HGFE"
    "DCBA"
]

它涵盖了West和-在重复对角线的过程之后-North West单词。

再次压缩和反转,我们获得:

[
    "IEA"
    "JFB"
    "KGC"
    "LHD"
]

覆盖北,在重复对角线的过程之后,覆盖东北词。

怎么运行的

该代码按照上一节中的说明进行操作,但有两个小区别:

  • 它从一开始就压缩和反转一次。
  • 计算len(A) + len(A[0])len(A + zip(A))

最后,它使用换行符作为分隔符,连接所有生成的数组的所有行,并在结果字符串中搜索单词。

qN%                                   " A := split(input(),'\n')                          ";
   {                    }4*           " Do 4 times:                                       ";
    _zW%                              "   B := reverse(zip(A))                            ";
        __,N**                        "   C := B.join(len(B) * '\n')                      ";
              2$2$+,)/z               "   D := zip(C.chunks(len(A + B) + 1))              ";
                       \              "   A := B                                          ";
                           ]          " Collect all values of A and D in an array R.      ";
                            :+        " R := flatten(R)                                   ";
                              N*      " R := R.join('\n')                                 ";
                                eas   " I := flatten(ARGV)                                ";
                                   #) " print R.index(I) + 1                              ";

7

Java的:183 211 321

boolean s(char[]w,char[]s){int j,z,a=s.length,i=a*9,f=1,q=0;for(;s[q++]>10;);for(;i-->0;)for(j=w.length,z=i/9;i%9!=4&j-->0&z>=0&z<a&&s[z]==w[j];z+=q*(i/3%3)+i%3-q-1)f*=j;return f==0;}

基本的蛮力。我想没什么可说的了。输入首先是针,然后是干草堆。假设grid是换行符终止的

带有测试用例的可读性更高的版本:

public class WordSearch {
    static String grid = "WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH";
    static String search = "RANDOM";

    public static void main(String[] args) {
        System.out.println(new WordSearch().s(search.toCharArray(),grid.toCharArray()));
    }

    boolean s(char[]w,char[]s){
        int j,z,a=s.length,i=a*9,f=1,q=0;
        for(;s[q++]>10;);
        for(;i-->0;)
            for(j=w.length,z=i/9;
                i%9!=4&j-->0&z>=0&z<a&&s[z]==w[j];
                z+=q*(i/3%3)+i%3-q-1)
                f*=j;
        return f==0;
    }
}

if(e<1)return 1>0;可能是return e<1;不能呢?
FryAmTheEggman 2014年

@FryAmTheEggman不,这将在找到第一个故障后返回,因此它不会搜索整个网格。
Geobits 2014年

1
抱歉,有点迷路了;
FryAmTheEggman 2014年

4
该出两个for循环,可以折叠成一个代替你会做i=a*9,for(;i-->0;),然后z=i/9;i%a!=4&对等?
2014年

1
哇,这和我的非常相似。我只是在开始后才看了一眼。我没有花时间去看它是如何工作的。+1。
等级河圣

6

JavaScript(E6)111116

蛮力搜索各个方向上的每个角色-尽我所能

F=(b,w)=>
  [1,-1,r=b.search('\n'),-r,++r,-r,++r,-r].some(d=>
    [...b].some((_,p)=>
      [...w].every(c=>c==b[p+=d],p-=d)
    )
  )

在FireFox / Firebug控制台中测试

;["RANDOM", "VERTICAL", "HORIZONTAL", "WORDSEARCH", "WIKIPEDIA", "TAIL",
"WordSearch", "CODEGOLF", "UNICORN"]
.forEach(w=>console.log('\n'+ w +' -> '+
  F("WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH",w)))

输出量

RANDOM -> true
VERTICAL -> true
HORIZONTAL -> true
WORDSEARCH -> true
WIKIPEDIA -> true
TAIL -> true
WordSearch -> false
CODEGOLF -> false
UNICORN -> false

5

巨蟒(175)

灵感不是很大,但是这里有:

def s(h,n):
 l=h.find('\n')+2;h+='\n'*l;L=i=len(h)
 while i>0:
  i-=1
  for d in[-l,1-l,2-l,-1,1,l-2,l-1,l]:
    j=i;m=len(n)
    for c in n:m-=c==h[j%L];j+=d
    if m<1:i=-1
 return-i

第一个论点是干草堆,第二个论点是针。


我认为您可以使用h,n=input()和保存6个字符print。此外,这是否适用于非平方输入?(m = len(n)?我承认不完全了解您在做什么,所以我可能完全错了!)
FryAmTheEggman 2014年

@FryAmTheEggman:是的,它适用于非方形输入。
2014年

1
一些标准的Python优化:while i>0to while i:(因为i永远不会变成负数), if m<1:i=-1to i-=m<1
xnor 2014年

1
@xnor我认为您可能读错了if m<1:i=-1if m<1:i-=1因为这两个都不起作用,因为他设置i为负面。
FryAmTheEggman 2014年

@FryAmTheEggman哦,是的,我完全没有读错。
xnor 2014年

5

击+的coreutils,214个 169字节

r()(tee >(rev) $@)
t()(eval paste -d'"\0"' `sed 's/.*/<(fold -1<<<"&")/'`)
d()(while IFS= read l;do echo "$a$l";a+=_;done|t)
r<<<"$2"|r >(d) >(r|t) >(r|d)|r|grep -q "$1"

使用3个变换函数rtd以所有必要的组合反转,转置和对角线移位。

更新-该r函数现在可以产生反向和非反向输出,从而提高了高尔夫球感

通过命令行参数输入-搜索字符串,后跟(以换行符分隔)矩形wordsearch块。

输出是习惯上正确的外壳出口状态代码-0表示TRUE,1表示FALSE。

输出:

$ for w in "Lorem" "mine" "uma bop" "tuetdod" "snol,a" "texas" "pii.d  v" "vexta" ; do ./ws.sh "$w" "Lorem ipsum dolor sit amet consectetu
r adipisicing elit sed do eiusmod tem
por incididunt ut labore et dolore ma
gna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco lab
oris nisi ut aliquip ex ea commodo co
nsequat. Duis aute irure dolor in rep
rehenderit in voluptate velit esse ci
llum dolore eu fugiat nulla pariatur."; echo $?; done
0
0
0
0
0
0
0
0
$ for w in WordSearch CODEGOLF UNICORN ; do ./ws.sh "$w" "Lorem ipsum dolor sit amet consectetu
r adipisicing elit sed do eiusmod tem
por incididunt ut labore et dolore ma
gna aliqua. Ut enim ad minim veniam, 
quis nostrud exercitation ullamco lab
oris nisi ut aliquip ex ea commodo co
nsequat. Duis aute irure dolor in rep
rehenderit in voluptate velit esse ci
llum dolore eu fugiat nulla pariatur."; echo $?; done
1
1
1
$ 

1.我本来建议T()(tee >(r) $@),但这更好。2.我认为我以前从未见过该函数语法。3.考虑到非空字符串为真和空字符串为假,我认为您可以省略-q
丹尼斯2014年

如果您定义r()(tee >(rev) $@),也r<<<"$2"|r >(d) >(r|t) >(r|d)|r|grep "$1"应该可以正常工作。
丹尼斯

我没有测试过其他任何东西,但是当我尝试时,问题中的两个测试用例都已签出。
丹尼斯

@Dennis Nice-是的,现在可以使用。我检查了马丁-他希望-q留下。
Digital Trauma 2014年

5

C 163

f(char*h,char*n){int i,j,d,p,y=0,l=strlen(h),w=strchr(h,10)-h+1;for(i=l*9;i--;y+=d&&!n[j]){p=i/9;d=i%9/3*w-w+i%3-1;for(j=0;p>=0&p<l&h[p]==n[j];j++)p+=d;}return y;}

无需重新排列网格,我只需尝试各个方向上的每个起始字母,然后一直走下去,直到我离开网格或发现不匹配为止。

我利用C字符串以零字节结尾的事实。由于网格中没有零字节,因此总是不匹配。但是,如果不匹配发生在零字节处,我们知道我们已经找到要搜索的字符串的结尾,并将其记录为匹配项。

脱离测试程序

char h[]="WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH\n";

f(char*h,char*n){                                   //haystack,needle
  int i,j,d,p,y=0,l=strlen(h),w=strchr(h,10)-h+1;   //l=length of whole grid. w=width of row, including terminal newline ASCII 10
  for(i=l*9;i--;){                                  //for each start letter and direction
    p=i/9;                                          //pointer to start letter
    d=i%9/3*w-w+i%3-1;                              //9 possible values of direction vector {-w,0,w}+{-1,0,1}
    for(j=0;p>=0&p<l&h[p]==n[j];j++)p+=d;           //walk p in the direction defined by d until we walk off the top or bottom of the grid or a mismatch is fount
    y+=d&&!n[j];                                    //if we got all the way to the terminal 0, record it as a hit. If d=0, don't record as this is an invalid direction.
  }
  return y;   
}

main(int c, char**v){
  printf("%d",f(h,v[1]));  
}

输出量

请注意,该函数将返回在网格中搜索的字符串出现的总数。因此,OD它返回6。如果未发现任何事件,则返回0,这是C语言中唯一的虚假值。更改为y|=d*!n[j]会保存一个字符,但会失去此功能。

$ ./a UNICORN
0

$ ./a CODEGOLF
0

$ ./a WordSearch
0

$ ./a RANDOM
1

$ ./a WORDSEARCH
1

$ ./a VERTICAL
1

$ ./a HORIZONTAL
1

$ ./a WIKIPEDIA
1

$ ./a TAIL
1

$ ./a OD
6

5

C# - 218个 197 186字节

C#函数需要2个字符串,第一个字符串要搜索,第二个字符串在行\n之间使用换行()。现在事情变得绝望了…… 实际上如此绝望,以至于我之前的编辑不起作用!

高尔夫代码:

bool F(string D,string S){int l=S.Length,i=l*13,r,p;for(S+="\n";i-->l*5;i=r<0?r:i)for(r=D.Length,p=i%l;p>-1&p<l&r-->0&&D[r]==S[p];p+=(S.IndexOf('\n')+1)*(i/l%9/3-1)+i/l%3-1);return i<0;}

测试代码较少:

class P
{
    static void Main()
    {
        System.Console.WriteLine(new P().F(System.Console.ReadLine(),System.Console.In.ReadToEnd())?"Truthy":"Falsy"); // because why not
    }

    bool F(string D,string S)
    {
        int l=S.Length,i=l*13,r,p;

        for(S+="\n";i-->l*5;i=r<0?r:i) // for each cell/direction
            for(r=D.Length,p=i%l;p>-1&p<l&r-->0&&D[r]==S[p];p+=(S.IndexOf('\n')+1)*(i/l%9/3-1)+i/l%3-1); // test against string (backwards)

        return i<0;
    }
}

4

哈斯克尔-173

我没有直接在网格上搜索,而是以不同的方式转换网格并将单词与新网格的每一行匹配。

例如,

G1    G2    G3       G4   G5

abcd  aA1   abcd     a..  ..1
ABCD  bB2   .ABCD    bA.  .A2
1234  cC3   ..1234   cB1  aB3
      dD4            dC2  bC4
                      D3  cD
                       4  d

在G1,G2,G4和G5的每一行中搜索单词,然后就可以完成了。请注意,未使用G3,我将其发布在这里只是为了说明。

将类似的想法应用于向前和向后搜索:仅搜索原始单词和反向单词。

所以现在我们搜索了8个方向。这是代码,其正确性已由另一个脚本验证。

import Data.List
v=reverse
t=transpose
y=any
d r=zipWith(++)(scanr(\_->('\n':))[]r)r
g r w=y(y$y((==w).take(length w)).tails)[r,t r,t.d$r,t.d.v$r]
f r w=y(g(lines r))[w,v w]

函数f就是我们想要的,其参数r是矩形字符串,w是要搜索的单词。


4

Python的2 - 246 259 275 308 298 297 294 313 322

w,s=input()
r=range
d='\n'
I=''.join
w=w.split(d)
t,u=len(w),len(w[0])
v=d.join([I(x)for x in zip(*w)]+[d]+[I([w[i+j][i]for i in r(min(u,t-j))])+d+I([w[i][i+j]for i in r(min(t,u-j))])for j in r(max(t,u))]+[d]+w)
print s in v or s[::-1]in v

感谢Will在处理打印和定义联接方面的帮助。

感谢地下铁路提醒我正确打高尔夫; p

修复了由于使用','作为分隔符导致的不匹配问题。

显然,打高尔夫球的最佳方法是增加大量的水平滚动。

输入用引号引起来的空格 bang换行符分隔的行:“ WVERTICALL \ nROOAFFLSAB \ nACRILIATOA \ nNDODKONWDC \ nDRKESOODDK \ nOEEPZEGLIW \ nMSIIHOAERA \ nALRKRRIRER \ nKODIDEDRCD \ nHELWSLEUTH”,“ RANDOM”


1
L=len;J=''.join等和print any(s in(v,d,w,r...))?当我看到您发布消息时,我的
2014年

@将感谢您的帮助!定义len所花费的字符数与所保存的字符数相同,而且我不确定如何以最佳方式定义连接(有些使用逗号),因此我将做一点。
FryAmTheEggman 2014年

无论您有空格)还是]跟随空格的地方,都可以拿走该空格。
地下


0

J60 53字节

<@[e.[:,[:(;|.)@>[:<\\.@>[:(<"1,</.)@>@(;|.@|:)[;.2@]

在线尝试!

要求第一个输入不包含换行符。

说明:

linkrotate=: ;|.@|:     NB. link with itself rotated 90° ccw
infixes   =: <\\.       NB. list of boxes containing the infixes
lines     =: <"1 , </.  NB. horizontal and diagonal lines, boxed
linkrev   =: ;|.        NB. link with itself reversed
appearin  =: <@[ e. [: , [: linkrev@> [: infixes@> [: lines@>@linkrotate [;.2@]

在线尝试!

钩子很有用。


看来也可行。(51个字节)
user202729 '18

0

果冻,16 字节

使用这16个字节中的15个作为代码的核心解决了一个相关的(可能是重复的)挑战 ...

ỴZU$3С;ŒD$€Ẏw€Ẹ

双向链接在左侧接受一个字符列表,在右侧接受一个字符列表,如果找到则返回1,否则返回0。

在线尝试!

怎么样?

ZU$3С;ŒD$€Ẏw€Ẹ - Link: words, grid
   3С          - repeat three times and collect the results (inc input):
  $             -   last two links as a monad:
Z               -     transpose
 U              -     upend     (together these rotate by a quarter)
          €     - for €ach:
         $      -   last two links as a monad:
       ŒD       -     get forward-diagonals
      ;         -     concatenate
           Ẏ    - tighten (to get all the runs across the grid) 
             €  - for €ach run:
            w   -   sublist-index (0 if not found)
              Ẹ - any truthy? (i.e. was the word found?)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.