Цикл де Брёйна, трабл с вызовом рекурсии - C#
Формулировка задачи:
Перевожу с питона на шарп цикл Де Брейна, на английской версии лежит скрипт, который приведен ниже (слегка его подчистил до неоходимого функционала).
Собственно в самом цикле неоднократно происходят вызовы db(x,y), а в шарпе код как будто игнорирует эту инструкцию и спокойно выполняет код дальше. При одинаковых параметрах k n = 2 2, питон выдает необходимые 0011, шарп выдает 0100, поскольку выполняет db единожды, ходя должен минимум трижды.
Что я делаю не так? Возможно кривой перевод программы, но питон не знаю и не разбирался до сегодняшнего дня, пытался даже вызвать из db другой метод - игнорирует.
Листинг программы
- 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))
Листинг программы
- 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;
- }
Решение задачи: «Цикл де Брёйна, трабл с вызовом рекурсии»
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);
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д