Чи це слово на дошці боглів?


38

Вступ

Після дня випиття та перегляду кубка світу, ви сідаєте, щоб пограти в дружню гру. Буряки піднімаються, коли вас звинувачують в тому, що ви витрачаєте час на дурницькі слова, яких немає навіть на дошці! Можливо, ви бачите подвійний, але, безумовно, ви думаєте досить прямо, щоб написати програму, яка перевірить, чи є ваші слова на дошці.

Ваше завдання

Напишіть програму, скрипт або функцію, яка приймає дошку заблокування та слово як введення та повертає True, якщо слово є на дошці, і False, якщо це слово не є.

Вхід буде у вигляді шести \nрозділених рядків. Перші п’ять рядків міститимуть дошку із забоєм 5х5 і кожен буде містити п’ять великих літер. Шостий рядок міститиме слово-питання, також усіма великими літерами.

Зразок введення:

AJNES
TNFTR
LSAIL
UDNEX
EQGMM
DAFTER

Вихід може бути будь-яким, що однозначно означає True або False у вибраній вами мові програмування та дотримується стандартних умовних позначень нуля, нуля та порожнього, що означають False.

Вибірка зразка для введення вище:

1

Вказівки щодо вводу / виводу

  • Вхід може бути прочитаний з stdin, а відповідь - на stdout.

Або

  • Вхід може бути аргументом одного рядка функції, а відповідь - поверненим значенням цієї функції.

Правила бред

  • Слово є "на дошці", якщо ви можете побудувати слово за допомогою послідовних, сусідніх неповторюваних плиток на дошці.
  • Плитка вважається сусідньою з вісьмома плитками, які її оточують (дозволені діагональні стежки). Плитки на краю дошки примикають лише до п’яти плиток. Плитки в кутку примикають лише до трьох.
  • Послідовні букви в слові повинні бути суміжними, iбуква букв у слові повинна бути сусідньою до i-1і- i+1ї.
  • Лист може з’являтися в слові більше одного разу, але ви не можете використовувати один і той же квадрат на дошці шахрайства більше одного разу за кожне слово.
  • Веб-сайт із фігнями wordplay.net може бути корисним, якщо ви ніколи раніше не грали в фігню, але хочете відчути ці правила.

На відміну від звичайних фігня:

  • НЕ потрібно турбуватися про те, що слово є дійсним англійським словом.
  • НЕ буде Quоднієї плитки.
  • Письмове слово може мати будь-яку довжину> 0

Приклад

На дошці

AJNES
TNFTR
LSAIL
UDNEX
EQGMM

Ці слова повинні повернути Істинно: ЛЮБИМИ, ДАТИ, СТАНЦІЇ, ЖИТТЯ.

Ці слова повинні повертати помилкові: SADDEN, SULTANS, EXIST, SUEDE, QUEST

Це проблема з кодовим гольфом, тому найкоротший виграш коду!


Чи обертається дошка? Я не можу згадати
Клавдіу

Ні, це не завершується, я оновив роз'яснення щодо сусідства, щоб відобразити це.
турбулентність

Чи може шлях перетинатися (по діагоналі)?
Мартін Ендер

@ m.buettner Yep
турбулентність

Boggle - це зазвичай дошка 4x4.
mbomb007

Відповіді:


11

GolfScript, 74 символи

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

Вхід повинен бути вказаний на STDIN. Друкує кількість дійсних шляхів на дошці, тобто 0для жодного та додатне число (справжнє).

Ви можете перевірити приклад в Інтернеті .

Код з коментарями:

:^              # 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 * Гольфскрипт. Моральна перемога ...

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 Перша версія, повинна бути більш зрозумілою

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 Я залишив старіший код без вольфів для ясності, після реорганізації. Але це не 100% синхронізація. Спробую уточнити
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 char

Еге, цей виглядає неприємно. І навіть не зв’язуючись з Гольфскриптом! Це функція, що приймає рядок як єдиний аргумент. Ви можете використовувати будь-який символьний роздільник, якщо він знайдений в кінці кожного рядка, включаючи останній.

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

З цього випливає пояснення. Зауважте, що функцію можна розбити на 5 різних частин верхнього рівня, кожну розділену ними @, тому ми розглянемо кожну з цих частин окремо, справа наліво.

  • (<;._2)- Це розбиває лінії вгору на символи нових рядків / роздільника. Він використовує символ в кінці рядка як символ, на який потрібно розділити. Ми поміщаємо все в коробки ( <), тому що якщо ми цього не зробимо, ми отримаємо деякі проблеми з прокладкою, коли J поверне нам результат.

  • (((<@#:i.)5 5)<@#~&,"2{:=/&:>}:) - Для перевірки кожної літери в слові створіть список індексів на дошці Boggle, де можна знайти цю букву.

    • {:це останній розрізний шматок (слово для перевірки) і }:це все, крім останнього (дошка Boggle).

    • &:>відкриває попередньо створені нами поля з корисним побічним продуктом перетворення }:в двовимірний масив символів. =/потім робить копію цієї дошки Boggle для кожної літери слова та перетворює позиції в булеві залежно від того, чи відповідає літера на дошці цій букві в слові.

    • ((<@#:i.)5 5)- це короткий спосіб вираження масиву індексів 5x5. x#:yперетворюється yв масив базового xподання. (Ну майже. Правда є складнішою, але це працює для наших цілей.)

    • <@#~&,"2- Для одержуваної булової матриці кожної літери зібрати разом усі відповідні справжні індекси. "2змушує все працювати над правильними результатами, #~&,робить вибір і <@збирає кожен результат у вікно, щоб підготуватися до наступного кроку.

  • {- Це дієслово, яке використовується монадично, називається Catalog, і воно бере аргумент списку полів. Він поєднує нутрощі кожного ящика всіляко. Так, наприклад, каталог на деяких полях, що містять рядки "AB" і "abc", дасть результати "Aa", "Ab", "Ac", "Ba", "Bb", "Bc".

    Якщо запустити це у нашому списку, що міститься у вікні списків індексів, це робить усі можливі поєднання індексів. Це може бути великим набором, якщо там слово довге і багато повторених букв, а також порожнє, якщо жодна літера не є на дошці. Також зауважимо, що ми повторно використовуємо плитки в деяких із цих шляхів: це буде враховано пізніше.

  • ([:*/"1^:2(2(=*)@-/\>@~.)S:1) - Тут ми перевіряємо кожен шлях, щоб перевірити, чи він дійсний.

    • (...)S:1застосовує (...)до кожного шляху і збирає результати в плоский список. Це має вирішальне значення, тому що результат {- це багатовимірний масив, і нас не хвилює структура цього масиву, а лише його вміст у кожному полі.

    • 2(=*)@-/\>дає 1, якщо кожна координата кожного індексу знаходиться не більше однієї від тієї, що йде за ним, і 0 в іншому випадку. Вони 2і /\відповідають за це попарно.

    • */"1^:2логічно-І це все разом у кінці. Ця [:частина є структурною річчю в J, не переживайте про це.

    • Додавання @~.до знань >насправді розумний спосіб виключити шляхи з повторними записами. ~.приймає унікальні елементи списку, тому список скорочується, якщо він перетинається, а короткі списки автоматично додаються до 0, коли вони збираються разом, як спосіб поєднання результатів, коли вони виходять S:. Це в кінцевому рахунку коротше, ніж явне виключення самопересічних шляхів.

  • +/- Нарешті, ми просто додаємо все разом у кінці. Результат - кількість дійсних шляхів, які складають слово на дошці, при цьому значення 0 не означає шляхів, тобто це слово не є на дошці. Для вартості одного символу ми можемо +./замість цього записати (логічно-ОРІОНУЙТЕ все разом), що явно дасть логічне значення 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

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 може бути хорошою мовою для цього, із вбудованою підтримкою зворотного відстеження, але, мабуть, він є більш сприятливим, потребуючи змінної майже для кожного обчисленого значення.

Тестували з 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, _, []).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.