import math class Rnumber: #Klasse, welche rationalen implementiert def __init__(self,num,nom): self.num = num #Zähler der Zahl self.nom = nom #Nenner der Zahl def __eq__(self,other): #prüft Gleichheit return self.nom*other.num == self.num*other.nom #a/b = c/d <=> a*d = b*c def __str__(self): #gibt Zahl als String zurück r ="" r+= str(self.num) + "/"+ str(self.nom) return r def __float__(self): #gibt Zahl als float zurück return self.num/self.nom def getRational(n): #diese Funktion listet rationale Zahlen auf n+=1 temp = math.sqrt(2*n+0.25)-0.5 #Berechnung der Diagonale via Dreieckszahlen t = math.floor(temp) #umstellen von t(t+1)/2 > n if temp-t !=0: #anschließend aufrunden t+=1 r = n-((t*(t-1))//2) #Berechnung der Stelle in Diagonale return Rnumber(t-r+1,r) #Rückgabe der rationalen Zahl def fun(n): #bloß umbenennung der obigen funktion return getRational(n) def phi(n,f): #konstruiert bijektive funktion aus surjektiver (rekursiv) if n==0: #Fall n=0 return f(0) #Rückgabe f(0) l = [phi(x,f) for x in range(n)] #Liste {phi(0),phi(1),..,phi(n-1)} #ACHTUNG: dies sorgt für LANGE Laufzeit, fall n nicht klein, da rekursiv c=0 while f(c) in l: #solange f(c) in obiger Liste enthalten c+=1 #nächste Zahl betrachten return f(c) #erste Zahl NICHT in Liste zurückgeben def phil(n,f): #gibt {phi(0),..,phi(n)} zurück l=[] #leere Liste initialisieren for i in range(n+1): #Laufvariable für gewünschte Eingabewerte c=0 while f(c) in l: #solange f(c) in bisheriger Liste enthalten c+=1 #nächste Zahl betrachten l.append(f(c)) #neuen Wert zu Liste hinzufügen return l #komplette Liste zurückgeben #falls man nur phi(n) haben will, dann phil(n,f)[n] aufrufen # Einige Beispiele #rationale Zahlen auflisten (mit doppelten) print(", ".join([str(fun(n)) for n in range(30)])) #rationale Zahlen auflisten (ohne doppelte) - rekursiv (LANGSAM!!!) print(", ".join([str(phi(n,fun)) for n in range(10)])) #rationale Zahlen auflisten (ohne doppelte) - iterativ print(", ".join(map(str,phil(30,fun))))