Conteggio degli endpoint di un'arte ASCII


14

È necessario scrivere un programma o una funzione che riceve una stringa che rappresenta un'arte ASCII come input e che genera o restituisce il numero di endpoint nell'input.

L'input consisterà in caratteri space - | +(rispettivamente con 0, 2, 2 e 4 punti finali) e interruzioni di riga. Per esempio:

-|++-
  +

Due personaggi adiacenti sono collegati e quindi perdono 1 endpoint ciascuno nei seguenti casi:

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

Il primo esempio ha

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

endpoint.

Ingresso

  • Ingresso sarà una stringa costituita dai caratteri spazio, -, |, +e ritorno a capo.
  • La lunghezza dell'input può essere pari a 0 e qualsiasi input corrispondente alla descrizione sopra è valido (in regex è input [ -+|\n]*).
  • Il trascinamento di newline è facoltativo.

Produzione

  • Un singolo numero intero non negativo, il numero di endpoint.

Esempi

Gli output sono dopo l'ultima riga dei loro input.

+
4 

-|++-
  +
12 

+--+
|  |
+--+
8 

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

--++
 |||--
10 

<empty input>
0 


|
|     
2 

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

 ----
30 

Questo è il codice golf, quindi vince l'ingresso più breve.

Risposte:


11

Lumache , 29

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

Ho aggiunto commenti di riga con ,,, al fine di creare una versione commentata.

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 '+'

5

JavaScript (ES6), 168

Utilizzando le stringhe modello, tutte le nuove righe sono significative e contate.

Prova a eseguire lo snippet di seguito in Firefox. (Chrome non supporta ancora ...)

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>


Quello che devo fare è dividere s in righe, quindi aggiungere una riga vuota in alto e una riga vuota in basso. Il tuo codice non divide affatto s. Potresti farlo ["",...s.split("\n"),""]più a lungo @ETHproductions
edc65,

Ah, giusto, scusa per quello.
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

Un metodo one-pass. Accetta come input una stringa con interruzioni di riga.

Per gli orizzontali, l'idea è quella di contare il numero di segmenti orizzontali, ognuno dei quali ha due punti finali. Un segmento inizia ogni volta che un personaggio è uno +-(booleano h) ma il precedente non lo è (booleano p).

Per i verticali, vorremmo fare la stessa cosa sull'input trasposto, osservando le sequenze di +|. Sfortunatamente, la trasposizione di Python è davvero goffa. Richiede qualcosa come map(None,*s.split('\n'))riempire gli spazi vuoti None, che sono anche loro stessi da affrontare.

Invece, facciamo il conteggio verticale mentre iteriamo orizzontalmente. Manteniamo un elenco ldi quali indici di colonne sono ancora "in esecuzione", ovvero dove si collega il carattere precedente in quella colonna. Quindi, facciamo la stessa cosa dell'orizzontale, contando i segmenti verticali appena iniziati. Quando colpiamo una nuova riga, tagliamo l'elenco a destra di dove siamo, poiché tutti i segmenti a destra erano rotti e ripristiniamo l'indice corrente su 0.


3

CJam, 66 62 61 byte

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

Provalo online nell'interprete CJam .

Idea

Possiamo calcolare gli endpoint come segue:

  1. Contare il numero di -s, se |s +nell'input.
  2. Moltiplica l'ultimo per 2 e aggiungi i risultati.
  3. Contare il numero di --s, -+s, +-s e ++s nelle righe.
  4. Contare il numero di ||s. |+s, +|s e ++s nelle colonne.
  5. Sottrai i risultati da 3 e 4 dal risultato da 2.
  6. Moltiplica il risultato per 5 per 2.

Codice

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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.