Bisakah Anda melipat hexomino menjadi kubus?

24

Salah satu mainan favorit anak saya adalah satu set seperti ini . Sebenarnya ini salah satu mainan favorit saya - saya sudah bermain dengannya dan memberi saya beberapa ide tantangan PPCG. Ini dia:

Tulis program atau fungsi yang menggunakan gambar garis ASCII sebagai input dan memutuskan apakah melipat menjadi kubus atau tidak.

Memasukkan

Input akan terdiri dari tepat satu hexomino yang dibangun dari kotak seperti ini:

+-+
| |
+-+

Misalnya input heximino yang valid adalah:

+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
  | |
  +-+

Keluaran

  • Nilai kebenaran jika hexomino dapat dilipat menjadi kubus, atau
  • Nilai falsey sebaliknya.

Untuk menghemat sedikit kerja, wikipedia memiliki grafik yang bagus:

  • Semua 35 hexomino:

  • Semua 11 hexominoes yang dilipat menjadi kubus:

Catatan

  • Input hexomino dapat memiliki rotasi atau refleksi, tidak hanya yang ditunjukkan pada gambar di atas
  • Input hexomino mungkin memiliki ruang utama, tetapi akan disejajarkan dengan benar sehubungan dengan diri mereka sendiri
  • Hexomino input mungkin memiliki spasi tambahan di ujung baris dan tertinggal baris baru di akhir input
Trauma Digital
sumber
1
Bisakah Anda jelaskan mengapa ada tag pemrosesan gambar di sini? Baik pertanyaan, maupun jawaban harus melakukan pemrosesan gambar apa pun untuk menyelesaikan tantangan.
Pengoptimal
Klarifikasi tentang spasi awal / akhir: apakah spasi spasi awal / akhir tidak perlu di setiap baris dan baris baru yang tidak perlu diizinkan dalam input? Haruskah saya dapat mengelola input 1000+ karakter?
edc65
@ edc65 ya Anda harus mengharapkan ruang putih yang tidak perlu Anda jelaskan. 1000 karakter ukuran input maks tampaknya masuk akal - Saya akan mengeditnya di
Digital Trauma
Hmm. Saya bertanya-tanya berapa banyak kubus hexomino yang dapat diperas, disandingkan, pada halaman yang dicetak?
luser droog

Jawaban:

7

PMA / Siput , 130

.!(z\ |o{c..!(z\ }3){w=(..!(z\ )|b..!(z\ )o{..!(z\ }2|c{..!(z\ }1,2w..!(z\ )|w{..!(z\ }1,2c..!(z\ }4o..!(z\ )(..!(z\ )|n..!(z\ )`2

atau lebih "mudah dibaca",

?
.!(z\  | o{c..!(z\ }3  )
{w =( ..!(z\ ) | b ..!(z\ ) o {..!(z\ }2  | c {..!(z\ }1,2w..!(z\ ) | w {..!(z\ }1,2c..!(z\  }4
o  ..!(z\ ) ( ..!(z\ ) | n ..!(z\ ) `2

Tidak seperti biasanya, muncul masalah yang dapat diatasi dengan terbatasnya fitur yang diimplementasikan sejauh ini. The !(z\ )pola menentukan bahwa posisi saat ini di ruang di tengah alun-alun menggunakan pernyataan negatif bahwa ada ruang di beberapa "octilinear" arah. Ide umumnya adalah untuk memeriksa pola yang menempatkan kuadrat di masing-masing dari 5 lokasi yang diperlukan relatif terhadap kuadrat tempat pertandingan dimulai. Juga, perlu memeriksa bahwa itu tidak dalam blok 2x2 kotak. Sebelum program bekerja, saya harus memperbaiki bug dengan parsing tanda kurung.

Jika hexomino tidak memetakan kubus, 0dicetak. Jika ya, beberapa bilangan bulat positif dicetak (jumlah kecocokan).

Saya mengadaptasi generator polyomino ini untuk membuat semua test case yang mungkin:

n=input()
r=range
T=lambda P:set(p-min(p.real for p in P)-min(p.imag for p in P)*1j for p in P)
A=[]
for i in r(1<<18):
 P=[k%3+k/3*1j for k in r(18)if i>>k&1]
 C=set(P[:1])
 for x in P:[any(p+1j**k in C for k in r(4))and C.add(p)for p in P]
 P=T(P)
 if not(C^P or P in A or len(P)-n):
  #for y in r(4):print''.join(' *'[y+x*1j in P] for x in r(6))
  o = [ [' ']*13 for _ in r(9)]
  for y in r(4):
   for x in r(6):
    if y+x*1j in P: X=2*x;Y=2*y; o[Y][X]=o[Y+2][X]=o[Y][X+2]=o[Y+2][X+2]='+'; o[Y][X+1]=o[Y+2][X+1]='-';o[Y+1][X+2]=o[Y+1][X]='|'
  print '\n'.join(map(''.join,o))
  A+=[T([p*1j**k for p in P])for k in r(4)]
feersum
sumber
hahahahahahahah lebih "mudah dibaca"
Pengoptimal
5

Ruby, 173 148 145 143 byte

h=->b,c{[c.count(c.max),c.count(c.min),3].max*2<b.max-b.min}
->s{x=[];y=[];i=j=0
s.bytes{|e|e==43&&x<<i|y<<j;i=e<32?0*j+=1:i+1}
h[x,y]||h[y,x]}

Perubahan terbaru: /2di sisi kanan <diganti dengan *2di sisi kiri. Mengizinkan penghapusan satu set()

Penjelasan

Kode ini dalam dua bagian: fungsi tanpa nama utama yang melakukan parsing, dan fungsi tanpa nama tambahan ditugaskan ke variabel hyang melakukan pengecekan.

Fungsi utama memindai bytewise melalui string, menambahkan koordinat x dan y i,jdari semua +simbol yang ditemukan ke x[]dan y[]. Itu kemudian memanggil hdua kali. Pertama kali mengasumsikan hexomino adalah horisontal ( x[]berisi panjang dan y[]lebar) dan kedua kali menganggap hexomino adalah vertikal.

Fungsi hmengambil koordinat memanjang dalam array bkemudian koordinat memanjang dalam array c. Ini menghitung panjang (dalam kotak) dengan ekspresi (b.max.b.min)/2. Jika ini kurang dari atau sama dengan 3, hexomino harus dievaluasi ke arah lain sehingga hkembali false.

Pemeriksaan hexominos akan menunjukkan bahwa jika panjangnya 4, hexominos yang akan dilipat menjadi kubus tidak memiliki lebih dari 2 kotak (3 +simbol) di baris pertama dan terakhir . Sebagian besar kotak terkonsentrasi di baris tengah, yang akan menjadi khatulistiwa kubus. Kondisi ini ternyata diperlukan dan cukup untuk heksomino dengan panjang 4 yang akan dilipat menjadi kubus.

Hanya ada satu hexomino dengan panjang 5 yang akan dilipat menjadi kubus. Ini memiliki 3 kotak (4 +simbol) di baris pertama dan terakhir. Semua hexominos lainnya dengan panjang 5 memiliki 5 atau lebih +simbol di baris pertama atau terakhir.

Hanya ada satu hexomino dengan panjang 6. Ini memiliki 7 +simbol di setiap baris.

Menyatukan semua ini, cukup untuk memeriksa bahwa panjang hexomino lebih besar dari 3, dan jumlah +simbol pada baris pertama dan terakhir (mana yang lebih tinggi) kurang dari panjangnya.

Tidak digabungkan dalam program uji

#checking function as explained in text
h=->b,c{[c.count(c.max),c.count(c.min),3].max<(b.max-b.min)/2}

#main function for parsing
f=->s{
  x=[]                 #separate assignments required, 
  y=[]                 #otherwise we get 2 pointers to the same array
  i=j=0                #start coordinates 0,0
  s.bytes{|e|          #scan string bytewise
    e==43&&x<<i|y<<j     #if byte is a + symbol (ascii 43) add the coordinates to arrays x and y
    i=e<32?0*j+=1:i+1    #if byte is before ascii 32 assume newline, increment j and zero i. Otherwise increment i
  }
  h[x,y]||h[y,x]       #call h twice, with x and y in each possible order
}



#VALID INPUTS
puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
| |
+-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
  | |
  +-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
+-+
| |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
      | |
      +-+"]

puts f["
    +-+
    | |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
    +-+
    | |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]


puts f["
  +-+
  | |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
  +-+
  | |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]  
puts f["
+-+-+
| | |
+-+-+-+
  | | |
  +-+-+-+
    | | |
    +-+-+"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+-+
      | | | |
      +-+-+-+
"]


#INVALID INPUTS

puts f["
  +-+-+-+
  | | | |
  +-+-+-+
  | | | |
  +-+-+-+
"]


puts f["
  +-+-+-+-+-+-+
  | | | | | | |
  +-+-+-+-+-+-+

"]


puts f["
  +-+-+
  | | |
  +-+-+
  | |
  +-+
  | |
  +-+
  | |
  +-+
  | |
  +-+
"]

puts f["
  +-+-+-+-+-+
  | | | | | |
  +-+-+-+-+-+
    | |
    +-+
"]

puts f["
      +-+
      | |
  +-+-+-+-+-+
  | | | | | |
  +-+-+-+-+-+
"]

puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+-+
        | | |
        +-+-+"]

puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
      | | |
      +-+-+
"] 


puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
  | | | |
  +-+ +-+
"]

puts f["
 +-+   +-+
 | |   | |
 +-+-+-+-+
 | | | | |
 +-+-+-+-+
"]

puts f["
   +-+-+
   | | |
 +-+-+-+-+
 | | | | |
 +-+-+-+-+
"]

puts f["
  +-+
  | |
  +-+
  | |
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
"]

puts f["
  +-+
  | |
  +-+-+-+
  | | | |
  +-+-+-+
  | |
  +-+
  | |
  +-+
"]

puts f["
  +-+
  | |
+-+-+-+
| | | |
+-+-+-+
| |
+-+
| |
+-+"]

puts f["
  +-+-+
  | | |
  +-+-+
  | |
  +-+-+
  | | |
  +-+-+
    | |
    +-+
"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+
    | | | |
    +-+-+-+
"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+
      | |
      +-+-+
      | | |
      +-+-+
"]


puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+
      | | |
      +-+-+
        | |
        +-+
"]
Level River St
sumber
pentonimo → hexonimo di teks Anda?
Paŭlo Ebermann
3

JavaScript (ES6), 443 431

Edit perbaikan bug, masalah saat input parse, hapus kolom kosong

F=t=>(a=b=c=d=e=f=g=h=0,M=Math.min,
t=t.split('\n').filter(r=>r.trim()>''),
t=t.map(r=>r.slice(M(...t.map(r=>r.search(/\S/))))),
t.map((r,i)=>i&1&&[...r].map((_,j)=>j&1&&r[j-1]==r[j+1]&t[i-1][j]==t[i+1][j]&r[j-1]=='|'
&&(y=i>>1,x=j>>1,z=y*5,w=x*5,a|=1<<(z+x),e|=1<<(w+y),b|=1<<(4+z-x),f|=1<<(4+w-y),c|=1<<(20-z+x),g|=1<<(20-w+y),d|=1<<(24-z-x),h|=1<<(24-w-y)
))),~[1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056].indexOf(M(a,b,c,d,e,f,g,h)))

Itu sangat panjang, dan bahkan lebih lama karena input parsing adalah bagian besar dari tugas.

Apa yang saya lakukan adalah verifyng jika input yang diberikan adalah salah satu dari 11 hexomino yang dapat dilipat.

Setiap hexomino yang dapat dilipat dapat dipetakan ke beberapa bitmap 5x5 (hingga 8 bit berbeda, dengan simetri dan rotasi). Mengambil bitmap sebagai angka 25bit, saya telah menemukan nilai min untuk 11 hexomino yang tercatat, menggunakan kode berikut (dengan format input yang sangat sederhana)

h=[ // Foldable hexominoes
'o\noooo\no', ' o\noooo\n o', // pink
'o\noooo\n   o', ' o\noooo\n  o', 'ooo\n  ooo', 'oo\n oo\n  oo', //blue
'o\noooo\n o', 'o\noooo\n  o', 'oo\n ooo\n o', 'oo\n ooo\n  o', 'o\nooo\n  oo' // gray
]
n=[]
h.forEach(t=>(
  a=[],
  t.split('\n')
    .map((r,y)=>[...r]
      .map((s,x)=>s>' '&&(
         a[0]|=1<<(y*5+x),a[1]|=1<<(x*5+y),  
         a[2]|=1<<(y*5+4-x),a[3]|=1<<(x*5+4-y),  
         a[4]|=1<<(20-y*5+x),a[5]|=1<<(20-x*5+y),  
         a[6]|=1<<(24-y*5-x),a[7]|=1<<(24-x*5-y))
     )
  ),
n.push(Math.min(...a))
))

Itu memberi [1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056]

Jadi, mengingat string input, saya harus melakukan hal yang sama untuk menemukan bitmap min, kemudian mengembalikan true jika nomor ini ada dalam daftar precalc saya.

// Not so golfed 

F=t=>(  
  a=b=c=d=e=f=g=h=0,M=Math.min,
  t=t.split('\n').filter(r=>r.trim()>''), // remove blank lines
  t=t.map(r=>r.slice(M(...t.map(r=>r.search(/\S/))))), // remove blank colums to the left
  t.map((r,i)=>i&1&&[...r] // only odd rows
   .map((_,j)=>j&1&& // only odd columns
      r[j-1]==r[j+1]&t[i-1][j]==t[i+1][j]&r[j-1]=='|' // found a cell
         &&(y=i>>1,x=j>>1,z=y*5,w=x*5, // find bitmaps for 8 rotations/simmetries
            a|=1<<(z+x),e|=1<<(w+y),  
            b|=1<<(4+z-x),f|=1<<(4+w-y),  
            c|=1<<(20-z+x),g|=1<<(20-w+y),  
            d|=1<<(24-z-x),h|=1<<(24-w-y)  
    ))),
   ~[1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056].indexOf(Math.min(a,b,c,d,e,f,g,h)) // look for min
)

Jalankan cuplikan untuk menguji di Firefox

edc65
sumber
Maafkan saya jika saya kehilangan sesuatu, tetapi tidak bisakah Anda ,\nt=tdari akhir baris kedua / awal baris ketiga?
Conor O'Brien
@CᴏɴᴏʀO'Bʀɪᴇɴ meninjau enam bulan kemudian, kode parsing bisa dibuat 10 ... 15 byte lebih pendek. Seperti, saya perlu tugas untuk t di baris 2 dan lagi di baris 3 karena di baris 3 itu digunakan untuk menemukan jumlah karakter kosong untuk memotong di sisi kiri.
edc65