Bagaimana cara menemukan elemen dari urutan Digit Sum secara efisien?

20

Hanya karena ketertarikan saya mencoba memecahkan masalah dari kategori "Baru-baru ini" dari Project Euler ( urutan Digit Sum ). Tetapi saya tidak dapat memikirkan cara untuk menyelesaikan masalah secara efisien. Masalahnya adalah sebagai berikut (dalam urutan pertanyaan asli memiliki dua yang di awal, tetapi tidak mengubah urutan):

Urutan Digit Sum adalah 1,2,4,8,16,23,28,38,49 .... di mana istilah adalah jumlah digit sebelum itu dalam urutan. Temukan istilah urutan. 10 15 t hnth1015th

Solusi naif tidak dapat diimplementasikan karena membutuhkan banyak waktu. Saya mencoba untuk mengurangi masalah untuk kasus matriks eksponensial (yang akan memakan waktu jumlah waktu) tetapi tidak dapat datang dengan perulangan seperti itu pas kriteria linier sebagai perulangan untuk urutan ini adalah cukup aneh. Dapat dilihat bahwa urutannya diatur oleh perulangan:O(log(1015))

an=an1+d(an1).....(1)

di mana adalah istilah dari urutan dan adalah fungsi yang ketika diberi nomor alami sebagai input mengembalikan jumlah digit nomor (mis. ). Pendekatan kedua saya adalah mencoba menemukan beberapa pola dalam urutan. Dapat dilihat bahwa beberapa istilah pertama dari urutan dapat ditulis sebagaiannthdd(786)=21

   a_1 = 1  
   a_2 = 1 + d( 1 )
   a_3 = 1 + d( 1 ) + d( 1 + d( 1 ) )
   a_4 = 1 + d( 1 ) + d( 1 + d( 1 ) ) + d( 1 + d( 1 ) + d( 1 + d( 1 ) ) )
   a_5 = 1 + d( 1 ) + d( 1 + d( 1 ) ) + d( 1 + d( 1 ) + d( 1 + d( 1 ) ) ) + d( 1 +  d(  
   1 ) + d( 1 + d( 1 ) ) + d( 1 + d( 1 ) + d( 1 + d( 1 ) ) ) )

Dari pola di atas, istilah urutan dapat dihasilkan dengan metode berikut:nth

  1. Tulis dengan simbol tambahan di antara mereka.2n1 1
  2. Meninggalkan pertama , lalu menerapkan fungsi pada istilah berikutnya lalu pada istilah berikutnya, lalu pada istilah berikutnya dan seterusnya.1d202122
  3. Kemudian menerapkan metode di atas secara rekursif pada argumen masing-masing fungsi diterapkan.d

misalnya jika n = 3 kami melakukan manipulasi berikut:

    1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
    1 + d( 1 ) + d( 1 + 1 ) + d( 1 + 1 + 1 + 1 )
    1 + d( 1 ) + d( 1 + d(1) ) + d( 1 + d( 1 ) + d( 1 +d( 1 ) ) )

Dengan pemrograman dinamis saya dapat menghasilkan istilah menggunakan metode di atas dalam waktu , yang lagi-lagi tidak lebih baik daripada solusi naif. O ( l o g ( 2 10 15 ) )nthO(log(21015))

EDIT 1
Hal lain yang dapat diamati adalah bahwa . Misalnya . Tetapi saya tidak dapat menggunakan poin ini. Saya kembali mencoba menemukan hubungan perulangan linear (untuk matriks eksponensial), tetapi saya tidak dapat menemukannya.d ( a 6 ) = d ( 23 ) = d ( 32 ) = 5d(an)=d(2n1)d(a6)=d(23)=d(32)=5

EDIT 2

Berikut ini adalah grafik ketika urutan diplot untuk rentang yang lebih kecil ( istilah urutan pertama diplot). 106masukkan deskripsi gambar di sini

PS: Saya tahu tidak disarankan untuk meminta solusi dari Project Euler. Tapi saya hanya ingin arah atau petunjuk baru, karena saya telah bergerak berputar-putar selama beberapa hari terakhir. Jika itu juga tidak dapat diterima, saya dapat menghapus pertanyaan jika disarankan.

sashas
sumber
1
Saya merasa seperti You are given a106 = 31054319.dalam masalah Euler asli adalah petunjuk.
Filip Haglund
@FilipHaglund itu bukan petunjuk. Seperti dengan kekerasan saja saya dapat menghitung nilai itu dengan mudah. Ini hanya untuk memeriksa pendekatan Anda.
sashas
3
Juga di OEIS: oeis.org/A004207 .
Yuval Filmus
@ EvilJS ya bisa saya merencanakan grafik untuk memperpanjang itu meningkat secara bertahap dalam mode zig zag. Bisakah Anda menguraikan titik terakhir Anda "" pola caching .. ".
sashas
Mengingat bahwa pola yang menarik muncul pada mod 9, apakah sesuatu yang menarik terjadi jika kita melihat urutan mod 11 atau mod 99? Nilai mod 11 dapat diturunkan dari jumlah digit indeks ganjil dan jumlah angka indeks genap. Nilai mod 99 dapat diturunkan dari jumlah dari pasangan-pasangan yang berdekatan.
DW

Jawaban:

4

Urutan Anda dijelaskan dalam oeis.org/A004207 sebagai jumlah digit. Ada beberapa poin bagus seperti urutan mod 9 memiliki pola berulang , ia berbagi akar digital dengan oeis.org/A065075 dan oeis.org/A001370 . Jika sifat-sifat itu berguna adalah masalah terbuka (karena tidak ada persamaan bentuk tertutup untuk nomor ). n - t h(1,2,4,8,7,5)nth

Ada beberapa properti dari urutan ini yang perlu disebutkan:
Ketika Anda menghitung angka , Anda hanya perlu menyimpan penghitung (untuk mengetahui angka itu) dan nomor itu sendiri. Untuk me-restart tidak ada lagi yang diperlukan, karena angka berikutnya adalah angka saat ini + jumlah digitnya.nth

Mengambil beberapa langkah untuk memastikan kecepatan pada awalnya itu baik untuk memasukkan angka ke dalam array, menghindari perhitungan mod dan div naif, yang mahal. Ini memberikan percepatan dengan konstan, tetapi melihat waktu itu penting.

Dari titik awal Anda dapat menghitung yang berikutnya, dan berikutnya, dan berfungsi sampai beberapa titik, titik ini adalah jumlah digit yang berubah.
Yang lebih penting, pola berubah dengan meningkatnya jumlah.
Jumlah digit kecil dibandingkan dengan angka itu sendiri, sehingga hanya bagian dari angka yang akan berubah pada sebagian besar operasi.
Jadi apa yang bisa kita cache?

Kita tahu bahwa dengan dua angka dengan jumlah digit yang sama penambahan untuk mendapatkan nomor berikutnya akan sama. Bagaimana dengan yang berikutnya?

sasha

Peringatan spoiler, di bawah ini adalah pola cache yang cukup eksplisit

Itu tergantung pada kondisi tambahan, seperti angka yang tidak berubah dalam menjalankan , saya akan menyebutnya bergeser , jumlah awal sebagai awal .

Mengambil beberapa langkah sewenang - wenang , seperti , dan mulai dari hingga kita dapat men-cache setiap pola dari titik awal hingga , menghitung jumlah elemen (untuk mengetahui cara menangani penghitung, yang diperlukan untuk memberikan angka ), dan hafalkan. 0 9 100 n - t h10009100nth

Baik. Sampai sekarang setiap permulaan dibahas, apa perubahan di atas ? Sayangnya, pola ini berhenti bekerja, karena jika Anda mencoba dari membuat mulai sama dengan , angka berikutnya dihitung dengan sempurna, tetapi yang kedua rusak. 100 1100
1001

Di sini kita harus membahas shift yang diatur ke dan mulai diatur ke . Ini juga berarti menghitung tabel untuk shift yang berbeda . 010

Apakah kita benar-benar perlu menghitung semuanya ? Tidak juga, tidak.
Bagian dari tabel hanyalah satu lagi item awal.
Misalnya mulai dari memberi urutan yang sama bergeser. Jadi apakah kita perlu menghitung cache yang lebih lama? Tidak, kami menghitungnya sampai dengan pergeseran perubahan untuk menjemput lain run , sehingga akan menghemat banyak memori. 1,2,4,8

Sekarang ketika tabel dicakup, kita mulai dari pengaturan awal, memilih jumlah dari tabel, menambah penghitung dan melihat bahwa: dari kita mencapai , memperbarui variabel dan melompat ke , mengulangi langkah-langkah -> -> -> -> -> -> -> . Baik. Apa sekarang? 101 218 305 406 517 607 719 805 904 100311012183054065176077198059041003

Kami dapat melanjutkan sampai pergeseran lebih tinggi dari yang dihitung.
Lebih jauh kita bisa membangun lebih banyak berjalan dengan cepat, menghitung ulang berlari lebih besar, atau mengamati pola lain (seperti kita dapat secara parsial menggunakan kembali tabel yang sudah dihitung).
Lihatlah berbeda pergeseran seperti mereka semua memberikan yang sama run menjadi lingkungan yang sama untuk jumlah digit, maka kita dapat menggunakan tabel yang sama. Membuat tabel yang lebih besar dari elemen mempercepat proses lebih lanjut, membuat lompatan yang lebih besar sekaligus.100100,1000,10000,100000,1000000...
100

Jahat
sumber
4

Karena Anda meminta "arah atau petunjuk baru" dan saya tidak tahu jawabannya, saya akan meninggalkan ini di sini, saya harap ini membantu. beberapa ide:

Masuk akal akan ada pola mod 9, karena

k>1,kZ10k1mod9

Yang bisa Anda buktikan dengan induksi.

Ini berarti bahwa semua angka kongruen dengan jumlah digit mereka mod 9.

Selanjutnya, an=d(an)mod9

an=an1+d(an1)=2d(an1)mod9

Jika kita terus memperluas pengulangan ini kita dapatkan

an=2nmod9

Yang menjelaskan pola mod 9.

Itu juga membuat kita . Setiap iterasi kita mendapatkan celah yang dapat dibagi 9. Berapa lebar celah itu?an=9k+2n

Berikut ini beberapa kode kurang umum:

import matplotlib.pyplot as plt
import numpy as np

#sum digits of n
def sum_digits(n):
    s = 0
    while n:
        s += n % 10
        n //= 10
    return s

#get the sequence to n digits
def calculate(n):
    retval = [1]
    for i in range(n):
        retval.append(retval[-1] + sum_digits(retval[-1]))
    return retval;

#empirically confirm that a_n = 2^n mod 9
def confirmPow2(a):
    count = 0
    for i in a[:10000]:
        if((i%9) != (2**count % 9)):
            print "false"
        count = count + 1

#find gaps divisible by 9 in a subset of a
def find9Gaps(a):
    count = 0
    S = []
    for i in a[:10000]:
         S.append(((2**count ) - i)/9)
         count = count + 1
    return S

#repeatedly sum the digits until they're less than 9...
#gives some interesting patterns
def repeatedDigitSum():
    for i in range(1000, 1100):
         print "=========for ",i
         while i > 9:
                 i = sum_digits(i)
                 print i 


a = calculate(10**6)
b = find9Gaps(a)
plt.plot(range(len(b[:100])), b[:100])
plt.show()

Plot (untuk 100 pertama) terlihat eksponensial, tapi saya pikir itu tidak sempurna.

plot untuk celah

Inilah output dari

>>> plt.plot(range(len(b[5:60])), np.log2(np.array(b[5:60])))
>>> plt.show()

plot logaritmik dari kesenjangan

Hal terakhir yang saya miliki adalah tampaknya jika Anda menjumlahkan angka-angka dari suatu angka, dan kemudian menjumlahkan angka-angka dari angka yang dihasilkan, dan mengulanginya, Anda akhirnya mendapatkan angka itu mod 9.

Masuk akal mengingat fakta di atas tentang kekuatan 10 mod 9.

nd(n)d(d(n))mod9

Ini memberikan urutan angka yang menarik.

Sunting: Rupanya ini disebut "root digital".

quietContest
sumber
1
Itu agak berkomentar setidaknya tiga kali. Juga ketika Anda melakukan plot yang terlihat eksponensial untuk Anda, mungkin Anda harus menggunakan logaritma, informasikan tentang itu pada sumbu skala? Jika Anda merencanakan istilah 10 ^ 16 yang dapat dibaca, saya akan sangat terkesan.
Evil
Apa yang dikomentari 3 kali? Orang-orang mengatakan ada "pola mod 9" tapi saya merasa tidak jelas apa itu. Saya hanya melakukan penjelajahan dan mengomentari apa yang saya miliki, karena saya pikir saya tidak akan dapat terus mengerjakan ini. Sekali lagi, saya tidak punya solusi, tetapi pertanyaannya tidak menanyakannya.
quietContest
Menambahkan plot log per saran EvilJS, tidak dapat merencanakan yang lebih besar karena istirahat numpy dan saya benar-benar tidak punya waktu untuk terus mengejar masalah ini
quietContest