La reconnaissance faciale

43

Le but de cette tâche est d'identifier, de nettoyer et de marquer tous les visages dans une "image" donnée.

Qu'y a-t-il dans un visage?

Une face sera un carré ZxZ où Z est un entier impair supérieur à 1. Les coins supérieurs gauche et droit et le centre sont composés de caractères "O", et la ligne du bas sera constituée d'un "\" et d'un "/" entourant suffisamment '_' caractères pour remplir le reste de la ligne. Exemples:

une face 3x3:

O O
 O
\_/

une face 5x5:

O   O

  O

\___/

une face 7x7:

O     O


   O


\_____/

etc.

Contribution

L’entrée sera sur STDIN et consistera en un nombre de chaînes de caractères de longueur égale.

Sortie

La sortie doit être l'entrée avec tous les visages reconnaissables effacés (c'est-à-dire que tous les caractères sauf les yeux, le nez et la bouche doivent être retirés des limites du visage) et encadrés (entourés de +, - et | caractères). Lorsque deux ou plusieurs faces se chevauchent, les deux doivent être nettoyées et encadrées, mais la priorité doit être donnée à la plus grande face (elle doit être placée sur le dessus). si les deux faces ont la même taille, la priorité est laissée à la discrétion de l'implémenteur. Si l'entrée n'a pas de faces, la sortie doit être identique à l'entrée.

Quelques exemples

Contribution:

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

Sortie:

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

Entrée (visage incomplet):

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

Sortie:

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

Entrée (faces imbriquées):

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

Sortie:

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

Entrée (plusieurs faces):

~{$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&^

Sortie:

+---+*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&^

Entrée (limite proche):

~{$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&^

Sortie:

---+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&^

Entrée (faces qui se chevauchent):

~{$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&^

Sortie:

~{$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
la source
Qu'en est-il des visages conjoints (par exemple, où un O sert également d'œil gauche et d'œil droit)? Celles-ci doivent-elles être traitées comme se chevauchant?
Joey Adams
@ Joey Adams: cela se produit dans le dernier exemple.
Lowjacker
@ Joey Adams @ Lowjacker Oui, tout comme le dernier exemple.
Gareth
Je trouve le visage 3x3 réaliste et le visage 7x7 derp. Juste mon avis. Triste que je n'ai pas le temps de gagner bountiez ... :)
tomsmeding
2
@tomsmeding Si vous trouvez le visage 3x3 réaliste, je détesterais voir les personnes que vous fréquentez. : - \
Gareth

Réponses:

19

Ruby, 304 298 295 caractères

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

En bas à droite est préférable sur le chevauchement si les faces sont de taille identique. Par exemple pour l'entrée

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

il reconnaît les quatre faces et les rendements

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

Edit 1: Comme Lowjacker l’a proposé, nous pouvons remplacer le indexpar une expression rationnelle (-3 caractères). De plus, le +1peut être compensé par un caractère factice supplémentaire avant la correspondance, ce qui enregistre un autre caractère (-2 pour le caractère +1, +3 pour le caractère factice, -2 car les crochets ne sont plus nécessaires). Deux autres puisque nous pouvons écrire la plage aussi sans crochets.

Edit 2: Deux autres caractères sont enregistrés en remplaçant les deux ifpar &&et un autre en supprimant complètement la plage.

Howard
la source
Vous pouvez utiliser à la (O=~/$/)place de O.index($/)la troisième ligne (enregistre 3 caractères).
Lowjacker
@ Lowjacker Merci. Je pourrais même en sauver un de plus avec votre astuce (voir mon édition).
Howard
Je pense que vous pouvez également enregistrer 2 caractères en remplaçant les ifinstructions par &&.
Lowjacker
4

Python - 1199 941

J'ai trouvé le problème assez intéressant, alors j'ai résolu en Python. Voici le code compressé.

#!/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

Voici le code le plus lisible:

#!/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
la source
2
S'il vous plaît ajoutez votre version golfée au-dessus de cette version dans votre réponse. C'est une question de code-golf et vous risquez d'obtenir des votes si vous n'avez pas au moins essayé de jouer au golf. Vous pouvez aussi laisser votre version lisible ici.
Gareth
1
À droite, @Gareth. J'écris souvent des solutions en Java, ce qui n'est pas très pratique pour le golf, mais je prends toujours le temps de jouer au golf avec ma solution, à la fois pour l'exercice (c'est amusant de penser à des moyens de réduire les caractères et de réduire la longueur totale) et code-golf (pour que votre solution soit aussi concise que possible). Alors, impatient de voir votre solution golfée, sgauria!
ProgrammeurDan
Merci Gareth & @ProgrammerDan! C'est un bon conseil - je suis assez nouveau sur codegolf. J'ai ajouté ma solution golfée ci-dessus en plus de la solution plus longue.
Sgauria