面部识别


43

此任务的目的是识别,清理和标记任何给定“图像”中的所有面孔。

脸上是什么?

人脸将是ZxZ正方形,其中Z是大于1的奇数整数。左上角和右上角以及中心将是'O'字符,而底线将是一个'\'和一个'/'足够包围'_'字符填充其余行。例子:

3x3的脸:

O O
 O
\_/

5x5的脸:

O   O

  O

\___/

7x7的脸:

O     O


   O


\_____/

等等

输入项

输入将在STDIN上,并且将由多个等长的字符串组成。

输出量

输出应该是输入,所有可识别的面部都被清除(即,除了眼睛,鼻子和嘴巴以外的所有字符都应从面部的范围内删除)并装箱(由+,-和|字符包围)。当两个或更多的脸重叠时,应将其清除并装箱,但应优先处理较大的脸(应放在最上面);如果两个面孔的大小相同,则优先级由实施者决定。如果输入没有面孔,则输出应与输入相同。

一些例子

输入:

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

输出:

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

输入(不完整的面孔):

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

输出:

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

输入(嵌套面):

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

输出:

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

输入(多个面):

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

输出:

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

输入(靠近边界):

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

输出:

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

输入(重叠面):

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

输出:

~{$FJ*TBNFU*YBVEXGY%
FX+---+-------+Z<>}+
X$|O  |O     O|JJKY%
@:|   |       |>?VKH
SD|  O|       |(UR$W
XV|   |   O   |*(&P:
>?|\__|       |:}~{&
~@+---|       |}P>OU
:@<L::|\_____/|%^*BI
@{PO{_+-------+*&G&^

连在一起的脸如何处理(例如,O兼作左眼和右眼)?应该将它们视为重叠吗?
乔伊·亚当斯

@Joey Adams:发生在最后一个示例中。
Lowjacker

@Joey Adams @Lowjacker是的,就像最后一个例子一样。
加雷斯

我发现3x3的面部逼真,而7x7的面部derp。只是我的观点。遗憾的是我没有时间获得赏金……:)
毁了2014年

2
@tomsmeding如果您发现3x3面孔逼真,我不希望看到与您有联系的人。:-\
Gareth 2014年

Answers:


19

红宝石,304个 298 295字符

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

如果面的大小相同,则重叠时最好使用右下角。例如输入

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

它可以识别所有四个面孔并产生

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

编辑1:按照Lowjacker的建议,我们可以用index正则表达式匹配项(-3个字符)代替。此外,+1可以在匹配之前通过附加的伪字符补偿该字符,从而节省了另一个字符(+1对于伪字符,为-2,对于伪字符为+3,因为不再需要括号,因此为-2)。还有两个,因为我们也可以不使用方括号来编写范围。

编辑2:通过将替换if&&和另一个完全删除范围来保存另外两个字符。


您可以使用(O=~/$/)代替O.index($/)第三行(节省3个字符)。
Lowjacker 2011年

@Lowjacker谢谢。我什至可以省下一笔钱(请参阅我的编辑)。
霍华德

我认为您也可以通过将if语句替换为来节省2个字符&&
Lowjacker

4

蟒蛇-1199 941

我发现这个问题非常有趣,因此我在Python中解决了问题。这是压缩的代码。

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

这是更具可读性的代码:

#!/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
请在您的答案中在此版本之上添加您的高尔夫版本。这是一个打高尔夫的问题,如果您至少没有尝试过打高尔夫球,您可能会面临投票失败的风险。您也可以在此处保留可读版本。
Gareth 2014年

1
就在@Gareth。我经常用Java编写解决方案,这对高尔夫并不十分友好,但是我总是花时间去打高尔夫,这不仅是为了练习(考虑如何修剪角色并减少总长),而且是为了满足我的精神。代码高尔夫球(这将使您的解决方案尽可能简洁)。因此,期待看到您的高尔夫解决方案,sgauria!
ProgrammerDan

谢谢Gareth和@ProgrammerDan!很好的建议-我在Codegolf上还很陌生。除了更长的解决方案之外,我还添加了我的高尔夫解决方案。
sgauria 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.