예제 #1
0
        static public List <Zyklus> TrefferBestimmen(BigInteger n, int[] zahlensysteme)
        {
            List <Zyklus> result = new List <Zyklus>();

            List <MddPaarImZahlensystem> mdPaare = mdPaareBestimmen(n, zahlensysteme);

            // Triviale Lösung wird an anderer Stelle geprüft
            var startwert = Helper.Wurzel(n);

            int maxSequenz = zahlensysteme.Max() * zahlensysteme.Max();

            BigInteger[] arbeitsSequenzM_ = new BigInteger[maxSequenz + 1];
            BigInteger[] arbeitsSequenzDD = new BigInteger[maxSequenz + 1];

            // da der Startwert sonst negativ ist, wenn nicht die Wurzel die Lösung ist
            BigInteger m           = BigInteger.Add(startwert.Item1, 1);
            BigInteger wurzelDelta = BigInteger.Add(BigInteger.Multiply(2, m), 1);

            // Sequenz einmalig berechnen
            arbeitsSequenzM_[0] = m;
            arbeitsSequenzDD[0] = BigInteger.Subtract(BigInteger.Pow(m, 2), n);

            for (int i = 1; i <= maxSequenz; i++)
            {
                arbeitsSequenzM_[i] = BigInteger.Add(arbeitsSequenzM_[i - 1], 1);
                arbeitsSequenzDD[i] = BigInteger.Add(arbeitsSequenzDD[i - 1], wurzelDelta);
                wurzelDelta         = BigInteger.Add(wurzelDelta, 2);
            }

            // Die Zahlen ins entsprechende Zahlensystem umwandeln und "Treffer" merken
            // Es werden nur die Abstände zwischen zwei "Treffern" vermerkt
            //int potenz;
            BigInteger tmpM_;
            BigInteger tmpDD;

            foreach (MddPaarImZahlensystem paar in mdPaare)
            {
                List <long> sequenz = new List <long>();
                //potenz = paar.Zahlensystem * paar.Zahlensystem;
                int zahlensystem = paar.Zahlensystem;

                for (int j = 0; j < zahlensystem; j++)
                {
                    BigInteger.DivRem(arbeitsSequenzM_[j], zahlensystem, out tmpM_);
                    BigInteger.DivRem(arbeitsSequenzDD[j], zahlensystem, out tmpDD);

                    if (paar.MddPaar.Exists(x => ((x.Item1 == tmpM_) && (x.Item2 == tmpDD))))
                    {
                        sequenz.Add(j);
                    }
                }

                Zyklus zyklus = new Zyklus(zahlensystem, sequenz.ToArray <long>());
                Zyklus.ZyklusVerkuerzen(ref zyklus);

                result.Add(zyklus);
            }

            return(result);
        }
예제 #2
0
        static public void ZyklusVerkuerzen(ref Zyklus zyklus)
        {
            // Zyklus mit keinem oder einem Element werden auf sich selbst abgebildet
            if (zyklus.NumberOfElements < 2)
            {
                return;
            }

            // Prüfe, ob sich wiederholende Teilsequenzen finden lassen
            int alteAnzahlDerElemente = zyklus.NumberOfElements;

            // Erste Element
            int  neueAnzahlDerElemente = 1;
            long differenz             = zyklus.Elemente[1] - zyklus.Elemente[0];

            // Sucht ab dem zweiten Element nach einem Element, welches den gleichen Wert wie das Erste hat.
            // -> In dem Fall wird geschaut, ob alle folgenden Elemente gilt: E[i] == E[i+offset]
            for (int i = 2; i < alteAnzahlDerElemente; i++)
            {
                if (zyklus.Elemente[i] != (zyklus.Elemente[i - neueAnzahlDerElemente] + differenz))
                {
                    neueAnzahlDerElemente = i;
                    differenz             = zyklus.Elemente[i] - zyklus.Elemente[0];
                }
            }

            // Letztes Element
            if ((zyklus.Elemente[0] + zyklus.ZyklusSumme) != (zyklus.Elemente[alteAnzahlDerElemente - neueAnzahlDerElemente] + differenz))
            {
                neueAnzahlDerElemente = alteAnzahlDerElemente;
            }

            // Prüfe, ob die Teilsequenzen als n-fache einen echten Zyklus bilden
            if (neueAnzahlDerElemente == alteAnzahlDerElemente)
            {
                return;
            }

            // Zyklus ist keine "sinnvoll teilbare" Teilmenge
            // Bsp: [7 5 8 8 7 5]
            if (alteAnzahlDerElemente % neueAnzahlDerElemente != 0)
            {
                return;
            }

            Console.WriteLine($"Zyklus komprimiert: {zyklus.ZyklusSumme} : {alteAnzahlDerElemente} -> {neueAnzahlDerElemente}");
            Console.WriteLine($"[{string.Join(",", zyklus.Elemente)}]");

            zyklus.Truncate(neueAnzahlDerElemente);
            zyklus.ZyklusSumme = (zyklus.ZyklusSumme * neueAnzahlDerElemente) / alteAnzahlDerElemente;

            return;
        }
예제 #3
0
        static public Zyklus EndgueltigenZyklusBestimmen(BigInteger n, int[] zahlensysteme)
        {
            List <Zyklus> zyklen = TrefferBestimmen(n, zahlensysteme);


            Zyklus endgueltigerZyklus = zyklen[0];

            for (int i = 1; i < zyklen.Count; i++)
            {
                endgueltigerZyklus = Zyklus.VerschmelzeZyklen(zyklen[i], endgueltigerZyklus);
            }

            Console.WriteLine($"Kombiniert: {endgueltigerZyklus.NumberOfElements,3:0} / {endgueltigerZyklus.ZyklusSumme,3:0} = {(endgueltigerZyklus.NumberOfElements / (double)endgueltigerZyklus.ZyklusSumme)}");

            return(endgueltigerZyklus);
        }
예제 #4
0
        static public (BigInteger A, BigInteger B) Run(BigInteger n, int[] zahlensysteme)
        {
            var startwert = Helper.Wurzel(n);

            if (startwert.Item2 == true)
            {
                Console.WriteLine(string.Format("Lösung ist die Wurzel {0}", startwert.Sqrt));
                return(startwert.Item1, startwert.Item1);
            }

            Zyklus zyklus = EndgueltigenZyklusBestimmen(n, zahlensysteme);

            zyklus.Sort();

            (BigInteger, bool)ergebnisDerWurzel;
            BigInteger offset = BigInteger.Add(startwert.Item1, 1);

            while (true)
            {
                for (int i = 0; i < zyklus.NumberOfElements; i++)
                {
                    // Formel: ab = SQRT( (x*x) - n) | mit x := x+1

                    ergebnisDerWurzel = Helper.Wurzel(BigInteger.Subtract(BigInteger.Pow(BigInteger.Add(offset, zyklus.Elemente[i]), 2), n));

                    if (ergebnisDerWurzel.Item2 == true)
                    {
                        BigInteger a = BigInteger.Add(BigInteger.Add(offset, zyklus.Elemente[i]), ergebnisDerWurzel.Item1);
                        BigInteger b = BigInteger.Subtract(BigInteger.Add(offset, zyklus.Elemente[i]), ergebnisDerWurzel.Item1);

                        return(a, b);
                    }
                }

                offset = BigInteger.Add(offset, zyklus.ZyklusSumme);
            }
        }
예제 #5
0
        static public Zyklus VerschmelzeZyklen(Zyklus zyklusA, Zyklus zyklusB)
        {
            Zyklus A;
            Zyklus B;

            if (zyklusA.ZyklusSumme > zyklusB.ZyklusSumme)
            {
                A = zyklusA;
                B = zyklusB;
            }
            else
            {
                A = zyklusB;
                B = zyklusA;
            }

            long ergebnisZyklusSumme;

            if (A.ZyklusSumme % B.ZyklusSumme == 0)
            {
                ergebnisZyklusSumme = A.ZyklusSumme;
            }
            else
            {
                ergebnisZyklusSumme = A.ZyklusSumme * B.ZyklusSumme;
            }

            Tuple <long, long> offset = BestimmeOffsetZahlenZweierZyklen(A.ZyklusSumme, B.ZyklusSumme);

            Zyklus ergebnis = new Zyklus(ergebnisZyklusSumme, A.NumberOfElements * B.NumberOfElements);


            long tmp;
            long tmp2;

            for (int i = 0; i < A.NumberOfElements; i++)
            {
                for (int j = 0; j < B.NumberOfElements; j++)
                {
                    tmp = B.Elemente[j] - A.Elemente[i];
                    if (tmp == 0)
                    {
                        ergebnis.Elemente.Add(A.Elemente[i]);
                    }
                    else
                    {
                        tmp2 = ((offset.Item2 * tmp) % A.ZyklusSumme) * B.ZyklusSumme + B.Elemente[j];
                        tmp2 = (tmp2 + ergebnisZyklusSumme) % ergebnisZyklusSumme; // Zyklus positiv halten
                        if (tmp2 < 0)
                        {
                            int k = 0;
                            k++;
                        }

                        ergebnis.Elemente.Add(tmp2);
                    }
                }
            }

            return(ergebnis);
        }