Patung Magnetik… di Luar Angkasa!

8

Latar Belakang

Ini adalah kelanjutan dari tantangan saya sebelumnya , di mana tugasnya adalah menghitung bentuk patung yang diperoleh dengan menjatuhkan magnet ke tumpukan besar.

Berita bagus: artis eksentrik menyukai karya Anda, dan memiliki proyek lain untuk Anda. Dia masih bekerja dengan pahatan magnetik, tetapi telah memutuskan untuk memperluas studio seninya - ke ruang angkasa ! Metodenya saat ini adalah meledakkan satu magnet berbentuk kubus ke dalam orbit, dan menembakkan magnet lain ke dalamnya untuk menciptakan satelit magnetik besar.

Memasukkan

Input Anda adalah daftar terbatas 0s dan 1s, diberikan dalam format daftar asli bahasa Anda, atau string. Ini ditafsirkan sebagai "cetak biru" dari sebuah karya seni, dan diproses secara berurutan dari kiri ke kanan sebagai berikut.

Anda mulai dengan magnet tunggal yang mengambang di beberapa koordinat bilangan bulat dari bidang 2D, dan terus menambahkan lebih banyak magnet sesuai arahan. Arahan 0memutar seluruh patung 90 derajat ke arah berlawanan arah jarum jam. Dalam hal arahan 1, artis menemukan kolom paling kiri dari patung, dan menembakkan magnet baru ke sana dari bawah. Magnet baru menempel pada magnet paling bawah yang ada di kolom, dan menjadi bagian dari patung. Perhatikan bahwa magnet tidak menempel pada magnet lain di kolom tetangga, tidak seperti pada tantangan sebelumnya; kecepatannya sekarang astronomi!

Keluaran

Artis ingin tahu apakah patung lengkap akan masuk ke garasinya (bagaimana ia akan turun dari orbit masih belum jelas). Dengan demikian, output Anda adalah lebar dan tinggi patung, dipesan dari yang lebih rendah ke yang lebih tinggi. Mereka dapat diberikan sebagai daftar dua elemen, sepasang, atau sebagai string yang dipisahkan oleh koma.

Contoh

Pertimbangkan urutan input

[1,0,1,1,0,1,0,0,1,1]

Untuk memprosesnya, kita mulai dengan satu magnet melayang di angkasa:

#

Arahan pertama adalah 1, jadi kami menembakkan magnet baru dari bawah:

#
#

Arahan berikutnya adalah 0, jadi kami memutar patung:

##

Dua arahan berikutnya adalah 1,1, yang berarti kami akan menembakkan dua magnet ke kolom paling kiri:

##
#
#

Kemudian, kami memutar lagi dan menembak sekali, seperti yang diarahkan oleh 0,1:

#
###
#

Akhirnya, kami memutar dua kali dan menembak dua kali:

  #
###
# #
#

Patung yang dihasilkan memiliki lebar 3dan tinggi 4, jadi kami output [3,4].

Aturan

Anda dapat memberikan fungsi atau program lengkap. Hitungan byte terendah menang, dan celah standar tidak diizinkan.

Uji Kasus

[1,0,1] -> [2,2]
[1,0,1,1,0,1,0,0,1,1] -> [3,4]
[1,1,0,1,1,0,1,0,1,1] -> [4,5]
[1,1,0,1,1,0,1,0,1,1,0] -> [4,5]
[1,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1] -> [3,3]
[0,1,0,1,1,1,1,0,0,1,0,1,0,0,1,1,0,1,0,1,0,0,1,1,0,1,0,0,0,0,1,0,1,0,1,1,0,0,1,1] -> [5,7]
[1,0,1,1,1,1,0,1,0,0,0,0,1,1,1,0,1,1,0,1,0,1,0,0,0,0,0,0,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,1,1,0,0,0,0,1,1,0,0,1,1,0,1,0,0,1,1,0,1,1,0,0,1,0,1,0,0,1,0,1,1,1,0,1,1,0,0,1,0,1,1,0,0,0,1,0,1,1,0,0,1,0,1,1,0] -> [11,12]
Zgarb
sumber
Tidak seharusnya [1,1,0,1,1,0,1,0,1,1,0]kembali [5,4]dan tidak [4,5]? Patung itu diputar pada bagian akhir.
algorithmshark
@algorithmshark Saya membuat kesalahan yang sama. Bagian Output menentukan bahwa hasilnya harus dipesan.
Martin Ender
1
@ MartinBüttner benar. Pembenarannya adalah bahwa orientasi tidak masalah ketika Anda berada di luar angkasa . : P
Zgarb

Jawaban:

8

Pyth : 34 33 byte

Sml{dCuS?+G,hhGtehGHm,_ekhkGQ],ZZ

Input adalah daftar satu dan nol, seperti dalam pertanyaan. Cobalah secara online: Pyth Compiler / Executor

Penjelasan:

Ini adalah terjemahan satu-satu dari kode Python 2 berikut ( 126 byte ).

print sorted(map(len,map(set,zip(*reduce(lambda s,i:([[-b,a]for a,b in s],s+[[min(s)[0],min(s)[1]-1]])[i],input(),[[0,0]])))))

Saya membuat daftar koordinat magnet tunggal. Ini diinisialisasi dengan magnet [0,0]. Kemudian untuk masing-masing bilangan cetak biru saya memanipulasi daftar dengan cara berikut. Jika integer berikutnya adalah 0, saya memutar patung dengan mengubah koordinat untuk setiap magnet [a,b]untuk [-b,a](pada dasarnya mengalikan dengan matriks rotasi). Jika bilangan bulat berikutnya adalah a 1, saya mencari bagian minimal [a,b](yang secara otomatis adalah magnet terendah dari kolom paling kiri) dan menambahkan magnet [a,b-1]ke daftar.

Setelah semua input diproses, saya membuat 2 set (untuk menghapus duplikat), satu untuk nilai x dan satu untuk nilai y, dan mencetak ukurannya dalam urutan yang diurutkan.

Sml{dCuS?+G,hhGtehGHm,_ekhkGQ],ZZ
                             ],ZZ  starting list G=[(0,0)]
      u                     Q],ZZ  for H in input(): manipulate G
       S                              Sort G after each manipulation
        ?          H                  G = ... if H==1 else ...
                    m,_ekhkG            [(-b,a) for a,b in G)] (rotate)
         +G,hhGtehG                     G+[(G[0][0],G[0][1]-1)]
                                        (G[0] is the lowest magnet in the leftmost column)
     C                             Zip the coords together
                                    (creates 2 lists, x- and y-coords)
 ml{d                              for each of those list compute number of unique values
S                                  sort and print

Sebuah ide untuk perbaikan : Menggunakan bilangan kompleks sebagai coords untuk magnet. Rotasi hanyalah perkalian dengan jdan mengurangi jdari magnet terendah di kolom paling kiri. Sayangnya menemukan magnet paling kiri ini membutuhkan terlalu banyak karakter di Python, bahkan tidak berbicara tentang menemukan persegi panjang.

Jakube
sumber
7

CJam, 48 byte

S]l~{{)S/);Sa+S*a+_z,f{_N*@\+<}}{zW%}?}/_,\z,]$p

Uji di sini.

Mengharapkan input sebagai larik gaya CJam (yaitu spasi alih-alih koma) dan akan menyajikan output yang sama. Jika Anda ingin menggunakan kasus uji dari pertanyaan secara langsung, salin langsung ke bidang input (sertakan ->dan hasil) dan gunakan test harness ini, yang mengubah baris ke format input yang benar (dan membuang hasilnya):

qN/{S/0=","Ser}%{[

S]\~{{)S/);Sa+S*a+_z,f{_N*@\+<}}{zW%}?}/_,\z,]$p

}/

Penjelasan

Saya hanya menerapkan aturan secara harfiah. Saya menyimpan kisi-kisi dengan pahatan saat ini (sebagai larik string), dan kemudian untuk setiap instruksi saya memutar kisi-kisi, atau saya menambahkan blok baru. Trik utama untuk menyimpan byte adalah:

  • Tambahkan ke baris bawah dari kanan . Ini sepenuhnya setara. Saya hanya satu putaran di depan, dan karena grid mulai berubah secara invarian, itu tidak masalah.
  • Gunakan spasi untuk mewakili blok yang ditempati dan karakter baris baru untuk mewakili blok kosong. Jadi jika Anda benar-benar mencetak kisi-kisi Anda tidak akan melihat banyak dan bahkan tidak akan terlihat persegi panjang. Saya melakukan ini, karena sebagian besar operator berbasis array hanya melakukan apa yang Anda inginkan jika elemen grid tersebut dibungkus dalam sebuah array. Dan dengan Sdan Nsaya memiliki akses ke string yang berisi karakter spasi dan baris baru (yaitu karakter yang dibungkus dalam array), daripada harus menggunakan, katakanlah, 1adan 0auntuk mendapatkan array yang berisi angka.

Mari kita lihat kodenya:

"Overall program structure:";
S]l~{{...}{...}?}/_,\z,]$p
S]                         "Push a string with a space and wrap it in an array.
                            This is the initial grid containing a single block.";
  l~                       "Read the input and evaluate it.";
    {           }/         "For each instruction in the input...";
     {...}{...}?           "Execute the first block if it's 1, the second if it's 0.";
                  _,       "Duplicate the resulting grid and get its length. This
                            is one of the dimensions.";
                    \      "Swap with the other copy of the grid.";
                     z,    "Zip/transpose it and get its length. This is the other
                            dimension of the grid.";
                       ]$p "Wrap both in an array, sort them, and print the result.";

"The rotation block is simple. A rotation is equivalent to two reflection operations
 along different axes. The simplest ones available are to transpose the grid (which
 is a reflection about the diagonal) and reversing the rows (which is a reflection
 about the horizontal). In CJam these are z for zip/tranpose and W% for reversing
 an array. So I simply put these together in the right order to get a counter-
 clockwise rotation:";
zW%

"Now the interesting part, adding new blocks and growing the grid. This part consists
 of two steps: appending a block to the rightmost block in the bottom row (allowing
 for empty blocks after it). And then potentially padding the rest of the grid with
 new empty cells if the bottom row got longer.";
)S/);Sa+S*a+_z,f{_N*@\+<}
)                         "Split off the bottom row.";
 S/                       "Split the row on occupied blocks.";
   );                     "Split off the final substring - this discards trailing
                           empty cells.";
     Sa+                  "Add a new substring containing an occupied block to the row.";
        S*                "Join all substrings together with spaces, putting back in
                           all the occupied blocks.";
          a+              "Wrap it in an array to add the row back onto the grid.";

 "At this point we need to make sure the grid is still rectangular. The easiest way
  (I found) is to find the maximum row length, add that many empty blocks to each 
  line and then truncate the lines to that length.";

            _             "Duplicate the grid.";
             z,           "Zip/transpose it and get the length. This is the length
                           of the longest row in a ragged array.";
               f{       } "Map this block onto each row, passing in the target length.";
                 _N*      "Duplicate the target length and get a string of that many
                           empty cells.";
                    @\    "Pull up the row and then swap it with those empty cells.";
                      +   "Add the empty cells to the end of the row.";
                       <  "Truncate to the target length.";
Martin Ender
sumber
Tidak tahu bagaimana ini bekerja, tetapi ternyata!
Luis Mendo
@LuisMendo Menambahkan penjelasan. Jika ada sesuatu yang tidak jelas dan Anda tertarik, silakan beri saya komentar lain. ;)
Martin Ender
Saya tidak tahu tentang CJam, dan sepertinya itu bukan bahasa yang mudah. Anda sudah memiliki +1 saya :-)
Luis Mendo
4

Matlab (92)

S=1;for d=input(''),if d,S(find(S(:,1),1,'last')+1,1)=1;else,S=rot90(S);end;end,sort(size(S))

Input standar digunakan. Data harus dimasukkan dalam formulir [1,0,1,1,0,1,0,0,1,1].

Tidak Disatukan:

S = 1; %// initial magnet
for d = input('') %// get directives, and pick them sequentially
    if d %// if directive is 1
        S(find(S(:,1),1,'last')+1,1) = 1; %// add 1 after lowest 1 in column 1. Grow if needed
    else %// if directive is 0
        S = rot90(S); %// rotate counterclockwise. Handy Matlab built-in function
    end
end
sort(size(S)) %// display size sorted

Contoh dijalankan:

>> clear all
>> S=1;for d=input(''),if d,S(find(S(:,1),1,'last')+1,1)=1;else,S=rot90(S);end;end,sort(size(S))
[1,0,1,1,0,1,0,0,1,1]
ans =
     3     4
Luis Mendo
sumber
1

Python - 211

import numpy as n
p=input()
q=len(p)
a=n.zeros([2*q+1]*2)
a[q,q]=1
for i in p:
 if i:x=a[:,n.where(a.any(0))[0][0]];x[len(x)-n.where(x[::-1])[0][0]+1]=1
 else:a=n.rot90(a)
z=a[:,a.any(1)]
print z[a.any(0)].shape
KSFT
sumber
Output harus diurutkan dari yang lebih rendah ke yang lebih tinggi! Juga istirahat program Anda untuk input [1].
Jakube
0

CJam, 47 byte

1]]q~{{0f+(W%_1#(1tW%a\+z{1b},}{W%}?z}/),\,)]$p

Ini membutuhkan input array bergaya CJam (dipisahkan dengan ruang alih-alih koma) dari STDIN dan mencetak hasilnya ke STDOUT.

Contoh:

[1 0 1 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1]

memberi

[3 3]

keluaran.

Penjelasan yang harus diikuti setelah saya yakin bahwa ini tidak dapat dipukul lebih lanjut.

Cobalah online di sini

Pengoptimal
sumber