Nhận diện khuôn mặt


43

Mục đích của nhiệm vụ này là xác định, dọn dẹp và đánh dấu tất cả các khuôn mặt trong bất kỳ "hình ảnh" nào.

Có gì trong khuôn mặt?

Một mặt sẽ là hình vuông ZxZ trong đó Z là số nguyên lẻ lớn hơn 1. Góc trên bên trái và bên phải và tâm sẽ là các ký tự 'O' và dòng dưới cùng sẽ là '\' và '/' bao quanh đủ Các ký tự '_' để điền vào phần còn lại của dòng. Ví dụ:

một khuôn mặt 3x3:

O O
 O
\_/

khuôn mặt 5x5:

O   O

  O

\___/

một khuôn mặt 7x7:

O     O


   O


\_____/

Vân vân.

Đầu vào

Đầu vào sẽ có trên STDIN và sẽ bao gồm một số chuỗi ký tự có độ dài bằng nhau.

Đầu ra

Đầu ra phải là đầu vào với tất cả các khuôn mặt dễ nhận biết được xóa (tức là tất cả các ký tự ngoại trừ mắt, mũi và miệng phải được loại bỏ từ trong giới hạn của khuôn mặt) và được đóng hộp (bao quanh bởi các ký tự +, - và |). Trường hợp hai hoặc nhiều mặt trùng nhau nên được xóa và đóng hộp nhưng nên ưu tiên cho mặt lớn hơn (nên đặt trên cùng); nếu cả hai mặt có cùng kích thước, thì mức độ ưu tiên sẽ tùy theo người thực hiện. Nếu đầu vào không có mặt, đầu ra phải giống như đầu vào.

Vài ví dụ

Đầu vào:

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

Đầu ra:

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

Đầu vào (mặt không hoàn chỉnh):

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

Đầu ra:

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

Đầu vào (các mặt lồng nhau):

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

Đầu ra:

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

Đầu vào (nhiều mặt):

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

Đầu ra:

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

Đầu vào (gần ranh giới):

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

Đầu ra:

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

Đầu vào (các mặt chồng chéo):

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

Đầu ra:

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

Còn những khuôn mặt dính liền nhau (ví dụ như chữ O nhân đôi mắt trái và mắt phải) thì sao? Những người nên được coi là chồng chéo?
Joey Adams

@Joey Adams: điều đó xảy ra trong ví dụ cuối cùng.
Lowjacker

@Joey Adams @Lowjacker Vâng, giống như ví dụ cuối cùng.
Gareth

Tôi thấy khuôn mặt 3x3 thực tế và khuôn mặt 7x7 derp. Chỉ là ý kiến ​​của tôi. Thật buồn khi tôi không có thời gian để kiếm tiền thưởng ... :)
tomsmeding

2
@tomsmeding Nếu bạn thấy khuôn mặt 3x3 thực tế tôi rất ghét nhìn thấy những người bạn liên kết. : - \
Gareth

Câu trả lời:


19

Ruby, 304 298 295 ký tự

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

Phía dưới bên phải được ưu tiên trên chồng lấp nếu các mặt có kích thước giống hệt nhau. Ví dụ cho đầu vào

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

nó nhận ra cả bốn mặt và năng suất

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

Chỉnh sửa 1: Như Lowjacker đã đề xuất, chúng tôi có thể thay thế indexbằng một trận đấu regex (-3 ký tự). Ngoài ra, +1có thể được bù bằng một char giả bổ sung trước khi khớp giúp lưu một char khác (-2 cho +1, +3 cho char giả, -2 vì dấu ngoặc không còn cần thiết nữa). Hai nữa vì chúng ta có thể viết phạm vi cũng không có dấu ngoặc.

Chỉnh sửa 2: Một hai nhân vật lưu bằng cách thay thế cả ifvới &&và một số khác bỏ phạm vi hoàn toàn.


Bạn có thể sử dụng (O=~/$/)thay vì O.index($/)trên dòng thứ ba (lưu 3 ký tự).
Lowjacker

@Lowjacker Cảm ơn bạn. Tôi thậm chí có thể tiết kiệm thêm một lần nữa với thủ thuật của bạn (xem phần chỉnh sửa của tôi).
Howard

Tôi nghĩ bạn cũng có thể lưu 2 ký tự bằng cách thay thế các ifcâu lệnh bằng &&.
Lowjacker

4

Con trăn - 1199 941

Tôi thấy vấn đề khá thú vị, vì vậy tôi đã giải quyết bằng Python. Đây là mã nén.

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

Đây là mã dễ đọc hơn:

#!/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
Vui lòng thêm phiên bản đánh gôn của bạn lên trên phiên bản này trong câu trả lời của bạn. Đây là một câu hỏi về môn đánh gôn và bạn có nguy cơ bị bỏ phiếu nếu ít nhất bạn chưa thử chơi nó. Bạn có thể để phiên bản dễ đọc của bạn ở đây quá.
Gareth

1
Ngay trên, @Gareth. Tôi thường viết các giải pháp bằng Java, không thân thiện với golf lắm, nhưng tôi luôn dành thời gian để chơi golf, cả về bài tập (thật thú vị khi nghĩ cách cắt tỉa nhân vật và giảm độ dài tổng thể) và để thỏa mãn tinh thần code-golf (đang nhận được giải pháp của bạn ngắn gọn nhất có thể). Vì vậy, mong muốn được nhìn thấy giải pháp chơi golf của bạn, sgauria!
Lập trình viên

Cảm ơn Gareth & @ProgrammerDan! Đó là lời khuyên tốt - Tôi khá mới về codegolf. Tôi đã thêm giải pháp đánh gôn của tôi ở trên ngoài giải pháp dài hơn.
sgauria
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.