Pengenalan wajah

43

Tujuan dari tugas ini adalah untuk mengidentifikasi, membersihkan, dan menandai semua wajah dalam 'gambar' tertentu.

Apa yang ada di wajah?

Wajah akan menjadi kotak ZxZ di mana Z adalah bilangan bulat ganjil yang lebih besar dari 1. Sudut kiri dan kanan atas dan pusat akan menjadi karakter 'O', dan garis bawah akan menjadi '\' dan '/' di sekitarnya cukup karakter '_' untuk mengisi sisa baris. Contoh:

wajah 3x3:

O O
 O
\_/

wajah 5x5:

O   O

  O

\___/

wajah 7x7:

O     O


   O


\_____/

dll.

Memasukkan

Input akan berada di STDIN dan akan terdiri dari sejumlah string karakter dengan panjang yang sama.

Keluaran

Keluaran harus berupa input dengan semua wajah yang dikenali dibersihkan (yaitu semua karakter kecuali mata, hidung dan mulut harus dikeluarkan dari batas wajah) dan kemas (dikelilingi oleh karakter +, -, dan |). Di mana dua atau lebih wajah tumpang tindih keduanya harus dibersihkan dan dikotakkan tetapi prioritas harus diberikan pada wajah yang lebih besar (harus ditempatkan di atas); jika kedua muka berukuran sama, prioritas diserahkan pada kebijaksanaan pelaksana. Jika input tidak memiliki wajah, output harus sama dengan input.

Beberapa contoh

Memasukkan:

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

Keluaran:

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

Input (wajah tidak lengkap):

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

Keluaran:

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

Input (wajah bersarang):

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

Keluaran:

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

Input (banyak wajah):

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

Keluaran:

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

Input (batas dekat):

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

Keluaran:

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

Input (wajah yang tumpang tindih):

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

Keluaran:

~{$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
sumber
Bagaimana dengan wajah siam (misalnya di mana O berfungsi sebagai mata kiri dan mata kanan)? Haruskah mereka diperlakukan sebagai tumpang tindih?
Joey Adams
@ Joey Adams: itu terjadi pada contoh terakhir.
Lowjacker
@ Joey Adams @ Lowjacker Ya, sama seperti contoh terakhir.
Gareth
Saya menemukan wajah 3x3 realistis dan derx wajah 7x7. Hanya pendapat saya saja. Sedih karena saya tidak punya waktu untuk mendapatkan hadiah ... :)
tomsmeding
2
@tomsmeding Jika Anda menemukan wajah 3x3 realistis, saya benci melihat orang-orang yang bergaul dengan Anda. : - \
Gareth

Jawaban:

19

Ruby, 304 298 295 karakter

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

Kanan bawah lebih disukai pada tumpang tindih jika wajah memiliki ukuran yang identik. Misal untuk input

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

itu mengakui keempat wajah dan hasil

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

Sunting 1: Seperti yang diusulkan Lowjacker, kita dapat mengganti indexdengan pertandingan regex (-3 karakter). Selain itu, +1dapat dikompensasi oleh char dummy tambahan sebelum pencocokan yang menyimpan char lain (-2 untuk +1, +3 untuk char dummy, -2 karena kurung tidak diperlukan lagi). Dua lagi karena kita dapat menulis rentang juga tanpa tanda kurung.

Sunting 2: Dua karakter lainnya disimpan dengan mengganti keduanya ifdengan &&dan yang lain menghapus kisaran sepenuhnya.

Howard
sumber
Anda dapat menggunakan (O=~/$/)alih-alih O.index($/)pada baris ketiga (menyimpan 3 karakter).
Lowjacker
@ Lowjacker Terima kasih. Saya bahkan bisa menyimpan satu lagi dengan trik Anda (lihat edit saya).
Howard
Saya pikir Anda juga dapat menyimpan 2 karakter dengan mengganti ifpernyataan dengan &&.
Lowjacker
4

Python - 1199 941

Saya menemukan masalah yang cukup menarik, jadi saya menyelesaikannya dengan Python. Ini kode terkompresi.

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

Berikut kode yang lebih mudah dibaca:

#!/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
sumber
2
Harap tambahkan versi golf Anda di atas versi ini dalam jawaban Anda. Ini adalah pertanyaan kode-golf dan Anda berisiko mengambil suara jika Anda setidaknya belum mencobanya. Anda juga dapat meninggalkan versi yang dapat dibaca di sini.
Gareth
1
Tepat, @Gareth. Saya sering menulis solusi di Jawa, yang tidak terlalu ramah golf, tapi saya selalu meluangkan waktu untuk golf solusi saya, baik untuk latihan (itu menyenangkan memikirkan cara untuk memangkas karakter dan mengurangi panjang keseluruhan) dan untuk memuaskan semangat kode-golf (yang mendapatkan solusi Anda sesingkat mungkin). Jadi, tak sabar untuk melihat solusi golf Anda, sgauria!
ProgrammerDan
Terima kasih Gareth & @ProgrammerDan! Itu saran yang bagus - Saya cukup baru dalam codegolf. Saya telah menambahkan solusi golf saya di atas selain solusi yang lebih lama.
sgauria