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

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.


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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.