Direk örnekten anlatayım 41 = 2 + 3 + 5 + 7 + 11 + 13
41 ardışık 6 tane asalın toplamı şeklinde yazılabiliyor.
üç basamaklı en uzun zincire sahip asal sayı 953 tür ve zincir uzunluğu 21 dir.
Buna göre 1 milyondan küçük en uzun zincire sahip asal hangisidir?
Ben şöyle bir şey düşündüm Fakat sorunum şu benim zincir hep eklemeli devam ediyor ve mesela 953 sayısını bulamıyor.nasıl bir yol izleyebilirim ?
import sympy
sayı=0
sayaç=0
liste=set()
for i in range(3900): #Burada listeyi inceledim 3900 yeterli geldiği için daha ileri gitmedim
if sympy.isprime(i):
sayı+=i
sayaç += 1
if sympy.isprime(sayı):
liste.add((sayı,sayaç))
print(max(sorted(liste)))
Zincirin 2 den mi başlaması gerekiyor?
hayır sıkıntımda o noktada zaten
sıkıntıyı çözdüm ama farklı yollarıda görmek isterim siz nasıl yaklaşıcaksınız acaba
import sympy
asallar=[]
for i in range(5000):
if sympy.isprime(i):
asallar.append(i)
for j in range(len(asallar)):
zincir=asallar[j:]
if sympy.isprime(sum(zincir))==True:
if len(zincir)>540 and sum(zincir)<10**6: # Burada 540 dan büyük almamın sebebi diğer kodla 536 bulmamdır.
print(sum(zincir), len(zincir))
sqlite3 modülü yardımıyla 1 milyona kadar olan asal sayıları barındıran bir veri tabanı oluşturdum. Veritabanı dosyasının adı “AsalSayılar1m.mbe”. Aşağıdaki kodlarlada sonucu buldum.
import numpy as np
import sqlite3
with sqlite3.connect("AsalSayılar1m.mbe") as vt1:
im1 = vt1.cursor()
liste = []
im1.execute("""select * from asal_sayilar""")
while True:
i = im1.fetchone()[0]
if i != 999983:
liste.append(i)
else:
liste.append(i)
break
ndizi = np.array(liste)
def zincirleme_bulucu(dizi,y,zincir):
for x in dizi:
y += x
zincir +=1
if y > 1000000:
break
if y in ndizi:
try:
if z != y:
z = y
istenen_son = z
istenen_zincir = zincir
except NameError:
z=y
liste2.append([istenen_son, istenen_zincir])
del istenen_son
del istenen_zincir
liste2 = []
s = 0
while ndizi[s]!=ndizi[-1]:
zincirleme_bulucu(ndizi[s:],0,0)
s+=1
if liste2[-1][1]<=400:
break
c = 0
for m in liste2:
if c<m[1]:
c=m[1]
for n in liste2:
if c==n[1]:
print("Asal sayı : "+str(int(n[0]))+" Zincir sayısı : "+str(int(n[1])))
break
Kodlar çalıştığında birkaç saniye sonra şu çıktıyı verir.
Asal sayı : 997651 Zincir sayısı : 543
İnşallah doğru bulmuşumdur.
Güzel yapmışsınız ama pek gerekli değil, sympy.sieve nesnesinin extend metodu kullanılabilir:
Bir de böyle basit bir iş için Sqlite kullanmaya gerek yok.
@EkremDincel sympy kütüphanesini bilmiyordum. Yorumunuz için teşekkürler. normal liste ile dahada uzun işlem yaptığı için veritabanı kullanmayı tercih ettim.
Asal jeneratoru:
import sympy
def primes():
n = 1
while True:
yield sympy.prime(n)
n += 1
(sympy’de yok mu?)
Suradaki inits
fonksiyonunun tembel/jenerator versiyonu:
def inits(it):
head = []
while True:
e = next(it)
yield head + [e]
head += [e]
Asal zinciri jeneratoru:
import itertools
def ranges_less_than(gen, sum_):
g1, g2 = itertools.tee(gen)
yield from itertools.takewhile(lambda ps: sum(ps) <= sum_, inits(g1))
try:
n = next(g2)
except StopIteration:
return
if n > sum_:
return
yield from ranges_less_than(g2, sum_)
Toplami asal < 999 olan cok halkali zincirler:
chains = filter(lambda ns_len_sum: ns_len_sum[1] > 1 and sympy.isprime(ns_len_sum[2]), map(lambda ns: (ns, len(ns), sum(ns)), ranges_less_than(primes(), 999)))
En uzun zincir:
print(sorted(chains, key=lambda n_l_s: n_l_s[1], reverse=True)[0])
([7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89], 21, 953)
Challenge:
Toplami sum_
'dan kucuk olan butun gen
zincirlerini ureten yukaridaki ranges_less_than
fonksiyonunun butun gen
zincirlerini ureten versiyonunu yazin.
Generator şeklinde var mı bilmiyorum ama liste olarak elde edebiliyoruz:
Benim oradaki kastım sizin de bir dosyaya yazabileceğinizdi.
Buradaki primerange de aynı işi görürmüş aslında