Example #1
0
        /// <summary>
        /// Test Millera-Rabina czy liczba n jest pierwsza, przy danym a
        /// patrz: Cormen i "Alogrytmika praktyczna" (rozdzial 31.8)
        /// https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
        ///
        /// Okresla czy liczba jest zlozona (true), podejrzenie ze pierwsza (false)
        /// </summary>
        /// <param name="a">podstawa</param>
        /// <param name="n">nieparzysta liczba do przetestowania</param>
        /// <returns>true - złożona, false - może być pierwsza</returns>
        public bool MillerRabinTest(long a, int n)
        {
            //dziala na zbiorze a [1, 2, .. n-1]
            if (a >= n)
            {
                return(false);
            }

            //n-1 = 2^t * u -> a^(n-1)=(a^n)^2^t, gdzie t>=1 i u nieparzyste
            long u = n - 1;
            long t = 0;

            while ((u & 1) == 0)
            {
                u /= 2;
                t++;
            }

            long x = NumbersTheory.ExpMod(a, u, n);
            long y = 0;

            for (; t > 0; t--)
            {
                y = (x * x) % n;
                //y = NumbersTheory.ExpMod(x, 2, n);
                if ((y == 1) && (x != 1) && (x != n - 1)) //nietrywialny dzielnik - liczba jest zlozona
                {
                    return(true);
                }
                x = y;
            }
            //liczba jest zlozona jezeli y!=1
            return(y != 1);
        }
Example #2
0
        public void TestLCM()
        {
            NumbersTheory.LCM(0, 56).ShouldBe(0);
            NumbersTheory.LCM(1, 56).ShouldBe(56);

            NumbersTheory.LCM(42, 56).ShouldBe(168);
            NumbersTheory.LCM(192, 348).ShouldBe(5568);
        }
Example #3
0
        public void TestGCDBinary()
        {
            NumbersTheory.GCDBinary(0, 0).ShouldBe(0);
            NumbersTheory.GCDBinary(10, 0).ShouldBe(10);
            NumbersTheory.GCDBinary(0, 10).ShouldBe(10);

            NumbersTheory.GCDBinary(1, 10).ShouldBe(1);
            NumbersTheory.GCDBinary(1, 100000000000).ShouldBe(1);
            NumbersTheory.GCDBinary(100000000000, 1).ShouldBe(1);

            NumbersTheory.GCDBinary(48, 180).ShouldBe(12);
            NumbersTheory.GCDBinary(180, 48).ShouldBe(12);
        }
Example #4
0
        public void TestGCDExt()
        {
            long l, k;
            long d;

            d = NumbersTheory.GCDExt(10, 15, out l, out k);
            d.ShouldBe(5);
            l.ShouldBe(-1);
            k.ShouldBe(1);
            d = NumbersTheory.GCDExt(123, 291, out l, out k);
            d.ShouldBe(3);
            l.ShouldBe(-26);
            k.ShouldBe(11);
        }
Example #5
0
        public void TestExpMod()
        {
            NumbersTheory.ExpMod(2, 0, 10).ShouldBe(1);

            NumbersTheory.ExpMod(1, 10, 10).ShouldBe(1);
            NumbersTheory.ExpMod(2, 100, 10).ShouldBe(6);
            NumbersTheory.ExpMod(3, 17, 123).ShouldBe(3);
            NumbersTheory.ExpMod(123456789, 2, 321).ShouldBe(90);
            NumbersTheory.ExpMod(1 << 32, (1 << 32) - 1, 999).ShouldBe(1);

            NumbersTheory.ExpMod(2, 32, 10).ShouldBe(6);
            NumbersTheory.ExpMod(2, 32, 2).ShouldBe(0);

            //NumbersTheory.ExpMod(2, 771604937422839, 1543209874845679).ShouldBe(1);
        }
Example #6
0
        /// <summary>
        /// sx, sy - rozmiar stolu (sx zawsze parzyste)
        /// px, py - polozenie kuli
        /// wx, wy - wektor ruchu/uderzenia
        /// </summary>
        /// <param name="sx"></param>
        /// <param name="sy"></param>
        /// <param name="px"></param>
        /// <param name="py"></param>
        /// <param name="wx"></param>
        /// <param name="wy"></param>
        /// <returns></returns>
        public Pocket CheckPocket(int sx, int sy, int px, int py, int wx, int wy)
        {
            //od razu w luzie
            if (IsMeshPoint(sx, sy, px, py))
            {
                return(SpecifyPocket(sx, sy, px, py));
            }

            //bez ruchu
            if ((wx == 0) && (wy == 0))
            {
                return(Pocket.NIE);
            }

            //przypadki poziome
            if (wy == 0)
            {
                return(GetHorizontalPocket(sx, sy, px, py, wx));
            }

            //przypadki pionowe
            if (wx == 0)
            {
                return(GetVerticalPocket(sx, px, wy));
            }

            //i pozostale, liczone dla rucho w prawo do gory, inne warianty trzeba przeksztalcic

            //jezeli ruch w lewo to odbijamy stol wzgledem srodka
            bool tablefilppedvertical   = (wx < 0);
            bool tableflippedhorizontal = (wy < 0);

            if (tablefilppedvertical)
            {
                FlipVertical(sx, ref px, ref wx);
            }
            if (tableflippedhorizontal)
            {
                FlipHorizontal(sy, ref py, ref wy);
            }

            //przeskalowanie wektora do najmniejszego mozliwego
            int wgcd = (int)NumbersTheory.GCDBinary(wx, wy);

            wx /= wgcd;
            wy /= wgcd;

            long a, b, c;

            a = (sx / 2) * wy;
            b = wx * py - wy * px;
            c = sy * wx;
            long n, m, p, q;

            n = a / c;
            m = NumbersTheory.Mod(a, c);
            p = b / c;
            q = NumbersTheory.Mod(b, c);

            //analizowane 4 przypadki A/C i B/C
            bool found = true;
            long coefa = 0;

            if ((m == 0) && (q == 0))
            {
                //t > 0 -> a > px/w
                coefa = px / (sx / 2) + 1;
            }
            else if ((m == 0) && (q != 0))
            {
                found = false;
            }
            else if ((m != 0) && (q == 0))
            {
                coefa = c / NumbersTheory.GCDBinary(m, c);
            }
            else if ((m != 0) && (q != 0))
            {
                long l, k;
                long d = NumbersTheory.GCDExt(m, c, out l, out k);
                if (-q % d == 0)
                {
                    long x0 = NumbersTheory.Mod(l * (-q / d), c);
                    coefa = x0;
                    for (long i = 1; i < d; i++) //zgodnie z alg z Cormena powinno byc od 0, ale element 0 jest obliczony wczesniej
                    {
                        long xx = NumbersTheory.Mod(x0 + i * (c / d), c);
                        if (xx < coefa)
                        {
                            coefa = xx;
                        }
                    }
                }
                else
                {
                    found = false;
                }
            }
            //ustalenie punktu kratowego i luzy
            Pocket res = Pocket.NIE;

            if (found)
            {
                long t  = (coefa * (sx / 2) - px) / wx;
                long rx = px + t * wx;
                long ry = py + t * wy;
                if (IsMeshPoint(sx, sy, rx, ry))
                {
                    res = SpecifyPocket(sx, sy, rx, ry);
                }
            }


            //korekta wyniku jezeli stol byl odbijany
            if (tablefilppedvertical)   //ruch byl w lewo - stol byl odbity pionowo -> zamieniamy luzy lewe z prawymi
            {
                res = BackflipVertical(res);
            }
            if (tableflippedhorizontal) //ruch byl w dol - stol odbity poziomo -> zmieniamy luzy gorne i dolne
            {
                res = BackflipHorizontal(res);
            }

            return(res);
        }