En kısa Golomb cetvellerini bulun


15

Golomb cetvelleri , kümedeki iki tam sayı çiftinin birbirinden aynı mesafe olmayacağı şekilde negatif olmayan tamsayı kümeleridir.

Örneğin, [0, 1, 4, 6]bu kümedeki iki tamsayı arasındaki tüm mesafeler benzersiz olduğu için bir Golomb cetvelidir:

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

Bu zorluktaki basitlik uğruna (ve çeviri önemsiz olduğu için), bir Golomb cetvelinin her zaman sayıyı içerdiğini (önceki örneğin yaptığı) empoze ediyoruz .0

Bu setin uzunluğu olduğundan 4, bunun bir Golomb düzen cetveli olduğunu söylüyoruz 4. Bu setteki (veya 0her zaman sette olduğu için eleman) en büyük mesafe, bu 6nedenle bunun bir Golomb Cetvel uzunluğu olduğunu söylüyoruz 6.

Senin görevin

Arasında Golomb cetvelleri bul düzenine 50 karşı 100küçük olarak sahip (dahil) uzunlukları bulabileceğinizin. Bulduğunuz cetvellerin optimal olması gerekmez (aşağıya bakın).

Optimalliği

Daha küçük bir uzunluğa sahip Nbaşka bir Golomb cetveli yoksa, bir Golomb cetvel cetvelinin optimal olduğu söylenir N.

Optimal Golomb cetvelleri 28'den az siparişler için bilinir , ancak sipariş arttıkça iyimserliği bulmak ve kanıtlamak daha zordur.

Bu nedenle, 50ve arasındaki emirlerden herhangi biri için en uygun Golomb cetvelini bulmanız beklenmemektedir 100(ve hatta bunların optimum olduğunu kanıtlayabilmeniz daha az beklenmektedir).

Programınızın yürütülmesinde herhangi bir zaman sınırı yoktur.

Temel

Aşağıdaki listeden Golomb hükümdarlarının uzunlukları listesi 50için 100(sırayla) bir naif arama stratejisi ile değerlendirilmiştir (bu liste için @PeterTaylor için teşekkür):

[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üm bu uzunlukların toplamı 734078.

puanlama

Puanınız 50ve arasındaki tüm Golomb cetvellerinizin uzunluklarının toplamı olacaktır ve taban çizgisi 100arasındaki 50ve 100arasındaki Golomb cetvellerinin uzunluklarının toplamına bölünecektir 734078.

Belirli bir sipariş için bir Golomb cetveli bulamazsanız, söz konusu sipariş için taban çizgisindeki uzunluğun iki katını kullanarak puanınızı aynı şekilde hesaplayacaksınız.

En düşük puana sahip cevap kazanır.

Beraberlik durumunda, iki cevabın farklı olduğu en büyük düzenin uzunlukları karşılaştırılır ve en kısa olanı kazanır. Her iki cevabın da tüm siparişler için aynı uzunlukta olması durumunda, ilk gönderilen cevap kazanır.


2
İlişkili. (2D'de aynı zorluk.)
Martin Ender


50 ila 100 arasında cetvel dediğinde, [50, 100) menzili mi demek istiyorsun? Yani 100 cetvel siparişi dahil değil mi? Çünkü taban çizgisi sadece 50 eleman içerir.
orlp

1
Yan Not: düzenin Golomb Cetvelin mümkün olan en küçük boy nolan n(n-1)/2birçok olumlu farklar vardır nasıl beri. Bu nedenle, bu mücadeledeki mümkün olan en küçük puan 147050/734078 > 0.2003193.
Greg Martin

2
@GregMartin Teşekkürler, bu oldukça "mümkün olan en küçük puan" değil, mümkün olan en küçük puan için bir alt sınır olsa!
17'de

Yanıtlar:


8

C #, 259421/734078 ~ = 0.3534

Yöntemler

Sonunda Genelleştirilmiş Sidon Setleri Konstrüksiyonları'nda projektif alan yönteminin (Singer yöntemi) az ya da çok okunabilir bir açıklamasını buldum , ancak yine de biraz geliştirilebileceğini düşünüyorum. Afin alan yöntemine (Bose yöntemi), okuduğum diğer makalelerin iletişiminden daha benzer olduğu ortaya çıktı.

Bu sonlu cisimler hakkında bilgi sahibi olur . Düşünün asal güç olduğunu ve izin F ( q ) bizim temel alan olması.q=pbirF(q)

Afin alan yöntemi üzerinden çalışır . Bir jeneratör al g 2 arasında F ( q, 2 ), ve sıfır olmayan bir eleman , k ve F ( k ) seti ve dikkate { a : g 2F(q2)g2F(q2)kF(q) Bu değerler modüler bir Golomb cetvel mod q 2 - 1'i oluşturur . Diğer cetveller, modulo q 2 - 1'in , modülle aynı olan herhangi bir sayı ileçarpılmasıyla elde edilebilir.

{bir:g2bir-kg2Fq}
q2-1q2-1

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

{0}{bir:g3bir-kg3Fq}
q2+q+1

Aralarındaki bu yöntemlerin 16'dan büyük her uzunluk için en iyi bilinen değerleri verdiğini unutmayın . Tomas Rokicki ve Gil Dogon, 36 ila 40000 uzunlukları için onları yenen herkes için 250 $ ödül sunuyor. Bu nedenle, bu cevabı yenen herkes para için. ödül.

kod

C # çok deyimsel değil, ama Mono'nun eski bir sürümü ile derlemek gerekir. Ayrıca, argüman kontrolüne rağmen, bu üretim kalite kodu değildir. Türlerden memnun değilim, ama C # için gerçekten iyi bir çözüm olduğunu düşünmüyorum. Belki deli templating ile F # veya 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();
        }
    }
}

Sonuçlar

Ne yazık ki cetvelleri eklemek beni yazı boyutu sınırını aşan yaklaşık 15 bin karakter alacaktı, bu yüzden macunbin üzerinde .


[50, 100] için yöneticilerinizi bir yere göndermek ister misiniz? Denemek istediğim, bazı tohum değerlerini besleyen genetik bir algoritmam var.
orlp

@orlp, bir bağlantı ekledi.
Peter Taylor

2
Şüphelendiğim gibi, evrimsel algoritma bu üstün örnekten hiçbir şey çıkaramaz. Başlangıçta evrimsel algoritmalar işe yarayabilir gibi görünse de (hemen hemen geçersiz yöneticilerden gerçek yöneticilere geçiyor), evrim algoritmasının çalışması için çok fazla küresel yapı gerekli.
orlp

5

Python 3, skor 603001/734078 = 0.82144

Erdős-Turan inşaatı ile birleştirilmiş saf arama:

2pk+(k2şıkp),k[0,p-1]

Garip asal p için asimptotik olarak en uygun golomb cetveli verir.

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

Bu yapının asimptotik olarak en uygun olduğunu düşünmüyorum: pyaklaşık bir düzen ve uzunluk Golomb cetveli 2p^2verirken asimptotik olarak düzen nve uzunluk Golomb cetvelleri var n^2.
Greg Martin

@GregMartin Asimptotik olarak 2p^2ve arasında bir fark yoktur p^2.
orlp

"Asimptotik" tanımınıza bağlı, sanırım, ama bana göre, bu bağlamda çok farklılar.
Greg Martin

3

Mathematica, skor 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}]

İşlev ruzsa, Imre Z. Ruzsa'da bulunan bir Golobm cetvelinin (Sidon seti olarak da adlandırılır) bir yapısını uygular. Bir tamsayı kümesinde doğrusal bir denklem çözme. I. Acta Arith., 65 (3): 259-282, 1993 . Herhangi bir prime göz önüne alındığında p, bu yapı p-1tamsayı modulounda bulunan elemanlara sahip bir Golomb cetveli verir p(p-1)(bu, tamsayıların kendisinde bir Golomb cetveli olmaktan daha güçlü bir durumdur).

Tamsayı modülounda çalışmanın bir başka avantajı, mherhangi bir Golomb cetvelinin döndürülebilmesidir (tüm elemanlar modulouna aynı sabit eklenebilir m) ve ölçeklendirilebilir (bu sabitin görece asal olduğu sürece tüm elemanlar aynı sabitle çarpılır m) ve sonuç hala bir Golomb hükümdarı; bazen en büyük tamsayı bu şekilde önemli ölçüde azalır. Böylece işlev scaledRuzsatüm bu ölçeklendirmeleri dener ve sonuçları kaydeder. manyRuzsaSetsilk 32 primerin tümü için bu yapının ve ölçeklendirmenin sonuçlarını içerir (biraz keyfi olarak seçilir, ancak 32. başbakan 131, 100'den çok daha büyüktür); bu sette yaklaşık 57.000 Golomb cetveli var, bu da hesaplanması birkaç dakika sürüyor.

Tabii ki, kbir Golomb cetvelinin ilk unsurları kendileri bir Golomb cetveli oluştururlar. Böylece fonksiyon tryGolomb, yukarıda hesaplanan setlerden herhangi birinden yapılmış böyle bir cetvele bakar. Son satır Table...her düzenin, yapabileceği en iyi Golomb cetvel, seçer 50için 100tüm Golomb cetveller bu şekilde bulduk gelen,.

Bulunan uzunluklar:

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

Başlangıçta bunu Singer ve Bose'un iki yapısı ile birleştirecektim; ama görünüşe göre Peter Taylor'ın cevabı bunu zaten uyguladı, bu yüzden muhtemelen bu uzunlukları kurtarırım.


Tamsayı modülounda çalışmanın mserbestçe dönebildiğini / ölçeklendirilebileceğini iddia ettiğiniz için kafam karıştı . [0, 1, 4, 6]Mod 7'ye bakın. 1 eklersem [0, 1, 2, 5], bu bir Golomb cetveli değildir .
orlp

Çünkü çalışması için bir mod-7 Golomb cetveli ile başlamalısınız. [0, 1, 4, 6]mod-7 Golomb cetveli değildir 1 – 0, çünkü 0 – 6modulo 7'ye eşittir .
Greg Martin

1
C # 'da sonlu alan uygulamamı yazarken ve hata ayıklarken Mathematica'yı daha iyi tanımamı diledim. Kesinlikle iş için doğru dillerden biri.
Peter Taylor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.