Bir listedeki sayılar içerisinden rakamları aynı sayıları nasıl ayırırız/süzeriz? (Örn. resimdeki gibi…)
Bir sayının normal okunuşunun, o sayının tersten okunuşuyla aynı olmasının sayıyı polindromik yaptığını fark ettim ve böyle bir yöntem izledim:
all_nums = [1331, 6623, 515, 235, 651, 38601, 9229, 333, 167, 9, 11]
polindromic_nums = []
for i in all_nums:
num = str(i)
if num == num[::-1]:
polindromic_nums.append(i)
print(polindromic_nums)
Teşekkürler. Fakat ben Palindrom sayıları listelemek değil, Palindrom sayı listesi içerisinde bulunan ve rakamları aynı olan sayıları (111, 222, 333, 5555, 6666, 777777 vb) ayırmak istiyorum.
Evet, bunun için ne denediniz? Bir de Python dili ile mi yazıyorsunuz?
Evet, Python dili ile yazıyorum. Kırmızı daireye aldığım kısmı denedim. Sayının ilk basamağındaki rakam ile basamak sayısını çarpıp rakamlar toplamına eşitledim (Örneğin 222 sayısının ilk rakamı 2*3=6 ile 2+2+2), eğer bunlar eşitse tüm rakamları aynıdır diye düşündüm. Bu yöntem 2 ve 3 basamaklı sayılarda işe yaradı fakat 4 basamaklı sayılarda patladı.
Probleminiz için bir fonksiyon tasarladım. Listeyi parametre olarak fonksiyona verirseniz size istedğiniz değerleri döndürecektir.
"""
Fonksiyon parametre olarak içine liste, demet ya da küme alır.
Rakamları aynı olan sayıları tespit eder ve bunu
bir kümenin içine aktarıp geri döndürür.
"""
def same_numbers(numbers):
same_numbers = set()
for i in numbers:
str_i = str(i)
counter = 0
for j in range(len(str_i)):
if j+1 == len(str_i):
if counter == len(str_i)-1:
same_numbers.add(i)
break
else:
break
if str_i[j] == str_i[j+1]:
counter += 1
return same_numbers
Teşekkürler. Resim olduğu için direkt kopyalayıp çalıştıramadım ama 4444 için de çalışıyor gibi. Siz denediğinizde ne oldu 4 basamaklılar için?
O halde siz “repdigit” sayıları ayrıştırmak istiyorsunuz. Ben bu sayıları ayrıştırmak için şöyle bir şey yaptım:
def areAllElementsSame(iterable):
firstElement = iterable[0]
for i in range(1, len(iterable)):
if iterable[i] != firstElement:
return False
return True
all_nums = [1331, 6623, 515, 235, 651, 38601, 9229, 333, 167, 9, 11, 4444]
repdigit_nums = []
for i in all_nums:
if areAllElementsSame(str(i)):
repdigit_nums.append(i)
print(repdigit_nums)
"""
output: [333, 9, 11, 4444]
"""
Çok teşekkürler. Ben fonksiyon konusuna yeni geçtiğim için fonksiyon oluşturmadan çözümü var mı diye merak edip araştırıyordum. Zahmet edip oluşturduğunuz fonksiyonu kullandığımda, evet 4 basamaklılarda da çalışıyor fakat diğer listeden ayırmamış oluyorum.
4 basamaklı 'Palindrom Sayı’ların listesi:
-
7777 3333 6666 2222 9999 5555 1111 8888 4444
-
1001 1111 1221 1331 1441 1551 1661 1771 1881 1991 2002 2112 2222 2332 2442 2552 2662 2772 2882 2992 3003 3113 3223 3333 3443 3553 3663 3773 3883 3993 4004 4114 4224 4334 4444 4554 4664 4774 4884 4994 5005 5115 5225 5335 5445 5555 5665 5775 5885 5995 6006 6116 6226 6336 6446 6556 6666 6776 6886 6996 7007 7117 7227 7337 7447 7557 7667 7777 7887 7997 8008 8118 8228 8338 8448 8558 8668 8778 8888 8998 9009 9119 9229 9339 9449 9559 9669 9779 9889 9999
Kullanıcının belirlediği basamak sayısına göre Palindrom Sayıların listesini veren programın orjinal hali bu. Bu programı çalıştırıp basamak sayısı girdiğimizde tek liste veriyor. Ben sonucu iki ayrı şekilde çıktı almak istiyorum.
n = int(input("'Palindrom Sayı'sının basamak sayısı?: "))
x = 10 ** (n - 1)
y = 10 ** n
print("\n{} basamaklı 'Palindrom Sayı'ların listesi:".format(n))
for sayi in range(x, y):
sayi = str(sayi)
tersi = sayi[::-1]
if sayi == tersi:
print(sayi, end=" ")
>>>
'Palindrom Sayı’sının basamak sayısı?: 3
3 basamaklı 'Palindrom Sayı’ların listesi:
101 111 121 131 141 151 161 171 181 191 202 212 222 232 242 252 262 272 282 292 303 313 323 333 343 353 363 373 383 393 404 414 424 434 444 454 464 474 484 494 505 515 525 535 545 555 565 575 585 595 606 616 626 636 646 656 666 676 686 696 707 717 727 737 747 757 767 777 787 797 808 818 828 838 848 858 868 878 888 898 909 919 929 939 949 959 969 979 989 999
Aslında yukarıda yazdığınız kod 4 basamaklılar da dahil çalışıyor ama sonrasında false positive’ler başlıyor. Zaten önce sayı tersten de aynı mı diye bakıyorsunuz dolayısıyla 1 basamaklılarda a formunda oluyor sayı ve rakamları toplamı da a oluyor (a = 1*a). 2 basamaklılarda da aa formunda oluyor ve 2a = 2*a’dan kurtarıyor. 3’te aba ve dolayısıyla 2a + b = 3a => a = b. 4’te abba ve 2a + 2b = 4a => a = b. Ama 5 basamakta abdba ve 2a + 2b + d = 5a => 2b + d = 3a oluyor ve 54745 gibi sayılar da sayılıyor.
5+ basamakta da çalışabilen başka bir yöntem bulmak için şu paylaşıma göz atabilirsiniz: https://twitter.com/raymondh/status/1254126501856870400
s[1:] == s[:-1]
min(s) == max(s) # s must be non-empty
g = itertools.groupby(s) next(g, True) and not next(g, False)
all(map(operator.eq, s, itertools.islice(s, 1, None)))
Yukarıdaki bir yanıtta da olan, ilk eleman diğer elemanlarla aynı mı diye bakma yolunu da izleyebilirsiniz:
ilk_rakam, *digerleri = str(sayi)
all(rakam == ilk_rakam for rakam in digerleri)
Burada önce sayıyı ilk rakamı ve diğer rakamları olacak şekilde ikiye ayırıyoruz. Sonrasında diğerlerindeki her rakamın ilkiyle aynı olup olmadığına bakıyoruz.
Aaa ayırmak istediğim sayıların adının “repdigit” sayılar olduğunu bilmiyordum. Bu konuyu bir araştırayım. Hem verdiğiniz bilgi hem oluşturduğunuz fonksiyon için çok teşekkür ederim.
Sizin fonksiyon anladığım kadarıyla karışık sayılar listesi içerisinde repdigit sayıları süzüyor.
Ben, aşağıdaki 3 basamaklılar listesini;
aşağıdaki gibi iki şekilde göstermek istiyorum…
veya, aşağıdaki 4 basamaklılar listesini;
aşağıdaki gibi ikiye ayırmak istiyorum…
#Listedeki rakamları aynı olan sayıları döndürür
def same_numbers(numbers):
same_numbers = set()
for i in numbers:
str_i = str(i)
counter = 0
for j in range(len(str_i)):
if j+1 == len(str_i):
if counter == len(str_i)-1:
same_numbers.add(i)
break
else:
break
if str_i[j] == str_i[j+1]:
counter += 1
return same_numbers
#Bir listenin içinden başka bir listeyi çıkartır ve sonucu döndürür
def list_remove(liste, silinecek):
new_liste = liste
for i in silinecek:
new_liste.remove(i)
return new_liste
# Karışık bir lsite tanımladık
array = [23,34,55,66,77]
#array içindeki rakamları aynı sayıları bulduk ve same_array değişkenine atadık.
same_array = same_numbers(array)
print(same_array)
#array içinde, same_array olan elemanları çıkarttık ve not_same_array değişkenine atadık
not_same_array = list_remove(array, same_array)
print(not_same_array)
İçimden bir ses daha verimli bir yol olduğunu söylüyor ama bir türlü aklıma gelmedi. Kod tam istedğiniz şekilde çalışıyor.
repdigitle pek bir alakası yok aslında. Mesela o fonksiyona argüman olarak bir liste
gönderecek olursanız; eğer bu listenin tüm elementleri aynıysa True
döner, aynı değilse False
Burada da aslında şunu diyorum: Eğer sayının tüm rakamları birbiriyle aynıysa repdigit_nums
listesine i
’yi gönder.
Bu bilgiyi siz de çok kolay bir şekilde edinebilirdiniz. Ben bu şekilde arama yaparak edindim: “What does a number that all of its digits are same called”
Aldığım sonuç da bu şekilde. Biraz aşağıda wikipedia’nın “repdigit” sayılarla ilgili yazdığı bir sayfa görebilirsiniz. Ayrıca “What are the numbers that having same digits” şeklinde de aranabilir, bu biraz daha güçlü sonuç verdi. Daha pek çok arama şekli üretilebilir.
Bilmediğiniz şeye çok yüksek ihtimalle internetten kolayca erişebileceğiniz gerçeğini asla unutmamanızı öneririm.
Gösterdiğiniz yol ve yöntemler için teşekkürler. İçlerinde daha görmediğim bilmediğim fonksiyon ve metotlar olduğu için nasıl uygulayacağımı pek anlamadım doğrusu.
Bahsettiğiniz son yöntem olan; “İlk eleman diğer elemanlarla aynı mı” bakma yolu ilgimi çekti. 2 gündür ben de bu yol üzerinden gidip yöntem geliştirmeye çalıştım ama hep yanlış sonuç çıktı alıyorum.
ilk_rakam, *digerleri = str(sayi)
all(rakam == ilk_rakam for rakam in digerleri)
Bahsettiğiniz bu yöntemi nasıl kullanıyoruz?
Resimdeki gibi girilen bir sayının rakamları birbiriyle aynı diye kontrol etmeye çalıştım fakat hangi sayıyı girersem gireyim hep “True” çıktısı veriyor. Son örnekte “1111” sayısında “False” çıktısı vermesi gerekmiyor muydu? Bi’yeri gözden mi kaçırıyorum acaba?
2 Üstte yazdığım koda bir kaç dakika bakarsanız aslında hiç de 2 gün uğraşılacak bir şey olmayacağını anlarsınız. remove() metodu listeden içeriğine parametre olarak verdiğimiz elemanı siliyor.
print(all(sayi))
dediğiniz için yukarıdaki işlemlerin pek bir değeri kalmıyor ve all(sayi)
'nın sonucu yazdırılıyor (o da tanım gereği tüm string’ler için True’ya tekabül ediyor).
İkinci satırdaki sonucu bir değişkene atayabilirsiniz:
sayi = input("sayı giriniz: ")
ilk_rakam, *digerleri = sayi
rakamlari_ayni_mi = all(rakam == ilk_rakam for rakam in digerleri)
print(rakamlari_ayni_mi)
Eğer all(rakam == ilk_rakam for rakam in digerleri)
kısmını bir değişkene atamazsak Python bunu değerlendirip sonucunu hesaplar ama bir nevi boşa gitmiş olur. Programın bir satırına sadece 41 + 13
yazmak gibi düşünebilirsiniz; x = 41 + 13
deyip onun havada kalmamasını sağlarız yoksa kaydadeğer bir şey yapmamış oluyor.
Aslında onda True diğerlerinde False olması gerekiyor zira tüm rakamları ilk rakamla aynı.
Bu arada fonksiyon kullanmak istemiyorsanız bu tek satırlık çözüm üsttekinden daha uygun olabilir. Bunun yaptığı, stringin 1:
ile elde edilen ilk karakterinden sonraki kısmının, :-1
ile elde edilen son karakterinden önceki kısmıyla aynı olup olmadığına bakmak. Yani "1234"
için "234"
ve "123"
aynı mı diye bakıyor. "44444"
için de "4444"
ile "4444"
aynı mı diye.
Burada string’deki “en küçük” karakter ile “en büyük” karakter aynı mı diye bakılıyor. Eğer tüm elemanlar aynıysa minimum ve maximum da aynı olmalıdır fikriyle. Küçüklük büyüklük asciibetik sıraya göre belirleniyor.
Bu arka arkaya gelen karakterleri grupluyor ve 1 mi yoksa daha fazla mı grup var diye karar veriyor.
Bu s[1:] == s[:-1]
demenin farklı bir hali gibi düşünülebilir. Son ikisi tweet için iyi ama okunabilirliği pek yok bana sorarsanız.
Yine bu yöntemlerin sonucunu da bir değişkene atamak veya if içerisinde direkt kullanmak gerekir:
if sayi[1:] == sayi[:-1]:
print(f"{sayi} sayısının tüm rakamları aynı")
veya
rakamlari_ayni = min(s) == max(s)
if rakamlari_ayni:
print(f"{sayi} sayısının tüm rakamları aynı")
gibi.
(bu aslında sayın Unnick’in benden çok önce paylaştığı şu yanıtında var; ama kodun yanında açıklama veya yorum olmadığı için gözden kaçmış olabilir.)
Aynen hocam, bu yeni haliyle kod tam istediğim gibi çalışıyor. Allah razi olsun, emeğinize sağlık.
same_numbers’ı siz küme yapmışsınız, ilk sonucu karışık sırayla çıktı veriyordu.
Ben bu kısmı liste olarak değiştirdim, sırayla veriyor. Tekrar çok sağolun. Kodlarınız hem 4 hem 5 basamaklılarda da doğru sonuç veriyor… Sanırım fonksiyon oluşturmak şart. Eğer aklınıza daha verimli, fonksiyonsuz bir yöntem gelirse çok sevinirim.
Evet hocam şimdi daha iyi anladım. "Mesela o fonksiyona argüman olarak bir liste
gönderecek olursanız; eğer bu listenin tüm elementleri aynıysa True
döner, aynı değilse False
" bu kısmı gözden kaçırmışım, sadece bir listede uygulayınca diğer listede tüm sonuçlar göründü. 3 liste oluşturup True sonucu dönenleri bir listeye, False dönenleri başka listeye atıp ekrana sadece bu iki listeyi yazdırınca tam istediğim sonucu hatasız alabiliyorum. Çok sağolun ilginize ve emeklerinize. Allah razi olsun…