Tumpukan dan Tumpukan Kerikil


8

Pekerjaan saya adalah menumpuk kerikil menjadi tumpukan segitiga. Saya hanya melakukan ini selama satu abad dan itu sudah cukup membosankan. Bagian terburuknya adalah saya memberi label setiap tumpukan. Saya tahu cara menguraikan kerikil menjadi tumpukan dengan ukuran maksimal , tetapi saya ingin meminimalkan jumlah tumpukan. Dapatkah kamu menolong?

Tugas

Diberikan bilangan bulat, dekomposisikan ke dalam jumlah minimum angka segitiga , dan hasilkan angka minimum itu.

Bilangan Segitiga

Angka segitiga adalah angka yang dapat dinyatakan sebagai jumlah dari nbilangan asli pertama , untuk beberapa nilai n. Demikianlah beberapa angka segitiga pertama

1 3 6 10 15 21 28 36 45 55 66 78 91 105

Contoh

Sebagai contoh, katakanlah inputnya 9. Ini bukan bilangan segitiga, sehingga tidak dapat dinyatakan sebagai jumlah 1bilangan segitiga. Dengan demikian jumlah minimum bilangan segitiga adalah 2, yang dapat diperoleh dengan [6,3], menghasilkan output yang benar 2.

Sebagai contoh lain, katakanlah inputnya 12. Solusi yang paling jelas adalah dengan menggunakan algoritma serakah dan menghapus angka segitiga terbesar pada suatu waktu, menghasilkan [10,1,1]dan menghasilkan 3. Namun, ada solusi yang lebih baik [6,6]:, menghasilkan output yang benar 2.

Uji Kasus

in out
1 1
2 2
3 1
4 2
5 3
6 1
7 2
8 3
9 2
10 1
11 2
12 2
13 2
14 3
15 1
16 2
17 3
18 2
19 3
20 2
100 2
101 2
5050 1

Aturan

  • Bilangan bulat input adalah antara 1 dan bilangan bulat maksimum bahasa Anda.
  • Saya dapat meniru bahasa apa pun dengan kerikil saya , dan saya ingin kode Anda sekecil mungkin karena saya tidak punya apa-apa selain kerikil untuk melacaknya. Jadi ini adalah , jadi kode terpendek di setiap bahasa menang.

Kotak pasir penuh dengan kerikil.
fireflame241



Jangan bingung dengan OEIS A057945 (perbedaan pertama terjadi untuk n = 12).
Martin Ender

Jawaban:


3

Retina , 57 49 byte

.+
$*
(^1|1\1)+$
1
(^1|1\1)+(1(?(2)\2))+$
2
11+
3

Cobalah online! Berdasarkan jawaban saya untuk Tiga angka segitiga . Ubah baris ketiga ke ^(^1|1\1)*$untuk mendukung input nol. Sunting: Disimpan 8 (tetapi mungkin lebih) byte berkat @MartinEnder.


Anda tidak perlu grup 1di tahap kedua, dan tidak grup 1maupun 3di tahap ketiga.
Martin Ender

Dan kemudian ((?(2)1\2|1))bisa disingkat menjadi (1(?(2)\2)).
Martin Ender

Sebenarnya, itu tiga byte lain yang lebih pendek untuk melakukan sesuatu yang aneh seperti ini: ^((?<2>)(1\2)+){2}$. Atau ^(()(?<2>1\2)+){2}$jika Anda suka.
Martin Ender

@ MartinEnder Versi terakhir itu membuat otak saya sakit, tapi saya bisa menggunakan komentar kedua Anda untuk jawaban tertaut saya, yang bagus.
Neil

Saya pikir yang terakhir sebenarnya lebih sederhana daripada pendekatan standar karena tidak memiliki referensi maju bersyarat aneh.
Martin Ender

1

Mathematica, 53 byte

Min[Plus@@@Table[$($+1)/2,{$,#+1}]~FrobeniusSolve~#]&

Kode ini sangat lambat. Jika Anda ingin menguji fungsi ini, gunakan versi berikut ini sebagai gantinya:

Min[Plus@@@Table[$($+1)/2,{$,√#+1}]~FrobeniusSolve~#]&

Cobalah di Wolfram Sandbox

Penjelasan

Min[Plus@@@Table[$($+1)/2,{$,#+1}]~FrobeniusSolve~#]&  (* input: n *)

           Table[$($+1)/2,{$,#+1}]                     (* Generate the first n triangle numbers *)
                                  ~FrobeniusSolve~#    (* Generate a Frobenius equation from the *)
                                                       (* triangle numbers and find all solutions. *)
    Plus@@@                                            (* Sum each solution set *)
Min                                                    (* Fetch the smallest value *)

1

Jelly ( garpu ), 9 byte

æFR+\$S€Ṃ

Ini bergantung pada garpu di mana saya mengimplementasikan atom pemecahan Frobenius yang tidak efisien. Aku tidak percaya ini sudah setahun sejak terakhir aku menyentuhnya.

Penjelasan

æFR+\$S€Ṃ  Input: n
æF         Frobenius solve with
     $     Monadic chain
  R          Range, [1, n]
   +\        Cumulative sum, forms the first n triangle numbers
      S€   Sum each
        Ṃ  Minimum

Darn Frobenius memecahkan atom, itu mengalahkan solusi Jelly normal saya dengan 6 seluruh byte :(
Erik the Outgolfer

@EriktheOutgolfer, saya harus menyelesaikannya dan menariknya.
miles

1

R , 69 58 byte

function(n)3-n%in%(l=cumsum(1:n))-n%in%outer(c(0,l),l,"+")

Cobalah online!

Penjelasan:

function(n){
 T <- cumsum(1:n)             # first n triangular numbers  [1,3,6]
 S <- outer(c(0,T),T,"+")     # sums of the first n triangular numbers,
                              # AND the first n triangular numbers [1,3,6,2,4,7,4,6,9,7,9,12]
 3 - (n %in% S) - (n %in% T)  # if n is in T, it's also in S, so it's 3-2: return 1
                              # if n is in S but not T, it's 3-1: return 2
                              # if n isn't in S, it's not in T, so 3-0: return 3
}


0

JavaScript (ES6), 75 63 61 byte

f=(n,x=y=0)=>y<n+2?x*x+y*y-8*n-2+!y?f(n,x<n+2?x+1:++y):2-!y:3

Bagaimana?

Kami menggunakan properti berikut:

  • Menurut teorema bilangan poligon Fermat , bilangan bulat positif apa pun dapat dinyatakan sebagai jumlah paling banyak dari 3 bilangan segitiga.
  • Angka t adalah segitiga jika dan hanya jika 8t + 1 adalah kuadrat sempurna (ini dapat dengan mudah dibuktikan dengan menyelesaikan t = n (n + 1) / 2 ).

Diberikan bilangan bulat positif n , cukup untuk menguji apakah kita dapat menemukan:

  • x> 0 sedemikian rupa sehingga 8n + 1 = x² ( n itu sendiri berbentuk segitiga)
  • atau x> 0 dan y> 0 sehingga 8n + 2 = x² + y² ( n adalah jumlah dari 2 angka segitiga)

Jika kedua tes gagal, n harus merupakan jumlah dari 3 angka segitiga.

f = (n, x = y = 0) =>                 // given n and starting with x = y = 0
  y < n + 2 ?                         // if y is less than the maximum value:
    x * x + y * y - 8 * n - 2 + !y ?  //   if x² + y² does not equal 8n + 2 - !y:
      f(                              //     do a recursive call with:
        n,                            //       - the original input n
        x < n + 2 ? x + 1 : ++y       //       - either x incremented or
      )                               //         y incremented and x set to y
    :                                 //   else:
      2 - !y                          //     return either 1 or 2
  :                                   // else:
    3                                 //   return 3

Uji kasus


0

MATL , 15 byte

`G:Ys@Z^!XsG-}@

Cobalah online!

Penjelasan

`         % Do...while
  G:      %   Push range [1 2 3 ... n], where n is the input
  Ys      %   Cumulative sum: gives [1 3 6 ... n*(n+1)/2]
  @Z^     %   Cartesian power with exponent k, where k is iteration index
          %   This gives a k-column matrix where each row is a Cartesian tuple
  !Xs     %   Sum of each row. Gives a column vector
  G-      %   Subtract input from each entry of that vector. This is the loop 
          %   condition. It is truthy if it only contains non-zeros
}         % Finally (execute before exiting the loop)  
  @       %   Push iteration index, k. This is the output
          % End (implicit). Proceeds with next iteration if the top of the
          % stack is truthy

0

Kotlin , 176 154 byte

pengajuan

{var l=it
var n=0
while(l>0){n++
val r=mutableListOf(1)
var t=3
var i=3
while(t<=l){r.add(t)
t+=i
i++}
l-=r.lastOrNull{l==it|| r.contains(l-it)}?:r[0]}
n}

Yg diperindahkan

{
    // Make a mutable copy of the input
    var l=it
    // Keep track of the number of items removed
    var n=0
    // While we still need to remove pebbles
    while (l > 0) {
        // Increase removed count
        n++
        // BEGIN: Create a list of triangle numbers
        val r= mutableListOf(1)
        var t = 3
        var i = 3
        while (t<= l) {
            // Add the number to the list and calculate the next one
            r.add(t)
            t+=i
            i++
        }
        // END: Create a list of triangle numbers
        // Get the fitting pebble, or the biggest one if none fit or make a perfect gap
        l -= r.lastOrNull {l==it|| r.contains(l-it)} ?: r[0]
    }
    //Return the number of pebbles
    n
}

Uji

var r:(Int)->Int =
{var l=it
var n=0
while(l>0){n++
val r=mutableListOf(1)
var t=3
var i=3
while(t<=l){r.add(t)
t+=i
i++}
l-=r.lastOrNull{l==it|| r.contains(l-it)}?:r[0]}
n}

data class TestData(val input:Int, val output:Int)

fun main(args: Array<String>) {
    val tests = listOf(
            TestData(1,1),
            TestData(2,2),
            TestData(3,1),
            TestData(4,2),
            TestData(5,3),
            TestData(6,1),
            TestData(7,2),
            TestData(8,3),
            TestData(9,2),
            TestData(10,1),
            TestData(11,2),
            TestData(12,2),
            TestData(13,2),
            TestData(14,3),
            TestData(15,1),
            TestData(16,2),
            TestData(17,3),
            TestData(18,2),
            TestData(19,3),
            TestData(20,2),
            TestData(100,2),
            TestData(101,2),
            TestData(5050,1)
    )
    tests.map { it to r(it.input) }.filter { it.first.output != it.second }.forEach { println("Failed for ${it.first}, output ${it.second} instead") }
}

TryItOnline

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.