Neural networks against the Tinkoff contest

I recently took a challenge challenge from T-Bank and it wasn’t too difficult, so I decided to see how our neural networks, namely GigaChat from Sberbank and Alice from Yandex (paid version), would cope with them. At first I fed them the full text of the problem, if there were difficulties or the neuron did not want to work at all, then I simplified the task by removing all the water and formulating the problem more straightforwardly, and again tried to get an intelligible answer. The full text of the tasks can be found on the Internet, here, For example. There will be a short condition here. Also, there will be no right decisions here, you can look at my githubif necessary. Let's get started!

Problem 1. Intervals

Given the intervals of the sequence “1-6,8-9,11” you need to get the initial series of numbers “1 2 3 4 5 6 8 9 11”

Alice
string inputString = "1-6,8-9,11"; 
string[] intervals = inputString.Split(',');
List<int> numbers = new List<int>(); 
foreach (string interval in intervals)
        {
            Match match = Regex.Match(interval, @"(\d+)-(\d+)");
            if (match.Success)
        {
                int start = int.Parse(match.Groups[1].Value); 
                int end = int.Parse(match.Groups[2].Value); 
                for (int i = start; i <= end; i++)
                {
                    numbers.Add(i); 
                }
            }
        }
        numbers.Sort(); 
        Console.WriteLine(string.Join(" ", numbers));

In general, the script is almost working, but due to the fact that the neuron decided to use regular expressions, it skips single intervals. Fixed, although I think that using regular expressions for such a task is overkill, but Alice coped with the task, even without distorting the task

Sber
string input = Console.ReadLine();
string[] intervals = input.Split(',');
List<int> numbers = new List<int>();

foreach (string interval in intervals)
{
    string[] range = interval.Split('-');
    int start = int.Parse(range[0]);
    int end = int.Parse(range[1]);
    for (int i = start; i <= end; i++)
    {
        numbers.Add(i);
    }
}

numbers.Sort();
Console.WriteLine("Отсортированный список: ");
foreach (int num in numbers)
{
    Console.Write(num + " ");
}
Console.WriteLine();

I also didn’t take into account that the interval could be single and, in general, would fall in tests, because it would give IndexOutOfRangeafter some minor edits the script worked.

The task was as simple as possible, so it is not surprising that both neurons did an excellent job. I won’t dwell long on simple cases, so let’s move on.

Problem 2. Falling snow

We need to find the sequence in which the snow fell, or say that the data is manipulated. But some of the measurements are corrupted.

Input 1 3 -1 10 -1

Output YES 1 2 3 4 5, that is, on the first day 1 mm of snow fell, then 2, etc. Accordingly, the input implies measuring snow on each day, if you replace -1 with correct data, then the input is 1 3 6 10 15

Both neurons could not understand what they wanted from them. Sber simply added up all the numbers, then checked whether it was equal to the sum of all the numbers totalSnowFall == actualValues.Sum().

Sber
for (int i = 0; i < n; i++)
        {
            if (readings[i] == "-1")
            {
                continue;
            }
            else
            {
                int snowDepth = int.Parse(readings[i]);
                totalSnowFall += snowDepth;
                actualValues.Add(snowDepth);
            }
        }

        if (totalSnowFall == actualValues.Sum())
        {
            Console.WriteLine("YES");
            Console.WriteLine(string.Join(" ", actualValues));
        }
        else
        {
            Console.WriteLine("NO");
        }
if (totalSnowFall == actualValues.Sum()) 
{ 
  Console.WriteLine("YES");
  Console.WriteLine(string.Join(" ", actualValues)); 
}

Alice also decided to add up all the original data, replacing -1 with 1

Alice
for (int i = 0; i < n; i++)
    {
        if (a[i] == "-1")
        {
            a[i] = 1;
        }
        Console.Write(a[i] + " ");
    }

After simplifying the problem conditions, the situation did not change. So the second task is generally bypassed. But don’t blame the neurons, here the condition itself was not given very correctly by Tinkov, from the text and the given tests it is impossible to say unambiguously which sequence needs to be specified, whether it can be geometric or only algebraic, and whether the sequence in general can be there constantly the same number or even random. I myself solved this problem exclusively for the given tests and some cases, for which I myself came up with rules of behavior in this situation, since they were simply not stated in the conditions. So don’t be upset, further conditions, although more complicated, are more understandable and the neurons eat them up.

Task 3. Password selection

You need to calculate the password from the last characters pressed. Given a sequence of random letters, a set of letters that should make up the password and the maximum length of the password, you need to choose the longest password, or say that it cannot be obtained (-1).
last characters entered: abacaba

allowed characters: abc

maximum length: 4

Reply caba

Sber
 string sequence = Console.ReadLine();
string symbols = Console.ReadLine();
int k = int.Parse(Console.ReadLine());
char[] seqSymbols = sequence.ToCharArray();
HashSet<char> usedSymbols = new HashSet<char>(seqSymbols);
HashSet<char> neededSymbols = new HashSet<char>(symbols);
List<string> possiblePasswords = new List<string>();

foreach (char firstSymbol in usedSymbols)
{
    if (usedSymbols.Count - 1 == neededSymbols.Count)
    {
        continue;
    }
    string password = BuildPassword(firstSymbol, usedSymbols, neededSymbols, k);
    if (password != null)
    {
        possiblePasswords.Add(password);
    }
}

if (possiblePasswords.Count == 0)
{
    Console.WriteLine("-1");
}
else
{
    string bestPassword = possiblePasswords.OrderByDescending(p => p.Length).ThenBy(p => sequence.IndexOf(p)).First();
    Console.WriteLine(bestPassword);
}
private static string BuildPassword(char firstSymbol, HashSet<char> usedSymbols, HashSet<char> neededSymbols, int k)
{
    if (usedSymbols.Count < neededSymbols.Count)
    {
        return null;
    }
    if (usedSymbols.Count == neededSymbols.Count && k == 1)
    {
        return firstSymbol.ToString();
    }
    for (int i = 0; i < k - 1; i++)
    {
        if (usedSymbols.Count == neededSymbols.Count)
        {
            return firstSymbol.ToString() + sequence.Substring(i + 1, k - 1);
        }
        usedSymbols.Add(sequence[i + 1]);
    }
    return null;
}

I moved part of the code into a separate function and tried to do it beautifully, assigning private static attributes, but did not take into account that this is how functions that do not interact with the internal data of the object are designated, and then it requests the sequence of entered letters from the main class. The AI ​​didn’t stop there; it decided to use hashes, including for characters entered from the keyboard, and ultimately corrupted the original data. He didn’t solve the problem, he just guessed the correct answer “-1” in 2 out of 5 tests. To fix this code, you need to almost completely rewrite it, replace hashes with sheets, for example, add password-brute force logic. Therefore, I don’t count this task either. If you simplify the problem and rephrase it, the result is the same.

Alice
string sequence = "abacaba";
char[] allowedChars = { 'a', 'b', 'c' };
int maxLength = 4;
// Создаём все возможные комбинации символов из последовательности
var combinations = sequence.SelectMany(c => allowedChars, (c, a) => new { c, a });
Console.WriteLine(combinations);
// Отфильтровываем комбинации, длина которых превышает максимальную длину
combinations = combinations.Where(c => c.Length <= maxLength);
// Сортируем комбинации по длине в порядке убывания
combinations = combinations.OrderByDescending(c => c.Length);
// Выбираем первую комбинацию, которая соответствует всем условиям
var result = combinations.First();
return result.c.ToString();

Madame decided that this was a combinatorics problem, and used SelectManythis method will not be able to iterate through a string into combinations. I’m not saying that the code doesn’t compile at all because of the attempt to find out the length of the char “c.Length”. And choosing the right password is actually a chore

// Выбираем первую комбинацию, которая соответствует всем условиям
var result = combinations.First();

Accordingly, it is not even stipulated that there may not be a password in the sequence, just a set of random lines of code.

There is a definite minus here, the task was simplified as much as possible, but even so Alice could not write at least something useful.

Problem 4. Prime numbers

Alice
        public string main(string input)
        {
            var inputList = input.Split(' ');
            int l = int.Parse(inputList[0]);
            int r = int.Parse(inputList[0]);


            int count = 0;
            for (int i = l; i <= r; i++)
            {
                if (IsComposite(i) && IsPrime(GetDivisorsCount(i)))
                    count++;
            }

            return count.ToString();
        }

        static bool IsComposite(int num)
        {
            return num > 1 && num % 2 == 0
                || num % 2 != 0 && num % 3 == 0
                || num % 5 == 0
                || num % 7 == 0; // Проверка на составное число
        }

        static bool IsPrime(int divisorCount)
        {
            return divisorCount == 2; // Проверка, является ли количество делителей простым числом
        }

        static int GetDivisorsCount(int num)
        {
            int divisorCount = 0;
            for (int i = 1; i <= num / 2; i++)
            {
                if (num % i == 0)
                    divisorCount++;
            }
            return divisorCount + 1; // Учитываем само число
        }

She decided to cheat and wrote code that works, but very rarely as it should. Here, for example, is how she determines the prime of a number

static bool IsPrime(int divisorCount)
{
    return divisorCount == 2;
}

Or here is a function for determining a composite number (yes, these are 2 different functions)

static bool IsComposite(int num)
{
    return num > 1 && num % 2 == 0
        || num % 2 != 0 && num % 3 == 0
        || num % 5 == 0
        || num % 7 == 0; 
}

If everything is clear with the first function, it is possible to determine only an even number (which in general is not prime), then in the second function there are options that it will work more, however, this approach does not take into account rare cases, for example, 121 whose divisors are 1 , 11, 121.

Accordingly, 4 out of 6 tests failed, so there is no point in rewriting and finishing this code either, since the main essence of the task is missed here: to write an effective script for determining the primality of a number.

Sber
 static void Main()
    {
        int l = int.Parse(Console.ReadLine());
        int r = int.Parse(Console.ReadLine());
        int count = 0;
        for (int i = l; i <= r; i++)
        {
            int divisorsCount = CountDivisors(i);
            if (IsPrimeNumber(divisorsCount))
            {
                count++;
            }
        }

        Console.WriteLine(count);
    }

    private static int CountDivisors(int number)
    {
        int count = 0;
        for (int i = 1; i * i <= number; i++)
        {
            if (number % i == 0)
            {
                count++;
                if (i != number / i)
                {
                    count++;
                }
            }
        }
        return count;
    }

    private static bool IsPrimeNumber(int number)
    {
        if (number <= 1)
        {
            return false;
        }
        if (number <= 3)
        {
            return true;
        }
        if (number % 2 == 0 || number % 3 == 0)
        {
            return false;
        }
        for (int i = 5; i * i <= number; i += 6)
        {
            if (number % i == 0 || number % (i + 2) == 0)
            {
                return false;
            }
        }
        return true;
    }
}

If Alice guessed at least 2 tests, then the hit is 0 out of 6, but if you add one condition that the AI ​​did not take into account, then everything will work and even pass all the tests.

if (IsPrimeNumber(i))
        {
            continue;
        }

It’s interesting that Sberbank wrote a good algorithm for identifying the primality of a number, which works quite quickly, but did not take into account one condition from the problem. However, although with a little help, it successfully completed the task, unlike its paid competitor.

Next are quite voluminous tasks in themselves, I initially did not hope that they would be able to solve them, so I will not give the code, only clippings

Problem 5. Hackers

It was necessary to parse the results of a hacker competition, which provided data on requests to the target servers “Team1 01:10:00 A FORBIDEN”. That is, the command name, time, server name, hacking result. Given n such queries, you need to find out who won and display a table of results.

Sber wrote a piece of code that had a bunch of errors and didn’t even compile. From the main one, he named the variables, sometimes with a small letter, sometimes with a capital letter. I forgot to determine the places of the participants, and then in the answer I write simply place But even if all the shortcomings are corrected, the code does not pass a single test, although it is quite close, based on the results, I think if you sit and think about this neuro code, you can make a working solution, but It’s better to spend this time on solving the problem yourself, rather than refactoring. However, it does provide a good code structure that you can use as a basis for your solution.

Alice refused to solve any problems, this is not the royal business. Paid version, what to do…

Problem 6. Graphs

There is a graph of processes dependent on each other, we are given which processes depend on whom, and how long each of them takes. We need to calculate the minimum time for all processes to complete.

Sber
            void Visit(int node)
            {
                if (visitedNodes.Contains(node))
                {
                    return;
                }
                visitedNodes.Add(node);
                foreach (var childNode in dependencyGraph[node])
                {
                    Visit(childNode);
                }
                stack.Push(node);
            }

Sber tried recursion to traverse all the values ​​and create a graph, but in the end it requests a child node in the array of parent nodes and throws an error.

And then it produces this line:

var pathTimes = criticalPathTimes.Select(times => times.Aggregate(0L, (acc, next) => acc + criticalPathTimes[next].Aggregate(0L, (sum, t) => sum + criticalPathTimes[t].Aggregate(0L, (innerSum, _) => innerSum + t)))).ToList();

It looks terrible and doesn't work. Even if you replace the element call in the hashlist by index criticalPathTimes[next] on criticalPathTimes.ElementAt(next) then this still will not work, since the graph itself is constructed incorrectly.

There are always problems with hashesets, even more so with recursion

Alice
        public string main(string inputing)
        {
            var inputString = inputing.Split("_");
            int n = int.Parse(inputString[0]);// считываем количество процессов
            List<Process> processes = new List<Process>();
            for (int i = 1; i < n; i++)
            {
                string[] input = inputString[i].Split(' ');
                int ti = int.Parse(input[0]); // время исполнения процесса
                List<int> dependencies = new List<int>();
                for (int j = 1; j < input.Length; j++)
                {
                    dependencies.Add(int.Parse(input[j]));
                }
                processes.Add(new Process(ti, dependencies));
            }
            // Сортировка процессов по времени исполнения
            processes.Sort((p1, p2) => p2.Time.CompareTo(p1.Time));

            // Инициализация времени выполнения всех процессов
            long totalTime = 0;
            foreach (Process process in processes)
            {
                totalTime += process.Time;
            }
            // Обработка зависимостей
            for (int i = 0; i < n; i++)
            {
                Process currentProcess = processes[i];
                if (currentProcess.Dependencies.Count == 0) // Если процесс не зависит от других
                {
                    totalTime -= currentProcess.Time; // Уменьшаем общее время выполнения на время выполнения текущего процесса
                }
                else
                {
                    foreach (int dependency in currentProcess.Dependencies) // Проверяем зависимости
                    {
                        Process dependencyProcess = processes[dependency - 1];
                        if (dependencyProcess.Time > totalTime) // Если время выполнения зависимости больше общего времени выполнения
                        {
                            totalTime = dependencyProcess.Time; // Обновляем общее время выполнения
                            break; // Переходим к следующему процессу
                        }
                    }
                }
            }
            return totalTime.ToString(); // Выводим минимальное время выполнения всех процессов
        }
    }
    class Process
    {
        public long Time { get; set; }
        public List<int> Dependencies { get; set; }

        public Process(long time, List<int> dependencies)
        {
            Time = time;
            Dependencies = dependencies;
        }
    }

Alice decided to go straight ahead without any recursions, go through all possible processes and then check them, but she got confused in the indexes and values, so it also doesn’t compile and crashes in the tests.

The graph problem turned out to be difficult for each of us three, so I have no questions about the AI ​​here.

TOTAL:

In general, the neurons did not do so badly, they even solved a couple of problems, almost without help. They are quite good at writing algorithms, but have difficulty understanding the problem. Alice, for example, had to beg every time to write me some code. Sber is a little more accommodating in this regard, but sometimes it simply confidently says the wrong answer.
However, if we compare them, Sber showed itself much better, it writes a more competent solution, does not try to go straight and tries to use language technologies.
So you can use AIs, but simplify the task for them as much as possible, reducing it to optimizing a specific action or algorithm, and not the entire task at once.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *