Tìm những người cai trị Golomb ngắn nhất


15

Thước kẻ Golomb là tập hợp các số nguyên không âm sao cho không có hai cặp số nguyên nào trong tập hợp có cùng khoảng cách.

Ví dụ: [0, 1, 4, 6]là một thước đo Golomb vì tất cả khoảng cách giữa hai số nguyên trong tập hợp này là duy nhất:

0, 1 -> distance 1
0, 4 -> distance 4
0, 6 -> distance 6
1, 4 -> distance 3
1, 6 -> distance 5
4, 6 -> distance 2

Vì mục đích đơn giản trong thử thách này (và vì dịch thuật là tầm thường), chúng tôi áp đặt rằng một người cai trị Golomb luôn chứa số0 (mà ví dụ trước đó làm).

Vì bộ này có độ dài 4, chúng tôi nói rằng đây là một người cai trị theo thứ tự Golomb 4. Khoảng cách lớn nhất trong tập hợp này (hoặc phần tử, vì 0luôn nằm trong tập hợp) là 6do đó chúng tôi nói rằng đây là Thước đo chiều dài Golomb 6.

Nhiệm vụ của bạn

Tìm Golomb cai trị của trật tự 50 để 100(bao gồm) có càng nhỏ dài như bạn có thể tìm thấy. Những người cai trị bạn thấy không cần phải tối ưu (xem bên dưới).

Sự tối ưu

Một người cai trị trật tự Golomb N, được cho là tối ưu nếu không có người cai trị trật tự Golomb khácN có chiều dài nhỏ hơn.

Những người cai trị Golomb tối ưu được biết đến với những đơn hàng dưới 28 , mặc dù việc tìm kiếm và chứng minh sự tối ưu ngày càng khó hơn khi đơn hàng tăng lên.

Do đó, bạn không nên tìm thấy thước kẻ Golomb tối ưu cho bất kỳ lệnh nào giữa 50100 (và thậm chí ít mong đợi hơn là bạn có thể chứng minh rằng chúng là tối ưu).

Không có giới hạn thời gian trong việc thực hiện chương trình của bạn.

Đường cơ sở

Danh sách dưới đây là danh sách độ dài của những người cai trị Golomb từ 50đến 100(theo thứ tự) được đánh giá bằng chiến lược tìm kiếm ngây thơ (Cảm ơn @PeterTaylor cho danh sách này):

[4850 5122 5242 5297 5750 5997 6373 6800 6924 7459 7546 7788 8219 8502 8729 8941 9881 10199 10586 10897 11288 11613 11875 12033 12930 13393 14046 14533 14900 15165 15687 15971 16618 17354 17931 18844 19070 19630 19669 20721 21947 22525 23290 23563 23880 24595 24767 25630 26036 26254 27218]

Tổng của tất cả các độ dài là 734078 .

Chấm điểm

Điểm của bạn sẽ là tổng độ dài của tất cả các thước kẻ Golomb của bạn giữa 50100, chia cho tổng độ dài của các thước kẻ Golomb nằm giữa 50100trong đường cơ sở:734078 .

Trong trường hợp bạn không tìm thấy thước kẻ Golomb cho một đơn hàng cụ thể, bạn sẽ tính điểm của mình theo cách tương tự, sử dụng gấp đôi độ dài trong đường cơ sở cho thứ tự cụ thể đó.

Câu trả lời với số điểm thấp nhất sẽ thắng.

Trong trường hợp hòa, độ dài của thứ tự lớn nhất trong đó hai câu trả lời khác nhau được so sánh và câu trả lời ngắn nhất sẽ thắng. Trong trường hợp cả hai câu trả lời có cùng độ dài cho tất cả các đơn đặt hàng, thì câu trả lời được đăng đầu tiên sẽ thắng.


2
Liên quan. (Thử thách tương tự trong 2D.)
Martin Ender


Khi bạn nói người cai trị trong khoảng từ 50 đến 100, bạn có nghĩa là phạm vi [50, 100)? Vì vậy, không bao gồm thứ tự 100 thước? Bởi vì đường cơ sở chỉ chứa 50 yếu tố.
orlp

1
Lưu ý bên lề: chiều dài nhỏ nhất có thể có của một người cai trị theo thứ tự Golomb nn(n-1)/2vì có bao nhiêu sự khác biệt tích cực. Do đó, điểm số nhỏ nhất có thể trong thử thách này là 147050/734078 > 0.2003193.
Greg Martin

2
@GregMartin Cảm ơn, mặc dù đây không hoàn toàn là "điểm nhỏ nhất có thể" mà là giới hạn thấp hơn về điểm số nhỏ nhất có thể đó!
Gây tử vong vào

Câu trả lời:


8

C #, 259421/734078 ~ = 0,3534

Phương pháp

Cuối cùng tôi đã tìm thấy một lời giải thích ít nhiều có thể đọc được về phương pháp trường chiếu (phương pháp của Singer) trong Cấu trúc của các bộ Sidon tổng quát , mặc dù tôi vẫn nghĩ rằng nó có thể được cải thiện đôi chút. Nó hóa ra tương tự như phương pháp trường affine (phương pháp của Bose) so với các bài báo khác mà tôi đọc đã truyền đạt.

Điều này giả định kiến ​​thức về các lĩnh vực hữu hạn . Coi là công suất chính và đặt F ( q ) là trường cơ sở của chúng ta.q= =pmộtF(q)

Phương pháp trường affine hoạt động trên . Lấy một bộ tạo g 2 của F ( q 2 ) và phần tử khác không k của F ( q ) và xem xét tập { a : g 2F(q2)g2F(q2)kF(q)

{một:g2một-kg2Fq}
q2-1q2-1

Phương pháp trường chiếu hoạt động trên . Hãy tạo g 3 của F ( q 3 ) và một yếu tố khác không k của F ( q ) và xem xét các thiết lập { 0 } { một : g 3F(q3)g3F(q3)kF(q) Những giá trị đó tạo thành một thước đo Golomb mô đun mod q 2 + q + 1 . Các thước đo khác có thể thu được bằng cách nhân mô-đun theo cách tương tự như đối với phương pháp trường affine.

{0}{a:g3akg3Fq}
q2+q+1

Lưu ý rằng các phương thức giữa chúng cung cấp các giá trị được biết đến tốt nhất cho mọi độ dài lớn hơn 16. Tomas Rokicki và Gil Dogon đang trao phần thưởng 250 đô la cho bất kỳ ai đánh bại chúng trong khoảng thời gian từ 36 đến 40000. Do đó, bất cứ ai đánh bại câu trả lời này đều là tiền tệ giải thưởng.

C # không phải là rất thành ngữ, nhưng tôi cần nó để biên dịch với một phiên bản cũ của Mono. Ngoài ra, mặc dù kiểm tra đối số, đây không phải là mã chất lượng sản xuất. Tôi không hài lòng với các loại, nhưng tôi không nghĩ có một giải pháp thực sự tốt cho điều đó trong C #. Có thể trong F # hoặc C ++ với templating điên rồ.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Sandbox {
    class Program {
        static void Main(string[] args) {
            var winners = ComputeRulerRange(50, 100);
            int total = 0;
            for (int i = 50; i <= 100; i++) {
                Console.WriteLine("{0}:\t{1}", i, winners[i][i - 1]);
                total += winners[i][i - 1];
            }
            Console.WriteLine("\t{0}", total);
        }

        static IDictionary<int, int[]> ComputeRulerRange(int min, int max) {
            var best = new Dictionary<int, int[]>();

            var naive = Naive(max);
            for (int i = min; i <= max; i++) best[i] = naive.Take(i).ToArray();

            var finiteFields = FiniteFields(max * 11 / 10).OrderBy(x => x.Size).ToArray();

            // The projective plane method generates rulers of length p^a + 1 for prime powers p^a.
            // We can then look at subrulers for a reasonable range, say down to two prime powers below.
            for (int ppi = 0; ppi < finiteFields.Length; ppi++) {
                // Range under consideration
                var field = finiteFields[ppi];
                int q = field.Size;
                int subFrom = Math.Max(min, ppi >= 2 ? finiteFields[ppi - 2].Size : 1);
                int subTo = Math.Min(max, q + 1);
                if (subTo < subFrom) continue;

                int m = q * q + q + 1;
                foreach (var ruler in ProjectiveRulers(field)) {
                    for (int sub = subFrom; sub <= subTo; sub++) {
                        var subruler = BestSubruler(ruler, sub, m);
                        if (subruler[sub - 1] < best[sub][sub - 1]) best[sub] = subruler;
                    }
                }
            }

            // Similarly for the affine plane method, which generates rulers of length p^a for prime powers p^a
            for (int ppi = 0; ppi < finiteFields.Length; ppi++) {
                // Range under consideration
                var field = finiteFields[ppi];
                int q = field.Size;
                int subFrom = Math.Max(min, ppi >= 2 ? finiteFields[ppi - 2].Size : 1);
                int subTo = Math.Min(max, q);
                if (subTo < subFrom) continue;

                int m = q * q - 1;
                foreach (var ruler in AffineRulers(field)) {
                    for (int sub = subFrom; sub <= subTo; sub++) {
                        var subruler = BestSubruler(ruler, sub, m);
                        if (subruler[sub - 1] < best[sub][sub - 1]) best[sub] = subruler;
                    }
                }
            }

            return best;
        }

        static int[] BestSubruler(int[] ruler, int sub, int m) {
            int[] expand = new int[ruler.Length + sub - 1];
            for (int i = 0; i < ruler.Length; i++) expand[i] = ruler[i];
            for (int i = 0; i < sub - 1; i++) expand[ruler.Length + i] = ruler[i] + m;

            int best = m, bestIdx = -1;
            for (int i = 0; i < ruler.Length; i++) {
                if (expand[i + sub - 1] - expand[i] < best) {
                    best = expand[i + sub - 1] - expand[i];
                    bestIdx = i;
                }
            }

            return expand.Skip(bestIdx).Take(sub).Select(x => x - ruler[bestIdx]).ToArray();
        }

        static IEnumerable<int[]> ProjectiveRulers(FiniteField field) {
            var q = field.Size;
            var fq3 = PowerField.Create(field, 3);
            var m = q * q + q + 1;
            var g = fq3.Generators.First();

            // Define the set T<k> = {0} \union {a \in [q^3-1] : g^a - kg \in F(q)} for 0 != k \in F(q)
            // This could alternatively be T<k> = {0} \union {log_g(b - kg) : b in F(q)} for 0 != k \in F(q)
            // Then T<k> % (q^2 + q + 1) gives a Golomb ruler.
            // For a given generator we seem to get the same ruler for every k.
            var t_k = new HashSet<int>();
            t_k.Add(0);
            var ga = fq3.One;
            for (int a = 1; a < fq3.Size; a++) {
                ga = ga * g;
                if (fq3.Convert(ga + g) < q) t_k.Add(a % m);
            }

            // TODO: optimise by detecting duplicates
            for (int s = 1; s < m; s++) {
                if (Gcd(s, m) == 1) yield return t_k.Select(x => x * s % m).OrderBy(x => x).ToArray();
            }
        }

        static IEnumerable<int[]> AffineRulers(FiniteField field) {
            var q = field.Size;
            var fq2 = PowerField.Create(field, 2);
            var m = q * q - 1;
            var g = fq2.Generators.First();

            // Define the set T<k> = {0} \union {a \in [q^2-1] : g^a - kg \in F(q)} for 0 != k \in F(q)
            // Then T<k> % (q^2 - 1) gives a Golomb ruler.
            var t_k = new HashSet<int>();
            var ga = fq2.One;
            for (int a = 1; a < fq2.Size; a++) {
                ga = ga * g;
                if (fq2.Convert(ga + g) < q) t_k.Add(a % m);
            }

            // TODO: optimise by detecting duplicates
            for (int s = 1; s < m; s++) {
                if (Gcd(s, m) == 1) yield return t_k.Select(x => x * s % m).OrderBy(x => x).ToArray();
            }
        }

        static int Gcd(int a, int b) {
            while (a != 0) {
                var t = b % a;
                b = a;
                a = t;
            }

            return b;
        }

        static int[] Naive(int size) {
            if (size == 0) return new int[0];
            if (size == 1) return new int[] { 0 };

            int[] ruler = new int[size];
            var diffs = new HashSet<int>();
            int i = 1, c = 1;
            while (true) {
                bool valid = true;
                for (int j = 0; j < i; j++) {
                    if (diffs.Contains(c - ruler[j])) { valid = false; break; }
                }

                if (valid) {
                    for (int j = 0; j < i; j++) diffs.Add(c - ruler[j]);
                    ruler[i++] = c;
                    if (i == size) return ruler;
                }

                c++;
            }
        }

        static IEnumerable<FiniteField> FiniteFields(int max) {
            bool[] isComposite = new bool[max + 1];
            for (int p = 2; p < isComposite.Length; p++) {
                if (!isComposite[p]) {
                     FiniteField baseField = new PrimeField(p); yield return baseField;
                    for (int pp = p * p, pow = 2; pp < max; pp *= p, pow++) yield return PowerField.Create(baseField, pow);
                    for (int pq = p * p; pq <= max; pq += p) isComposite[pq] = true;
                }
            }
        }
    }

    public abstract class FiniteField {
        private Lazy<FiniteFieldElement> _Zero;
        private Lazy<FiniteFieldElement> _One;

        public FiniteFieldElement Zero { get { return _Zero.Value; } }
        public FiniteFieldElement One { get { return _One.Value; } }
        public IEnumerable<FiniteFieldElement> Generators {
            get {
                for (int _g = 1; _g < Size; _g++) {
                    int pow = 0;
                    FiniteFieldElement g = Convert(_g), gpow = One;
                    while (true) {
                        pow++;
                        gpow = gpow * g;
                        if (gpow == One) break;
                        if (pow > Size) {
                            throw new Exception("Is this really a field? " + this);
                        }
                    }
                    if (pow == Size - 1) yield return g;
                }
            }
        }

        public abstract int Size { get; }
        internal abstract FiniteFieldElement Convert(int i);
        internal abstract int Convert(FiniteFieldElement f);

        internal abstract bool Eq(FiniteFieldElement a, FiniteFieldElement b);
        internal abstract FiniteFieldElement Negate(FiniteFieldElement a);
        internal abstract FiniteFieldElement Add(FiniteFieldElement a, FiniteFieldElement b);
        internal abstract FiniteFieldElement Mul(FiniteFieldElement a, FiniteFieldElement b);

        protected FiniteField() {
            _Zero = new Lazy<FiniteFieldElement>(() => Convert(0));
            _One = new Lazy<FiniteFieldElement>(() => Convert(1));
        }
    }

    public abstract class FiniteFieldElement {
        internal abstract FiniteField Field { get; }

        public static FiniteFieldElement operator -(FiniteFieldElement a) {
            return a.Field.Negate(a);
        }

        public static FiniteFieldElement operator +(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != b.Field) throw new ArgumentOutOfRangeException("b");
            return a.Field.Add(a, b);
        }

        public static FiniteFieldElement operator *(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != b.Field) throw new ArgumentOutOfRangeException("b");
            return a.Field.Mul(a, b);
        }

        public static bool operator ==(FiniteFieldElement a, FiniteFieldElement b) {
            if (Equals(a, null)) return Equals(b, null);
            else if (Equals(b, null)) return false;

            if (a.Field != b.Field) throw new ArgumentOutOfRangeException("b");
            return a.Field.Eq(a, b);
        }

        public static bool operator !=(FiniteFieldElement a, FiniteFieldElement b) { return !(a == b); }

        public override bool Equals(object obj) {
            return (obj is FiniteFieldElement) && (obj as FiniteFieldElement).Field == Field && this == (obj as FiniteFieldElement);
        }

        public override int GetHashCode() { return Field.Convert(this).GetHashCode(); }

        public override string ToString() { return Field.Convert(this).ToString(); }
    }

    public class PrimeField : FiniteField {
        private readonly int _Prime;
        private readonly PrimeFieldElement[] _Featherweight;

        internal int Prime { get { return _Prime; } }
        public override int Size { get { return _Prime; } }

        public PrimeField(int prime) {
            if (prime < 2) throw new ArgumentOutOfRangeException("prime");

            // TODO A primality test would be nice...

            _Prime = prime;
            _Featherweight = new PrimeFieldElement[Math.Min(prime, 256)];
        }

        internal override FiniteFieldElement Convert(int i) {
            if (i < 0 || i >= _Prime) throw new ArgumentOutOfRangeException("i");
            if (i >= _Featherweight.Length) return new PrimeFieldElement(this, i);
            if (Equals(_Featherweight[i], null)) _Featherweight[i] = new PrimeFieldElement(this, i);
            return _Featherweight[i];
        }

        internal override int Convert(FiniteFieldElement f) {
            if (f == null) throw new ArgumentNullException("f");
            if (f.Field != this) throw new ArgumentOutOfRangeException("f");

            return (f as PrimeFieldElement).Value;
        }

        internal override bool Eq(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            if (b.Field != this) throw new ArgumentOutOfRangeException("b");

            return (a as PrimeFieldElement).Value == (b as PrimeFieldElement).Value;
        }

        internal override FiniteFieldElement Negate(FiniteFieldElement a) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            var fa = a as PrimeFieldElement;
            return fa.Value == 0 ? fa : Convert(_Prime - fa.Value);
        }

        internal override FiniteFieldElement Add(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            if (b.Field != this) throw new ArgumentOutOfRangeException("b");

            return Convert(((a as PrimeFieldElement).Value + (b as PrimeFieldElement).Value) % _Prime);
        }

        internal override FiniteFieldElement Mul(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            if (b.Field != this) throw new ArgumentOutOfRangeException("b");

            return Convert(((a as PrimeFieldElement).Value * (b as PrimeFieldElement).Value) % _Prime);
        }

        public override string ToString() { return string.Format("F({0})", _Prime); }
    }

    internal class PrimeFieldElement : FiniteFieldElement {
        private readonly PrimeField _Field;
        private readonly int _Value;

        internal override FiniteField Field { get { return _Field; } }
        internal int Value { get { return _Value; } }

        internal PrimeFieldElement(PrimeField field, int val) {
            if (field == null) throw new ArgumentNullException("field");
            if (val < 0 || val >= field.Prime) throw new ArgumentOutOfRangeException("val");

            _Field = field;
            _Value = val;
        }
    }

    public class PowerField : FiniteField {
        private readonly FiniteField _BaseField;
        private readonly FiniteFieldElement[] _Polynomial;

        internal FiniteField BaseField { get { return _BaseField; } }
        internal int Power { get { return _Polynomial.Length; } }
        public override int Size { get { return (int)Math.Pow(_BaseField.Size, Power); } }

        public PowerField(FiniteField baseField, FiniteFieldElement[] polynomial) {
            if (baseField == null) throw new ArgumentNullException("baseField");
            if (polynomial == null) throw new ArgumentNullException("polynomial");
            if (polynomial.Length < 2) throw new ArgumentOutOfRangeException("polynomial");
            for (int i = 0; i < polynomial.Length; i++) if (polynomial[i].Field != baseField) throw new ArgumentOutOfRangeException("polynomial[" + i + "]");

            // TODO Check that the polynomial is irreducible over the base field.

            _BaseField = baseField;
            _Polynomial = polynomial.ToArray();
        }

        internal override FiniteFieldElement Convert(int i) {
            if (i < 0 || i >= Size) throw new ArgumentOutOfRangeException("i");

            var vec = new FiniteFieldElement[Power];
            for (int j = 0; j < vec.Length; j++) {
                vec[j] = BaseField.Convert(i % BaseField.Size);
                i /= BaseField.Size;
            }

            return new PowerFieldElement(this, vec);
        }

        internal override int Convert(FiniteFieldElement f) {
            if (f == null) throw new ArgumentNullException("f");
            if (f.Field != this) throw new ArgumentOutOfRangeException("f");

            var pf = f as PowerFieldElement;
            int i = 0;
            for (int j = Power - 1; j >= 0; j--) i = i * BaseField.Size + BaseField.Convert(pf.Value[j]);
            return i;
        }

        internal override bool Eq(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            if (b.Field != this) throw new ArgumentOutOfRangeException("b");

            var fa = a as PowerFieldElement;
            var fb = b as PowerFieldElement;
            for (int i = 0; i < Power; i++) if (fa.Value[i] != fb.Value[i]) return false;
            return true;
        }

        internal override FiniteFieldElement Negate(FiniteFieldElement a) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            return new PowerFieldElement(this, (a as PowerFieldElement).Value.Select(x => -x).ToArray());
        }

        internal override FiniteFieldElement Add(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            if (b.Field != this) throw new ArgumentOutOfRangeException("b");

            var fa = a as PowerFieldElement;
            var fb = b as PowerFieldElement;
            var vec = new FiniteFieldElement[Power];
            for (int i = 0; i < Power; i++) vec[i] = fa.Value[i] + fb.Value[i];
            return new PowerFieldElement(this, vec);
        }

        internal override FiniteFieldElement Mul(FiniteFieldElement a, FiniteFieldElement b) {
            if (a.Field != this) throw new ArgumentOutOfRangeException("a");
            if (b.Field != this) throw new ArgumentOutOfRangeException("b");

            var fa = a as PowerFieldElement;
            var fb = b as PowerFieldElement;

            // We consider fa and fb as polynomials of a variable x and multiply modulo (x^Power - _Polynomial).
            // But to keep things simple we want to manage the cascading modulo.
            var vec = Enumerable.Repeat(BaseField.Zero, Power).ToArray();
            var fa_xi = fa.Value.ToArray();
            for (int i = 0; i < Power; i++) {
                for (int j = 0; j < Power; j++) vec[j] += fb.Value[i] * fa_xi[j];
                if (i < Power - 1) ShiftLeft(fa_xi);
            }

            return new PowerFieldElement(this, vec);
        }

        private void ShiftLeft(FiniteFieldElement[] vec) {
            FiniteFieldElement head = vec[vec.Length - 1];
            for (int i = vec.Length - 1; i > 0; i--) vec[i] = vec[i - 1] + head * _Polynomial[i];
            vec[0] = head * _Polynomial[0];
        }

        public static FiniteField Create(FiniteField baseField, int power) {
            if (baseField == null) throw new ArgumentNullException("baseField");
            if (power < 2) throw new ArgumentOutOfRangeException("power");

            // Since the field is cyclic, there is only one finite field of a given prime power order (up to isomorphism).
            // For most practical purposes that means that we can pick any arbitrary monic irreducible polynomial.
            // We can abuse PowerField to do polynomial multiplication in the base field.
            var fakeField = new PowerField(baseField, Enumerable.Repeat(baseField.Zero, power).ToArray());
            var excluded = new HashSet<FiniteFieldElement>();
            for (int lpow = 1; lpow <= power / 2; lpow++) {
                int upow = power - lpow;
                // Consider all products of a monic polynomial of order lpow with a monic polynomial of order upow.
                int xl = (int)Math.Pow(baseField.Size, lpow);
                int xu = (int)Math.Pow(baseField.Size, upow);
                for (int i = xl; i < 2 * xl; i++) {
                    var pi = fakeField.Convert(i);
                    for (int j = xu; j < 2 * xu; j++) {
                        var pj = fakeField.Convert(j);
                        excluded.Add(-(pi * pj));
                    }
                }
            }

            for (int p = baseField.Size; true; p++) {
                var pp = fakeField.Convert(p) as PowerFieldElement;
                if (!excluded.Contains(pp)) return new PowerField(baseField, pp.Value.ToArray());
            }
        }

        public override string ToString() {
            var sb = new System.Text.StringBuilder();
            sb.AppendFormat("GF({0}) with primitive polynomial x^{1} ", Size, Power);
            for (int i = Power - 1; i >= 0; i--) sb.AppendFormat("+ {0}x^{1}", _Polynomial[i], i);
            sb.AppendFormat(" over base field ");
            sb.Append(_BaseField);
            return sb.ToString();
        }
    }

    internal class PowerFieldElement : FiniteFieldElement {
        private readonly PowerField _Field;
        private readonly FiniteFieldElement[] _Vector; // The version of Mono I have doesn't include IReadOnlyList<T>

        internal override FiniteField Field { get { return _Field; } }
        internal FiniteFieldElement[] Value { get { return _Vector; } }

        internal PowerFieldElement(PowerField field, params FiniteFieldElement[] vector) {
            if (field == null) throw new ArgumentNullException("field");
            if (vector == null) throw new ArgumentNullException("vector");
            if (vector.Length != field.Power) throw new ArgumentOutOfRangeException("vector");
            for (int i = 0; i < vector.Length; i++) if (vector[i].Field != field.BaseField) throw new ArgumentOutOfRangeException("vector[" + i + "]");

            _Field = field;
            _Vector = vector.ToArray();
        }
    }
}

Các kết quả

Thật không may, việc thêm các thước kẻ sẽ đưa tôi khoảng 15 nghìn ký tự vượt quá giới hạn kích thước bài đăng, vì vậy chúng nằm trên pastebin .


Bạn có tử tế khi đăng những người cai trị của bạn cho [50, 100] ở đâu đó không? Tôi có một thuật toán di truyền mà tôi muốn thử, cung cấp cho nó một số giá trị hạt giống.
orlp

@orlp, thêm một liên kết.
Peter Taylor

2
Như tôi nghi ngờ, thuật toán tiến hóa có thể trích xuất không có gì sử dụng từ các mẫu vật ưu việt này. Mặc dù ban đầu có vẻ như các thuật toán tiến hóa có thể hoạt động (nó chuyển ngay lập tức từ các nhà cai trị không hợp lệ sang các nhà cai trị thực tế), có quá nhiều cấu trúc toàn cầu cần thiết để thuật toán tiến hóa hoạt động.
orlp

5

Python 3, điểm 603001/734078 = 0.82144

Tìm kiếm ngây thơ kết hợp với xây dựng Erdős Nhận Turan:

2pk+(k2modp),k[0,p1]

Đối với các số nguyên tố p, điều này cung cấp một thước đo golomb tối ưu không có triệu chứng.

def isprime(n):
    if n < 2: return False
    if n % 2 == 0: return n == 2
    k = 3
    while k*k <= n:
         if n % k == 0: return False
         k += 2
    return True

rulers = []
ruler = []
d = set()
n = 0
while len(ruler) <= 100:
    order = len(ruler) + 1
    if order > 2 and isprime(order):
        ruler = [2*order*k + k*k%order for k in range(order)]
        d = {a-b for a in ruler for b in ruler if a > b}
        n = max(ruler) + 1
        rulers.append(tuple(ruler))
        continue

    nd = set(n-e for e in ruler)
    if not d & nd:
        ruler.append(n)
        d |= nd
        rulers.append(tuple(ruler))
    n += 1


isuniq = lambda l: len(l) == len(set(l))
isruler = lambda l: isuniq([a-b for a in l for b in l if a > b])

assert all(isruler(r) for r in rulers)

rulers = list(sorted([r for r in rulers if 50 <= len(r) <= 100], key=len))
print(sum(max(r) for r in rulers))

Tôi không nghĩ rằng việc xây dựng này là tối ưu không có triệu chứng: nó mang lại một người cai trị Golomb về trật tự pvà độ dài 2p^2, trong khi đó có những người cai trị Golomb về trật tự nvà chiều dài về sự n^2bất đối xứng.
Greg Martin

@GregMartin Không có triệu chứng không có sự khác biệt giữa 2p^2p^2.
orlp

Tôi phụ thuộc vào định nghĩa của bạn về "không có triệu chứng", tôi đoán, nhưng với tôi, trong bối cảnh này, chúng rất khác nhau.
Greg Martin

3

Toán học, điểm 276235/734078 <0.376302

ruzsa[p_, i_] := Module[{g = PrimitiveRoot[p]},
  Table[ChineseRemainder[{t, i PowerMod[g, t, p]}, {p - 1, p}], {t, 1, p - 1}] ]

reducedResidues[m_] := Select[Range@m, CoprimeQ[m, #] &]

rotate[set_, m_] := Mod[set - #, m] & /@ set

scaledRuzsa[p_] := Union @@ Table[ Sort@Mod[a b, p (p - 1)],
  {a, reducedResidues[p (p - 1)]}, {b, rotate[ruzsa[p, 1], p (p - 1)]}]

manyRuzsaSets = Join @@ Table[scaledRuzsa[Prime[n]], {n, 32}];

tryGolomb[set_, k_] := If[Length[set] < k, Nothing, Take[set, k]]

Table[First@MinimalBy[tryGolomb[#, k] & /@ manyRuzsaSets, Max], {k, 50, 100}]

Hàm này ruzsathực hiện việc xây dựng một thước kẻ Golobm (còn được gọi là bộ Sidon) được tìm thấy trong Imre Z. Ruzsa. Giải phương trình tuyến tính trong tập hợp các số nguyên. I. Acta Arith., 65 (3): 259 Từ282, 1993 . Với bất kỳ số nguyên tố nào p, công trình này mang lại một thước đo Golomb với p-1các phần tử có trong các số nguyên modulop(p-1) (đó là một điều kiện thậm chí còn mạnh hơn là một thước đo Golomb trong chính các số nguyên).

Một lợi thế khác khi làm việc trong modulo số nguyên mlà bất kỳ thước đo Golomb nào cũng có thể được xoay (hằng số được thêm vào tất cả các phần tử modulo m) và được chia tỷ lệ (tất cả các phần tử được nhân với cùng một hằng số, miễn là hằng số đó tương đối nguyên tố m), và kết quả vẫn là một người cai trị Golomb; đôi khi số nguyên lớn nhất bị giảm đáng kể bằng cách làm như vậy. Vì vậy, hàm scaledRuzsathử tất cả các tỷ lệ này và ghi lại kết quả. manyRuzsaSetschứa kết quả thực hiện việc xây dựng và nhân rộng này cho tất cả 32 số nguyên tố đầu tiên (được chọn một chút tùy ý, nhưng số nguyên tố thứ 32, 131, lớn hơn 100); có gần 57.000 người cai trị Golomb trong bộ này, phải mất vài phút để tính toán.

Tất nhiên, các kyếu tố đầu tiên của một người cai trị Golomb tự tạo thành một người cai trị Golomb. Vì vậy, hàm tryGolombnhìn vào một thước đo như vậy được làm từ bất kỳ bộ nào được tính ở trên. Dòng cuối cùng Table...chọn thước kẻ Golomb tốt nhất có thể, theo mọi thứ tự từ 50đến 100, từ tất cả các thước kẻ Golomb được tìm thấy theo cách này.

Độ dài được tìm thấy là:

{2241, 2325, 2399, 2578, 2640, 2762, 2833, 2961, 3071, 3151, 3194, 3480, 3533, 3612, 3775, 3917, 4038, 4150, 4237, 4368, 4481, 4563, 4729, 4974, 5111, 5155, 5297, 5504, 5583, 5707, 5839, 6077, 6229, 6480, 6611, 6672, 6913, 6946, 7025, 7694, 7757, 7812, 7969, 8139, 8346, 8407, 8678, 8693, 9028, 9215, 9336}

Ban đầu tôi dự định kết hợp nó với hai công trình khác, đó là Singer và Bose; nhưng có vẻ như câu trả lời của Peter Taylor đã thực hiện điều này, vì vậy có lẽ tôi chỉ đơn giản là sẽ phục hồi những chiều dài đó.


Tôi bối rối bởi tuyên bố của bạn rằng làm việc trong modulo số nguyên, mbạn có thể xoay / chia tỷ lệ một cách tự do. Nhìn vào [0, 1, 4, 6]mod 7. Nếu tôi thêm 1 chúng tôi nhận được [0, 1, 2, 5], đó không phải là thước đo Golomb.
orlp

Đó là bởi vì bạn phải bắt đầu với một thước đo Golomb mod-7 để nó hoạt động. [0, 1, 4, 6]không phải là thước đo Golomb mod-7 vì ví dụ 1 – 0bằng 0 – 6modulo 7.
Greg Martin

1
Trong khi tôi đang viết và gỡ lỗi triển khai trường hữu hạn của mình trong C #, tôi ước tôi biết Mathicala tốt hơn. Chắc chắn là một trong những ngôn ngữ phù hợp cho công việc.
Peter Taylor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.