Task: Addition chains


C++: #include <iostream>
#include <tuple>
#include <vector>

std::pair<int, int> tryPerm(int, int, const std::vector<int>&, int, int);

std::pair<int, int> checkSeq(int pos, const std::vector<int>& seq, int n, int minLen) {
    if (pos > minLen || seq[0] > n) return { minLen, 0 };
    else if (seq[0] == n)           return { pos, 1 };
    else if (pos < minLen)          return tryPerm(0, pos, seq, n, minLen);
    else                            return { minLen, 0 };
}

std::pair<int, int> tryPerm(int i, int pos, const std::vector<int>& seq, int n, int minLen) {
    if (i > pos) return { minLen, 0 };

    std::vector<int> seq2{ seq[0] + seq[i] };
    seq2.insert(seq2.end(), seq.cbegin(), seq.cend());
    auto res1 = checkSeq(pos + 1, seq2, n, minLen);
    auto res2 = tryPerm(i + 1, pos, seq, n, res1.first);

    if (res2.first < res1.first)       return res2;
    else if (res2.first == res1.first) return { res2.first, res1.second + res2.second };
    else                               throw std::runtime_error("tryPerm exception");
}

std::pair<int, int> initTryPerm(int x) {
    return tryPerm(0, 0, { 1 }, x, 12);
}

void findBrauer(int num) {
    auto res = initTryPerm(num);
    std::cout << '\n';
    std::cout << "N = " << num << '\n';
    std::cout << "Minimum length of chains: L(n)= " << res.first << '\n';
    std::cout << "Number of minimum length Brauer chains: " << res.second << '\n';
}

int main() {
    std::vector<int> nums{ 7, 14, 21, 29, 32, 42, 64, 47, 79, 191, 382, 379 };
    for (int i : nums) {
        findBrauer(i);
    }

    return 0;
}


C#: using System;

namespace AdditionChains {
    class Program {
        static int[] Prepend(int n, int[] seq) {
            int[] result = new int[seq.Length + 1];
            Array.Copy(seq, 0, result, 1, seq.Length);
            result[0] = n;
            return result;
        }

        static Tuple<int, int> CheckSeq(int pos, int[] seq, int n, int min_len) {
            if (pos > min_len || seq[0] > n) return new Tuple<int, int>(min_len, 0);
            if (seq[0] == n) return new Tuple<int, int>(pos, 1);
            if (pos < min_len) return TryPerm(0, pos, seq, n, min_len);
            return new Tuple<int, int>(min_len, 0);
        }

        static Tuple<int, int> TryPerm(int i, int pos, int[] seq, int n, int min_len) {
            if (i > pos) return new Tuple<int, int>(min_len, 0);

            Tuple<int, int> res1 = CheckSeq(pos + 1, Prepend(seq[0] + seq[i], seq), n, min_len);
            Tuple<int, int> res2 = TryPerm(i + 1, pos, seq, n, res1.Item1);

            if (res2.Item1 < res1.Item1) return res2;
            if (res2.Item1 == res1.Item1) return new Tuple<int, int>(res2.Item1, res1.Item2 + res2.Item2);

            throw new Exception("TryPerm exception");
        }

        static Tuple<int, int> InitTryPerm(int x) {
            return TryPerm(0, 0, new int[] { 1 }, x, 12);
        }

        static void FindBrauer(int num) {
            Tuple<int, int> res = InitTryPerm(num);
            Console.WriteLine();
            Console.WriteLine("N = {0}", num);
            Console.WriteLine("Minimum length of chains: L(n)= {0}", res.Item1);
            Console.WriteLine("Number of minimum length Brauer chains: {0}", res.Item2);
        }

        static void Main(string[] args) {
            int[] nums = new int[] { 7, 14, 21, 29, 32, 42, 64, 47, 79, 191, 382, 379 };
            Array.ForEach(nums, n => FindBrauer(n));
        }
    }
}