Пошук головоломки


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"

Відповіді:


7

CJam, 46 37 байт

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

Читає сітку з STDIN і слово як аргумент командного рядка. Друкує додатні цілі числа для матчів та 0 для не збігів.

За ціною двох зайвих байтів обидва рядки (word, linefeed, grid) можна прочитати з 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

Розщеплюючи на linefeeds, ми отримуємо такий масив:

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"
]

Це охоплює Захід і - після повторення процесу діагоналей - слова Північного Заходу.

Знову перетягуючи та обертаючи, ми отримуємо:

[
    "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

Ява: 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;}

Основна груба сила. Думаю, ще нема чого сказати. Вхід - голка перша, а сіна друга. Припускає, що сітка закінчується новим рядком .

Трохи більш читабельна версія із показаним тестовим кейсом:

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

@FryAmTheEggman Ні, це повернеться після виявлення першої помилки, тому він не буде шукати всю сітку.
Геобіць

1
Ах вибачте, там заблукали; _;
FryAmTheEggman

4
З двох петель для може бути згорнуті в один замість так ви могли б зробити , i=a*9,і , for(;i-->0;)а потім z=i/9;і i%a!=4&і так далі?
Буде

1
Ого, це так схоже на моє. І я поглянув на це лише після того, як я вже почав. Я не потребував часу, щоб побачити, як це працює. +1.
Рівень р. Св.

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

Пітона, 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

Перший аргумент - стог сіна, другий - голка.


Я думаю, ви можете зберегти 6 символів за допомогою h,n=input()і print. Також це працює з неквадратичними входами? (m = len (n)? Я визнаю, що не до кінця розумію, що ти робиш, тому я можу бути абсолютно невірним!)
FryAmTheEggman

@FryAmTheEggman: Так, він працює з неквадратичними входами.
Ell

1
Деякі стандартні оптимізації Python: while i>0to while i:(оскільки iніколи не може стати негативним), if m<1:i=-1to i-=m<1.
xnor

1
@xnor Я думаю, що ви можете неправильно прочитати if m<1:i=-1, if m<1:i-=1оскільки жоден із них не буде працювати, оскільки він налаштований iна негатив.
FryAmTheEggman

@FryAmTheEggman О, так, я цілком неправильно це прочитав.
xnor

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 функції перетворення r, tа також dдля зворотного, переміщення та діагонального зсуву у всіх необхідних комбінаціях.

Оновлення - rтепер функція виробляє зворотний та неперевернутий вихід для додаткової гольфності

Введіть через аргументи командного рядка - рядок пошуку, а потім прямокутний блок пошуку слів (відокремлений новим рядком).

Вихід - це ідіоматично правильний код статусу виходу з оболонки - 0, що означає ПРАВИЛЬНЕ і 1 означає ЛІЖНЕ.

Вихід:

$ 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.
Денніс

Якщо ви визначитеся r()(tee >(rev) $@), r<<<"$2"|r >(d) >(r|t) >(r|d)|r|grep "$1"слід також працювати.
Денніс

Я ще нічого не перевіряв, але два тестові випадки у питанні перевірялися, коли я намагався.
Денніс

@Dennis Nice - так, це працює і зараз. Я поспілкувався з Мартіном - він хоче -qзалишитися.
Цифрова травма

5

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

Ungolfed в тестовій програмі

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

Пітон 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

Дякую Віллу за допомогу в роботі з друком та визначенням приєднання.

Завдяки підземній залізниці за те, що добре нагадував мені місця для гольфу; стор

Виправлено погані відповіді завдяки використанню "," як роздільника.

Мабуть, найкращий спосіб гольфу - додати тонни горизонтальної прокрутки.

Введіть як пробіли відбивання рядків з обмеженими рядками в лапки: "WVERTICALL \ nROOAFFLSAB \ nACRILIATOA \ nNDODKONWDC \ nDRKESOODDK \ nOEEPZEGLIW \ nMSIIHOAERA \ nALRKRRIRER \ nKODIDEDHCD"


1
L=len;J=''.joinтощо і print any(s in(v,d,w,r...))? Я йшов по тій же схемі , коли я побачив вас в курсі :)
Вілл

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

Куди завгодно, )або ]після цього пробіл, ви можете вийняти простір.
підземниймонорельс

2

APL (Dyalog Classic) , 44 байти

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

Спробуйте в Інтернеті!


Гм, вибачте, але, схоже, що ви не можете отримати такий вхід тут, його потрібно \nрозділити (тобто мати ⎕TC[2]як роздільник).
Ерік Аутгольфер

@EriktheOutgolfer о, лайно ... я це виправлю пізніше. Спасибі.
ngn

виправлено зараз, на жаль, набагато довше
пн

0

J , 60 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 байт)
користувач202729

0

Желе , 16 байт

Вирішили пов'язану (можливо, копію) проблему з 15 з цих 16 байтів як ядро ​​коду ...

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