Jumlah angka ganjil berturut-turut


24

Meskipun tantangan terkait telah diajukan, yang satu ini berbeda untuk menjamin pertanyaannya sendiri.


Tantangan

Diberikan bilangan bulat positif, kembalikan urutan terpanjang dari bilangan bulat ganjil positif berurutan yang jumlahnya adalah bilangan bulat yang diberikan. Jika tidak ada urutan seperti itu, Anda dapat melaporkan kesalahan dengan cara apa pun yang masuk akal untuk bahasa Anda, termasuk mengembalikan nilai palsu atau melemparkan pengecualian.

Uji Kasus

  1 -> [1]
  2 -> []
  3 -> [3]
  4 -> [1, 3]
  5 -> [5]
  6 -> []
  9 -> [1, 3, 5] (perhatikan bahwa [9] bukan jawaban yang valid)
 15 -> [3, 5, 7]
104 -> [23, 25, 27, 29] (perhatikan bahwa [51, 53] bukan jawaban yang valid)

Mencetak gol

Ini adalah , jadi jawaban tersingkat di setiap bahasa menang.


2
Bisakah program saya berjalan selamanya jika tidak ada solusi?
Dennis

Sangat terkait . Kenyataan bahwa beberapa angka genap tidak dapat diwakili dalam nomor ini mungkin menyelamatkannya dari penipuan.
ETHproduk

6
Tidak bisakah 15 memberi [-1, 1, 3, 5, 7]? Jika hanya nilai positif yang diizinkan, Anda harus mengatakannya.
xnor

2
@ ЕвгенийНовиков Anda melewatkan 17
kalsowerus

1
@alsowerus ya. Saya salah paham kata "consecutive"
Евгений Новиков

Jawaban:


11

Haskell, 67 65 63 62 58 byte

Disimpan 4 byte berkat Julian Wolf

f x=[[2*n+1,2*n+3..2*m]|n<-[0..x],m<-[n..x],m^2-n^2==x]!!0

Cobalah online!

Aku memeriksa apakah nomor tersebut dapat dinyatakan sebagai dia perbedaan dari dua kotak: m^2-n^2. Saya kemudian dapat membangun daftar nomor ganjil berturut-turut: [2n+1,2n+3...2m-1]. Perhatikan bahwa karena minimum ndipilih, daftar terpanjang akan ditampilkan


7
Down-voter: Akan lebih bersahabat dan lebih konstruktif untuk menambahkan komentar yang memberikan alasan Anda, terutama ketika memilih seorang pengguna baru.
Jonathan Allan

1
Kecuali jika saya melewatkan sesuatu, Anda dapat menyimpan 4 byte dengan hanya naik xuntuk keduanya ndanm
Julian Wolf

Asal tahu saja, downvote dilakukan secara otomatis oleh pengguna Komunitas saat Anda mengedit jawaban Anda. Saya menganggap ini sebagai bug . (CC @JonathanAllan)
Dennis

Ahh, itu salah satunya.
Jonathan Allan

9

Python 2 , 66 62 byte

f=lambda n,k=0,*r:n-sum(r)and f(n,k+1,*range(k%n|1,k/n,2))or r

Keluar dengan RuntimeError (kedalaman rekursi maksimum terlampaui) jika tidak ada solusi.

Cobalah online!


1
Jika nilai input cukup tinggi, tetapi ada solusinya, apakah ini akan menghasilkan RuntimeError ?
Okx

Jika batas rekursi tidak cukup tinggi dan / atau tumpukan tidak cukup besar, ya. Namun, itu biasa untuk mengabaikan keterbatasan fisik (misalnya, jawaban C hanya harus bekerja untuk int 32-bit), dan OP secara eksplisit mengatakan bahwa menjalankan selamanya dapat diterima jika tidak ada solusi.
Dennis

9

Jelly ,  11  10 byte

-1 byte terima kasih kepada Dennis (gunakan pengembangan rentang implisit - ganti Rm2Ẇdengan ẆḤ’)

ẆḤ’S_¥Ðḟ⁸Ṫ

Tautan monadik yang mengembalikan daftar puncak jika mungkin, atau 0jika tidak.

Cobalah online!

Bagaimana?

ẆḤ’S_¥Ðḟ⁸Ṫ - Link: number, n
Ẇ          - all sublists (implicit range of input) note: ordered by increasing length
           -                i.e. [[1], [2], [3], ..., [1,2], [2,3], ..., [1,2,3], ...]]
 Ḥ         - double              [[2], [4], [6], ..., [2,4], [4,6], ..., [2,4,6], ...]]
  ’        - decrement           [[1], [3], [5], ..., [1,3], [3,5], ..., [1,2,5], ...]]
        ⁸  - link's left argument, n
      Ðḟ   - filter out items for which the following yields a truthy value:
     ¥     -   last two links as a dyad:
   S       -     sum
    _      -     subtract the right from the left = sum - n
         Ṫ - tail (last and hence longest such run)

1
ẆḤ’menghemat satu byte.
Dennis

8

JavaScript (ES7), 87 86 85 81 byte

Mengembalikan daftar bilangan bulat yang dipisah koma, atau 0jika tidak ada solusi.

n=>(g=(s,k,x=n+s)=>(x**.5|0)**2-x?k>n?0:g(s+k,k+2):(n-=k)?k+','+g(-n,k+2):k)(0,1)

Bagaimana?

Kami melihat pertama untuk sempurna persegi terkecil s sehingga x = n + s persegi lain sempurna.

Jika s ada, n adalah selisih x - s dari 2 kuadrat sempurna, yang dapat ditulis sebagai selisih 2 urutan bilangan ganjil berturut-turut. Kami kemudian membangun daftar yang dihasilkan.

Contoh:

Untuk n = 104 :

Kami menemukan s = 11² = 121 yang memenuhi x = n + s = 225 = 15²

Kemudian:

15² = 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21 + 23 + 25 + 27
11² = 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21
104 = 15² - 11² = 23 + 25 + 27 + 29


3
Tunggu, apakah Anda memberi tahu saya bahwa n^2itu selalu sama dengan jumlah nangka ganjil pertama ? Huh, menarik
Skidsdev

2
@ Mayube Memang !
Arnauld


7

05AB1E , 9 8 byte

-1 byte terima kasih kepada Emigna

ÅÉŒʒOQ}н

Penjelasan:

ÅÉ           Generate a list of odd numbers up to, and including, the input
  Œ          Substrings
   ʒ         Only keep values
    O          where the sum
     Q         equals the input
       }     End
             For 9, the result would look like this:
             [[1, 3, 5], [9]]
        н    Get the first value

Pada input yang tidak valid, tidak menghasilkan apa-apa.

Cobalah online!


ʒOQ}bukannya DO¹QÏmenyimpan byte.
Emigna

@JonathanAllan Docs mengatakan "tidak rata" sehingga mungkin telah bingung ...
Erik the Outgolfer

1
@ JonathanAllan Kesalahan kecil. Tetap.
Okx

6

Haskell , 61 60 byte

Terima kasih kepada @maple_shaft untuk mencukur 1 byte

f n=[k|r<-[1,3..],s<-[r,r+2..n],k<-[[r,r+2..s]],sum k==n]!!0

Cobalah online!

Menggunakan fakta bahwa proses terpanjang akan selalu menjadi proses yang dimulai dengan angka terendah.

Saya ingin melakukan sesuatu dengan aritmatika sebagai pengganti kekerasan k, tetapi fromIntegertampaknya membunuhnya.


Anda dapat menghemat satu byte dengan mengubah [1,3..n]ke[1,3..]
maple_shaft

1
Anda dapat menyimpan 7 byte dengan fungsi pembantu r?n=[r,r+2..n]. Cobalah online!
Ørjan Johansen

4

Python , 67 byte

f=lambda n,R=[1]:n-sum(R)and f(n,[R+[R[-1]+2],R[1:]][sum(R)>n])or R

Cobalah online!

Saya menyalin jawaban saya dari tantangan jumlah berturut-turut sebelumnya dan mengubah +1ke +2. Siapa yang tahu bahwa kode golf bisa sangat modular?

Strategi aneh langsung: mencari interval Rdengan jumlah yang diinginkan.

  • Jika jumlahnya terlalu kecil, geser titik akhir kanan dari interval ke atas 2 dengan menambahkan angka 2 berikutnya di atasnya.
  • Jika jumlahnya terlalu besar, geser ke atas titik akhir kiri dengan menghapus elemen terkecil
  • Jika jumlahnya benar, hasilkan R.

Karena ujung bawah interval hanya meningkat, interval yang lebih lama ditemukan sebelum yang lebih pendek. Jika tidak ada interval yang mungkin dapat ditemukan, akhiri dengan IndexError.


4

JavaScript (ES6), 65 64 byte

f=(a,i=1)=>a>i?(c=f(a-i,i+=2))[0]==i?[i-2,...c]:f(a,i):a<i?0:[i]

Mengembalikan array jika ada solusi, atau 0 tanpa solusi.

Ini adalah solusi yang sangat tidak efisien namun golf untuk masalah ini.

Ini mencari solusi pertama menggunakan a-idan i=1, bahkan jika itu tidak berhasil menumpuk stack rekursif. Jika solusi itu tidak dimulai dengan i+2, maka kami secara rekursif mencari solusi pertama menggunakan adan i+2.

Tidak disatukan

f=(a,i=1)=>
  a > i ? 
    (c = f(a - i, i += 2))[0] == i ? 
      [i-2, ...c] : 
      f(a, i) :
  a < i ? 
    0 :
    [i]

Kasus uji:

Untuk gagasan tentang betapa tidak efisiennya ini, solusi untuk f(104)meminta 69.535 panggilan rekursif. Tumpukan tidak pernah lebih dari 51 level, jadi tidak ada masalah dengan stack overflow.

Solusi untuk f(200)membutuhkan 8,6 juta panggilan rekursif, dengan kedalaman 99 level. (Solusinya adalah [11,13,15,17,19,21,23,25,27,29].)

Berikut ini adalah representasi visual dari program yang sedang berjalan:


3

Python 2.7, 109 108 97 byte

11 byte ke bawah, Terima kasih kepada Erik the Outgolfer.

Ini golf kode pertamaku!

def f(N):
 for n in range(N):
    x=(n*n+N)**.5-n
    if x%1==0:return[2*(k+n)+1for k in range(int(x))]

Bagaimana itu bekerja

Saya menggunakan identitas yang terkenal itu 1 + 3 + 5 + ... + (2n - 1) = n²

Ambil kasusnya 15

15 = 3 + 5 + 7 = (1 + 2) + (3 + 2) + (5 + 2) = (1 + 3 + 5) + 3×2 = 3² + 3×2

Secara umum, jika ada x istilah mulai dari 2n + 1, suka

(2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))


Itu sama dengan 2nx + x²

Jika Nbilangan bulat input, masalahnya berkurang hingga menemukan maksimum xsehingga

x² + 2nx - N = 0

Ini adalah persamaan kuadratik dengan solusi

x = sqrt(n² + N) - n

Urutan terpanjang adalah urutan yang terbesar x. Program iterates ndari 0ke Ndan ketika menemukan itu xadalah bilangan bulat, itu membuat daftar (2n + 1) + (2n + 3) + (2n + 5) ... (2n + (2x-1))dan mengembalikannya.



@EriktheOutgolfer, Terima kasih, saya lupa menggunakan tab (=
dark32

3

Python 3, 190 81 Bytes

def c(q,l,i):
    if sum(l)0:
        l.append(i)
        return c(q,l,i+2)
    elif sum(l)>q:
        l.pop(0)
        return c(q,l,i)
    else:
        print(l)
c(q,[1],1)

c=lambda q,l=[1]:c(q,l+[l[-1]+2])if(sum(l)<q)*l else c(q,l[1:])if sum(l)>q else l

Terima kasih kepada @ovs dan @ musicman523


4
Anda bisa mendapatkan ini hingga 122 byte hanya dengan menghapus beberapa lekukan . Jika Anda ingin mempersingkat kode Anda lebih lanjut, lihat Tips untuk bermain golf dengan Python .
Ovs

3
Ini tidak berjalan di Python 3, karena panggilan ke printtanda kurung hilang
musicman523

2
Anda dapat menghapus l.append(i)dengan hanya menggunakan l+[i]dalam panggilan rekursif. Anda dapat menghapus l.pop(0)dengan menggunakan l[1:]dalam panggilan rekursif. Anda dapat menghapus panggilan ke cbagian paling bawah dengan menggunakan argumen kata kunci. Anda dapat menghapus >0pada baris 2. Akhirnya, Anda dapat mengubah ifdan elsepernyataan Anda menjadi ekspresi, menggunakan formulir ternary, yang membuat Anda turun ke 92 byte sebagai ekspresi lambda. Cobalah online!
musicman523

1
Berdasarkan pada saran @ musicman523 kami masih dapat mempersingkat kondisi dan menurunkan ihingga total 81 byte .
Ovs

Saya pikir Anda bisa mengubah sum(l)>q elseuntuk q<sum(l)elsemenyimpan 1 byte.
Zacharý

2

QBIC , 47 byte

{_Cg=q┘q=q+2~g>:|_Xp\?g,[q,a,2|?b,┘g=g+b~g=a|_X

Ini mencoba menghitung semua angka ganjil dari satu sampai jumlahnya n. Jika berhasil n, setel ulang loop, naikkan 1 ke 3 dan coba lagi. Berhenti, cetak 0, jika pada awal perulangan nomor kita > n.

Penjelasan

{       Do infinitely
_C      Clear the screen (we basically print every run of odd numbers, but clear out everything that doesn't sum up to n)
g=q     Set g to the first num of this cycle (q starts as 1 in QBIC)    
┘       (Syntatcic linebreak)
q=q+2   Raise q to the next odd number, this sets up both the next outer loop as well as a coming FOR loop
~g>:|   If we start out with a number > n (read as 'a' from the cmd line)
_Xp     THEN quit, printing 0 (the value of the number var 'p')
\       ELSE
[q,a,2| FOR b = q, b <= n, b+=2
?b,┘    PRINT b followed by a tab
g=g+b   Add 'b' to running total 'g'
~g=a|   and if that lands us on 'n'
_X      QUIT (printing nothing: everything is already printed)

1

R , 90 byte

f=function(x,y=1)'if'(length(w<-which(cumsum(r<-y:x*2-1)==x)),r[1:w],'if'(y>x,0,f(x,y+1)))

Cobalah online!

Menggunakan fungsi rekursif yang menguji jumlah kumulatif urutan y: x yang dikonversi ke urutan bilangan ganjil. y bertambah pada setiap rekursi hingga melebihi x. Urutan pertama yang menjumlahkan target akan dikembalikan.


1

Python 2 , 89 byte

lambda n,r=range:[v for v in[r(1,n+1,2)[i:j]for i in r(n)for j in r(n+1)]if sum(v)==n][0]

Fungsi tanpa nama mengambil bilangan bulat positif n,, dan mengembalikan hasilnya jika ada dan menaikkan yang IndexErrorsebaliknya.

Cobalah online!

Membuat daftar semua angka ganjil yang relevan dengan r(1,n+1,2)itu range(start=1, stop=n+1, step=2); membuat semua sub-irisan yang relevan (ditambah beberapa yang kosong) dengan mengirisnya dari iinklusif menjadi jeksklusif dengan [i:j]di idalam [0, n) menggunakan r(n)dan jdalam [0, n] menggunakan r(n+1)(yang kosong ketika i>=jatau di iluar batas); filter untuk mereka dengan jumlah yang benar dengan if sum(v)==n; mengembalikan irisan pertama (dan karenanya terpanjang) menggunakan [0].


1

Python 2 , 91 90 byte

-1 byte terima kasih kepada @CMcAvoy

lambda n,r=range:[r(i,j+1,2)for i in r(1,n+1,2)for j in r(i,n+1,2)if(i+j)*(2+j-i)==4*n][0]

Cobalah online!



1

PHP , 73 byte

tidak ada solusi yang merupakan infinite loop

for($e=-1;$s-$i=$argn;)$s+=$s<$i?$n[]=$e+=2:-array_shift($n);print_r($n);

Cobalah online!

PHP , 83 byte

tidak mencetak apapun tanpa solusi

setiap input mod 4 == 2 tidak memiliki solusi

for($e=-1;($i=$argn)%4-2&&$s-$i;)$s+=$s<$i?$n[]=$e+=2:-array_shift($n);print_r($n);

Cobalah online!


gagal mendeteksi input yang tidak dapat dipecahkan
Titus

@Titus diperbaiki ...
Jörg Hülsermann


0

Python 3 , 93 byte

lambda n,r=range:[[*r(s,e+1,2)]for s in r(1,n+1,2)for e in r(s,n+1,2)if(s+e)*(2+e-s)==4*n][0]

Cobalah online!

Satu-satunya hal khusus yang saya lakukan adalah mencatat bahwa (s+e)*(2+e-s)==4*nitu setara dengan sum(range(s,e+1,2))==n, dan meskipun ukurannya sama ketika r=range, yang pertama dapat ditempatkan lebih dekat dengan ifpernyataan.


0

Python 3 , 185 byte

def f(s):
  d={k:v for k,v in{a:(1-a+((a-1)**2+4*s)**(.5))/2 for a in range(1,s,2)}.items()if int(v)==v};m=max(d.keys(), key=(lambda k: d[k]));return list(range(int(m),int(m+2*d[m]),2))

Cobalah online!


Adapun cara kerjanya, saya mencoba mencari solusi yang sedikit lebih elegan daripada pencarian brute force sederhana. Saya mengatur ulang rumus untuk jumlah urutan aritmatika dan menerapkan rumus kuadratik untuk mendapatkan ekspresi (1-a+((a-1)**2+4*s)**(.5))/2, yang muncul dalam kode. Apa ekspresi menghitung, diberikan jumlah yang diinginkan sdan istilah pertama untuk urutan aritmatika a, panjang urutan. Panjang ini disimpan dalam kamus sebagai nilai untuk istilah pertama sebagai kunci.

Selanjutnya, semua nilai non-integer dihapus dari kamus, karena itu mewakili urutan yang tidak valid. Dari sana, nilai terbesar diidentifikasi dengan max(d.keys(), key=(lambda k: d[k]))dan urutan bilangan ganjil pada posisi itu dan pada panjang itu dibuat dengan list(range(int(m),int(m+2*d[m]),2)).


Saya mencari bantuan untuk bermain golf jika Anda melihat sesuatu. Saya lebih tertarik melihat seberapa baik yang bisa saya lakukan dengan algoritma non-sepele; jawaban saya hampir dua kali lipat dari solusi Python terbaik.


Apakah ini akan berhasil? repl.it/JTt7 (177 byte)
Zacharý

0

Mathematica, 56 byte

Last@Cases[Subsequences@Table[n,{n,1,#,2}],x_/;Tr@x==#]&

Functiondengan argumen pertama #. Table[n,{n,1,#,2}]menghitung daftar angka ganjil positif kurang dari atau sama dengan #. Subsequencesmengembalikan semua urutan daftar yang dipesan dengan menambah panjang. Kami kemudian mengambil pasangan Casesyang cocok x_/;Tr@x==#, yaitu urutan xsedemikian sehingga jumlah mereka Tr@xsama dengan input #. Kami kemudian mengambil Lasturutan seperti itu.


0

JavaScript (ES6), 72 byte

n=>(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?l+' '+g(s,l+=2):u)(n-1,l=u=1)

Mengembalikan string angka ganjil yang dipisah-ruang atau melempar pada input yang tidak valid. Versi 84 byte yang mengembalikan array (kosong saat yang sesuai):

n=>n%4-2?(g=s=>s?s>0?g(s-(u+=2)):g(s+l,l+=2):u-l?[l,...g(s,l+=2)]:[u])(n-1,l=u=1):[]

Penjelasan: Secara longgar didasarkan pada solusi awk @ Cabbie407 untuk Sums of Consecutive Integers kecuali saya dapat menyimpan beberapa byte dengan menggunakan rekursi.


0

PHP, 78 byte

for($b=-1;$s-$argn;)for($n=[$s=$x=$b+=2];$s<$argn;)$s+=$n[]=$x+=2;print_r($n);

infinite loop jika tidak ada solusi. masukkan ?$b>$argn+2?$n=[]:1:0setelahnya $s-$argnuntuk mencetak array kosong saja.

Jalankan dengan -nRatau coba online .


0

C # (.NET Core) , 129 byte

(i)=>{int s,j,b=1,e=3;for(;;){var o="";s=0;for(j=b;j<e;j+=2){s+=j;o+=j+" ";}if(s==i)return o;s=s<i?e+=2:b+=2;if(b==e)return"";}};

Menghasilkan angka dalam string, dibatasi ruang (karakter lain apa pun hanya perlu mengubah " "). Input tanpa solusi mengembalikan string kosong (meskipun jika berjalan selamanya tanpa kesalahan adalah cara yang valid untuk menunjukkan tidak ada solusi, maka 17 byte dapat disimpan dengan menghapus if(b==e)return"";).

Algoritma adalah:

  1. Mulai dengan [1]
  2. Jika jumlahnya sama dengan target, kembalikan daftar
  3. Jika jumlahnya kurang dari target, tambahkan angka ganjil berikutnya
  4. Jika jumlahnya lebih besar dari target, hapus item pertama
  5. Jika daftar itu kosong, kembalikan
  6. Ulangi dari 2

Anda dapat menulis (i)=>sebagaii=>
aloisdg kata Reinstate Monica

0

C ++, 157 -> 147 Bytes


-10 Bytes berkat DJMcMayhem

akan mengembalikan 0 jika tidak ada jawaban, 1 sebaliknya

baris terakhir yang dicetak adalah jawabannya

int f(int n){for(int i=1;;i+=2){int v=0;for(int k=i;;k+=2){v+=k;std::cout<<k<<" ";if(v==n)return 1;if(v>n)break;}if(i>n)return 0;std::cout<<"\n";}}

ungolfed:

int f(int n)
{
    for (int i = 1;; i += 2)
    {
        int v = 0;
        for (int k = i;; k += 2)
        {
            v += k;
            std::cout << k << " ";
            if (v == n)
                return 1;
            if (v > n)
                break;

        }
        if (i > n)
            return 0;
        std::cout << "\n";
    }
}

ini adalah kode golf pertama saya ^^


Anda dapat menyimpan beberapa byte jika Anda menjadikannya fungsi int dan mengembalikan 0 atau 1. Selain itu, Anda dapat melakukan int v=0;alih - alih int v;....v=0;dan jika Anda membuat output Newline Anda dibatasi, Anda dapat melakukan std::cout<<k<<"\n";dan kemudian menghapus Newline kedua sekaligus
DJMcMayhem

jika saya melakukan rekomendasi terakhir maka akan mencetak baris baru pada setiap nomor tetapi saya ingin memisahkan kelompok angka, tetapi terima kasih lagi untuk -10 Bytes
SeeSoftware

0

Kotlin, 152 byte

fun f(a:Double){var n=Math.sqrt(a).toInt()+1;var x=0;while(n-->0){if(((a/n)-n)%2==0.0){x=((a/n)-n).toInt()+1;while(n-->0){println(x.toString());x+=2}}}}

Cobalah online (Tunggu 4-5 detik, kompiler lambat)

Tidak disatukan

fun f(a: Double){
    var n=Math.sqrt(a).toInt()+1;
    var x=0;

    while(n-->0){
        if(((a/n)-n)%2==0.0){
            x=((a/n)-n).toInt()+1;

            while(n-->0){
                println(x.toString());
                x+=2;
            }

        }
    }
}

0

Excel VBA, 139 Bytes

Subrutin yang mengambil input ndari integer tipe yang diharapkan dan melaporkan urutan terpanjang dari angka ganjil berturut-turut ke sel[A1]

Sub a(n)
For i=1To n Step 2
s=0
For j=i To n Step 2
s=s+j
If s=n Then:For k=i To j-1 Step 2:r=r &k &"+":Next:[A1]=r &j:End
Next j,i
End Sub
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.