Compter les points de terminaison d'un art ASCII

14

Vous devez écrire un programme ou une fonction qui reçoit une chaîne représentant un art ASCII en entrée et génère ou renvoie le nombre de points de terminaison dans l'entrée.

L'entrée sera constituée des caractères space - | +(avec 0, 2, 2 et 4 points de terminaison respectivement) et des sauts de ligne. Par exemple:

-|++-
  +

Deux personnages adjacents sont connectés et perdent donc 1 point d'extrémité chacun dans les cas suivants:

--  -+  +- |  |  +  +  ++
           |  +  |  +

Le premier exemple a

2+2+2+2+1+
    3        = 12

points finaux.

Contribution

  • Entrée sera une chaîne composée de l'espace de caractères, -, |, +et retour à la ligne.
  • La longueur d'entrée peut être 0 et toute entrée correspondant à la description ci-dessus est valide (en entrée regex est [ -+|\n]*).
  • Le retour à la ligne est facultatif.

Production

  • Un seul entier non négatif, le nombre de points de terminaison.

Exemples

Les sorties se trouvent après la dernière ligne de leurs entrées.

+
4 

-|++-
  +
12 

+--+
|  |
+--+
8 

  |  |
  +--+-- |||
12 

--++
 |||--
10 

<empty input>
0 


|
|     
2 

--
++--
 ++
   --+
  +++ || 

 ----
30 

C'est le golf de code, donc l'entrée la plus courte gagne.

randomra
la source

Réponses:

11

Escargots , 29

A
\+|\-)lr!\-|(\+|\|)n!\|}!\+

J'ai ajouté des commentaires en ligne avec ,,, afin de faire une version commentée.

A                    ,, Count all accepting paths
        \+ | \- )    ,, Literal '+' or '-'        
        lr           ,, Set direction to left or right
        !\-          ,, Assert next char is not '-'
    |                ,, Or...
        ( \+ | \| )  ,, Literal '+' or '|'
        n            ,, Turn 90 degrees right or left (from initial direction right)
        !\|          ,, Assert next char is not '|'
}                    ,, Group everything previous
!\+                  ,, Assert next char is not '+'
feersum
la source
5

JavaScript (ES6), 168

En utilisant des chaînes de modèle, toutes les nouvelles lignes sont significatives et comptées.

Testez l'exécution de l'extrait ci-dessous dans Firefox. (Chrome ne prend toujours pas en charge ...)

f=s=>`
${s}
`.split`
`.map((r,y,s,v=c=>c>' '&c!='-',h=c=>c>' '&c<'|')=>[...r].map((c,x)=>t+=(v(c)?2-v(s[y-1][x])-v(s[y+1][x]):0)+(h(c)?2-h(r[x-1])-h(r[x+1]):0)),t=0)&&t

// Less golfed
u=s=>{
  s = ('\n' + s + '\n').split('\n'); // split in rows, adding a blank line at top and one at bottom
  t = 0; // init counter
  v = c => c>' ' & c!='-'; // function to check if a character has vertical end points
  h = c => c>' ' & c<'|'; // function to check if a character has horizontal end points
  s.forEach( (r,y) =>
    [...r].forEach( (c,x) => {
     if (v(c)) // if current character has vertical endpoints, check chars in previous and following row
        t += 2 - v(s[y-1][x]) - v(s[y+1][x]); 
     if (h(c))  // if current character has horizontal endpoints, check previous and following chars in row
        t += 2 - h(r[x-1]) - h(r[x+1]);
    })
  )  
  return t
}

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

;[
 [`+`,4]
,[`-|++-
  +`,12]
,[`+--+
|  |
+--+`,8]
,[`  |  |
  +--+-- |||`,12]
,[`--++
 |||--`,10]
,[``,0]
,[`
|
|`,2]
,[`
--
++--
 ++
   --+
  +++ || 

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

edc65
la source
Ce que je dois faire est de fractionner les s en lignes, puis d'ajouter une ligne vide en haut et une ligne vide en bas. Votre code ne divise pas du tout les s. Vous pourriez le faire ["",...s.split("\n"),""]plus longtemps @ETHproductions
edc65
Ah, d'accord, désolé.
ETHproductions
3

Python 2, 123

l=[]
i=p=t=0
for c in input():
 l+=0,;h=c in'-+';t+=h>p;p=h;v=c in'|+';t+=v>l[i];l[i]=v;i+=1
 if' '>c:l=l[:i];i=0
print t*2

Une méthode en un seul passage. Prend en entrée une chaîne avec des sauts de ligne.

Pour les horizontales, l'idée est de compter le nombre de segments horizontaux, chacun ayant deux extrémités. Un segment démarre chaque fois qu'un caractère fait partie de +-(booléen h) mais pas le précédent (booléen p).

Pour les verticales, nous aimerions faire la même chose sur l'entrée transposée, en regardant les séquences de +|. Malheureusement, la transposition de Python est vraiment maladroite. Cela nécessite quelque chose comme map(None,*s.split('\n'))de remplir les blancs None, qui sont eux-mêmes à gérer.

Au lieu de cela, nous effectuons le comptage vertical tout en itérant horizontalement. Nous gardons une liste ldes colonnes où les index sont toujours "en cours d'exécution", c'est-à-dire où le caractère précédent de cette colonne se connecte. Ensuite, nous faisons la même chose qu'avec l'horizontale, en comptant les segments verticaux nouvellement démarrés. Lorsque nous atteignons une nouvelle ligne, nous coupons la liste à droite de l'endroit où nous nous trouvons, car tous les segments à droite ont été cassés, et nous réinitialisons l'index actuel 0.

xnor
la source
3

CJam, 66 62 61 octets

q_N/_z,S*f.e|zN*"-|++"2$fe=1b"|-"{'++:R:a@+2ew{aR2m*&},,-}/2*

Essayez-le en ligne dans l' interpréteur CJam .

Idée

Nous pouvons calculer les points de terminaison comme suit:

  1. Comptez le nombre de -s, |s et +s dans l'entrée.
  2. Multipliez le dernier par 2 et ajoutez les résultats.
  3. Comptez le nombre de --s, -+s, +-s et ++s dans les rangées.
  4. Comptez le nombre de ||s. |+s, +|s et ++s dans les colonnes.
  5. Soustrayez les résultats de 3 et 4 du résultat de 2.
  6. Multipliez le résultat de 5 par 2.

Code

q        e# Read all input from STDIN.
_N/      e# Push a copy and split it at linefeeds.
_z,      e# Count the number of rows of the transposed array.
         e# This pushes the length of the longest row.
S*       e# Push a string of that many spaces.
f.e|     e# Perform vectorized logical OR with the rows.
         e# This pads all rows to the same length.
zN*      e# Transpose and join, separating by linefeeds.
"-|++"   e# Push that string.
2$       e# Copy the original input.
fe=      e# Count the occurrences of '-', '|', '+' and '+' in the input.
1b       e# Add the results.
"|-"{    e# For '|' and '-':
  '++    e#   Concatenate the char with '+'.
  :R     e#   Save the resulting string in R.
  :a     e#   Convert it into an array of singleton strings.
  @      e#   Rotate one of the two bottom-most strings on top of the stack.
         e#   This gets the transposed input for '|' and the original input for '-'.
  +      e#   Concatenate both arrays.
         e#   This pads the input with nonsense to a length of at least 2.
  2ew    e#   Push a overlapping slices of length 2.
  {      e#   Filter the slices; for each:
    a    e#     Wrap it in an array.
    R2m* e#     Push the second Cartesian power of R.
         e#     For '|', this pushes ["||" "|+" "+|" "++"].
    &    e#     Intersect.
  },     e#   If the intersection was non-empty, keep the slice.
  ,      e#   Count the kept slices.
  -      e#   Subtract the amount from the integer on the stack.
}/       e#
2*       e# Multiply the result by 2.
Dennis
la source