Zählen der Endpunkte eines ASCII Art

14

Sie sollten ein Programm oder eine Funktion schreiben, die eine Zeichenfolge empfängt, die eine ASCII-Grafik als Eingabe und Ausgabe darstellt, oder die Anzahl der Endpunkte in der Eingabe zurückgibt.

Die Eingabe besteht aus den Zeichen space - | +(mit 0, 2, 2 bzw. 4 Endpunkten) und Zeilenumbrüchen. Z.B:

-|++-
  +

Zwei benachbarte Zeichen sind verbunden und verlieren in den folgenden Fällen jeweils 1 Endpunkt:

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

Das erste Beispiel hat

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

Endpunkte.

Eingang

  • Eingangs wird eine Zeichenfolge sein , die aus dem Raum Zeichen, -, |, +und Neue - Zeile.
  • Die Länge der Eingabe kann 0 sein, und jede Eingabe, die der obigen Beschreibung entspricht, ist gültig (in Regex-Eingabe ist [ -+|\n]*).
  • Der Zeilenumbruch ist optional.

Ausgabe

  • Eine einzelne nicht negative Ganzzahl, die Anzahl der Endpunkte.

Beispiele

Die Ausgänge stehen nach der letzten Zeile ihrer Eingänge.

+
4 

-|++-
  +
12 

+--+
|  |
+--+
8 

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

--++
 |||--
10 

<empty input>
0 


|
|     
2 

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

 ----
30 

Dies ist Code Golf, also gewinnt der kürzeste Einstieg.

randomra
quelle

Antworten:

11

Schnecken , 29

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

Ich habe mit Zeilenkommentare hinzugefügt ,,, um eine kommentierte Version zu erstellen.

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

JavaScript (ES6), 168

Bei Verwendung von Vorlagenzeichenfolgen werden alle Zeilenumbrüche signifikant und gezählt.

Testen Sie das folgende Snippet in Firefox. (Chrome unterstützt immer noch nicht ...)

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
quelle
Was ich tun muss, ist, s in Reihen zu teilen, dann eine leere Reihe oben und eine leere Reihe unten hinzuzufügen. Ihr Code teilt s überhaupt nicht. Sie könnten ["",...s.split("\n"),""]das länger machen @ETHproductions
edc65
Ah, richtig, tut mir leid.
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

Eine One-Pass-Methode. Nimmt als Eingabe einen String mit Zeilenumbrüchen.

Für die Horizontalen besteht die Idee darin, die Anzahl der horizontalen Segmente zu zählen, von denen jedes zwei Endpunkte hat. Ein Segment beginnt immer dann, wenn ein Zeichen eines von +-(boolean isth ) ist, das vorherige jedoch nicht (Boolescher Wert p).

Für die Vertikalen möchten wir dasselbe mit der transponierten Eingabe machen und uns die Läufe von ansehen +|. Leider ist die Transposition von Python sehr klobig. Es erfordert so etwas wie map(None,*s.split('\n'))das Ausfüllen der Lücken, mit Nonedenen man sich auch selbst befassen muss.

Stattdessen zählen wir vertikal, während wir horizontal iterieren. Wir führen eine Liste, lwelche Spaltenindizes noch "laufen", dh wo das vorherige Zeichen in dieser Spalte nach unten verbindet. Dann machen wir dasselbe wie mit der Horizontalen und zählen neu beginnende vertikale Segmente. Wenn wir eine neue Zeile treffen, schneiden wir die Liste rechts von unserer Position ab, da alle Segmente rechts unterbrochen wurden, und setzen den aktuellen Index auf zurück 0.

xnor
quelle
3

CJam, 66 62 61 Bytes

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

Probieren Sie es online in der CJam-Interpreter aus .

Idee

Wir können die Endpunkte wie folgt berechnen:

  1. Zähle die Anzahl von -s, |s und+ s in der Eingabe.
  2. Multiplizieren Sie die letzte mit 2 und addieren Sie die Ergebnisse.
  3. Zähle die Anzahl von --s, -+s, +-s und++ s in den Zeilen.
  4. Zähle die Anzahl von ||s. |+s, +|s und++ s in den Spalten.
  5. Subtrahieren Sie die Ergebnisse von 3 und 4 vom Ergebnis von 2.
  6. Multiplizieren Sie das Ergebnis von 5 mit 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
quelle