Le chemin forestier

9

Après votre désastreuse balade en canoë , vous avez fini par tomber d'une cascade au bout des rapides de la rivière. Votre canoë a explosé, mais vous avez réussi à survivre à l'explosion. Cependant, votre voyage sur la rivière a complètement disparu de la carte - vous vous êtes maintenant retrouvé perdu au milieu d'une forêt. Heureusement, vous avez toujours vos compétences en programmation, vous décidez donc de graver un programme sur le côté d'un arbre pour vous aider à trouver votre chemin à travers la forêt. Cependant, il n'y a pas beaucoup de surface sur l'arbre, vous devez donc rendre votre programme aussi court que possible.

La forêt peut être décrite comme un carré de caractères nby n( n > 5), qui ne sera composé que de lettres minuscules a-z. Un exemple de forêt:

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

Vous avez peut-être remarqué que dans cette forêt, une ligne diagonale de acaractères la traverse du coin supérieur gauche au coin inférieur droit. C'est un "chemin" à travers la forêt qui vous mènera quelque part si vous le suivez. Votre tâche consiste à écrire un programme qui trouvera le chemin singulier. Je vais maintenant décrire plus précisément ce qui connote un «chemin» dans ce défi.

Un «chemin», dans ce défi, est défini comme une ligne similaire à celle qui aurait pu être générée avec un algorithme de Bresenham , mais avec les exigences supplémentaires qui:

  • La ligne doit comporter au moins 6 caractères
  • Chaque groupe colinéaire (complètement adjacent) de caractères de la ligne doit avoir la même longueur .
  • Il commencera à un bord de la forêt et se terminera au bord opposé (voir mon commentaire ici pour l'élaboration)

Pour expliquer plus clairement la deuxième exigence, considérez la ligne suivante:

aaa
   aaa
      aaa
         aaa
            aaa

Cette ligne est composée de "segments" colinéaires de caractères, chacun ayant exactement trois caractères. Il est considéré comme un chemin. Considérez maintenant cette ligne:

a
 aa
   a
    aa
      a
       aa

Cette ligne est composée de "segments" colinéaires qui ne sont pas tous exactement de la même longueur de caractères (certains ont 1 caractère et certains 2). Ainsi, celui-ci ne peut pas être qualifié de chemin.

Votre programme, compte tenu d'une carte de la forêt, identifie les caractères utilisés dans le chemin. L'entrée est à tout ce qui est pratique (par exemple, argument de ligne de commande, STDIN prompt(), etc.). Il ne peut pas être pré-initialisé en variable. La première partie de l'entrée est un entier unique nreprésentant la taille de la forêt (la forêt est toujours un carré). Après cela, il y a un espace, puis la forêt entière en une seule chaîne. Par exemple, l'exemple de forêt serait présenté, en entrée, comme ceci:

13  anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua

La sortie pour cela serait:

a

parce que le chemin est formé en utilisant la lettre a. Il n'y aura qu'un seul chemin dans la forêt. C'est le golf de code, donc le plus petit nombre de personnages gagne. Si vous avez des questions, posez-les dans les commentaires.

Absinthe
la source
Et s'il y a plusieurs chemins?
Eric Tressler
@EricTressler Il n'y aura qu'un seul chemin dans une forêt donnée. Je vais modifier la spécification pour refléter cela.
absinthe
La lettre de chemin pourrait-elle être utilisée ailleurs où elle n'appartient pas au chemin?
Martin Ender
L'exemple de forêt contient cela probablement. Le premier a sur cette ligne dans l'exemple de forêt ne fait pas partie du chemin anhahirrnrauc
Spade
@ MartinBüttner Oui. Mais ce ne seront à aucun moment deux chemins créés à partir de la même lettre.
absinthe

Réponses:

3

APL (Dyalog 14) (70)

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

Explication:

  • ⎕ML←3: défini MLsur 3, la signification a sa signification APL2.
  • I←⍞: lire une ligne du clavier et la stocker dans I
  • I⊂⍨' '≠I: divisé Isur les espaces
  • {... }/: appliquez cette fonction aux deux chaînes résultantes:
    • 2/⍎⍺: évaluer l'argument de gauche et le répliquer deux fois, en donnant la taille de la matrice
    • ⍵⍴⍨: formatez le bon argument en utilisant cette taille
  • F←⊃: déballez-le et stockez-le F.
  • {(⍳≢⍵)⌷¨↓⍵}¨(⊂F),⊂⌽F: obtenir les diagonales: à partir de chaque ligne des deux Fet ⌽F(en miroir vertical F), obtenir la valeur à la colonne X, où X est son numéro de ligne
  • (↓⍉F),(↓F),: récupère les lignes et les colonnes de F
  • Z←∪¨: recherchez les valeurs uniques sur chaque ligne, colonne et diagonale et stockez-les Z.

Étant donné que la «forêt» est rectangulaire, s'il existe un chemin valide, cela signifie que l'un d'entre eux sera composé d'un seul caractère, qui est le caractère du chemin, donc:

  • Z/⍨1=≢¨Z: prenez ces sous-tableaux Zqui n'ont qu'un seul élément.

Cela affichera les caractères pour tous les chemins valides, mais comme il ne devrait y en avoir qu'un qui n'a pas d'importance.

marinus
la source
4

Lua - 506 380 - octets

Je me sentais un peu mal que vous n'ayez reçu aucune soumission pour votre défi bien pensé, alors j'ai jeté cela ensemble. C'était amusant de déduire quelles propriétés distinctes minimales le chemin doit avoir des informations que vous avez fournies. J'espère avoir bien compris ... ET correctement mis en œuvre.

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

Il peut être testé avec:

lua divisorPath.lua "input"

Si un challenger sauvage apparaît, je chercherai à jouer à mon code pour ce qu'il vaut.

Mise à jour : golfé en l'honneur de ceux qui s'élèveront au-dessus de nous. Pendant que j'y étais, j'ai dû fixer mon code sur un chemin reconnu allant de droite à gauche. Oops.

AndoDaan
la source
3

MATLAB - 270 caractères

Ce qui suit définit une fonction xqui accepte une chaîne de forêt comme argument et retourne le caractère représentant le "chemin" valide à travers la forêt soumis aux règles données.

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

La version non réduite est

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

Le principe de base est de construire un masque booléen pour chaque chemin valide possible et de renvoyer tout caractère dont la fonction d'index dans la matrice couvre n'importe quel masque. Pour ce faire, seuls des masques en forme de barre oblique verticale ou de haut en bas sont créés, mais la matrice forestière est comparée dans les quatre orientations: identité, retournée, pivotée de 90 °, retournée pivotée de 90 °.

La fonction s'exécute pour tout n. Un exemple de son invocation sur la ligne de commande est

x('13 anehcienwlndmbaneiryeivownbnabncmxlriruanhahirrnraucriwuafuvocvncriwnbaueibnxzhyirorairenerruwiiwuauawoeqnnvcizdaiehriefyioeorauviquoeuroenraibcuivoaisdfuaeefoiebnxmcsua')

ans =

    a
Eric K.
la source
3

Python - 384 325 275

Cet algorithme vérifie essentiellement la première et la dernière ligne de la matrice pour les caractères correspondants, puis calcule la longueur de chaque segment de ligne

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

Dans l'exemple ci-dessus:
le V dans la première ligne est à l'index 2, le V dans la dernière ligne à l'index 4.
Ainsi, la longueur de chaque segment de ligne serait n / (4-2) +1 = 2 avec n = 6 .

Il vérifie ensuite si la ligne est valide.

Afin de trouver un chemin de gauche à droite, il échange des lignes avec des colonnes et refait la même chose.

Edit: Je ne peux pas vraiment atteindre 270 (Damn you Python and your damn indentation !!)

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
la source