ค้นหาผู้ปกครอง Golomb ที่สั้นที่สุด


15

ผู้ปกครอง Golombเป็นชุดของจำนวนเต็มไม่เป็นลบเช่นนั้นไม่มีสองคู่ของจำนวนเต็มในชุดเป็นระยะห่างกัน

ตัวอย่างเช่น[0, 1, 4, 6]เป็นไม้บรรทัด Golomb เพราะระยะทางทั้งหมดระหว่างสองจำนวนเต็มในชุดนี้ไม่ซ้ำกัน:

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

เพื่อความเรียบง่ายในการท้าทายนี้ (และเนื่องจากการแปลนั้นไม่สำคัญ) เรากำหนดว่าไม้บรรทัด Golomb จะมีหมายเลขอยู่เสมอ0 (ซึ่งเป็นตัวอย่างก่อนหน้านี้)

ตั้งแต่ชุดนี้คือความยาวของ4เราบอกว่านี่คือการปกครอง Golomb ของการสั่งซื้อ 4ระยะทางที่ใหญ่ที่สุดในชุดนี้ (หรือองค์ประกอบตั้งแต่0อยู่เสมอในการตั้งค่า) เป็น6ดังนั้นเราจึงบอกว่านี้เป็น Golomb ไม้บรรทัดของความยาว 6

งานของคุณ

ค้นหาผู้ปกครอง Golomb เพื่อที่ 50จะ100(รวม) ที่มีความยาวขนาดเล็กเท่าที่คุณสามารถหาได้ ผู้ปกครองที่คุณพบว่าไม่จำเป็นต้องเหมาะสมที่สุด (ดูด้านล่าง)

optimality

ผู้ปกครองลำดับ Golomb Nกล่าวกันว่าเหมาะสมถ้าไม่มีผู้ปกครอง Golomb คนอื่นNที่มีความยาวน้อยกว่า

ผู้ปกครอง Golomb ที่ดีที่สุดเป็นที่รู้จักกันสำหรับการสั่งซื้อน้อยกว่า 28แม้ว่าการค้นหาและการพิสูจน์ในแง่ดีนั้นยากขึ้นและยากขึ้นตามคำสั่งที่เพิ่มขึ้น

ดังนั้นจึงไม่คาดว่าคุณจะพบผู้ปกครอง Golomb ที่ดีที่สุดสำหรับคำสั่งซื้อใด ๆ ระหว่าง50และ100(และแม้แต่คาดหวังน้อยลงว่าคุณสามารถพิสูจน์ได้ว่าเหมาะสมที่สุด)

ไม่มีการ จำกัด เวลาในการเรียกใช้โปรแกรมของคุณ

พื้นฐาน

รายการด้านล่างคือรายการความยาวของผู้ปกครอง Golomb ตั้งแต่50ถึง100(เรียงตามลำดับ) ประเมินโดยใช้กลยุทธ์การค้นหาแบบไร้เดียงสา (ขอบคุณ @PeterTaylor สำหรับรายการนี้):

[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]

734078ผลรวมของความยาวทั้งหมดนั้นคือ

เกณฑ์การให้คะแนน

คะแนนของคุณจะเป็นผลรวมของความยาวทั้งหมดของผู้ปกครอง Golomb ของคุณระหว่าง50และ100หารด้วยผลรวมของความยาวของผู้ปกครอง Golomb ระหว่าง50และในพื้นฐาน:100734078

ในกรณีที่คุณไม่พบผู้ปกครอง Golomb สำหรับคำสั่งซื้อที่เฉพาะเจาะจงคุณจะต้องคำนวณคะแนนของคุณในลักษณะเดียวกันโดยใช้ความยาวสองเท่าในพื้นฐานสำหรับคำสั่งซื้อนั้น

คำตอบที่มีคะแนนต่ำสุดชนะ

ในกรณีที่เสมอกันความยาวของลำดับที่ใหญ่ที่สุดที่คำตอบทั้งสองต่างกันจะถูกเปรียบเทียบและอันดับที่สั้นที่สุดจะชนะ ในกรณีที่คำตอบทั้งคู่มีความยาวเท่ากันสำหรับคำสั่งซื้อทั้งหมดคำตอบที่โพสต์ก่อนชนะ


2
ที่เกี่ยวข้อง (ความท้าทายแบบเดียวกันใน 2D)
Martin Ender

และOEIS รายการ
Martin Ender

เมื่อคุณพูดว่าผู้ปกครองระหว่าง 50 ถึง 100 คุณหมายถึงช่วง [50, 100) หรือไม่? ดังนั้นไม่รวมไม้บรรทัด 100 อันดับ? เพราะพื้นฐานมีเพียง 50 องค์ประกอบ
orlp

1
หมายเหตุด้านข้าง: ความยาวที่เล็กที่สุดเท่าที่จะเป็นไปได้ของไม้บรรทัด Golomb nคือn(n-1)/2เพราะนั่นคือความแตกต่างในเชิงบวกที่มี 147050/734078 > 0.2003193ดังนั้นคะแนนเป็นไปได้ที่เล็กที่สุดในความท้าทายนี้คือ
Greg Martin เมื่อ

2
@ GregMartin ขอบคุณ แต่นี่ไม่ใช่ "คะแนนที่เล็กที่สุดที่เป็นไปได้" แต่ค่อนข้างต่ำกว่าในคะแนนที่เล็กที่สุดที่เป็นไปได้!
ลดขนาด

คำตอบ:


8

C #, 259421/734078 ~ = 0.3534

วิธีการ

ในที่สุดฉันก็พบคำอธิบายวิธีฟิลด์ projective (วิธีการของนักร้อง) ที่อ่านได้มากขึ้นหรือน้อยลงในการสร้างชุด Generalized Sidonแม้ว่าฉันจะยังคิดว่ามันจะดีขึ้นเล็กน้อย ดูเหมือนว่าจะคล้ายกับวิธีการเลียนแบบฟิลด์ (วิธีการของ Bose) มากกว่าเอกสารอื่น ๆ ที่ฉันอ่านที่มีการสื่อสาร

q=paF(q)

F(q2)g2F(q2)kF(q)

{a:g2akg2Fq}
q21q21

F(q3)g3F(q3)kF(q)

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

โปรดทราบว่าวิธีการเหล่านี้ระหว่างพวกเขาให้คุณค่าที่รู้จักกันดีที่สุดสำหรับทุกความยาวที่มากกว่า 16 Tomas Rokicki และ Gil Dogon กำลังเสนอรางวัล $ 250สำหรับผู้ที่ชนะพวกเขาในความยาว 36 ถึง 40000 ดังนั้นใครก็ตามที่ชนะคำตอบนี้จะเป็นเงิน รางวัล.

รหัส

C # ไม่ใช่เรื่องแปลก แต่ฉันต้องการมันเพื่อคอมไพล์กับ Mono เวอร์ชั่นเก่า นอกจากนี้แม้จะมีการตรวจสอบข้อโต้แย้งนี่ไม่ใช่รหัสคุณภาพการผลิต ฉันไม่พอใจกับประเภท แต่ฉันไม่คิดว่าจะมีวิธีแก้ปัญหาที่ดีใน C # อาจอยู่ใน F # หรือ C ++ ที่มีเทมเพลตบ้า

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();
        }
    }
}

ผล

แต่น่าเสียดายที่การเพิ่มผู้ปกครองจะพาฉันเกี่ยวกับ 15k ตัวละครที่ผ่านมาขนาด จำกัด โพสต์เพื่อให้พวกเขาอยู่บน Pastebin


คุณจะกรุณาโพสต์ผู้ปกครองของคุณเพื่อ [50, 100] ไหม? ฉันมีอัลกอริทึมทางพันธุกรรมที่ฉันต้องการลองป้อนค่าเมล็ด
orlp

@orlp เพิ่มลิงค์
ปีเตอร์เทย์เลอร์

2
อย่างที่ฉันสงสัยว่าอัลกอริธึมวิวัฒนาการสามารถแยกสิ่งที่ไม่มีประโยชน์ออกจากตัวอย่างที่เหนือกว่าเหล่านี้ แม้ว่าในตอนแรกดูเหมือนว่าอัลกอริธึมวิวัฒนาการอาจใช้งานได้ (มันจะย้ายจากผู้ปกครองที่ไม่ถูกต้องไปยังผู้ปกครองที่เกิดขึ้นจริงในทันที) แต่ก็มีโครงสร้างระดับโลกที่จำเป็นสำหรับอัลกอริทึมวิวัฒนาการในการทำงาน
orlp

5

Python 3 คะแนน 603001/734078 = 0.82144

การค้นหาที่ไร้เดียงสารวมกับการก่อสร้างErdős – Turan:

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

สำหรับช่วงเวลาที่แปลกหน้านี้จะช่วยให้ผู้ปกครอง Golomb asymptotically ดีที่สุด

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))

ฉันไม่คิดว่าสิ่งก่อสร้างนี้เหมาะสมที่สุดสำหรับ asymptotically: มันให้ผู้ปกครองของ Golomb pเกี่ยวกับคำสั่งและความยาวเกี่ยวกับ2p^2ในขณะที่มีผู้ปกครอง Golomb ของคำสั่งnและความยาวเกี่ยวกับn^2asymptotically
เกร็กมาร์ติ

@GregMartin asymptotically มีความแตกต่างระหว่างไม่มีและ2p^2 p^2
orlp

ขึ้นอยู่กับคำจำกัดความของคุณของ "asymptotically" ฉันเดา แต่สำหรับฉันในบริบทนี้มันแตกต่างกันมาก
เกร็กมาร์ติ

3

Mathematica, คะแนน 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}]

ฟังก์ชั่นนี้ruzsaใช้การสร้างไม้บรรทัด Golobm (เรียกอีกอย่างว่าชุด Sidon) ที่พบในImre Z. Ruzsa การแก้สมการเชิงเส้นในชุดจำนวนเต็ม I. Acta ARITH 65 (3):. 259-282 1993 จากการที่นายกpก่อสร้างสิ่งนี้ยอมให้ผู้ปกครอง Golomb ด้วยp-1องค์ประกอบที่มีอยู่ในโมดูโลจำนวนเต็มp(p-1)(ซึ่งเป็นเงื่อนไขที่แข็งแกร่งยิ่งกว่าการเป็นผู้ปกครอง Golomb ในจำนวนเต็มเอง)

ข้อดีอีกอย่างของการทำงานในจำนวนเต็มแบบโมดูโลmคือผู้ปกครอง Golomb สามารถหมุนได้ (ค่าคงที่เดียวกันที่เพิ่มเข้ากับทุกองค์ประกอบโมดูโลm) และปรับขนาด (องค์ประกอบทั้งหมดคูณด้วยค่าคงที่เดียวกันตราบใดที่ค่าคงที่นั้นค่อนข้างไพเราะm) ผลที่ได้คือผู้ปกครอง Golomb; บางครั้งจำนวนเต็มที่มากที่สุดจะลดลงอย่างมีนัยสำคัญโดยการทำเช่นนั้น ดังนั้นฟังก์ชั่นจึงscaledRuzsaพยายาม scalings เหล่านี้ทั้งหมดและบันทึกผลลัพธ์ manyRuzsaSetsมีผลลัพธ์ของการดำเนินการก่อสร้างและปรับขนาดสำหรับช่วง 32 ทั้งหมดแรก (เลือกบิตโดยพลการ แต่อันดับ 32, 131, มีขนาดใหญ่กว่า 100); มีผู้ปกครอง Golomb เกือบ 57,000 คนในชุดนี้ซึ่งใช้เวลาในการคำนวณหลายนาที

แน่นอนว่าkองค์ประกอบแรกของผู้ปกครอง Golomb เองก็เป็นผู้ปกครอง Golomb ดังนั้นฟังก์ชั่นtryGolombจะดูที่ไม้บรรทัดที่ทำจากชุดใด ๆ ที่คำนวณข้างต้น บรรทัดสุดท้ายTable...เลือกผู้ปกครอง Golomb ที่ดีที่สุดเท่าที่จะทำได้จากทุกคำสั่งจาก50ถึง100ผู้ปกครอง Golomb ทั้งหมดที่พบในวิธีนี้

ความยาวที่พบคือ:

{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}

เดิมทีฉันจะรวมสิ่งนี้เข้ากับสิ่งปลูกสร้างอีกสองแห่งคือซิงเกอร์และโบส; แต่ดูเหมือนว่าคำตอบของปีเตอร์เทย์เลอร์ได้ดำเนินการตามนี้ไปแล้วดังนั้นฉันน่าจะกู้คืนความยาวเหล่านั้นได้


ฉันสับสนโดยการกล่าวอ้างของคุณว่าการทำงานในโมดูโลจำนวนเต็มmคุณสามารถหมุน / ปรับขนาดได้อย่างอิสระ ดู[0, 1, 4, 6]mod 7 ถ้าฉันบวก 1 เราจะได้[0, 1, 2, 5]ซึ่งไม่ใช่ไม้บรรทัด Golomb
orlp

นั่นเป็นเพราะคุณต้องเริ่มต้นด้วยไม้บรรทัด Golomb mod-7 เพื่อให้สามารถใช้งานได้ [0, 1, 4, 6]ไม่ใช่ไม้บรรทัด Golomb mod-7 เพราะ1 – 0เท่ากับ0 – 6modulo 7 เป็นต้น
เกร็กมาร์ติ

1
ในขณะที่ฉันกำลังเขียนและแก้ไขจุดบกพร่องในการใช้งานฟิลด์ จำกัด ของฉันใน C # ฉันต้องการให้ฉันรู้ Mathematica ได้ดีขึ้น แน่นอนหนึ่งในภาษาที่เหมาะสมสำหรับงาน
ปีเตอร์เทย์เลอร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.