Цикл де Брёйна, трабл с вызовом рекурсии - C#

Узнай цену своей работы

Формулировка задачи:

Перевожу с питона на шарп цикл Де Брейна, на английской версии лежит скрипт, который приведен ниже (слегка его подчистил до неоходимого функционала).
def de_bruijn(k, n):
    """
    De Bruijn sequence for alphabet k
    and subsequences of length n.
    """
    alphabet = list(map(str, range(k)))
    a = [0] * k * n
    sequence = []
 
    def db(t, p):
        if t > n:
            if n % p == 0:
                sequence.extend(a[1:p + 1])
        else:
            a[t] = a[t - p]
            db(t + 1, p)
            for j in range(a[t - p] + 1, k):
                a[t] = j
                db(t + 1, t)
    db(1, 1)
    return "".join(alphabet[i] for i in sequence)
 
print(de_bruijn(2, 2))
Собственно в самом цикле неоднократно происходят вызовы db(x,y), а в шарпе код как будто игнорирует эту инструкцию и спокойно выполняет код дальше. При одинаковых параметрах k n = 2 2, питон выдает необходимые 0011, шарп выдает 0100, поскольку выполняет db единожды, ходя должен минимум трижды.
static int k=2, n=2;
        int[] a = new int[k * n];
        static List<int> sequence = new List<int>();
 
        void db(int t, int p)
        {
            if (t > p)
            {
                if (n % p==0)
                {
                    for (int i = 1; i >= p + 1; i++)
                    {
                        sequence.Add(a[i]);
                    }
                }
            }
            else
            {
                a[t] = a[t - p];
                db(t + 1, p);
                for (int j = a[t - p] + 1; j < k; j++)
                {
                    a[t] = j;
                    db(t + 1, t);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            db(1, 1);
            string s = string.Empty;
            for (int i = 0; i < a.Length; i++)
            {
                s += a[i];  
            }
            textBox1.Text = "" + s;
        }
Что я делаю не так? Возможно кривой перевод программы, но питон не знаю и не разбирался до сегодняшнего дня, пытался даже вызвать из db другой метод - игнорирует.

Решение задачи: «Цикл де Брёйна, трабл с вызовом рекурсии»

textual
Листинг программы
using System;
using Google.OrTools.ConstraintSolver;
 
public class DeBruijn
{
 
    // [url]https://github.com/google/or-tools/releases[/url]
 
    /**
     *
     *  ToNum(solver, a, num, base)
     *
     *  channelling between the array a and the number num.
     *
     */
    private static Constraint ToNum(IntVar[] a, IntVar num, int bbase)
    {
        int len = a.Length;
 
        IntVar[] tmp = new IntVar[len];
        for (int i = 0; i < len; i++)
        {
            tmp[i] = (a[i] * (int)Math.Pow(bbase, (len - i - 1))).Var();
        }
        return tmp.Sum() == num;
    }
 
 
 
    /**
     *
     * Implements "arbitrary" de Bruijn sequences.
     * See [url]http://www.hakank.org/or-tools/debruijn_binary.py[/url]
     *
     */
    private static void Solve(int bbase, int n, int m)
    {
        Solver solver = new Solver("DeBruijn");
 
 
        // Ensure that the number of each digit in bin_code is
        // the same. Nice feature, but it can slow things down...
        bool check_same_gcc = false; // true;
 
        //
        // Decision variables
        //
        IntVar[] x = solver.MakeIntVarArray(m, 0, (int)Math.Pow(bbase, n) - 1, "x");
        IntVar[,] binary = solver.MakeIntVarMatrix(m, n, 0, bbase - 1, "binary");
 
        // this is the de Bruijn sequence
        IntVar[] bin_code =
          solver.MakeIntVarArray(m, 0, bbase - 1, "bin_code");
 
        // occurences of each number in bin_code
        IntVar[] gcc = solver.MakeIntVarArray(bbase, 0, m, "gcc");
 
        // for the branching
        IntVar[] all = new IntVar[2 * m + bbase];
        for (int i = 0; i < m; i++)
        {
            all[i] = x[i];
            all[m + i] = bin_code[i];
        }
        for (int i = 0; i < bbase; i++)
        {
            all[2 * m + i] = gcc[i];
        }
 
 
        //
        // Constraints
        //
 
        solver.Add(x.AllDifferent());
 
        // converts x <-> binary
        for (int i = 0; i < m; i++)
        {
            IntVar[] t = new IntVar[n];
            for (int j = 0; j < n; j++)
            {
                t[j] = binary[i, j];
            }
            solver.Add(ToNum(t, x[i], bbase));
        }
 
        // the de Bruijn condition:
        // the first elements in binary[i] is the same as the last
        // elements in binary[i-1]
        for (int i = 1; i < m; i++)
        {
            for (int j = 1; j < n; j++)
            {
                solver.Add(binary[i - 1, j] == binary[i, j - 1]);
            }
        }
 
        // ... and around the corner
        for (int j = 1; j < n; j++)
        {
            solver.Add(binary[m - 1, j] == binary[0, j - 1]);
        }
 
        // converts binary -> bin_code (de Bruijn sequence)
        for (int i = 0; i < m; i++)
        {
            solver.Add(bin_code[i] == binary[i, 0]);
 
        }
 
 
        // extra: ensure that all the numbers in the de Bruijn sequence
        // (bin_code) has the same occurrences (if check_same_gcc is True
        // and mathematically possible)
        solver.Add(bin_code.Distribute(gcc));
        if (check_same_gcc && m % bbase == 0)
        {
            for (int i = 1; i < bbase; i++)
            {
                solver.Add(gcc[i] == gcc[i - 1]);
            }
        }
 
        // symmetry breaking:
        // the minimum value of x should be first
        // solver.Add(x[0] == x.Min());
 
 
        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(all,
                                              Solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
                                              Solver.ASSIGN_MIN_VALUE);
 
        solver.NewSearch(db);
 
        while (solver.NextSolution())
        {
            Console.Write("x: ");
            for (int i = 0; i < m; i++)
            {
                Console.Write(x[i].Value() + " ");
            }
 
            Console.Write("\nde Bruijn sequence:");
            for (int i = 0; i < m; i++)
            {
                Console.Write(bin_code[i].Value() + " ");
            }
 
            Console.Write("\ngcc: ");
            for (int i = 0; i < bbase; i++)
            {
                Console.Write(gcc[i].Value() + " ");
            }
            Console.WriteLine("\n");
 
 
            // for debugging etc: show the full binary table
            /*
            Console.Write("binary:");
            for(int i = 0; i < m; i++) {
              for(int j = 0; j < n; j++) {
                Console.Write(binary[i][j].Value() + " ");
              }
              Console.WriteLine();
            }
            Console.WriteLine();
            */
 
        }
 
        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());
 
        solver.EndSearch();
 
    }
 
    public static void Main(String[] args)
    {
        int bbase = 2;
        int n = 3;
        int m = 8;
 
        if (args.Length > 0)
        {
            bbase = Convert.ToInt32(args[0]);
        }
 
        if (args.Length > 1)
        {
            n = Convert.ToInt32(args[1]);
        }
 
        if (args.Length > 2)
        {
            m = Convert.ToInt32(args[2]);
        }
 
        Solve(bbase, n, m);
    }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

12   голосов , оценка 4 из 5
Похожие ответы