Keacakan Sewenang-wenang


26

Keacakan itu menyenangkan. Tantangan tanpa poin itu menyenangkan.

Tulis fungsi yang, jika diberi input bilangan bulat n, akan mengeluarkan satu set (tidak berurutan, unik) nantara bilangan bulat acak antara 1dan n^2(inklusif) sehingga jumlah semua bilangan bulat sama dengann^2 .

Keacakan tidak tidak harus seragam, disediakan setiap set yang valid memiliki non-nol kesempatan untuk terjadi.

Jawaban terpendek dalam byte (per setiap bahasa) menang.

Contohnya

Input (n) = 1, Target (n^2) = 1
Sample of possible outputs:
1

Input = 2, Target = 4
Sample of possible outputs:
3, 1
1, 3

Input = 3, Target = 9
Sample of possible outputs:
6, 1, 2
3, 5, 1
4, 3, 2

Input = 4, Target = 16
Sample of possible outputs:
1, 3, 5, 7
2, 4, 1, 9
8, 3, 1, 4

Input = 5, Target = 25
Sample of possible outputs:
11, 4, 7, 1, 2
2, 3, 1, 11, 8
6, 1, 3, 7, 8

Input = 8, Target = 64
Sample of possible outputs:
10, 3, 9, 7, 6, 19, 8, 2
7, 16, 2, 3, 9, 4, 13, 10
7, 9, 21, 2, 5, 13, 6, 1

Tugas Bonus: Apakah ada rumus untuk menghitung jumlah permutasi yang valid untuk suatu yang diberikan n?


2
terkait , tetapi sangat berbeda
Giuseppe

1
(p / s: Jika Anda memiliki algoritme cepat tetapi membutuhkan lebih banyak byte, pertimbangkan untuk menunggu hingga edisi kecepatan (saat ini dalam kotak pasir) untuk mempostingnya.)
user202729

1
@EriktheOutgolfer Meskipun ada (banyak) cara yang lebih baik daripada membuat semua set dan memilih set acak, mereka jauh lebih sulit untuk diimplementasikan dan kemungkinan lebih lama. Simpan untuk edisi kecepatan.
user202729

2
Jumlah set adalah OEIS A107379 .
nwellnhof

1
Keduanya. Lihat komentar "Juga jumlah partisi n ^ 2 menjadi n bagian yang berbeda."
nwellnhof

Jawaban:


9

Brachylog (v2), 15 byte (acak) atau 13 byte (semua kemungkinan)

Acak

~lℕ₁ᵐA+√?∧A≜₁ᵐ≠

Cobalah online!

Pengajuan fungsi (terlihat di TIO dengan pembungkus membuatnya menjadi program lengkap).

Penjelasan

~lℕ₁ᵐA+√?∧A≜₁ᵐ≠
~l               Specify a property of a list: its length is equal to the input,
    ᵐ              and it is composed entirely of
  ℕ₁                 integers ≥ 1,
       √           for which the square root of the
      +              sum of the list
        ?              is the input.
     A   ∧A      Restricting yourself to lists with that property,
           ≜₁      pick random possible values
             ᵐ       for each element in turn,
              ≠    until you find one whose elements are all distinct.

Semua kemungkinan

~lℕ₁ᵐ<₁.+√?∧≜

Cobalah online!

Pengajuan fungsi, yang menghasilkan semua kemungkinan output.

Penjelasan

~lℕ₁ᵐ<₁.+√?∧≜
~l               Specify a property of a list: its length is equal to the input,
    ᵐ              it is composed entirely of
  ℕ₁                 integers ≥ 1,
     <₁            it is strictly increasing,
         √         and the square root of the
        +            sum of the list
          ?            is the input.
       .   ∧≜    Generate all specific lists with that property.

Saya cukup terkejut bahwa ∧≜berfungsi (Anda biasanya harus menulis ∧~≜untuk memaksa-paksa output daripada input), tetapi ternyata yang memiliki input = output asumsi sehingga tidak masalah ke arah mana Anda menjalankannya.

Tugas bonus

Untuk mendapatkan beberapa wawasan tentang urutan jumlah kemungkinan, saya membuat pembungkus TIO berbeda yang menjalankan program pada bilangan bulat berturut-turut untuk memberikan urutan jumlah keluaran:

1,1,3,9,30,110,436,1801,7657,33401

Perjalanan ke OEIS menemukan bahwa ini adalah urutan yang sudah diketahui, A107379 , dijelaskan cukup banyak seperti dalam pertanyaan (tampaknya Anda mendapatkan urutan yang sama jika Anda membatasi ke angka ganjil). Halaman ini mencantumkan beberapa rumus untuk urutan (meskipun tidak ada yang sangat sederhana; yang kedua terlihat seperti rumus langsung untuk nilai tetapi saya tidak mengerti notasinya).


Rumus kedua adalah "koefisien x^(n*(n-1)/2)dalam ekspansi seri Product_{k=1..n} 1/(1 - x^k)" (sayangnya tidak langsung sama sekali)
user202729

Menempatkan kendala "semua berbeda" sebelum langkah pelabelan acak (mis. A≠≜₁ᵐ) Menjadikan waktu berjalan lebih cepat rata-rata.
Fatalkan

Saya tidak mengerti mengapa Anda menjadikan ini sebagai wiki komunitas. Itu adalah cara kuno untuk memiliki posting yang dapat diedit sebelum dimungkinkan untuk diedit.
pipa


7

05AB1E , 11 byte

nÅœʒDÙQ}sùΩ

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

n             # Take the square of the (implicit) input
              #  i.e. 3 → 9
 Ŝ           # Get all integer-lists using integers in the range [1, val) that sum to val
              #  i.e. 9 → [[1,1,1,1,1,1,1,1,1],...,[1,3,5],...,[9]]
   ʒ   }      # Filter the list to only keep lists with unique values:
    D         # Duplicate the current value
     Ù        # Uniquify it
              #  i.e. [2,2,5] → [2,5]
      Q       # Check if it's still the same
              #  i.e. [2,2,5] and [2,5] → 0 (falsey)
        s     # Swap to take the (implicit) input again
         ù    # Only leave lists of that size
              #  i.e. [[1,2,6],[1,3,5],[1,8],[2,3,4],[2,7],[3,6],[4,5],[9]] and 3
              #   → [[1,2,6],[1,3,5],[2,3,4]]
          Ω   # Pick a random list from the list of lists (and output implicitly)


5

R , 68, 75 48 byte (acak) dan 70 byte (deterministik)

Metode pengambilan sampel penolakan @ Giuseppe:

function(n){while(sum(F)!=n^2)F=sample(n^2,n);F}

Cobalah online!

Golf asli:

function(n,m=combn(1:n^2,n))m[,sample(which(colSums(m)==n^2)*!!1:2,1)]

Cobalah online!

The *!!1:2bisnis adalah untuk menghindari cara yang aneh sampletindakan ketika argumen pertama memiliki panjang 1.


@Giuseppe "diperbaiki" :-)
ngm

sangat bagus. menggunakan psecara langsung sebagai indeks alih-alih menghitungnya dan menggunakannya kembali akan menghemat beberapa byte.
Giuseppe

1
Saya punya function(n){while(sum(F)!=n^2)F=sample(n^2,n);F}untuk 48 juga ...
Giuseppe

1
@ J.Apakah untuk menghindari masalah saat memanggil sesuatu seperti sample(2,1)yang terjadi n=2. Jadi rephanya menjamin bahwa ini tidak akan pernah terjadi. Mungkin ada cara yang lebih baik tetapi ini cepat dan saya marah sample.
ngm

1
Anda dapat menyimpan byte dengan x*!!1:2lebih dari itu rep(x,2)jika pertanyaan meta Anda tidak.
J.Do


4

Java 10, 250 242 222 byte

import java.util.*;n->{for(;;){int i=n+1,r[]=new int[i],d[]=new int[n];for(r[n<2?0:1]=n*n;i-->2;r[i]=(int)(Math.random()*n*n));var S=new HashSet();for(Arrays.sort(r),i=n;i-->0;)S.add(d[i]=r[i+1]-r[i]);if(!S.contains(0)&S.size()==n)return S;}}

-20 byte terima kasih kepada @nwellnhof .

Awas, Jawa masuk .. Ini 'hanya' lima kali selama empat jawaban lainnya digabungkan, jadi tidak terlalu buruk kurasa .. rofl.
Itu berjalan n=1melalui n=25(gabungan) dalam waktu kurang dari 2 detik, jadi saya mungkin akan memposting versi yang dimodifikasi ke versi kecepatan dari tantangan ini (yang saat ini masih di Sandbox) juga.

Cobalah online.

Penjelasan:

Dalam pseudo-code kami melakukan hal berikut:

1) Menghasilkan sebuah array berukuran n+1mengandung: 0, nkuadrat, dan n-1jumlah bilangan bulat acak dalam kisaran [0, n squared)
2) Urutkan array ini
3) Buat array kedua dari ukuran nyang mengandung perbedaan maju pasangan
ini tiga langkah pertama akan memberi kita sebuah array yang berisi nrandom integer (dalam rentang [0, n squared)yang dijumlahkan menjadi nkuadrat.
4a) Jika tidak semua nilai acak adalah unik, atau salah satunya adalah 0: coba lagi dari langkah 1
4b) Lain-lain: kembalikan array perbedaan ini sebagai hasilnya

Adapun kode aktual:

import java.util.*;      // Required import for HashSet and Arrays
n->{                     // Method with int parameter and Set return-type
  for(;;){               //  Loop indefinitely
    int i=n+1,           //   Set `i` to `n+1`
        r[]=new int[i];  //   Create an array of size `n+1`
    var S=new HashSet(); //   Result-set, starting empty
    for(r[n<2?           //   If `n` is 1:
           0             //    Set the first item in the first array to:
          :              //   Else:
           1]            //    Set the second item in the first array to:
             =n*n;       //   `n` squared
        i-->2;)          //   Loop `i` in the range [`n`, 2]:
      r[i]=              //    Set the `i`'th value in the first array to:
           (int)(Math.random()*n*n); 
                         //     A random value in the range [0, `n` squared)
    for(Arrays.sort(r),  //   Sort the first array
        i=n;i-->0;)      //   Loop `i` in the range (`n`, 0]:
      S.add(             //    Add to the Set:
        r[i+1]-r[i]);    //     The `i+1`'th and `i`'th difference of the first array
    if(!S.contains(0)    //   If the Set does not contain a 0
       &S.size()==n)     //   and its size is equal to `n`:
      return S;}}        //    Return this Set as the result
                         //   (Implicit else: continue the infinite loop)

1
n=25di bawah 2 detik sangat mengesankan! Saya harus membaca penjelasannya dan melihat bagaimana melakukannya. Apakah ini masih merupakan metode bruteforce?
Skidsdev

Apakah seragam? -
user202729

@ user202729 Meskipun saya tidak yakin bagaimana membuktikannya, saya pikir itu benar. Java builtin adalah seragam, dan menggunakannya untuk mendapatkan nilai acak dalam rentang [0, n squared)pertama, dan kemudian menghitung perbedaan antara nilai-nilai acak yang diurutkan (termasuk memimpin 0dan mengikuti n squared. Jadi saya cukup yakin perbedaan itu seragam juga. Tapi sekali lagi , Saya tidak yakin bagaimana cara membuktikannya. Keseragaman dalam keacakan sebenarnya bukan keahlian saya tbh
Kevin Cruijssen

3
Anda tidak pernah membaca dari array perbedaan datau saya kehilangan sesuatu?
nwellnhof

1
Saya senang dengan solusi 127 byte saya : D
Olivier Grégoire

4

Perl 6 , 41 byte

{first *.sum==$_²,(1..$_²).pick($_)xx*}

Cobalah online!

  • (1 .. $_²) adalah rentang angka dari 1 hingga kuadrat dari nomor input
  • .pick($_) secara acak memilih subset berbeda dari rentang itu
  • xx * mereplikasi ekspresi sebelumnya tanpa batas
  • first *.sum == $_² memilih yang pertama dari set angka yang menjumlahkan kuadrat dari nomor input


2

Pyth, 13 12 byte

Ofq*QQsT.cS*

Cobalah online di sini . Perhatikan bahwa penerjemah online mengalami MemoryError untuk input yang lebih besar dari 5.

Ofq*QQsT.cS*QQQ   Implicit: Q=eval(input())
                 Trailing QQQ inferred
          S*QQQ   [1-Q*Q]
        .c    Q   All combinations of the above of length Q, without repeats
 f                Keep elements of the above, as T, where the following is truthy:
      sT            Is the sum of T...
  q                 ... equal to...
   *QQ              ... Q*Q?
O                 Choose a random element of those remaining sets, implicit print

Sunting: menyimpan satu byte dengan mengambil pendekatan alternatif. Versi sebelumnya: Of&qQlT{IT./*


2

Python 3 , 136 134 127 121 114 byte

from random import*
def f(n):
	s={randint(1,n*n)for _ in range(n)}
	return len(s)==n and sum(s)==n*n and s or f(n)

Cobalah online!

Seorang komentator mengoreksi saya, dan ini sekarang mengenai kedalaman maksimum rekursi pada f (5), bukan f (1). Jauh lebih dekat untuk menjadi jawaban yang bersaing nyata.

Saya pernah melihatnya melakukan f (5) satu kali , dan saya sedang berusaha mengimplementasikannya dengan shuffle.

Saya mencoba membuat beberapa ekspresi lambda s=..., tetapi itu tidak membantu pada byte. Mungkin orang lain dapat melakukan sesuatu dengan ini: s=(lambda n:{randint(1,n*n)for _ in range(n)})(n)

Terima kasih kepada Kevin karena telah memangkas 7 byte lagi.


1
Jadi ini menggunakan rekursi untuk "meregenerasi" set jika yang dihasilkan tidak valid? Pasti ada sesuatu yang salah dengan kode Anda jika mencapai kedalaman rekursi f(1), satu-satunya array yang mungkin dapat dihasilkan n=1adalah [1]juga ada banyak spasi kosong yang harus dihapus di sini. Ingat ini adalah tantangan kode-golf, jadi tujuannya adalah mencapai bytecount terendah
Skidsdev

1
range(1,n)-> range(n)Saya percaya harus menyelesaikan bug.
Jonathan Allan

1
Ini akan memperbaiki bug Anda, dan juga menghilangkan spasi kosong. Saya membayangkan ada lebih banyak ruang untuk bermain golf juga
Skidsdev

1
Meskipun rekursi sedikit memburuk dari 5 menjadi 4, Anda dapat menggabungkan dua pernyataan pengembalian Anda seperti ini: return len(s)==n and sum(s)==n*n and s or f(n)( Coba online 114 byte ).
Kevin Cruijssen

1
Anda dapat memiliki semuanya dalam satu baris. 111 byte
Jo King

2

APL (Dyalog Unicode) , 20 byte SBCS

Lambda awalan anonim.

{s=+/c←⍵?s←⍵*2:c⋄∇⍵}

Cobalah online!

{...}  "dfn";adalah argumen

⍵*2 kuadratkan argumen

s← tetapkan ke s(untuk s quare)

⍵? temukan nindeks acak dari 1 ...s tanpa penggantian

c← ditugaskan untuk c(untuk c andidate)

+/ jumlahkan mereka

s= dibandingkan dengan s

: jika sama

  c kembalikan kandidat

 lain

  ∇⍵ kembalilah pada argumen


apakah Anda melihat 18 byte saya dan H.PWiz ?
ngn

@ ngn Tidak, jelas tidak, tetapi saya memeriksa bahwa tidak ada solusi APL yang diposting sebelum saya diposting. Mengapa tidak ada satu pun dari Anda‽
Adám

baik, begitu saya sudah golf dan menunjukkannya ke kebun, hampir tidak ada insentif untuk memposting :)
ngn

@ Ngn Untuk Anda, tidak, tapi bagi saya ada
Adám

1
tentu, dan saya pikir Anda melakukan pekerjaan yang baik mempopulerkan apl di sini. saya hanya memastikan Anda tahu solusi yang lebih pendek telah ditemukan dan mungkin lebih baik untuk menjelaskan salah satu dari mereka (atau variasi) sebagai gantinya
ngn

2

APL (Dyalog Classic) , 18 byte

(≢?≢×≢)⍣(0=+.-∘≢)⍳

Cobalah online!

menggunakan ⎕io←1

menghasilkan angka 1 2 ... n

(... )⍣(... )terus menerapkan fungsi di sebelah kiri sampai fungsi di sebelah kanan mengembalikan true

panjangnya, yaitu n

≢?≢×≢pilih nbilangan bulat yang berbeda secara acak antara 1 dan n2

+.-∘≢ kurangi panjang dari setiap angka dan jumlah

0= jika jumlahnya 0, hentikan perulangan, jika tidak coba lagi


1

MATL , 18 13 byte

`xGU:GZrtsGU-

Cobalah online!

`	# do..while:
x	# delete from stack. This implicitly reads input the first time
	# and removes it. It also deletes the previous invalid answer.
GU:	# paste input and push [1...n^2]
GZr	# select a single combination of n elements from [1..n^2]
tsGU-	# is the sum equal to N^2? if yes, terminate and print results, else goto top

Saya tidak akan mencoba ini dalam karakter R - acak hampir tidak pernah menghasilkan program yang valid.
ngm

@ ngm hahaha Saya kira penjelasannya berurutan.
Giuseppe

1

Japt, 12 byte

²õ àU ö@²¥Xx

Cobalah

                 :Implicit input of integer U
²                :U squared
 õ               :Range [1,U²]
   àU            :Combinations of length U
      ö@         :Return a random element that returns true when passed through the following function as X
        ²        :  U squared
         ¥       :  Equals
          Xx     :  X reduced by addition

Menurut komentar yang dibuat oleh OP, urutan elemen dalam output tidak relevan sehingga àharus baik-baik saja.
Kamil Drakari

Terima kasih, @KamilDrakari. Diperbarui.
Shaggy

1

Java (JDK) , 127 byte

n->{for(int s;;){var r=new java.util.TreeSet();for(s=n*n;s>0;)r.add(s-(s-=Math.random()*n*n+1));if(r.size()==n&s==0)return r;}}

Cobalah online!

Infinite loop hingga satu set dengan kriteria cocok.

Saya harap Anda punya waktu, karena sangat sloooooow! Bahkan tidak bisa pergi ke 10 tanpa waktu habis.


Anda dapat golf 3 byte dengan mengubah if(r.size()==n&s==0)ke if(r.size()+s==n).
Kevin Cruijssen

@KevinCruijssen Saya sudah memikirkannya juga, tapi tidak, saya tidak bisa karena s bisa -1 dan n bisa menjadi ukuran () - 1.
Olivier Grégoire

Ah tunggu, Anda terus menambahkan item ke set selama s>0, jadi ukurannya bisa lebih besar dari n. Ok, dalam kasus itu memang tidak berhasil. nadalah konstanta, tetapi sayangnya keduanya sdan r.size()merupakan variabel yang dapat keduanya di bawah atau di atas 0dan nmasing - masing.
Kevin Cruijssen

1

Batch, 182 145 byte

@set/an=%1,r=n*n,l=r+1
@for /l %%i in (%1,-1,1)do @set/at=n*(n-=1)/2,m=(r+t+n)/-~n,r-=l=m+%random%%%((l-=x=r+1-t)*(l^>^>31)+x-m)&call echo %%l%%

Penjelasan: Menghitung pick minimum dan maksimum yang diizinkan, mengingat bahwa angka-angka harus diambil dalam urutan menurun, dan memilih nilai acak dalam kisaran. Contoh untuk input 4:

  • Kami mulai dengan 16 kiri. Kami tidak dapat memilih 11 atau lebih karena 3 picks yang tersisa harus menambah setidaknya 6. Kami juga harus memilih setidaknya 6, karena jika kami hanya memilih 5, 3 picks yang tersisa hanya dapat menambah menjadi 9, yang tidak cukup untuk 16. Kami memilih nilai acak dari 6 hingga 10, katakanlah 6.
  • Kami memiliki 10 yang tersisa. Kami tidak dapat memilih 8 atau lebih karena 2 pick yang tersisa harus menambah setidaknya 3. Seperti yang terjadi, kami tidak dapat memilih 6 atau lebih karena kami memilih 6 terakhir kali. Kita juga harus memilih setidaknya 5, karena jika kita hanya mengambil 4, 2 pick yang tersisa hanya dapat menambah 5, dengan total besar 15. Kita memilih nilai acak dari 5 hingga 5, katakan 5 (!).
  • Kami memiliki 5 yang tersisa. Kami tidak dapat memilih 5 atau lebih karena sisa pick harus menambah setidaknya 1, dan juga karena kami memilih 5 terakhir kali. Kita juga harus memilih setidaknya 3, karena jika kita hanya memilih 2, sisa pick hanya bisa 1, untuk total 14. Kita memilih nilai acak dari 3 hingga 4, katakanlah 4.
  • Kami punya 1 yang tersisa. Ternyata, algoritme memilih rentang 1 hingga 1, dan kami memilih 1 sebagai angka terakhir.

1

JavaScript, 647 291 261 260 259 251 239 byte

Berkat @Veskah untuk -10 byte pada versi asli dan "Oh yeah, Anda mengeluarkan semua set sedangkan tantangannya meminta yang acak untuk dikembalikan"

(n,g=m=n**2,r=[...Array(g||1)].map(_=>m--).sort(_=>.5-Math.random()).slice(-n),c=_=>eval(r.join`+`),i=_=>r.includes(_))=>[...{*0(){while(g>1&&c()!=g){for(z of r){y=c();r[m++%n]=y>g&&!(!(z-1)||i(z-1))?z-1:y<g&&!i(z+1)?z+1:z}}yield*r}}[0]()]

Cobalah online!

Buat array n^2indeks berbasis 1, sortir array secara acak, nelemen slice dari array. Sedangkan jumlah elemen acak tidak sama dengan n^2array loop elemen acak; jika jumlah elemen array lebih besar dari n^2dan elemen saat -1ini tidak sama dengan nol atau elemen saat -1ini tidak dalam array saat ini, kurangi 1; jika jumlah array kurang dari n^2dan elemen saat +1ini tidak dalam array, tambahkan 1ke elemen. Jika jumlah array sama dengan n^2break loop, output array.


1
637 byte dengan menarik z.join ke dalam variabel, dank++
Veskah

@ Veskah Kedua whileloop mungkin juga dapat direduksi menjadi badan fungsi tunggal yang menerima parameter; dan dapat menggantikan operator bersyarat (ternary) untuk if..elsepernyataan tersebut; di antara bagian-bagian lain dari kode yang kemungkinan besar dapat disesuaikan untuk golf; ieg, menghapus letpernyataan.
tamu271314

@Veskah 601 byte tanpa mengganti terner untukif..else
guest271314

1
Oh ya, kamu mengeluarkan semua set sedangkan tantangan meminta yang acak untuk dikembalikan (Lihat komentar OP untuk lebih jelasnya)
Veskah

@Veskah Pasti salah mengartikan tantangan dan contoh, atau terlalu fokus untuk menyelesaikan bagian dari pertanyaan ini " Tugas Bonus: Apakah ada rumus untuk menghitung jumlah permutasi yang valid untuk suatu hadiah n?" . menguji hasil yang diharapkan jika algoritma konsisten kembali untuk n^2array output yang dihasilkan dalam satu panggilan ke fungsi, dan secara bersamaan mengingat kemiripan dengan pertanyaan ini N N-dimensi ^ N array yang penuh dengan N .
tamu271314

0

Japt , 20 byte

²õ ö¬oU íUõ+)Õæ@²¥Xx

Cobalah online!

Sangat mengambil keuntungan dari keacakan "Non-seragam", hampir selalu menampilkan nangka ganjil pertama , yang terjadi pada jumlahn^2 . Secara teori itu dapat menampilkan set valid lainnya, meskipun saya hanya bisa mengkonfirmasi itu untuk kecil n.

Penjelasan:

²õ                      :Generate the range [1...n^2]
   ö¬                   :Order it randomly
     oU                 :Get the last n items
        í   )Õ          :Put it in an array with...
         Uõ+            : The first n odd numbers
              æ_        :Get the first one where...
                  Xx    : The sum
                ²¥      : equals n^2


0

C (gcc) , 128 125 byte

p(_){printf("%d ",_);}f(n,x,y,i){x=n*n;y=1;for(i=0;++i<n;p(y),x-=y++)while(rand()&&(n-i)*(n-i+1)/2+(n-i)*(y+1)+y<x)y++;p(x);}

Cobalah online!

-3 bytes berkat ceilingcat

CATATAN: Peluangnya sangat jauh dari seragam. Lihat penjelasan untuk apa yang saya maksud dan cara yang lebih baik untuk menguji itu berhasil (dengan membuat distribusi lebih dekat ke seragam [tetapi masih jauh dari itu]).

Bagaimana?

Ide dasarnya adalah hanya memilih angka yang terus bertambah agar tidak khawatir tentang duplikat. Setiap kali kami memilih nomor, kami memiliki peluang tidak-nol untuk 'melewatkannya' jika diizinkan.

Untuk memutuskan apakah kita dapat melewati angka, kita perlu mengetahui xjumlah yang tersisa untuk dijangkau, kjumlah elemen yang masih harus kita gunakan, dan ynilai kandidat saat ini. Jumlah terkecil yang mungkin masih bisa kita pilih

y+(y+1)+(y+2)+...
ditambahkan ke nilai saat ini. Secara khusus kami memerlukan ungkapan di atas kurang dari x. Rumusnya adalah
k(k+1)2+k(y+1)+y<x
Sayangnya kita harus sedikit berhati-hati mengatur ulang rumus ini karena pemotongan bilangan bulat dalam C, jadi saya tidak bisa menemukan cara untuk golf itu.

Meskipun demikian logikanya adalah memiliki kesempatan untuk membuang apa pun yyang memenuhi persamaan di atas.

Kode

p(_){printf("%d ",_);}  // Define print(int)
f(n,x,y,i){             // Define f(n,...) as the function we want
    x=n*n;              // Set x to n^2
    y=1;                // Set y to 1
    for(i=0;++i<n;){    // n-1 times do...
        while(rand()&&  // While rand() is non-zero [very very likely] AND
            (n-i)*      // (n-i) is the 'k' in the formula
            (n-i+1)/2+  // This first half takes care of the increment
            (n-i)*(y+1) // This second half takes care of the y+1 starting point
            +y<x)       // The +y takes care of the current value of y
        y++;            // If rand() returned non-zero and we can skip y, do so
    p(y);               // Print y
    x-=y++;             // Subtract y from the total and increment it
    }p(x);}             // Print what's left over.

Trik yang saya sebutkan untuk menguji kode dengan lebih baik melibatkan penggantian rand()&&dengan rand()%2&&sehingga ada kemungkinan 50-50 bahwa setiap y yang diberikan dilewati, daripada RAND_MAXpeluang 1 jika y diberikan digunakan.


Saya akan senang jika seseorang memeriksa matematika saya untuk konsistensi. Saya juga bertanya-tanya apakah solusi semacam ini dapat membuat tantangan kecepatan acak yang seragam menjadi sederhana. Rumus menempatkan batas atas dan bawah pada jawaban, apakah angka acak seragam dalam rentang itu menghasilkan hasil acak seragam? Saya tidak mengerti mengapa tidak - tetapi saya belum melakukan banyak kombinatorik untuk sementara waktu.
LambdaBeta

Sarankan p(y),x-=y++)while(rand()&&(i-n)*((~n+i)/2+~y)+y<x)y++;alih-alih){while(rand()&&(n-i)*(n-i+1)/2+(n-i)*(y+1)+y<x)y++;p(y);x-=y++;}
ceilingcat

@ceilingcat Saya suka perbaikan kecil ini yang Anda temukan. Saya selalu fokus pada algoritma keseluruhan sehingga saya lupa untuk mengoptimalkan implementasi (pada dasarnya saya menggunakan mode golf autopilot begitu saya memiliki sumber non-golf yang berfungsi - jadi saya kehilangan banyak penghematan)
LambdaBeta

Hei, bukan hanya kamu yang punya sintaks-golf. Saya menemukan sedikit perbaikan dalam banyak jawaban C / C ++ seperti itu (kecuali tidak ada pada Anda, @ceilingcat biasanya mengambilnya).
Zacharý

Ya, saya perhatikan bahwa Anda berdua mungkin adalah putter C / C ++ yang paling aktif (dapatkah kita menggunakan put untuk memperluas analogi golf ke beberapa pukulan terakhir? Mengapa tidak!). Itu selalu mengesankan saya bahwa Anda bahkan dapat memahami kode golf dengan cukup baik untuk memperbaikinya.
LambdaBeta

0

Bersih , 172 byte

import StdEnv,Math.Random,Data.List
? ::!Int->Int
?_=code{
ccall time "I:I"
}
$n=find(\s=length s==n&&sum s==n^2)(subsequences(nub(map(inc o\e=e rem n^2)(genRandInt(?0)))))

Cobalah online!


0

Python (2 atau 3), 84 byte

from random import*;l=lambda n,s=[]:(sum(s)==n*n)*s or l(n,sample(range(1,n*n+1),n))

Cobalah online!

Hits kedalaman rekursi maksimal sekitar l (5)



0

Mathematica 40 byte

RandomChoice[IntegerPartitions[n^2, {n}]]

1
Pertama-tama adalah n ^ 2, bukan 2 ^ n. Kedua, program Anda harus fungsi dan juga golf. Coba ini RandomChoice@IntegerPartitions[#^2,{#}]&
J42161217

1
Juga hasilnya harus (tidak berurutan, unik) tetapi fungsi ini gagal di keduanya
J42161217

0

Bahasa Wolfram (Mathematica) , 49 byte

(While[Tr[s=RandomSample[Range[#^2],#]]!=#^2];s)&

Cobalah online!

Versi golf oleh @ J42161217.


Bahasa Wolfram (Mathematica) , 62 byte

Range[#-1,0,-1]+RandomChoice@IntegerPartitions[#*(#+1)/2,{#}]&

Cobalah online!

Bagaimana itu bekerja

Terutama didasarkan pada pertanyaan Math.SE ini . Untuk mendapatkan partisin2 ke n bagian yang berbeda, dapatkan partisi n2-(n2-n)/2=(n2+n)/2 sebagai gantinya dan tambahkan 0n-1untuk setiap elemen. Karena Mathematica memberikan partisi dalam urutan menurun,n-10 ditambahkan sebagai gantinya.


Jawaban untuk Tugas Bonus

Tugas Bonus: Apakah ada rumus untuk menghitung jumlah permutasi yang valid untuk suatu yang diberikan n?

Iya nih. MenetapkanhalSebuahrt(n,k) sebagai jumlah partisi n menjadi tepat kbagian. Maka itu memenuhi hubungan pengulangan berikut:

halSebuahrt(n,k)=halSebuahrt(n-1,k-1)+halSebuahrt(n-k,k)

Anda dapat memahaminya sebagai "Jika sebuah partisi berisi 1, hapus; jika tidak, kurangi 1 dari setiap istilah". Penjelasan lebih lanjut di sini pada pertanyaan Math.SE lain . Dikombinasikan dengan kondisi awalpart(n,1)=1 and n<kpart(n,k)=0, you can compute it with a program. The desired answer will be:

part(n2+n2,n)

which is, in Mathematica:

Length@IntegerPartitions[#*(#+1)/2,{#}]&

Try it online!


This is code golf.. 49 bytes (While[Tr[s=RandomSample[Range[#^2],#]]!=#^2];s)&
J42161217
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.