Mempartisi grid menjadi segitiga

18

Tujuan

Tujuan dari tantangan ini adalah untuk menghasilkan fungsi nyang menghitung sejumlah cara untuk membagi n X 1kisi - kisi menjadi segitiga di mana semua simpul segitiga berada pada titik-titik kisi.

Contoh

Sebagai contoh, ada 14 cara untuk mempartisi kisi 2 x 1, jadi f(2) = 14melalui partisi berikut ini di Partisi 2 x 1 mana partisi memiliki masing-masing 2, 2, 2, 2, 4, dan 2 orientasi berbeda.

Mencetak gol

Ini , jadi kode terpendek menang.

Peter Kagey
sumber
10
Beberapa kasus uji tambahan akan bermanfaat, sehingga kami dapat memverifikasi kiriman kami sudah benar.
AdmBorkBork
8
Anda mungkin ingin menentukan segitiga yang tidak mengalami degenerasi .
Arnauld
1
Saya telah mengedit urutan OEIS A051708 untuk mencerminkan interpretasi ini.
Peter Kagey

Jawaban:

2

05AB1E , 13 byte

·LÉœÙεÅγo;P}O

Pelabuhan @Bubbler 's Jelly jawabannya .

Sangat lambat karena permutasi bawaan.

Cobalah online atau verifikasi empat input pertama .

Penjelasan:

·                # Double the (implicit) input
 L               # Create a list in the range [1, doubled_input]
  É              # Check for each if they're odd (1 if truthy, 0 is falsey)
                 # We now have a list of n 0s and n 1s (n being the input)
   œ             # Get all permutations of that list
    Ù            # Only leave the unique permutations
     ε     }     # Map each permutation to:
      Åγ         #  Run-length encode the current value (short for `γ€g`)
        o        #  Take 2 to the power for each
         ;       #  Halve each
          P      #  Take the product of the mapped permutation
            O    # Sum all mapped values together (and output implicitly)
Kevin Cruijssen
sumber
19

Haskell , 60 55 54 52 byte

Setelah menggambar dan memprogram banyak contoh, terlintas dalam benak saya bahwa ini sama dengan masalah benteng:

Pada papan catur , berapa banyak cara untuk naik dari rook ke hanya dengan bergerak ke kanan atau lebih tinggi ?(n+1)×(n+1)(0,0)(n,n)+(1,0)+(0,1)

Pada dasarnya Anda memiliki garis atas dan bawah dari kisi . Sekarang Anda harus mengisi garis non-horisontal. Setiap segitiga harus memiliki dua garis non-horizontal. Apakah salah satu sisinya merupakan bagian atas atau garis bawah sesuai dengan arah dan panjang Anda akan pergi dalam masalah benteng. Ini adalah OEIS A051708 . Sebagai ilustrasi korespondensi ini, perhatikan contoh-contoh berikut. Di sini garis atas berhubungan dengan gerakan ke atas, sedangkan garis bawah berhubungan dengan gerakan ke kanan.1×n

Terima kasih @PeterTaylor untuk -6 byte dan @PostLeftGarfHunter untuk -2 byte!

b 0=1
b 1=2
b n=div((10*n-6)*b(n-1)-9*(n-2)*b(n-2))n

Cobalah online!

cacat
sumber
Saya menemukan urutan OEIS dengan mencari dengan beberapa nilai pertama. Penjelasan yang bagus untuk mengapa itu cocok. Apakah Anda ingin mengeditnya untuk menambahkan komentar tentang interpretasi kombinasi alternatif ini? Jika tidak, saya mungkin.
Peter Taylor
BTW Anda perlu menyesuaikan pengindeksan, karena jawaban yang benar di sini adalah A051708(n+1). Jadi saya memposting jawaban yang benar pertama :-P
Peter Taylor
Saya bawa rook move map ke segitiga dengan membuat segitiga dengan tepi atas dan bawah sesuai dengan gerakan ke atas atau kanan?
Neil
@PeterTaylor Damn, terima kasih telah menunjukkan kesalahan saya :)
flawr
5
@Nil Saya menambahkan penjelasan grafis.
flawr
8

Haskell , 42 byte

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

Cobalah online!

Implementasi yang cukup langsung yang berulang lebih dari 2 variabel.

Inilah cara kami mendapatkan solusi ini. Mulai dengan kode yang menerapkan formula rekursif langsung:

54 byte

0%0=1
a%b=sum$map(a%)[0..b-1]++map(b%)[0..a-1]
f n=n%n

Cobalah online!

Menggunakan interpretasi benteng bergerak flawr ini , a%badalah jumlah jalur yang mendapatkan benteng dari (a,b)ke (0,0), menggunakan hanya bergerak penurunan koordinat. Langkah pertama mengurangi aatau mengurangi b, menjaga yang lain sama, maka rumus rekursif.

49 byte

a?b=sum$map(a%)[0..b-1]
0%0=1
a%b=a?b+b?a
f n=n%n

Cobalah online!

Kita dapat menghindari pengulangan map(a%)[0..b-1]++map(b%)[0..a-1]dengan memperhatikan bahwa kedua bagiannya sama adan bbertukar. Panggilan tambahan a?bmenghitung jalur di mana langkah pertama menurun a, dan b?amenghitung jalur di mana langkah pertama berkurang b. Ini pada umumnya berbeda, dan mereka menambah a%b.

Penjumlahan dalam a?bjuga dapat ditulis sebagai daftar pemahaman a?b=sum[a%i|i<-[0..b-1]].

42 byte

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

Cobalah online!

Akhirnya, kita menyingkirkan %dan hanya menulis rekursi dalam hal ?dengan mengganti a%idengan a?i+i?apanggilan rekursif.

Basis kasus baru menyebabkan ini ?untuk memberikan output dua kali lipat dari ?pada versi 49-byte, karena dengan 0?0=1, kita akan melakukannya 0%0=0?0+0?0=2. Ini memungkinkan penggunaan define f n=n?ntanpa mengurangi separuh yang harus kita lakukan.

Tidak
sumber
Solusi 49-byte Anda menggunakan rekursi yang sama dengan jawaban saya, tetapi saya belum menemukan solusi 42-byte. Penjelasan akan menyenangkan.
Peter Taylor
Saya pikir saya menggunakan pendekatan yang sama di salah satu program saya sebelumnya: Idenya adalah menghasilkan (atau menghitung) semua partisi dengan menghasilkan garis non-horizontal dari kanan ke kiri. Anda mulai dengan garis vertikal. Kemudian Anda dapat mengulang: Ambil salah satu dari simpul akhir dari garis sebelumnya dan hubungkan ke sebuah simpul pada garis horizontal berlawanan yang lebih jauh ke kiri dari semua simpul sebelumnya pada baris ini.
flawr
Operator a%bmenghitung jumlah partisi menggunakan node 0,1,...,adi garis atas, dan anggukan 0,1,..,bdi garis bawah. Operator a?bmenghitung jumlah cara Anda dapat menambahkan baris baru dari simpul atas ajika simpul bawah bsudah digunakan. (Anda dapat terhubung ake semua node [0,1,...,b-1], tetapi kemudian Anda harus mengulang untuk masing-masing node .)
flawr
@ flawr, itu yang 49-byte, yang saya mengerti. Ini adalah salah satu ?dari 42 byte yang tidak saya miliki, dan yang paling aneh adalah bahwa itu tidak simetris.
Peter Taylor
@ PeterTaylor Maaf atas kebingungan, saya entah bagaimana mencampuradukkan dua solusi. Saya pikir kita dapat dengan mudah mengubah dua solusi menjadi satu sama lain: Pada langkah pertama kita dapat mengganti map...dengan pemahaman daftar, pada langkah kedua kita cukup tancapkan definisi %:a?b=sum$map(a%)[0..b-1], a%b=a?b+b?a a?b=sum[a%i|i<-[0..b-1]], a%b=a?b+b?a a?b=sum[a?i+i?a|i<-[0..b-1]]
flawr
7

CJam (24 byte)

{2,*e!{e`0f=:(1b2\#}%1b}

Demo online

Ini menggunakan pendekatan Bubbler untuk menjumlahkan permutasi n0s dan n1s.

Pembedahan

{         e# Define a block
  2,*     e#   Given input n, create an array of n 0s and n 1s
  e!      e#   Generate all permutations of that array
  {       e#   Map:
    e`    e#     Run-length encode
    0f=:( e#     Extract just the lengths and decrement them
    1b    e#     Sum
    2\#   e#     Raise 2 to the power of that sum
  }%
  1b      e#  Sum the mapped values
}

Pendekatan alternatif (28 byte)

{_1aa{_2$,f{j}@@,f{j}+1b}2j}

Demo online

Pembedahan

Segitiga memiliki satu tepi horizontal dan dua tepi yang menghubungkan garis horizontal. Beri label tepi non-horizontal dengan tupel dari dua x-coord dan urutkan secara leksikografis. Kemudian tepi pertama adalah (0,0), tepi terakhir adalah (n,n), dan dua tepi berturut-turut berbeda persis satu dari dua posisi. Ini menghasilkan rekursi sederhana, yang telah saya terapkan menggunakan operator rekursi memoised j:

{            e# Define a block
  _          e#   Duplicate the argument to get n n
  1aa        e#   Base case for recursion: 0 0 => 1
  {          e#   Recursive body taking args a b
    _2$,f{j} e#     Recurse on 0 b up to a-1 b
    @@,f{j}  e#     Recurse on a 0 up to a b-1
    +1b      e#     Combine and sum
  }2j        e#   Memoised recursion with 2 args
}

Catatan

Ini bukan pertama kalinya saya ingin fjdidukung di CJam. Di sini itu akan membawa skor menjadi 24 byte juga. Mungkin saya harus mencoba menulis tambalan ...

Peter Taylor
sumber
Yay, saya mengalahkan Anda 10 detik, saya pikir saya tidak pernah sedekat ini :)
flawr
@ flawr, saya memang mempertimbangkan posting sebelum menulis pembedahan, tapi saya pikir saya punya waktu untuk merobohkannya dengan cepat. Kemudian saya melihat "Jawaban baru", jadi saya menghapus pembedahan tertulis bagian saya, diposting, dan diedit.
Peter Taylor
1
Terima kasih untuk -5 byte btw: D
flawr
4

Jelly , 15 14 byte

Ø.xŒ!QŒɠ€’§2*S

Cobalah online!

-1 byte berdasarkan komentar Peter Taylor.

Gunakan ilustrasi flawr secara langsung, bukan formula yang dihasilkan.

Bagaimana itu bekerja

Ø.xŒ!QŒɠ€’§2*S    Main link (monad). Input: positive integer N.
Ø.x               Make an array containing N zeros and ones
   Œ!Q            All unique permutations
      Œɠ€         Run-length encode on each permutation
         ’§       Decrement and sum each
           2*S    Raise to power of 2 and sum

Ambil setiap rute yang memungkinkan pada kotak persegi. Jumlah cara untuk memindahkan unit L dalam satu arah sebagai benteng adalah 2**(L-1). Terapkan ini untuk setiap rute dan jumlah jumlah cara untuk melintasi setiap rute.

Bubbler
sumber
Pendekatan yang bagus. Ketika saya porting ke CJam lebih pendek untuk mengurangi panjang, jumlah, dan kemudian menaikkan 2 ke jumlah; daripada menaikkan 2 panjangnya, membagi dua, dan kemudian mengalikan. Tidak tahu apakah itu bisa menghemat satu byte.
Peter Taylor
3

Arang , 44 31 byte

dicoret 44 masih teratur 44

F⊕θ«≔⟦⟧ηF⊕θ⊞ηΣ∨⁺ηEυ§λκ¹⊞υη»I⊟⊟υ

Cobalah online! Penjelasan: Bekerja dengan menghitung jumlah cara untuk mempartisi trapesium dengan panjang sisi yang berlawanan m,nmenjadi segitiga yang semuanya terletak pada offset bilangan bulat. Ini hanyalah kasus umum dari ukuran persegi panjang ndalam pertanyaan. Jumlah partisi diberikan secara rekursif sebagai jumlah dari jumlah partisi untuk semua sisi m,0..n-1dan n,0..m-1. Ini setara dengan masalah umum dari benteng, OEIS A035002 . Kode hanya menghitung jumlah partisi bekerja dari 0,0hingga n,nmenggunakan nilai-nilai yang sebelumnya dihitung sebagai kelanjutannya.

F⊕θ«

Lingkari baris 0..n.

≔⟦⟧η

Mulai dengan baris kosong.

F⊕θ

Ulangi kolom di baris 0..n.

⊞ηΣ∨⁺ηEυ§λκ¹

Ambil baris sejauh ini dan nilai-nilai di baris sebelumnya di kolom saat ini, dan tambahkan jumlah total ke baris saat ini. Namun, jika tidak ada nilai sama sekali, maka gantikan 1dengan jumlah tersebut.

⊞υη»

Tambahkan baris yang sudah selesai ke daftar baris sejauh ini.

I⊟⊟υ

Keluarkan nilai akhir yang dihitung.

Neil
sumber
2

Pari / GP , 43 byte

Menurut OEIS , fungsi pembangkit dari urutan ini adalah

12(1x19x+1)

n->Vec(sqrt((1-x)/(1-9*x)+O(x^n++))+1)[n]/2

Cobalah online!

alephalpha
sumber