この言葉はボッグルボードにありますか?


38

前書き

飲みながらワールドカップを観戦した後は、腰を下ろして友好的なゲームをプレイします。あなたがボード上にさえないナンセンスな言葉でみんなの時間を無駄にしていると非難されると、気性が上がります!あなたは二重に見えるかもしれませんが、確かにあなたはあなたの言葉がボード上にあることを確認するプログラムを書くのに十分にまっすぐ考えています。

あなたのタスク

入力としてボッグルボードと単語を受け取り、単語がボード上にある場合はTrueを返し、単語がない場合はFalseを返すプログラム、スクリプト、または関数を作成します。

入力は、\n区切られた6 行の形式になります。最初の5行は5x5ボッグルボードで構成され、各行には5つの大文字が含まれます。6行目には、同様にすべて大文字で質問中の単語が含まれます。

サンプル入力:

AJNES
TNFTR
LSAIL
UDNEX
EQGMM
DAFTER

出力は、選択したプログラミング言語で明確にTrueまたはFalseを意味し、0、null、および空を意味するFalseの標準規則に準拠するものであれば何でもかまいません。

上記の入力のサンプル出力:

1

I / Oガイドライン

  • 入力は標準入力から読み取られ、出力は標準出力に返されます。

または

  • 入力は関数への単一の文字列引数であり、answerはその関数の戻り値です。

切り替えルール

  • ボード上の連続した隣接する非繰り返しタイルのパスを介して単語を構築できる場合、単語は「ボード上」にあります。
  • タイルは、それを囲む8つのタイルに隣接していると見なされます(斜めのパスは許可されます)。ボードの端のタイルは、5つのタイルにのみ隣接しています。コーナーのタイルは3つだけに隣接しています。
  • 単語内の連続する文字はi隣接している必要があり、単語内のth文字はi-1thとi+1thに隣接している必要があります。
  • 1つの文字が1つの単語に2回以上表示される場合がありますが、1単語につき2回以上、同じ枠を使用することはできません。
  • あなたが以前にboggleをプレイしたことがないが、これらのルールを感じたい場合、オンラインboggleサイトwordsplay.netは役に立つかもしれません。

通常のboggleとは異なり:

  • 単語が有効な英語であることを心配する必要はありません。
  • Qu単一のタイルはありません。
  • 質問中の単語の長さは0を超えます。

ボード上

AJNES
TNFTR
LSAIL
UDNEX
EQGMM

これらの単語はTrue、FATE、DATING、STANDS、LIFTSを返す必要があります。

これらの単語はFalseを返す必要があります:SADDEN、SULTANS、EXIST、SUEDE、QUEST

これはコードゴルフの挑戦なので、最短のコードが勝ちます!


ボードはラップアラウンドしますか?私は覚えていないことができます
クラウディウ

いいえ、ラップしません。これを反映するために、隣接関係の説明を更新しました。
turbulencetoo

パスはそれ自体を(斜めに)交差できますか?
マーティンエンダー

@ m.buettnerうん
turbulencetoo

Boggleは通常4x4ボードです。
mbomb007

回答:


11

GolfScript、74文字

:^n%5>)]){{^@==}+29,\,{{+}+1$/}%\;}/{:s$..&=[s{.@-\}*;]1567`{7&.~)}%-!&},,

入力はSTDINで指定する必要があります。ボード上の有効なパスの数を出力します。つまり0、なしの場合と正の数(true)の場合です。

オンラインでサンプルをテストできます

コメント付きのコード:

:^              # assign the input to variable ^
n%              # split at newlines
5>              # truncate array such that [WORD] remains
)])             # prepares [[]] and WORD on the stack

# the following loop generates all possible paths (valid and invalid ones)
# by looking up all index combinations which yield the correct word
{               # loop over all characters
  {^@==}+29,\,  # get all indices of current character in the board
  {{+}+1$/}%\;  # append any index to all lists in the result set
}/              # end loop

# filter the results list for valid paths
{               # {...}, -> apply filter
  :s            # save path to variable s
  $..&=         # check if all numbers in path are unique
  [s{.@-\}*;]   # calculate differences along the path
  1567`{7&.~)}% # generate the array [1 -1 5 -5 6 -6 7 -7] of valid
                # differences
  -!            # check if all differences were valid
  &             # are both conditions fulfilled?
},              # end of filter block

,               # count the number of remaining paths

12

Javascriptを(E6)137 160 175 190

2 * Golfscript未満。道徳的な勝利...

F=a=>[...a].some((e,p,b)=>(Q=(p,n)=>p>29||b[p]!=b[n]||(b.r|=!b[++n])||(b[p]=b[n+~[1,5,6,7].map(q=>Q(p+q,n)|Q(p-q,n),b[p]=0)]))(p,30)&b.r)

Golfedコードの再編成を編集します。何回も何回も

Ungolfedの最後のバージョン、ややこしい

F = a => 
  [...a] // input string to array, 30 chars of board then the target word
  .some ( // use some to scan the board, return true when found
      (e,p,b)=> // params to callback: element, position, complete array 
      (         // NB array b has no .r property, so use it for return value (it's undefined at start) 
        Q = (p,n) =>         // Scan function, p=position in board, n=nth char of target word
          p > 29 ||          // Chaek if going outside the board to the target word
          b[p] != b[n] ||    // if invalid char at current position, return
          (b.r |= !b[++n]) ||  // if at end of target, set r to 1 and return (also increment n )
          (                  // else... (NB next tree lines are coalesced in golfed code)
            b[p] = 0,        // remove current char (to avoid reusing) 
            [1,5,6,7].map( q => Q(p+q,n)|Q(p-q,n)), // recursive call for + - 1,5,6,7
            b[p] = b[n-1]    // put current char into array again 
          )
      )(p,30) & b.r // initial position 0 in target word is 30 in the array
  ) 

Ungolfed Firstバージョン、より明確に

F = a => (
  b = a.split('\n'),
  w = b.pop(),
  r = 0,
  Q = (p, n) => 
    (r |= !w[n]) || 
    (
      b[p] = 0,
      [1,5,6,7,-1,-5,-6,-7].map( q => b[q+=p]==w[n] && Q(q,n+1)),
      b[p] = w[n-1]
    ),
  b = [...b+''],
  b.map((e, p) => e==w[0] && Q(p,1)),
  r
)

使用法

F("AJNES\nTNFTR\nLSAIL\nUDNEX\nEQGMM\nLIFTS\nDAFTER")

テスト

['DAFTER', 'STANDS', 'LIFTS', 'FATE', 'DATING' ,
 'SADDEN','SULTANS', 'EXIST', 'SUEDE', 'QUEST']
.map(w => [w, F("AJNES\nTNFTR\nLSAIL\nUDNEX\nEQGMM\n" +w)])

出力:

[["DAFTER", true], ["STANDS", true], ["LIFTS", true], ["FATE", true], ["DATING", true], 
["SADDEN", false], ["SULTANS", false], ["EXIST", false], ["SUEDE", false], ["QUEST", false]]

1
いくつかのマイナーな最適化:F=a=>(b=a.split('\n'),w=b.pop(Q=(p,n)=>((R|=!w[n])||(b[p]=0)||[1,5,6,7,-1,-5,-6,-7].map(q=>b[q+=p]==w[n]&&Q(q,n+1,b[q]=w[n])))),[Q(~~p,1)for(p in b=[...b.join(R=0)])if(b[p]==w[0])],R)
nderscore

w = a.pop()(ゴルフをする)またはw = b.pop()(ゴルフをしない、2行目)を想定していますか?(おそらく後者、私は思う)
HLT

@androyd再編成後、わかりやすくするために、古いバージョンのコードを残しました。しかし、完全に同期しているわけではありません。私は明らかにしてみます
edc65

私の悪いが、あなたはそれを変更し表示されませんでしたa=a.pop()代わりにb=a.pop()...
HLT

4

パイソン、207 204 203

g=raw_input
r=range
b=''.join(g()for _ in r(5))
w=g()
s=lambda b,w,i:0<=i<25and(not w or(b[i]==w[0])*any(s(b[:i]+'_'+b[i+1:],w[1:],i+j+k*5-6)for j in r(3)for k in r(3)))
print any(s(b,w,i)for i in r(25))

に置き換える... (b[i]==w[0])*any ...... b[i]==w[0]and any ...、2文字のコストではるかに優れたパフォーマンスが得られます。


1
数字とコマンドの間にあるスペースを削除できます。0<=i<25and
seequ

3

J-75文字

ええ、これは厄介に見えます。そして、Golfscriptとの結び付けさえしません!これは、文字列を唯一の引数としてとる関数です。最後を含む各行の最後にある限り、任意の1文字の区切り文字を使用できます。

+/@([:*/"1^:2(2(=*)@-/\>@~.)S:1)@{@(((<@#:i.)5 5)<@#~&,"2{:=/&:>}:)@(<;._2)

説明が続きます。関数は5つの異なるトップレベルの部分に分割でき、それぞれがで区切られている@ため、これらの各部分を右から左に個別に扱うことに注意してください。

  • (<;._2)-これは、改行/区切り文字で行を分割します。文字列の末尾の文字を分割する文字として使用します。<Jが結果を返すときにパディングの問題が発生しないため、すべてをボックス()に入れます。

  • (((<@#:i.)5 5)<@#~&,"2{:=/&:>}:) -チェックする単語の各文字について、その文字を見つけることができるBoggleボードにインデックスのリストを作成します。

    • {:は最後の分割ピース(チェックする単語)であり}:、最後以外(Boggleボード)です。

    • &:>は、以前に作成したボックスを開き}:、2D配列の文字に変換する便利な副産物を使用します。=/次に、単語内の各文字に対してこのBoggleボードのコピーを作成し、ボード内の文字が単語内のその文字と一致したかどうかに応じて、位置をブール値に変換します。

    • ((<@#:i.)5 5)は、インデックスの5x5配列を表す簡単な方法です。x#:yy、ベースx表現の配列に変換されます。(まあ、ほぼ。真実はもっと複雑ですが、これは私たちの目的のために機能します。)

    • <@#~&,"2-各文字の結果のブール行列について、対応するすべての真のインデックスを一緒に収集します。"2すべてが適切な結果で#~&,動作するようにし、選択<@を行い、次のステップの準備のために各結果をボックスに収集します。

  • {-この動詞は単項で使用され、カタログと呼ばれ、引数としてボックスのリストを取ります。各ボックスの内部をあらゆる方法で結合します。たとえば、文字列「AB」と「abc」を含む一部のボックスのカタログは、結果「Aa」、「Ab」、「Ac」、「Ba」、「Bb」、「Bc」を返します。

    インデックスのリストのボックス化されたリストでこれを実行すると、インデックスのすべての可能な組み合わせが作成されます。単語が長く、繰り返し文字が多い場合は大きなセットになりますが、ボード上に文字がない場合は空になります。また、これらのパスの一部でタイルを再利用することにも注意してください。これについては後で説明します。

  • ([:*/"1^:2(2(=*)@-/\>@~.)S:1) -ここで、各パスをチェックして、有効かどうかを確認します。

    • (...)S:1(...)各パスに適用し、結果をフラットリストに収集します。の結果は{多次元配列であるため、これは重要です。配列の構造は気にしません。各ボックスの内容だけです。

    • 2(=*)@-/\>各インデックスの各座標が後続の座標から最大で1離れている場合は1、それ以外の場合は0を返します。2そして/\、このペアワイズを行うための責任があります。

    • */"1^:2最後にこれらをすべて論理積します。この[:部分はJの構造的なものであり、心配する必要はありません。

    • に追加する@~.と、>実際には、繰り返し入力されるパスを除外する賢い方法です。~.リストの一意のアイテムを取得するため、リストが自己交差する場合はリストが短縮され、短いリストはまとめられたときに自動的に0でパディングされますS:。これは、自己交差パスを明示的に除外するよりも最終的に短くなります。

  • +/-最後に、最後にすべてを追加します。結果は、ボード上の単語を作成する有効なパスの数です。0はパスがないことを意味します。つまり、この単語はボード上にありません。1文字のコストについては、+./代わりに(すべての論理和をとる)を記述できます。これにより、ブール値1または0が明示的に与えられます。

以下にいくつかの実行例を示します。あなたはでJインタプリタを得ることができますjsoftware.comまたはオンラインでそれを試してみてくださいtryj.tk

   NB. the  0 : 0 ... )  thing is how you do multiline strings in J
   +/@([:*/"1^:2(2(=*)@-/\>@~.)S:1)@{@(((<@#:i.)5 5)<@#~&,"2{:=/&:>}:)@(<;._2) 0 : 0
AJNES
TNFTR
LSAIL
UDNEX
EQGMM
DAFTER
)
1
   b =: +/@([:*/"1^:2(2(=*)@-/\>@~.)S:1)@{@(((<@#:i.)5 5)<@#~&,"2{:=/&:>}:)@(<;._2)
   b 'AJNES TNFTR LSAIL UDNEX EQGMM FATE '    NB. any separator will do
1
   b 'AJNES TNFTR LSAIL UDNEX EQGMM SADDEN '  NB. not on the board
0
   b 'AJNES TNFTR LSAIL UDNEX EQGMM SANDS '   NB. self-intersecting path
0
   b 'AJNES TNFTR LSAIL UDNEX EQGMM MEND '    NB. multiple paths
2

1
詳細については+1。このような答えをもっと見たいです!
edc65 14年

2

プロローグ-315

r(L):-get_char(C),(C='\n',!,L=[];r(T),L=[C|T]).
b(0,[]):-!.
b(N,[R|T]):-M is N-1,r(R),b(M,T).
d(-1). d(0). d(1).
d([A,B],[C,D]):-d(X),C is A+X,d(Y),D is B+Y.
f([L|W],B,P,U):-P=[X,Y],nth(Y,B,R),nth(X,R,L),\+member(P,U),(W=[];d(P,Q),f(W,B,Q,[P|U])).
m:-b(5,B),r(W),f(W,B,_,[]),write(t);write(f).
:-initialization(m).

Prologは、組み込みのバックトラッキングサポートを備えたこの言語に適した言語であると考えましたが、ほとんどすべての計算値に変数が必要なため、Prologの方が障害があると思います。

GNU Prologでテスト済み。ISO Prologに準拠する必要があります。

ゴルフをしていない:

get_line(Line) :-
    get_char(C),
    (   C='\n', !, Line=[]
    ;   get_line(Tail), Line=[C|Tail]
    ).

% The cut prevents recursion to help_get_board(-1, MoreRows)
% (and golfs one character shorter than putting N>0 in the second rule).
help_get_board(0, []) :- !.
help_get_board(N, [Row|Tail]) :-
    M is N-1, get_line(Row), help_get_board(M, Tail).

% The golfed version doesn't define an equivalent to get_board/1.
% help_get_board(5,Board) is used directly instead.
get_board(Board) :- help_get_board(5,Board).

small(-1). small(0). small(1).
step([X1,Y1],[X2,Y2]) :-
    small(DX), X2 is X1+DX,
    small(DY), Y2 is Y1+DY.

% The golfed version doesn't define an equivalent to letter_at/3.
% See find_word/4.
letter_at([X,Y], Letter, Board) :-
    nth(Y, Board, Row),
    nth(X, Row, Letter).

find_word([Letter|Word], Board, Pos1, Used) :-
%    letter_at(Pos1, Letter, Board),  % "inlined" to next three lines:
    ( Pos1 = [X,Y],
      nth(Y, Board, Row),
      nth(X, Row, Letter) ),
    \+member(Pos1, Used),
    (   Word=[]
    ;
        step(Pos1, Pos2),
        find_word(Word, Board, Pos2, [Pos1|Used])
    ).

main :-
    get_board(Board),
    get_line(Word),
    % Begin at any position. Initially no positions are "Used".
    find_word(Word, Board, _, []).
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.