単語検索パズル


29

単語検索パズルとしての長方形のテキストと検索文字列を指定して、テキストに検索文字列が含まれているかどうかを判断します。検索文字列が表示される場合があります。

  • 水平、垂直、または斜めに
  • 前方または後方

関数またはプログラムを作成し、関数引数ARGVまたはSTDINを介して入力として2つの文字列を使用できます。出力は、関数から返されるか、STDOUTに書き込まれる可能性のある、真実または偽の結果でなければなりません。

テキストに任意の印刷可能なASCII文字(16進コード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"

回答:


7

CJam、46 37バイト

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

STDINからグリッドを読み取り、単語をコマンドライン引数として読み取ります。一致する場合は正の整数を、一致しない場合は0を出力します。

余分な2バイトのコストで、両方の文字列(単語、改行、グリッド)を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"
]

配列を「zip」する(行と列を入れ替える)と、次のようになります。

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

それは南東の言葉をカバーしています。

Aを圧縮し、結果の行の順序を逆にすると、次のようになります。

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

これは南を対象とし、対角線のプロセスを繰り返した後、南西語を対象としています。

再び圧縮して反転すると、以下が得られます。

[
    "LKJI"
    "HGFE"
    "DCBA"
]

それは西部をカバーし、対角線のプロセスを繰り返した後、北西部の言葉をカバーします。

もう一度圧縮して反転すると、以下が得られます。

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

これは北を対象とし、対角線のプロセスを繰り返した後、北東語を対象とします。

使い方

コードは前のセクションで説明したように機能しますが、2つの小さな違いがあります。

  • それは最初に一度圧縮して反転します。
  • 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;}

基本的なブルートフォース。他に言いたいことはないでしょう。入力は針が先、干し草が2番目です。グリッドが改行で終わると仮定します

テストケースが表示された、もう少し読みやすいバージョン:

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 14

@FryAmTheEggmanいいえ、最初の失敗を見つけた後に戻るので、グリッド全体を検索しません。
ジオビット14

1
ああ、そこにちょっと迷子になった; _;
FryAmTheEggman 14

4
ループのうち二人は、あなたがしたいので、代わりに一つにまとめることができi=a*9,そしてfor(;i-->0;)、その後、z=i/9;およびi%a!=4&等々 ?
ウィル

1
うわー、これは私のものにとても似ています。そして、私はすでに始めてからそれを見ただけです。私はそれがどのように機能するかを見るのに時間をかけませんでした。+1。
レベルリバーセント14

6

JavaScript(E6)111 116

あらゆる方向のあらゆるキャラクターのブルートフォース検索-可能な限りゴルフ

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

Python、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

最初の引数はhaystackで、2番目の引数はneedleです。


私はあなたが使用して6つの文字を救うことができると思うh,n=input()print。また、これは非正方形入力でも機能しますか?(!?私は完全に間違っているかもしれないので、M = LEN(n)の私は、完全にあなたが何をしているか理解していないために認める)
FryAmTheEggman

@FryAmTheEggman:はい、非正方形入力で動作します。
エル14

1
Pythonの標準的な最適化:while i>0to while i:i負になることはないため)、 if m<1:i=-1to i-=m<1
xnor 14

1
@xnor 彼はネガティブに設定されているため、どちらもif m<1:i=-1機能if m<1:i-=1しないので、あなたは誤読しているかもしれませんi
FryAmTheEggman 14

@FryAmTheEggmanああ、はい、私はそれを完全に誤解しました。
xnor 14

5

Bash + 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は、変換関数rtおよびd必要なすべての組み合わせで、逆に、転置と対角線シフト。

更新- rゴルフィネスを高めるために、関数は反転出力と非反転出力を生成するようになりました

コマンドライン引数を介した入力-文字列を検索し、その後に(改行で区切られた)長方形の単語検索ブロックが続きます。

出力は、慣用的に正しいシェル終了ステータスコードです。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
デニス14

を定義するとr()(tee >(rev) $@)r<<<"$2"|r >(d) >(r|t) >(r|d)|r|grep "$1"同様に機能するはずです。
デニス14

私は他に何もテストしていませんが、質問の2つのテストケースは試したときにチェックアウトしました。
デニス14

@Dennis Nice-うん、今は動作します。私はマーティンに確認しました-彼は-q残りたいです。
デジタル外傷14

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

出力

この関数は、グリッドで検索された文字列の出現回数の合計を返すことに注意してください。したがって、OD6を返します。発生が見つからない場合、Cで唯一の偽の値である0を返します。に変更するy|=d*!n[j]と、1文字が保存されますが、この機能は失われます。

$ ./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バイト

2つの文字列を受け取るC#関数。最初に検索する単語、後の行に改行(\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

区切り文字として「、」を使用しているため、不適切な一致が修正されました。

どうやらゴルフに最適な方法は、大量の水平スクロールを追加することです。

入力空白 バン改行は引用符で行を区切ら: "WVERTICALL \ nROOAFFLSAB \ nACRILIATOA \ nNDODKONWDC \ nDRKESOODDK \ nOEEPZEGLIW \ nMSIIHOAERA \ nALRKRRIRER \ nKODIDEDRCD \ nHELWSLEUTH"、 "RANDOM"


1
L=len;J=''.joinなどprint any(s in(v,d,w,r...))?私はあなたが:)投稿を見たとき、私は同じラインに沿って行っていた
ウィル

@ウィル助けてくれてありがとう!lenを定義すると、節約できる文字数だけコストがかかります。また、結合を最適に定義する方法(コンマがあるものもある)がわからないので、少し説明します。
FryAmTheEggman 14

どこでもあなたが持っている)か、]スペースに続いて、あなたがスペースを取ることができます。
地下

2

APL(Dyalog Classic)、44バイト

1∊⍞⍷↑{⍉0,⍵,↑(0,⊢)\↓0,⍵}¨{⍉⌽⍵}\4⍴⊂↑a⊆⍨a≠⊃⌽a←⎕

オンラインでお試しください!


申し訳ありませんが、ここではそのような入力を取得できないようです。- \nseparated(つまり⎕TC[2]、セパレータとして)する必要があります。
エリックアウトゴルファー

@EriktheOutgolferなんてこった...後で修正します。ありがとう。
-ngn

現在は修正されていますが、残念ながらはるかに長い
ngn

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

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?)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.