Apakah Ada Lebih Banyak Objek Keras atau Objek Lunak

19

Terinspirasi oleh pembukaan oleh buku What-If.

Input adalah persegi panjang spasi sebagai string, daftar string, dll., Dengan objek yang terbuat dari #dalamnya:

########          
#      #          
########          

   ###        ####
   ###        ####
   ###             

Objek akan selalu non-berpotongan, tidak menyentuh, persegi panjang. Objek lunak didefinisikan sebagai objek yang tidak diisi dengan #'s di tengah dan hanya perbatasan, objek keras adalah yang diisi. Objek dengan lebar atau tinggi <=2dianggap keras. Semua benda itu keras atau lunak.

Jika ada lebih banyak objek keras di input, output "Hard", jika lebih lunak, output "Soft", jika mereka sama, output "Equal".

Ini adalah , jadi kode terpendek dalam byte menang!

Uji Kasus

Kasing-kasing ini bukan input penuh, melainkan apa yang harus dicirikan oleh setiap objek. Masukan yang sebenarnya akan seperti ascii-art di bagian atas pertanyaan.

Keras

#

####

##
##

##########
##########
##########

Lembut

###
# #
###

###################
#                 #
#                 #
#                 #
###################

####
#  #
#  #
#  #
#  #
#  #
#  #
#  #
####

Kasus Uji Aktual

########          
#      #          
########          

   ###        ####
   ###        ####
   ###             

Hard

###                
###                
###                

###################
#                 #
#                 #
#                 #
###################

Equal

   ######    
   #    #    
   ######    
          ###
   ##  #  # #
          ###


 ########    
 #      #    
 ########  

Soft
Maltysen
sumber
2
Apakah outputnya ketat, atau bisakah 3 output yang ambigu digunakan (seperti H / S / E atau -1/0/1)?
trichoplax
@trichoplax mereka ketat
Maltysen
3
Meta menjawab pada format I / O yang rumit (bukan untuk mengatakan Anda tidak dapat melakukan apa yang Anda pilih, tetapi hanya untuk memberikan tempat bagi orang-orang untuk mengekspresikan pendapat yang lebih halus jika mereka mau).
trichoplax
@Dosc yakin tidak apa-apa, menambahkan.
Maltysen
@LuisMendo no, menambahkan.
Maltysen

Jawaban:

8

MATL , 105 104 58 50 49 byte

Terima kasih kepada @Neil untuk saran yang memungkinkan saya menghapus 46 byte!

2\TTYaEq4:HeqgEqZ+K/Zot0>+ss'Soft Hard Equal'Ybw)

Input adalah array char 2D, dengan baris dipisahkan oleh ;. Contoh dalam tantangannya adalah

['########          ';'#      #          ';'########          ';'                  ';'   ###        ####';'   ###        ####';'   ###            ']

Ini contoh lain:

['###                ';'###                ';'###                ';'                   ';'###################';'#                 #';'#                 #';'#                 #';'###################']

Ini sesuai dengan

###                
###                
###                

###################
#                 #
#                 #
#                 #
###################

dan karenanya harus memberi 'Equal'.

Sebagai contoh ketiga, terkait dengan 'Soft',

['   ######    ';'   #    #    ';'   ######    ';'          ###';'   ##  #  # #';'          ###';'             ';'             ';' ########    ';' #      #    ';' ########    ']

itu adalah,

   ######    
   #    #    
   ######    
          ###
   ##  #  # #
          ###


 ########    
 #      #    
 ########  

Cobalah online!

Penjelasan

Ini menggunakan konvolusi 2D untuk mendeteksi bentuk. Input dikonversi ke array 2D dengan 1menunjukkan #dan -1untuk ruang; dan diisi dengan bingkai -1nilai. Ini memastikan bahwa bentuk-bentuk di tepi bidang asli juga terdeteksi.

Sebuah objek yang lembut terdeteksi oleh topeng

 1   1
 1  -1

yang sesuai dengan sudut kiri atas objek dengan satu titik interior kosong. Perhatikan bahwa konvolusi membalikkan mask, sehingga didefinisikan seperti [-1 1; 1 1]dalam kode. Jumlah S dari posisi di mana konvolusi sama dengan 4adalah jumlah total objek lunak.

Sebuah objek (lunak atau keras) terdeteksi oleh topeng

-1  -1
-1   1

yang sesuai dengan sudut kiri atas objek bersama-sama dengan beberapa titik eksterior kosong. Topeng ini adalah versi yang dinegasikan dari yang sebelumnya, sehingga hasil konvolusi sebelumnya dapat digunakan kembali. Secara khusus, jumlah T dari posisi di mana hasil yang sama dengan itu -4adalah jumlah total objek.

Jumlah H dari benda keras adalah T - S . Output string ditentukan oleh tanda S - H = 2 * S - T .

2\                 % Input. Modulo 2: '#' gives 1, ' ' gives 0
TTYa               % Add a frame of zeros
Eq                 % Convert 0 to -1
4:HeqgEq           % Generate mask [-1 1; 1 1], for soft objects
Z+                 % 2D convolution, preserving size
K/Zo               % Divide by 4 and round towards 0. Gives 1 or -1 for 4 or -4
t0>                % Duplicate. 1 for positive entries (soft objects), 0 otherwise
+                  % Add. This corresponds to the factor 2 that multiplies number S
ss                 % Sum of 2D array. Gives 2*S-T
'Soft Hard Equal'  % Push this string
Yb                 % Split by spaces. Gives cell array
w)                 % Swap. Apply (modular) index to select one string
Luis Mendo
sumber
1
Jadi, saya tidak tahu apa konvolusi itu, tetapi tidak bisakah Anda menghitung semua benda (dengan menemukan misalnya sudut kiri atas) dan membandingkan dengan dua kali jumlah objek lunak?
Neil
@ Neil yang terlihat sangat menjanjikan, terima kasih! Dengan begitu saya bisa mengurangi 5 hingga 2 konvolusi. (Konvolusi pada dasarnya melihat apakah pola tertentu cocok pada beberapa posisi). Saya akan mencobanya nanti
Luis Mendo
... atau bahkan hanya 1 belitan! Terima kasih banyak! Diskon 46 byte :-) @Neil
Luis Mendo
3
Itu hampir setara dengan JS ... @Neil sisi mana Anda berada ;-)
edc65
6

JavaScript (ES6), 123 121 118 byte

s=>s.replace(/#+/g,(m,i)=>s[i+l]>" "?0:n+=!m[1]|s[i-l+1]==s[i-l]||-1,n=l=~s.search`
|$`)|n>l?"Hard":n<l?"Soft":"Equal"

Disimpan 2 byte berkat @ edc65!

Mengambil input sebagai string multiline yang diisi dengan spasi untuk membentuk kisi.

Penjelasan / Tes

Sangat dekat dengan panjang MATL! Pada dasarnya, ia mencari garis atas #s dari setiap objek, dan jika panjang garis atas kurang dari 2 atau 2 karakter pertama di bawah garis atas adalah sama, itu sulit, jika tidak lembut.

var solution =

s=>
  s.replace(/#+/g,(m,i)=>        // for each run of consecutive # characters
    s[i+l]>" "?                  // if the position above the match contains a #
      0                          // do nothing (this object has already been counted)
    :n+=                         // add 1 to the counter (hard) if
      !m[1]                      // the match is only 1 # wide
      |s[i-l+1]==s[i-l]          // or the characters below are the same
      ||-1,                      // else decrement the counter (soft)
    n=                           // n = counter, hard objects increase n, soft decrease
    l=~s.search`\n|$`            // l = (negative) line length
  )
  |n>l?"Hard":n<l?"Soft":"Equal" // return the result string

// Test
document.write("<pre>" + [`

########          
#      #          
########          
                  
   ###        ####
   ###        ####
   ###            

`,`

###                
###                
###                
                   
###################
#                 #
#                 #
#                 #
###################

`,`

   ######    
   #    #    
   ######    
          ###
   ##  #  # #
          ###
             
             
 ########    
 #      #    
 ########    

`,`

########          
#      #          
########          
                  
   ###        ####
   # #        ####
   ###            

`,`

########          
#      #          
########          
                  
   ###  ###   ####
   ###  # #   ####
   ###  ###       

`,`

#

`,`

##

`,`

#
#

`,`

###
# #
###

`].map((test) => solution(test.slice(2, -2))).join("\n")
)

pengguna81655
sumber
Tampaknya ada masalah dengan input baris tunggal; ###kembali Equal.
Dennis
@ Dennis Kamu benar. Tampaknya untuk input satu baris kode saya sebelumnya mengandalkan bug yang saya perbaiki. Diperbaiki sekarang
user81655
IMHO ~g.search(/$/m)sedikit lebih mudah dibaca daripada ~g.search`\n`||-1.
Neil
@Neil Benar. Ada bug jadi saya buru-buru ||-1memasang untuk memperbaikinya, tetapi saran Anda membuat saya menyadari bahwa menambahkan |$ke regex akan menghemat 2 byte. Terima kasih!
user81655
Anda bisa menggunakan hanya 1 countern=l=... n>l?...:n<l?...:...
edc65
4

Jelly, 50 49 46 43 38 34 33 32 byte

Ḥ+ḊZ
>⁶ÇÇFµċ7_ċ4$Ṡị“¤Ỵf“¢*ɦ“¡⁺ƒ»

Cobalah online! atau verifikasi semua kasus uji .

Latar Belakang

Ada 16 pola blok dan spasi 2 × 2 yang berbeda :

|  |  |  | #|  | #| #|# | #|# |# |##|# |##|##|##|
|  | #|# |  |##| #|# |  |##| #|# |  |##| #|# |##|

Dari jumlah tersebut, karena dua benda tidak akan pernah menyentuh,

| #|# |
|# | #|

tidak akan pernah terjadi pada input, meninggalkan kita dengan 14 pola yang mungkin.

Menetapkan    nilai 0 dan #nilai 1 , kita dapat mengkodekan 2 × 2 pola

|ab|
|cd|

sebagai 2 (2a + c) + (2b + d) = 4a + 2b + 2c + d , meninggalkan nilai berikut untuk 14 pola.

|  |  |  | #|  | #|# | #|# |##|# |##|##|##|
|  | #|# |  |##| #|  |##|# |  |##| #|# |##|
  0  1  2  2  3  3  4  5  6  6  7  7  8  9

Untuk pola parsial 2 × 1 , 1 × 2 atau 1 × 1 di batas bawah dan / atau kanan, kami akan memperlakukannya seolah-olah diisi dengan spasi, masing-masing dikodekan sebagai 4a + 2b , 4a + 2c dan 4a . .

Dengan cara ini, setiap objek (lunak atau keras) akan memiliki tepat satu 4 pola (sudut kanan bawahnya); setiap objek lunak akan memiliki tepat dua pola 7 (kiri bawah dan sudut kanan atas).

Jadi, mengurangkan jumlah 4 pola dari jumlah 7 pola yang ditemui dalam input akan menghasilkan (s + h) - 2s = h - s: = d , di mana h dan s adalah jumlah benda keras dan lunak yang mereka bentuk.

Kami mencetak Hard jika d> 0 , Soft jika d <0 dan Equal jika d = 0 .

Bagaimana itu bekerja

Ḥ+ḊZ                         Helper link. Input: M (n×m matrix)

Ḥ                            Unhalve; multiply all entries of M by 2.
  Ḋ                          Dequeue; remove the first row of M.
 +                           Perform vectorized addition.
                             This returns 2 * M[i] + M[i + 1] for each row M[i].
                             Since the M[n] is unpaired, + will not affect it,
                             as if M[n + 1] were a zero vector.
   Z                         Zip; transpose rows with columns.


>⁶ÇÇFµċ7_ċ4$Ṡị“¤Ỵf“¢*ɦ“¡⁺ƒ»  Main link. Input: G (character grid)

>⁶                           Compare each character with ' ', yielding 1 for '#'
                             and 0 for ' '.
  Ç                          Call the helper link.
                             This will compute (2a + c) for each pattern, which is
                             equal to (2b + d) for the pattern to its left.
   Ç                         This yields 2(2a + c) + (2b + d) for each pattern.
    F                        Flatten; collect all encoded patterns in a flat list.

     µ                       Begin a new, monadic link. Argument: A (list)
      ċ7                     Count the amount of 7's.
         ċ4$                 Count the amount of 4's.
        _                    Subtract the latter from the former.
            Ṡ                Yield the sign (1, -1 or 0) of the difference.
              “¤Ỵf“¢*ɦ“¡⁺ƒ»  Yield ['Hard', 'Soft', Equal'] by indexing into a
                             built-in dictionary.
             ị               Retrieve the string at the corresponding index.
Dennis
sumber
1

Julia, 99 95 93 byte

~=t->2t'+[t[2:end,:];0t[1,:]]'
!x=("Hard","Equal","Soft")[sign(~~(x.>32)∩(4,7)-5.5|>sum)+2]

!mengharapkan array Char dua dimensi sebagai argumen. Cobalah online!

Bagaimana itu bekerja

Ini menggunakan ide yang hampir sama persis dengan jawaban Jelly saya , dengan satu peningkatan:

Alih-alih menghitung jumlah 4 dan 7 , kami menghapus semua angka lainnya, lalu kurangi 5,5 untuk memetakan (4, 7) menjadi (-1,5, 1,5) . Dengan cara ini, tanda jumlah perbedaan yang dihasilkan menentukan keluaran yang benar.

Dennis
sumber
0

TSQL, 328 249 byte

Mendeklarasikan variabel dan data uji:

DECLARE @l int = 20
DECLARE @ varchar(max)=''
SELECT @+=LEFT(x + replicate(' ', @l), @l)
FROM (values
(' xxxx'),
(' xxxx'),
(' xxxx'),
('x'),
(''),
('xxx'),
('x x  xxx'),
('xxx  x x'),
('     xxx    ')) x(x)

Kode:

SELECT substring('Soft EqualHard',sign(sum(iif(substring(@,N,@l+2)like'xx'+replicate('_', @l-2)+'x ',-1,1)))*5+6,5)FROM(SELECT row_number()OVER(ORDER BY Type)N FROM sys.all_objects)x WHERE n<=len(@)AND' x'=substring(@,N-1,2)AND''=substring(@,N-@l,1)

Kode kempes:

SELECT
  substring('Soft EqualHard',
    sign(sum(iif(substring(@,N,@l+2)like'xx'+replicate('_', @l-2)+'x ',-1,1)))*5+6,5)
FROM(SELECT row_number()OVER(ORDER BY Type)N FROM sys.all_objects)x
WHERE n<=len(@)AND' x'=substring(@,N-1,2)AND''=substring(@,N-@l,1)

Penjelasan:

Script memindai teks untuk polanya:

      space
space x

Masing-masing adalah awal dari sebuah kotak

Untuk posisi itu, skrip kemudian memeriksa polanya, tidak perlu memeriksa x pertama:

  x
x space 

Ketika yang ada itu adalah objek yang lunak, kalau tidak itu adalah objek yang keras.

t-clausen.dk
sumber