Gesichtserkennung

43

Ziel dieser Aufgabe ist es, alle Gesichter in einem bestimmten „Bild“ zu identifizieren, zu bereinigen und zu markieren.

Was steckt in einem Gesicht?

Eine Fläche ist ein ZxZ-Quadrat, wobei Z eine ungerade Ganzzahl größer als 1 ist. Die obere linke und rechte Ecke und die Mitte sind 'O'-Zeichen, und die untere Zeile ist ein' \ 'und ein' / ', die genug umgeben '_' Zeichen, um den Rest der Zeile auszufüllen. Beispiele:

ein 3x3 Gesicht:

O O
 O
\_/

ein 5x5 Gesicht:

O   O

  O

\___/

ein 7x7 Gesicht:

O     O


   O


\_____/

usw.

Eingang

Die Eingabe erfolgt über STDIN und besteht aus einer Reihe von Zeichenfolgen gleicher Länge.

Ausgabe

Die Ausgabe sollte die Eingabe sein, bei der alle erkennbaren Gesichter gelöscht sind (dh alle Zeichen mit Ausnahme von Augen, Nase und Mund müssen innerhalb der Gesichtsgrenzen entfernt werden) und umrahmt (umgeben von den Zeichen +, - und |). Wenn sich zwei oder mehr Gesichter überlappen, sollten beide gelöscht und eingerahmt werden, aber das größere Gesicht sollte Vorrang haben (es sollte oben platziert werden). Wenn beide Flächen gleich groß sind, liegt die Priorität im Ermessen des Implementierers. Wenn die Eingabe keine Flächen enthält, sollte die Ausgabe mit der Eingabe identisch sein.

Einige Beispiele

Eingang:

*******
*******
**O*O**
***O***
**\_/**
*******
*******

Ausgabe:

*******
*+---+*
*|O O|*
*| O |*
*|\_/|*
*+---+*
*******

Eingabe (unvollständiges Gesicht):

*******
*******
**O*O**
*******
**\_/**
*******
*******

Ausgabe:

*******
*******
**O*O**
*******
**\_/**
*******
*******

Eingabe (verschachtelte Gesichter):

*******
*O***O*
**O*O**
***O***
**\_/**
*\___/*
*******

Ausgabe:

+-----+
|O   O|
|     |
|  O  |
|     |
|\___/|
+-----+

Eingabe (mehrere Gesichter):

~{$FJ*TBNFU*YBVEXGY%
FOCO$&N|>ZX}X_PZ<>}+
X$OOPN ^%£)LBU{JJKY%
@\_/$£!SXJ*)KM>>?VKH
SDY%£ILO(+{O:HO(UR$W
XVBFTER^&INLNLO*(&P:
>?LKPO)UJO$£^&L:}~{&
~@?}{)JKOINLM@~}P>OU
:@<L::@\___/GER%^*BI
@{PO{_):<>KNUYT*&G&^

Ausgabe:

+---+*TBNFU*YBVEXGY%
|O O|&N|>ZX}X_PZ<>}+
| O |N ^%£)LBU{JJKY%
|\_/|£+-----+M>>?VKH
+---+I|O   O|HO(UR$W
XVBFTE|     |LO*(&P:
>?LKPO|  O  |&L:}~{&
~@?}{)|     |@~}P>OU
:@<L::|\___/|ER%^*BI
@{PO{_+-----+YT*&G&^

Eingabe (nahe Grenze):

~{$FJ*TBNFU*YBVEXGY%
OCO$&N|>ZX}X_PZ<>}+^
$OOPN ^%£)LBU{JJKY%{
\_/$£!SXJ*)KM>>?VKHU
SDY%£ILO(+{8:HO(UR$W
XVBFTER^&INLNLO*(&P:
>?LKPO)UJ^$£^&L:}~{&
~@?}{)JKOINLM@~}P>OU
:@<L::@BJYT*GER%^*BI
@{PO{_):<>KNUYT*&G&^

Ausgabe:

---+J*TBNFU*YBVEXGY%
O O|&N|>ZX}X_PZ<>}+^
 O |N ^%£)LBU{JJKY%{
\_/|£!SXJ*)KM>>?VKHU
---+£ILO(+{8:HO(UR$W
XVBFTER^&INLNLO*(&P:
>?LKPO)UJ^$£^&L:}~{&
~@?}{)JKOINLM@~}P>OU
:@<L::@BJYT*GER%^*BI
@{PO{_):<>KNUYT*&G&^

Eingabe (überlappende Flächen):

~{$FJ*TBNFU*YBVEXGY%
FXC£$&N|>ZX}X_PZ<>}+
X$*OPN O%£)LBO{JJKY%
@:U%$£!SXJ*)KM>>?VKH
SDY%£OLO(+{P:HO(UR$W
XVBFTER^&IOLNLO*(&P:
>?L\___/JR$£^&L:}~{&
~@?}{)JKOINLM@~}P>OU
:@<L::@\_____/R%^*BI
@{PO{_):<>KNUYT*&G&^

Ausgabe:

~{$FJ*TBNFU*YBVEXGY%
FX+---+-------+Z<>}+
X$|O  |O     O|JJKY%
@:|   |       |>?VKH
SD|  O|       |(UR$W
XV|   |   O   |*(&P:
>?|\__|       |:}~{&
~@+---|       |}P>OU
:@<L::|\_____/|%^*BI
@{PO{_+-------+*&G&^
Gareth
quelle
Was ist mit verbundenen Gesichtern (z. B. wo ein O als linkes und rechtes Auge fungiert)? Sollten diese als überlappend behandelt werden?
Joey Adams
@ Joey Adams: das passiert im letzten Beispiel.
Lowjacker
@ Joey Adams @ Lowjacker Ja, genau wie im letzten Beispiel.
Gareth
Ich finde das 3x3 Gesicht realistisch und das 7x7 Gesicht derp. Nur meine Meinung. Schade, dass ich keine Zeit habe, um Kopfgeld zu verdienen ... :)
tomsmeding
2
@tomsmeding Wenn Sie das 3x3-Gesicht realistisch finden, würde ich es hassen, die Personen zu sehen, mit denen Sie in Verbindung stehen. : - \
Gareth

Antworten:

19

Ruby, 304 298 295 Zeichen

I=$<.read
q=(O=I*s=1).size
k=??+O=~/$/
o=->m,n{n.chars{|c|(m+=1)*(m%k)>0&&m<q&&O[m-1]=c}}
q.times{f=[[?\\+?_*s+?/,k*s+=1],[?O,0],[?O,s],[?O,(s+=1)/2*(1+k)]]
q.times{|x|f.all?{|a,b|I[x+b,a.size]==a}&&(o[x+k*s-1,o[x-k-1,?++?-*s+?+]]
s.times{|a|o[x+k*a-1,?|+' '*s+?|]}
f.map{|a,b|o[x+b,a]})}}
$><<O

Die Überlappung unten rechts wird bevorzugt, wenn die Flächen die gleiche Größe haben. ZB für die Eingabe

O.OO.O
.O..O.
\_/\_/
O.OO.O
.O..O.
\_/\_/

es erkennt alle vier Gesichter und gibt nach

O |O O
 O| O
--+---
O |O O
 O| O
\_|\_/

Edit 1: Wie von Lowjacker vorgeschlagen, können wir das indexdurch ein Regex-Match (-3 Zeichen) ersetzen . Darüber hinaus +1kann dies durch ein zusätzliches Dummy-Zeichen vor dem Matching ausgeglichen werden, wodurch ein weiteres Zeichen gespeichert wird (-2 für das +1, +3 für Dummy-Zeichen, -2, da keine Klammern mehr erforderlich sind). Zwei mehr, da wir den Bereich auch ohne Klammern schreiben können.

Bearbeiten 2: Zwei weitere Zeichen werden gespeichert, indem beide durch ersetzt ifwerden &&und ein weiteres Zeichen den Bereich vollständig entfernt.

Howard
quelle
Sie können (O=~/$/)statt O.index($/)in der dritten Zeile verwenden (spart 3 Zeichen).
Lowjacker
@ Lowjacker Vielen Dank. Ich könnte sogar noch einen mit deinem Trick retten (siehe meine Bearbeitung).
Howard
Ich denke, Sie können auch 2 Zeichen speichern, indem Sie die ifAnweisungen durch ersetzen &&.
Lowjacker
4

Python - 1199 941

Ich fand das Problem ziemlich interessant und löste es in Python. Hier ist der komprimierte Code.

#!/usr/bin/env python
import fileinput,sys
m=[[c for c in l if c!='\n'] for l in fileinput.input()]
X=len(m[0])
Y=len(m)
t=[]
for n in range(3,min(X,Y)+1,2):
  for x in range(X-n+1):
    for y in range(Y-n+1):
      if m[y][x]=='O' and m[y][x+n-1]=='O' and m[y+(n//2)][x+(n//2)]=='O' and m[y+n-1][x]=='\\' and m[y+n-1][x+n-1]=='/' and "".join(m[y+n-1][x+1:x+n-1])=='_'*(n-2):
        t.append((x,y,n))
for x,y,n in t:
  def a(v,h,c):
    w=x+h; z=y+v;
    if z>=0 and z<len(m):
      if w>=0 and w<len(m[y]):
        m[z][w]=c
  for v in range(n):
    for h in range(n): 
      a(v,h,' ')
  a(0,0,'O')
  a(0,n-1,'O')
  a(n/2,n/2,'O')
  a(n-1,0,'\\')
  a(n-1,n-1,'/')
  for w in range(1,n-1):
    a(n-1,w,'_')
  for v in [-1,n]:
    for h in range(n):
      a(v,h,'-')
  for h in [-1,n]:
    for v in range(n):
      a(v,h,'|')
  a(-1,-1,'+')
  a(-1,n,'+')
  a(n,-1,'+')
  a(n,n,'+')
for l in m:
  for c in l:
    sys.stdout.write(c)
  print

Hier ist der besser lesbare Code:

#!/usr/bin/env python

import fileinput, sys

matrix = [[c for c in l if c != '\n'] for l in fileinput.input()]

max_X = len(matrix[0])
max_Y = len(matrix)

tuples = []
for n in range(3, min(max_X, max_Y)+1, 2):
  for x in range(max_X-n+1):
    for y in range(max_Y-n+1):
      # if is_face(matrix, x, y, n):
      if matrix[y][x] == 'O' and matrix[y][x+n-1] == 'O' and matrix[y+(n//2)][x+(n//2)] == 'O' and matrix[y+n-1][x] == '\\' and matrix[y+n-1][x+n-1] == '/' and "".join(matrix[y+n-1][x+1:x+n-1]) == '_'*(n-2) :
        tuples.append((x, y, n))

for x,y,n in tuples:
  # blank_and_border(matrix,x,y,n)
  def assign(dy, dx, c):
    xx = x + dx; yy = y + dy;
    if yy >= 0 and yy < len(matrix) :
      if xx >= 0 and xx < len(matrix[y]) :
        matrix[yy][xx] = c

  # blank
  for dy in range(n):
    for dx in range(n): 
      assign(dy, dx, ' ')

  # face
  assign(0, 0, 'O')
  assign(0, n-1, 'O')
  assign(n/2, n/2, 'O')
  assign(n-1, 0, '\\')
  assign(n-1, n-1, '/')
  for w in range(1,n-1):
    assign(n-1, w, '_')

  # border
  for dy in [-1,n]:
    for dx in range(n):
      assign(dy, dx, '-')

  for dx in [-1,n]:
    for dy in range(n):
      assign(dy, dx, '|')

  assign(-1, -1, '+')
  assign(-1,  n, '+')
  assign( n, -1, '+')
  assign( n,  n, '+')

for l in matrix:
  for c in l:
    sys.stdout.write(c)
  print
Sgauria
quelle
2
Bitte fügen Sie in Ihrer Antwort Ihre Golf-Version oberhalb dieser Version hinzu. Dies ist eine Code-Golf-Frage und Sie riskieren Abstimmungen, wenn Sie nicht zumindest versucht haben, Golf zu spielen. Hier können Sie auch Ihre lesbare Version hinterlassen.
Gareth
1
Richtig, @Gareth. Ich schreibe oft Lösungen in Java, was nicht sonderlich golffreundlich ist, aber ich nehme mir immer die Zeit, um meine Lösung zu golfen, sowohl für die Übung (es macht Spaß, über Möglichkeiten nachzudenken, Zeichen zu trimmen und die Gesamtlänge zu reduzieren) als auch um den Geist von zu befriedigen Code-Golf (das Ihre Lösung so präzise wie möglich macht). Freuen Sie sich also auf Ihre Golf-Lösung, Sgauria!
ProgrammerDan
Vielen Dank, Gareth & @ProgrammerDan! Das ist ein guter Rat - ich bin ziemlich neu in Codegolf. Ich habe meine oben genannte Golflösung zusätzlich zur längeren Lösung hinzugefügt.
Sgauria