Лесная тропа

9

После вашей катастрофической поездки на каноэ вы в конечном итоге упали с водопада в конце речных порогов. Ваше каноэ взорвалось, но вам удалось пережить взрыв. Тем не менее, ваше речное путешествие полностью исчезло с карты - вы теперь потерялись посреди леса. К счастью, у вас все еще есть свои навыки программирования, поэтому вы решили вырезать программу в стороне дерева, чтобы помочь вам найти свой путь через лес. Однако на дереве не так много поверхности, поэтому вы должны сделать вашу программу максимально короткой.

Лес может быть описан как с nпомощью n( n > 5) квадратом символов, который будет состоять только из строчных букв a-z. Пример леса:

anehcienwlndm
baneiryeivown
bnabncmxlriru
anhahirrnrauc
riwuafuvocvnc
riwnbaueibnxz
hyirorairener
ruwiiwuauawoe
qnnvcizdaiehr
iefyioeorauvi
quoeuroenraib
cuivoaisdfuae
efoiebnxmcsua

Возможно, вы заметили, что в этом лесу есть диагональная линия aсимволов, проходящих через него из верхнего левого угла в нижний правый угол. Это «путь» через лес, который приведет вас куда-нибудь, если вы пойдете по нему. Ваша задача - написать программу, которая найдет единственный путь. Сейчас я более конкретно опишу, что означает «путь» в этом вызове.

«Путь» в этой задаче определяется как линия, аналогичная линии, которая могла бы быть сгенерирована с помощью алгоритма Брезенхэма , но с дополнительными требованиями, которые:

  • Строка должна содержать не менее 6 символов
  • Каждая коллинеарная (полностью смежная) группа символов в строке должна быть одинаковой длины .
  • Это начнется на одном краю леса и закончится на противоположном краю (см. Мой комментарий здесь для уточнения)

Чтобы объяснить второе требование более четко, рассмотрим следующую строку:

aaa
   aaa
      aaa
         aaa
            aaa

Эта строка состоит из коллинеарных «сегментов» символов, каждый из которых имеет длину ровно три символа. Это квалифицируется как путь. Теперь рассмотрим эту строку:

a
 aa
   a
    aa
      a
       aa

Эта строка состоит из коллинеарных «сегментов», которые не имеют одинаковую длину символов (некоторые из них имеют длину 1 символ, а некоторые - 2). Таким образом, этот не квалифицируется как путь.

Ваша программа, учитывая карту леса, идентифицирует символы, используемые в пути. Ввод в любой удобный (например, аргумент командной строки, STDIN prompt()и т. Д.). Его нельзя предварительно инициализировать в переменную. Первая часть ввода представляет собой одно целое число, nпредставляющее размер леса (лес всегда является квадратом). После этого пробел, а затем весь лес в виде одной строки. Например, пример леса будет представлен как входные данные, например:

13  anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua

Выход для этого будет:

a

потому что путь формируется с помощью буквы a. В лесу будет только один путь. Это код гольф, поэтому выигрывает меньшее количество персонажей. Если у вас есть вопросы, задавайте в комментариях.

абсент
источник
Что если есть несколько путей?
Эрик Тресслер
@EricTressler В каждом лесу будет только один путь. Я отредактирую спецификацию, чтобы отразить это.
Абсент
Может ли буква пути использоваться где-то еще, где она не принадлежит пути?
Мартин Эндер
Пример леса содержит это так, вероятно. Первый a на этой строке в примере леса не является частью пути anhahirrnrauc
Spade
@ MartinBüttner Да. Но они не будут двумя путями из одной буквы в любой момент.
Абсент

Ответы:

3

APL (Dyalog 14) (70)

⎕ML←3⋄Z/⍨1=≢¨Z←∪¨(↓⍉F),(↓F),{(⍳≢⍵)⌷¨↓⍵}¨(⊂F),⊂⌽F←⊃{⍵⍴⍨2/⍎⍺}/I⊂⍨' '≠I←⍞

Объяснение:

  • ⎕ML←3: set MLto 3, смысл имеет значение APL2.
  • I←⍞: прочитать строку с клавиатуры и сохранить ее в I
  • I⊂⍨' '≠I: разделить Iна пространства
  • {... }/: применить эту функцию к двум полученным строкам:
    • 2/⍎⍺: оценить левый аргумент и повторить его дважды, задав размер матрицы
    • ⍵⍴⍨: форматировать правильный аргумент, используя этот размер
  • F←⊃: распаковать его и сохранить в F.
  • {(⍳≢⍵)⌷¨↓⍵}¨(⊂F),⊂⌽F: получить диагонали: из каждой строки в и Fи ⌽F(вертикально отразить F) получить значение в столбце X, где X - номер строки
  • (↓⍉F),(↓F),: получить строки и столбцы F
  • Z←∪¨: найдите уникальные значения в каждой строке, столбце и диагонали и сохраните их в Z.

Поскольку «лес» является прямоугольным, если существует допустимый путь, это означает, что один из них будет состоять только из одного символа, который является символом пути, поэтому:

  • Z/⍨1=≢¨Z: возьмите те подмассивы, у Zкоторых есть только один элемент.

Это отобразит символы для всех допустимых путей, но так как должен быть только один, который не имеет значения.

Мэринус
источник
4

Lua - 506 380 - байт

Мне было немного жаль, что вы не получили никакого представления для вашей хорошо продуманной задачи, поэтому я бросил все это вместе. Было довольно забавно предположить, какими минимальными различимыми свойствами должен обладать путь из предоставленной вами информации. Надеюсь, я правильно понял ... И правильно его реализовал.

a=io.read"*l"n=a:match("%d+")+0 m=a:match"[a-z]+"o=""for i=1,n do for k=1,n^2,n do o=o..m:sub(i+k-1,i+k-1)end end q={m,o}for g=1,n^2 do for u=1,2 do l=q[u]:sub(g,g)for r=1,n do i=1 t=0 e=0 while i do s,e=q[u]:find(l:rep(r),e+1)if s then x=s-(e-s)-i-1 print(s,i,r,n,r)if x==n or x==n-2 or t==0 then t=t+1 i=s end else i=nil end end if t*r==n then print(l)os.exit()end end end end

Это может быть проверено с:

lua divisorPath.lua "input"

Если появится дикий претендент, я поищу в своем коде гольф, чтобы узнать, чего он стоит.

Обновление : игра в гольф в честь тех, кто поднимется над нами. Пока я занимался этим, мне пришлось исправить свой код по распознанному пути, идущему справа налево. К сожалению.

AndoDaan
источник
3

MATLAB - 270 знаков

Далее определяется функция, xкоторая принимает строку леса в качестве аргумента и возвращает символ, представляющий действительный «путь» через лес в соответствии с заданными правилами.

function F=x(s),A=sscanf(s,'%d%s');n=A(1);A=reshape(A(2:end),n,n);for c=A(:)',B=A==c;for i=1:n,if~mod(n,i),C=[kron(eye(i),ones(n/i,1)),zeros(n,n-i)];for j=0:n-i,f=@(B)sum(sum(B&circshift(C,[0,j]))==n;D=fliplr(B);if f(B)|f(B')|f(D)|f(D'),F=char(c);end;end;end;end;end;end

Не минимизированная версия

function F = x(s)
    A = sscanf( s, '%d %s' );
    n = A(1);
    A = reshape( A(2:end), n,n );
    for c = A(:)'
        B = A==c;
        for i = 1:n
            if ~mod( n, i )
                C = [kron( eye(i), ones( n/i,1 ) ), zeros( n,n-i )];
                for j = 0:n-i
                    f = @(B) sum(sum( B & circshift( C, [0 j] ))) == n;
                    D = fliplr(B);
                    if f(B) | f(B') | f(D) | f(D')
                        F = char(c);
                    end
                end
            end
        end
    end
end

Основная предпосылка состоит в том, чтобы создать логическую маску для каждого возможного допустимого пути и вернуть любой символ, индексная функция которого в матрице покрывает любую маску. Для этого создаются только вертикальные или сверху вниз маски обратной косой черты, но матрица леса сравнивается во всех четырех ориентациях: идентичность, перевернутая, повернутая на 90 °, перевернутая повернутая на 90 °.

Функция работает для любого n. Пример того, что он вызывается из командной строки:

x('13 anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua')

ans =

    a
Эрик К.
источник
3

Питон - 384 325 275

Этот алгоритм в основном проверяет первую и последнюю строки матрицы на соответствие символов, а затем вычисляет длину каждого отрезка строки

012345
------
aaVaaa|0
aaVaaa|1
aaaVaa|2
aaaVaa|3
aaaaVa|4
aaaaVa|5

В приведенном выше примере:
V в первой строке находится в индексе 2, V в последней строке в индексе 4.
Таким образом, длина каждого сегмента линии будет n / (4-2) +1 = 2 с n = 6 ,

Затем он проверяет, является ли строка действительной.

Чтобы найти путь слева направо, он меняет строки на столбцы и снова делает то же самое.

Редактировать: Не могу добраться до 270 (Будь ты проклят, Питон и твое проклятое отступление !!)

n,m=raw_input().split()
n,r=int(n),range
t=r(n)
a=[m[i:i+n]for i in r(0,n*n,n)]
for v in a,["".join([a[i][j]for i in t])for j in t]:
 for i in t:
  for j in t:
   p=1-2*(j-i<0);d,c=p*(j-i)+1,v[0][i]
   if 6<=sum([v[z][i+(z/(n/d))*p*(n%d==0)]==c for z in t])==n:print c;exit()
Markuz
источник