Avast, vous scallywags!

10

Barbe Noire était un pirate anglais du début du XVIIIe siècle. Bien qu'il soit connu pour avoir pillé et pris des navires, il commandait ses navires avec la permission de leurs équipages. Il n'y a aucun récit de lui ayant jamais blessé ou tué ses prisonniers.

Ce défi est en l'honneur du tristement célèbre Barbe Noire et inspiré par la Journée internationale Talk Like a Pirate (19 septembre). C'est aussi l'inverse de ce défi de Pyrrha .


Le défi

Créez un programme qui prend une carte au trésor en entrée (composée des caractères répertoriés ci-dessous) et génère ses directions.


Contribution

Toutes les entrées consisteront v, >, <, ^, les espaces, et un seul X.

Vous pouvez supposer ce qui suit:

  • la carte ne se boucle ou ne se croise jamais

  • la flèche de départ sera toujours le caractère le plus bas dans la colonne la plus à gauche

  • il y aura toujours un trésor ( X)

Un exemple d'entrée est illustré ci-dessous.

  >>v   >>>>>>v
  ^ v   ^     v
  ^ v   ^   v<<
  ^ v   ^   v
  ^ >>>>^   >>X
  ^
>>^

Production

La sortie doit être une ", "chaîne de directions délimitée. Voici la sortie correcte de la carte ci-dessus.

E2, N6, E2, S4, E4, N4, E6, S2, W2, S2, E2

Un seul saut de ligne ou espace est autorisé.


Exemples

In:
>>>>>>>>>>>>>>>v
               v
               v
               >>>>X

Out:
E15, S3, E4

In:
>>>>>>v
^     v
^     >>>>X

Out:
N2, E6, S2, E4

In:
X
^
^
^

Out:
N3

In:
>>>>>>v
^     v
^     v
      v
      >>>>>>X

Out:
N2, E6, S4, E6

In:
 X
 ^
 ^
>^

Out:
E1, N3

In:
>X

Out:
E1

In:
v<<<<<
vX<<<^
>>>>^^
>>>>>^

Out:
E5, N3, W5, S2, E4, N1, W3

Happy International Talk Like a Pirate Day!

Portes Zach
la source
Vous voudrez peut-être inclure un exemple où il y a plus d'une flèche pointant vers la droite dans la colonne la plus à gauche, c'est-à-dire où le chemin revient en boucle dans la première colonne. Dans ce cas, il est légèrement difficile d'identifier le début du chemin.
Reto Koradi
J'ai ajouté un exemple par votre demande. J'ai également ajouté le détail que le caractère de départ sera le dernier de la colonne. @RetoKoradi
Zach Gates
Étant donné que j'ai soulevé une certaine inquiétude dans la question connexe concernant la longueur du dernier segment, je vais encore une fois dire que ce n'est pas exactement la question inverse ici. Quelqu'un essaie encore une fois de piéger les pirates, pense-je.
coredump
La seule différence est le nombre de pas de la dernière direction. @coredump Du moins, pour autant que je sache.
Zach Gates
1
@ZachGates Oui, exactement (et juste pour être clair, je ne dis pas que la question devrait être modifiée, c'est bien comme c'est le cas actuellement).
coredump

Réponses:

3

CJam, 78 octets

qN/_:,$W=:Tf{Se]}s:U,T-{_U="><^vX"#"1+'E1-'WT-'NT+'S0"4/=~_@\}g;;]e`{(+}%", "*

Essayez-le en ligne .

Explication

L'idée principale ici est de trouver la ligne la plus longue (nous appellerons cette longueur T), puis de remplir toutes les lignes à la même longueur et de les concaténer (cette nouvelle chaîne est U). De cette façon, un seul compteur est nécessaire pour se déplacer sur la carte. Ajouter / soustraire 1signifie se déplacer vers la droite / gauche sur la même ligne, ajouter / soustraire Tsignifie se déplacer vers le bas / vers le haut d'une ligne.

qN/    e# Split the input on newlines
_:,    e# Push a list of the line lengths
$W=:T  e# Grab the maximum length and assign to T
f{Se]} e# Right-pad each line with spaces to length T
s:U    e# Concatenate lines and assign to U

Il est maintenant temps de configurer la boucle.

,T-    e# Push len(U) - T
       e# i.e. position of first char of the last line
{...}g e# Do-while loop
       e# Pops condition at the end of each iteration

Le corps de la boucle utilise une table de recherche et une évaluation pour choisir quoi faire. Au début de chaque itération, l'élément de pile supérieur est la position actuelle. En dessous, il y a toutes les directions NSWE traitées. À la fin de l'itération, la nouvelle direction est placée sous la position et une copie de celle-ci est utilisée comme condition pour la boucle. Les caractères non nuls sont véridiques. Lorsqu'un X est rencontré, 0 est poussé comme direction, terminant la boucle.

_U=      e# Push the character in the current position
"><^vx"# e# Find the index in "><^Vx"
"..."4/  e# Push the string and split every 4 chars
         e# This pushes the following list:
         e# [0] (index '>'): "1+'E" pos + 1, push 'E'
         e# [1] (index '<'): "1-'W" pos - 1, push 'W'
         e# [2] (index '^'): "T-'N" pos - T, push 'N'
         e# [3] (index 'v'): "T+'S" pos + T, push 'S'
         e# [4] (index 'X'): "0"    push 0
=~       e# Get element at index and eval
_@\      e# From stack: [old_directions position new_direction]
         e# To stack: [old_directions new_direction position new_direction]
         e# (You could also use \1$)
         e# new_direction becomes the while condition and is popped off

Maintenant , les regards de la pile comme ceci: [directions 0 position]. Générons la sortie.

;;    e# Pop position and 0 off the stack
]     e# Wrap directions in a list
e`    e# Run length encode directions
      e# Each element is [num_repetitions character]
{     e# For each element:
 (+   e#   Swap num_repetitions and character
}%    e# End of map (wraps in list)
", "* e# Join by comma and space
Andrea Biondo
la source
3

CJam, 86 octets

qN/_,{1$=cS-},W=0{_3$3$==_'X-}{"^v<>"#_"NSWE"=L\+:L;"\(\ \)\ ( )"S/=~}w];Le`{(+}%", "*

Essayez-le en ligne

Explication:

qN/     Get input and split into rows.
_,      Calculate number of rows.
{       Loop over row indices.
  1$=     Get row at the index.
  c       Get first character.
  S-      Compare with space.
},      End of filter. The result is a list of row indices that do not start with space.
W=      Get last one. This is the row index of the start character.
0       Column number of start position. Ready to start tracing now.
{       Start of condition in main tracing loop.
  _3$3$   Copy map and current position.
  ==      Extract character at current position.
  _'X-    Check if it's the end character `X.
}       End of loop condition.
{       Start of loop body. Move to next character.
  "^v<>"  List of directions.
  #       Find character at current position in list of directions.
  _       Copy direction index.
  "NSWE"  Matching direction letters.
  =       Look up direction letter.
  L\+:L;  Append it to directions stored in variable L.
  "\(\ \)\ ( )"
          Space separated list of commands needed to move to next position for each of
          the 4 possible directions.
  S/      Split it at spaces.
  =       Extract the commands for the current direction.
  ~       Evaluate it.
}w      End of while loop for tracking.
];      Discard stack content. The path was stored in variable L.
Le`     Get list of directions in variable L, and RLE it.
{       Loop over the RLE entries.
  (+      Swap from [length character] to [character length].
}%      End of loop over RLE entries.
", "*   Join them with commas.
Reto Koradi
la source
2

Javascript (ES6), 239 octets

a=>(b=a.split`
`,b.reverse().some((c,d)=>c[0]!=' '&&((e=d)||1)),j=[],eval("for(g=b[e][f=0];b[e][f]!='X';g=b[e][f],j.push('NSEW'['^v><'.indexOf(i)]+h))for(h=0;g==b[e][f];e+=((i=b[e][f])=='^')-(i=='v'),f+=(i=='>')-(i=='<'),h++);j.join`, `"))

Explication:

a=>(
    b = a.split('\n'),
    // loops through list from bottom to find arrow
    b.reverse().some(
        (c, d)=>
            // if the leftmost character is not a space, saves the index and exit
            // the loop
            // in case d == 0, the ||1 makes sure the loop is exited
            c[0] != ' ' && ((e = d) || 1)
    ),
    j = [], // array that will hold the instructions
    eval("  // uses eval to allow a for loop in a lambda without 'return' and {}

        // loops through all sequences of the same character
        // e is the first coordinate of the current character being analyzed
        // f is the second coordinate
        // defines g as the character repeated in the sequence
        // operates on reversed b to avoid using a second reverse
        // flips ^ and v to compensate

        for(g = b[e][f = 0];
            b[e][f] != 'X'; // keep finding sequences until it finds the X
            g = b[e][f],    // update the sequence character when it hits the start of a
                            // new sequence
            j.push('NSEW'['^v><'.indexOf(i)] + h)) // find the direction the sequence is
                                                   // pointing to and add the
                                                   // instruction to j

            // loops through a single sequence until it hits the next one
            // counts the length in h
            for(h = 0;
                g == b[e][f]; // loops until there is a character that isn't part of
                              // the sequence
                // updates e and f based on which direction the sequence is pointing
                // sets them so that b[e][f] is now the character being pointed toward
                e += ((i = b[e][f]) == '^') - (i == 'v'),
                f += (i == '>') - (i == '<'),
                // increments the length counter h for each character of the sequence
                h++);

            // return a comma separated string of the instructions
            j.join`, `
    ")
)
DankMemes
la source
0

JavaScript (ES6), 189

Testez l'exécution de l'extrait ci-dessous dans un navigateur compatible EcmaScript 6.

f=m=>{(m=m.split`
`).map((r,i)=>r[0]>' '?y=i:0);for(x=o=l=k=p=0;p!='X';++l,y+=(k==1)-(k<1),x+=(k>2)-(k==2))c=m[y][x],c!=p?(o+=', '+'NSWE'[k]+l,l=0):0,k='^v<>'.search(p=c);alert(o.slice(7))}

// Testable version, no output but return (same size)
f=m=>{(m=m.split`
`).map((r,i)=>r[0]>' '?y=i:0);for(x=o=l=k=p=0;p!='X';++l,y+=(k==1)-(k<1),x+=(k>2)-(k==2))c=m[y][x],c!=p?(o+=', '+'NSWE'[k]+l,l=0):0,k='^v<>'.search(p=c);return o.slice(7)}


// TEST
out = x => O.innerHTML += x+'\n';

test = 
[[`>>>>>>>>>>>>>>>v
               v
               v
               >>>>X`,'E15, S3, E4']
,[`>>>>>>v
^     v
^     >>>>X`,'N2, E6, S2, E4']
,[`X
^
^
^`,'N3']
,[`>>>>>>v
^     v
^     v
      v
      >>>>>>X`,'N2, E6, S4, E6']
,[` X
 ^
 ^
>^`,'E1, N3']
,[`>X`,'E1']
,[`v<<<<<
vX<<<^
>>>>^^
>>>>>^`,'E5, N3, W5, S2, E4, N1, W3']];

test.forEach(t=>{
  var k = t[1];
  var r = f(t[0]);
  out('Test ' + (k==r ? 'OK' : 'Fail')
      +'\n'+t[0]+'\nResult: '+r
      +'\nCheck:  '+k+'\n');
})
<pre id=O></pre>

Moins golfé

f=m=>{
  m=m.split('\n'); // split in rows

  x = 0; // Starting column is 0
  m.forEach( (r,i) => r[0]>' '? y=i : 0); // find starting row

  o = 0; // output string
  p = 0; // preceding character
  l = 0; //  sequence length (this starting value is useless as will be cutted at last step)
  k = 0; //  direction (this starting value is useless as will be cutted at last step)
  while(p != 'X') // loop until X found
  {
    c = m[y][x]; // current character in c
    if (c != p) // changing direction
    {  
      o +=', '+'NSWE'[k]+l; // add current direction and length to output
      l = 0 // reset length
    );
    p = c;
    k = '^v<>'.search(c); // get new current direction
    // (the special character ^ is purposedly in first position)
    ++l; // increase sequence length
    y += (k==1)-(k<1); // change y depending on direction
    x += (k>2)-(k==2); // change x depending on direction
  }
  alert(o.slice(7)); // output o, cutting the useless first part
}
edc65
la source