Contando los puntos finales de un arte ASCII

14

Debe escribir un programa o función que reciba una cadena que represente un arte ASCII como entrada y salidas o devuelva el número de puntos finales en la entrada.

La entrada consistirá en los caracteres space - | +(con 0, 2, 2 y 4 puntos finales respectivamente) y saltos de línea. P.ej:

-|++-
  +

Dos caracteres adyacentes están conectados y, por lo tanto, pierden 1 punto final cada uno en los siguientes casos:

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

El primer ejemplo tiene

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

puntos finales

Entrada

  • De entrada será una cadena formada por los caracteres espacio, -, |, +y la nueva línea.
  • La longitud de entrada puede ser de 0 y cualquier entrada que coincida con la descripción anterior es válida (en regex, la entrada es [ -+|\n]*).
  • La nueva línea final es opcional.

Salida

  • Un solo entero no negativo, el número de puntos finales.

Ejemplos

Las salidas son posteriores a la última fila de sus entradas.

+
4 

-|++-
  +
12 

+--+
|  |
+--+
8 

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

--++
 |||--
10 

<empty input>
0 


|
|     
2 

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

 ----
30 

Este es el código de golf, por lo que gana la entrada más corta.

randomra
fuente

Respuestas:

11

Caracoles , 29

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

Agregué comentarios de línea con el ,,fin de hacer una versión comentada.

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
fuente
5

JavaScript (ES6), 168

Usando cadenas de plantillas, todas las nuevas líneas son significativas y contadas.

Prueba a ejecutar el fragmento a continuación en Firefox. (Chrome todavía no es compatible ...)

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
fuente
Lo que necesito hacer es dividir s en filas, luego agregar una fila vacía en la parte superior y una fila vacía en la parte inferior. Su código no divide s en absoluto. Podrías hacerlo por ["",...s.split("\n"),""]más tiempo @ETHproductions
edc65
Ah, cierto, perdón por eso.
ETHproductions
3

Pitón 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

Un método de una pasada. Toma como entrada una cadena con saltos de línea.

Para las horizontales, la idea es contar el número de segmentos horizontales, cada uno de los cuales tiene dos puntos finales. Un segmento comienza cada vez que un personaje es uno de +-(booleano h) pero el anterior no lo es (booleano p).

Para las verticales, nos gustaría hacer lo mismo en la entrada transpuesta, mirando las ejecuciones de +|. Desafortunadamente, la transposición de Python es realmente torpe. Requiere algo como map(None,*s.split('\n'))llenar los espacios en blanco None, que también son ellos mismos para tratar.

En cambio, hacemos el recuento vertical mientras iteramos horizontalmente. Mantenemos una lista lde los índices de las columnas que todavía están "ejecutándose", es decir, dónde se conecta el carácter anterior en esa columna. Luego, hacemos lo mismo que con la horizontal, contando los segmentos verticales recién comenzados. Cuando tocamos una nueva línea, cortamos la lista a la derecha de donde estamos, ya que todos los segmentos a la derecha estaban rotos, y restablecemos el índice actual a 0.

xnor
fuente
3

CJam, 66 62 61 bytes

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

Pruébelo en línea en el intérprete de CJam .

Idea

Podemos calcular los puntos finales de la siguiente manera:

  1. Contar el número de -s, |s y +s en la entrada.
  2. Multiplique el último por 2 y agregue los resultados.
  3. Contar el número de --s, -+s, +-s y ++S en las filas.
  4. Cuenta el número de ||s. |+s, +|sys ++en las columnas.
  5. Resta los resultados de 3 y 4 del resultado de 2.
  6. Multiplica el resultado de 5 por 2.

Código

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
fuente