O caminho da floresta

9

Depois de seu desastroso passeio de canoa , você acabou caindo de uma cachoeira no final das corredeiras do rio. Sua canoa explodiu, mas você conseguiu sobreviver à explosão. No entanto, sua jornada no rio ficou completamente fora do mapa - agora você se perdeu no meio de uma floresta. Felizmente, você ainda possui suas habilidades de programação e decide gravar um programa no lado de uma árvore para ajudá-lo a encontrar o caminho pela floresta. No entanto, como não há muita área de superfície na árvore, você deve tornar o seu programa o mais curto possível.

A floresta pode ser descrito como um nde n( n > 5) quadrado de caracteres, que só vai consistir nas letras minúsculas a-z. Um exemplo de floresta:

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

Você deve ter notado que nesta floresta, há uma linha diagonal de acaracteres que a percorre, do canto superior esquerdo ao canto inferior direito. Este é um "caminho" pela floresta que o levará a algum lugar, se você o seguir. Sua tarefa é escrever um programa que encontre o caminho singular. Agora, descreverei mais especificamente o que conota um "caminho" nesse desafio.

Um "caminho", neste desafio, é definido como uma linha semelhante a uma linha que pode ter sido gerada com um algoritmo de Bresenham , mas com os requisitos adicionais de que:

  • A linha deve ter no mínimo 6 caracteres
  • Cada grupo de caracteres colineares (completamente adjacentes) na linha deve ter o mesmo comprimento .
  • Começará em uma borda da floresta e terminará na borda oposta (veja meu comentário aqui para elaboração)

Para explicar o segundo requisito mais claramente, considere a seguinte linha:

aaa
   aaa
      aaa
         aaa
            aaa

Essa linha é composta por "segmentos" colineares de caracteres, cada um com exatamente três caracteres. Qualifica-se como um caminho. Agora considere esta linha:

a
 aa
   a
    aa
      a
       aa

Essa linha é composta por "segmentos" colineares que não têm exatamente o mesmo comprimento de caracteres (alguns deles têm 1 caractere e outros 2). Assim, este não se qualifica como um caminho.

Seu programa, dado um mapa da floresta, identifica os caracteres usados ​​no caminho. A entrada é para o que for conveniente (por exemplo, argumento da linha de comando, STDIN prompt(), etc.). Não pode ser pré-inicializado em uma variável. A primeira parte da entrada é um único inteiro nrepresentando o tamanho da floresta (a floresta é sempre um quadrado). Depois disso, há um espaço e, em seguida, toda a floresta como uma única sequência. Por exemplo, o exemplo de floresta seria apresentado, como uma entrada, assim:

13  anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua

A saída para isso seria:

a

porque o caminho é formado utilizando a letra a. Só haverá um caminho na floresta. Isso é código de golfe, então o menor número de caracteres vence. Se você tiver dúvidas, pergunte nos comentários.

absinto
fonte
E se houver vários caminhos?
Eric Tressler
@EricTressler Haverá apenas um caminho em qualquer floresta. Vou editar a especificação para refletir isso.
absinthe
A letra do caminho poderia ser usada em outro lugar onde não pertence ao caminho?
Martin Ender
O exemplo de floresta contém isso provavelmente. O primeiro um nesta linha no exemplo da floresta não é parte do anhahirrnrauc caminho
Spade
@ MartinBüttner Sim. Mas eles não serão dois caminhos feitos da mesma letra a qualquer momento.
absinthe

Respostas:

3

APL (Diálogo 14) (70)

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

Explicação:

  • ⎕ML←3: definido MLcomo 3, o significado tem seu significado em APL2.
  • I←⍞: leia uma linha do teclado e armazene-a I
  • I⊂⍨' '≠I: dividir Inos espaços
  • {... }/: aplique esta função às duas cadeias resultantes:
    • 2/⍎⍺: avalie o argumento esquerdo e replique-o duas vezes, fornecendo o tamanho da matriz
    • ⍵⍴⍨: formate o argumento correto usando esse tamanho
  • F←⊃: descompacte-o e guarde-o F.
  • {(⍳≢⍵)⌷¨↓⍵}¨(⊂F),⊂⌽F: obtém as diagonais: de cada linha em ambos Fe ⌽F(verticalmente espelhado F), obtém o valor na coluna X, onde X é o número da linha
  • (↓⍉F),(↓F),: obtenha as linhas e colunas de F
  • Z←∪¨: encontre os valores exclusivos em cada linha, coluna e diagonal e armazene-os Z.

Como a 'floresta' é retangular, se houver um caminho válido, significa que um deles consistirá em apenas um caractere, que é o caractere do caminho, portanto:

  • Z/⍨1=≢¨Z: pegue aquelas sub-matrizes Zque possuem apenas um elemento.

Isso exibirá os caracteres para todos os caminhos válidos, mas como deve haver apenas um que não importa.

marinus
fonte
4

Lua - 506 380 - bytes

Eu me senti um pouco mal por você não ter recebido nenhuma submissão por seu desafio bem pensado, então joguei isso juntos. Foi divertido inferir quais as propriedades mínimas distinguíveis que o caminho deve ter das informações que você forneceu. Espero ter acertado ... E implementado corretamente.

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

Pode ser testado com:

lua divisorPath.lua "input"

Se um desafiante selvagem aparecer, vou procurar no meu código o que vale a pena.

Atualização : jogou golfe em homenagem àqueles que se elevarão acima de nós. Enquanto estava nisso, tive que corrigir meu código no caminho reconhecido, indo da direita para a esquerda. Opa

AndoDaan
fonte
3

MATLAB - 270 caracteres

A seguir, define uma função xque aceita uma string de floresta como argumento e retorna o caractere que representa o "caminho" válido através da floresta, sujeito às regras especificadas.

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

A versão não minificada é

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

A premissa básica é construir uma máscara booleana para cada caminho válido possível e retornar qualquer caractere cuja função de índice na matriz cubra qualquer máscara. Para fazer isso, apenas máscaras verticais ou em forma de barra invertida de cima para baixo são criadas, mas a matriz florestal é comparada em todas as quatro orientações: identidade, invertida, girada 90 °, rotação invertida 90 °.

A função é executada para qualquer n. Um exemplo disso sendo chamado na linha de comando é

x('13 anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua')

ans =

    a
Eric K.
fonte
3

Python - 384 325 275

Esse algoritmo basicamente verifica a primeira e a última linha da matriz quanto a caracteres correspondentes e calcula o comprimento de cada segmento de linha

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

No exemplo acima:
V na primeira linha está no índice 2, V na última linha no índice 4.
Portanto, o comprimento de cada segmento de linha seria n / (4-2) +1 = 2 com n = 6 .

Em seguida, verifica se a linha é válida.

Para encontrar um caminho da esquerda para a direita, ele troca linhas com colunas e faz a mesma coisa novamente.

Edit: Não é possível chegar a 270 (Droga, Python e seu maldito recuo !!)

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
fonte