Ответы пользователя по тегу Алгоритмы
  • Доверительный интервал

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    С лотереей, если её правила за это время не менялись, оценка 2/(365*3) будет достаточно точной.
    С листовками всё гораздо сложнее - надо оценивать репрезентативность выборки, то есть насколько точно 50 человек, получивших листовки, соответствуют той аудитории, среди которой будут розданы все листовки и целевой аудитории, на которую они расчитаны.
    Ответ написан
    Комментировать
  • Какой метод преобразования температуры в цвет используется в тепловизорах?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Выбирается палитра и ей в какое-либо соответствие (например линейное) ставится диапазон температур.
    Ответ написан
  • Покритикуйте, пожалуйста, мой нубо-код (алгоритм нахождения наибольшего общего делителя 2ух чисел, c#)

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    while (second != 0) {
        reminder = first % second;
        first = second;
        second = reminder;
    }
    nod = first;
    Ответ написан
    Комментировать
  • Сколько существует различных уникальных подпоследовательностей из последовательности цифр длиной N?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    На C++
    #include <iostream>
    #include <vector>
    #include <set>
    #include <time>
    
    std::set<std::string> subSeqs;
    struct _element {
        char digit;
        int  count;
    };
    std::vector<_element> elemSeq;
    
    void recurse(std::vector<_element>::iterator elemRest, std::string subSeqHead) {
      bool fin = (elemRest+1 == elemSeq.end());
        for (int i = 0; i <= elemRest->count; i++, subSeqHead += elemRest->digit)
            if (fin)
                subSeqs.insert(subSeqHead);
            else
                recurse(elemRest+1, subSeqHead);
    }
    
    void main(void)
    {
      int i;
      _element element;
      std::string initialSeq = "1234567890123";
    
        std::cout << "Initial sequence: " << initialSeq << "\n";
    
        clock_t start = clock();
    
        element.digit = initialSeq[0];
        element.count = 1;
        for (i = 1; i < initialSeq.length(); i++) {
            if (element.digit == initialSeq[i])
                element.count++;
            else {
                elemSeq.push_back(element);
                element.digit = initialSeq[i];
                element.count = 1;
            }
        }
        elemSeq.push_back(element);
    
        recurse(elemSeq.begin(), "");
    
        clock_t finish = clock();
    
        i = 0;
        std::cout << "Elements: (";
        for (std::vector<_element>::iterator t = elemSeq.begin();
                                                    t != elemSeq.end(); t++) {
            if (i++ != 0)
                std::cout << ", ";
            std::cout << "{'" << t->digit << "', " << t->count << "}";
        }
        std::cout << ")\n";
        std::cout << subSeqs.size()-1 << " unique subsequences\n";
        std::cout << "Calculation time " << finish-start << " clicks, ";
        std::cout << ((float)(finish-start))/CLOCKS_PER_SEC << " sec\n";
    /*     for (std::set<std::string>::iterator t = subSeqs.begin();
                                                    t != subSeqs.end(); t++) {
            std::cout << *t << "\n";
        } */
    }

    Результаты:
    Initial sequence: 8246
    Elements: ({'8', 1}, {'2', 1}, {'4', 1}, {'6', 1})
    15 unique subsequences
    Calculation time 0 clicks, 0 sec
    ================================================================
    Initial sequence: 88885
    Elements: ({'8', 4}, {'5', 1})
    9 unique subsequences
    Calculation time 0 clicks, 0 sec
    ================================================================
    Initial sequence: 12345678901234567890
    Elements: ({'1', 1}, {'2', 1}, {'3', 1}, {'4', 1}, {'5', 1}, {'6', 1}, {'7', 1},
     {'8', 1}, {'9', 1}, {'0', 1}, {'1', 1}, {'2', 1}, {'3', 1}, {'4', 1}, {'5', 1},
     {'6', 1}, {'7', 1}, {'8', 1}, {'9', 1}, {'0', 1})
    1043455 unique subsequences
    Calculation time 4383 clicks, 4.383 sec
    ================================================================
    Initial sequence: 11223344556677889900
    Elements: ({'1', 2}, {'2', 2}, {'3', 2}, {'4', 2}, {'5', 2}, {'6', 2}, {'7', 2},
     {'8', 2}, {'9', 2}, {'0', 2})
    59048 unique subsequences
    Calculation time 187 clicks, 0.187 sec
    Ответ написан
    3 комментария
  • Сколько существует различных уникальных подпоследовательностей из последовательности цифр длиной N?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Несколько сократить количество вариантов при переборе можно сгруппировав подряд идущие одинаковые цифры. Скажем для (1 1 1 2 1 1) получим исходный набор ((1, 3), (2, 1), (1, 2)). После этого рекурсивно его перебираем.
    функция рекурсия(набор, результат) {
        если набор пуст {
            если результат уникален { 
                добавить результат в список уникальных
            }
        }
        ((цифра, количество), следующий_набор) = набор;
        для i от 0 до количество {
            рекурсия(следующий_набор, результат+(цифра i раз));
        }
    }
    рекурсия(исходный_набор, '');

    Первый шаг рекурсии даст варианты '', '1', '11' или '111'. Второй шаг к каждому из них допишет '' или '2'. Третий шаг к каждому из 8 получившихся вариантов допишет '', '1' или '11'. То есть вместо 26 = 64 вариантов для поиска уникальности получим 4*2*3 = 24.
    Чем больше будет в исходной последовательности групп подряд идущих одинаковых цифр тем больше будет выигрыш. Если таких групп нет, то упрёмся в полный перебор.
    Ответ написан
    1 комментарий
  • Сколько существует различных уникальных подпоследовательностей из последовательности цифр длиной N?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    В общем случае получается только полный перебор, количество всех подпоследовательностей = 2n-1
    Ответ написан
    4 комментария
  • Как найти кратчайший путь в динамическом графе?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    IMHO, у Вас не совсем корректная модель. Сами рёбра графа никуда не исчезают, меняется их цена. То есть, если из A в B мы можем попасть в момент T, то цена ребра B-C будет равняться времени от момента T до момента самого раннего прибытия маршрута из B в C с учётом отправления не ранее T+время на пересадку.
    Ответ написан
    4 комментария
  • Как составить программу "Расставить знаки арифметических операций и скобки чтобы выполнялось равенство"?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    И нехилый такой переборчик получается.
    В варианте "расставить знаки и скобки в левой части, чтобы выполнилось равенство":
    Пусть строка цифр в левой части имеет длину n.
    1. Разбить всеми возможными способами строку на числа. То есть получаем от 1 до n чисел. Количество вариантов разбиения строки из n цифр на m чисел
    mwvtag8.png
    2. Так как в условии сказано про скобки, то операции могут выполняться в разном порядке. Для указания порядка операций по каждому массиву из m чисел можно построить бинарное дерево, используя элементы массива как листья. Каждое дерево будет содержать m-1 вершину. Количество таких деревьев (число Каталана)
    loo5xnj.png
    3. Каждая из вершин задаёт одну из четырёх математических операций (+, -, *, /). Таким образом, количество возможных формул для одного дерева
    kmr2zxr.png
    4. Если добавить унарные минусы, то их можно раставить для каждого из m листьев
    m57sarh.png
    Итого вариантов
    n546hm7.png
    После этого обходом дерева выполняем расчёт и, если результат правильный, выводим дерево в виде выражения со скобками. Вот количество вариантов для разных n (хотя часть из них и окажется дублями или математически неверными из-за деления на 0).
    +----+---------------------+---------------------+
    |  n | без унарных минусов | с унарными минусами |
    +----+---------------------+---------------------+
    |  1 |                   1 |                   2 |
    |  2 |                   5 |                  18 |
    |  3 |                  41 |                 290 |
    |  4 |                 320 |               5'938 |
    |  5 |               5'073 |             136'770 |
    |  6 |              64'469 |           3'379'794 |
    |  7 |             859'385 |          87'547'746 |
    |  8 |          11'853'949 |       2'345'800'050 |
    |  9 |         167'763'361 |      64'477'920'386 |
    | 10 |       2'422'342'053 |   1'807'930'569'874 |
    +----+---------------------+---------------------+

    Мне кажется, или действительно перебор? :-)
    Ответ написан
  • В чем проблема с использованием алгоритма Брезенхэма?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    А в Octave рисуются отдельные точки или линии между точками? Ваша реализация алгоритма, для отрезка (0, 0) - (2,3) выводит:
    2 3
    0 0
    1 1
    1 2

    То есть, если задана отрисовка отрезков, то сначала отрезок (2, 3) - (0, 0), затем (0, 0) - (1, 1) и т.д.
    Для нормального вывода перенесите в конец программы строку
    print ("%d %d" %(x2, y2))
    Ответ написан
    5 комментариев
  • Как найти максимальную сумму, которую можно получить сложением произвольной неразрывной последовательности элементов массива?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    int sum = 0;
    int maxSum = 0;
    for (int i = 0; i < len; i++) {
        sum += val[i];
        if (sum > maxSum)
            maxSum = sum;
        if (sum < 0)
            sum = 0;
    }
    Ответ написан
    Комментировать
  • Алгоритм Флойда-Уоршелла

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Прогнал вашу реализацию с выводом на каждом шаге - всё работает.
    Исходный массив
    0  8  0  0  10
    8  0  4  0  0
    0  4  0  6  16
    0  0  6  0  2
    10 0  16 2  0
    -- Шаг 1 -----
    0  8  0  0  10
    8  0  4  0  18
    0  4  0  6  16
    0  0  6  0  2
    10 18 16 2  0
    -- Шаг 2 -----
    0  8  12 0  10
    8  0  4  0  18
    12 4  0  6  16
    0  0  6  0  2
    10 18 16 2  0
    -- Шаг 3 -----
    0  8  12 18 10
    8  0  4  10 18
    12 4  0  6  16
    18 10 6  0  2
    10 18 16 2  0
    -- Шаг 4 -----
    0  8  12 18 10
    8  0  4  10 12
    12 4  0  6  8
    18 10 6  0  2
    10 12 8  2  0
    -- Шаг 5 -----
    0  8  12 12 10
    8  0  4  10 12
    12 4  0  6  8
    12 10 6  0  2
    10 12 8  2  0

    Так что придётся Вам всё же лезть в дебаг и смотреть, что происходит и что идёт не так именно в вашей системе.
    Ответ написан
  • Как в игре "Жизнь" определить предыдущее состояние клеток по текущему? (Одномерное поле)?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Верно так:
    // Инициализируем C, надо заменить на ввод исходных данных
    $C = array(1, 1, 1, 0, 0, 1, 1, 1, 0, 1);
    $N = count($C);
    
    // Добавляем в начало и конец нули
    array_unshift($C, 0);
    $C[] = 0;
    
    // Создаём массив P, заполняем 0 и N+1 элементы нулями
    $P[0] = 0;
    $P[$N+1] = 0;
    
    // Заполняем чётные ячейки
    for ($i = 1; $i <= $N; $i += 2)
        $P[$i+1] = $P[$i-1] ^ $C[$i];
    
    // Заполняем нечётные ячейки
    if (($N&1) == 0) {
        // Вариант с чётным количеством ячеек
        for ($i = $N; $i >= 1; $i -= 2)
            $P[$i-1] = $P[$i+1] ^ $C[$i];
    } else {
        // Вариант с нечётным количеством ячеек
        $P[1] = 0;
        for ($i = 1; $i <= $N; $i -= 2)
            $P[$i-1] = $P[$i+1] ^ $C[$i];
    }
    
    // Выводим результат
    for ($i = 1; $i <= $N; $i++)
        print $P[$i];

    Получаем 0110100111.
    Проверяем, (0110100111) даёт по правилам (1110011101)
    Ответ написан
    1 комментарий
  • Как в игре "Жизнь" определить предыдущее состояние клеток по текущему? (Одномерное поле)?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Обозначим текущее состояние как C[1..N], предыдущее как P[1..N], С[0] = P[0] = C[N+1] = P[N+1] = 0 - клетки за пределами поля.
    На текущем шаге клетка жива тогда и только тогда, когда на предыдущем шаге у неё был ровно один сосед, то есть C[i] = P[i-1] xor P[i+1] => P[i+1] = C[i] xor P[i-1].
    1. P[0] = 0, C[1] известна => P[2] = P[0] xor C[1]. Теперь, зная P[2] можно найти P[4] = P[2] xor C[3] или в общем случае:
    для i от 1 до N с шагом 2
        P[i+1] = P[i-1] xor C[i];
    Получили все предыдущие значения чётных ячеек.

    2a. Для чётных N обратным ходом можно восстановить нечётные ячейки:
    для i от N до 1 с шагом -2
        P[i-1] = P[i+1] xor C[i];

    2b. Для нечётных N однозначного решения нет. В зависимости от значения P[1] будет получен один из двух вариантов решения:
    P[1] = 0; // или 1
    для i от 2 до N с шагом 2
        P[i+1] = P[i-1] xor C[i];
    Ответ написан
    7 комментариев
  • Задача расчета расстояния путей между городами с использование графов в C++?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Самое простое - двумерный массив w[N][N], где w[i][j] - стоимость перехода из узла i в узел j или -1 если такого пути нет. Если узлов много, а связность низкая, то надо уже копать в сторону разреженных массивов.
    Ответ написан
    Комментировать
  • Какой алгоритм использовать лля определения доступности временного промежутка?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Поразмыслив пришёл к варианту:
    SELECT count(*) AS x FROM records 
        WHERE (begin BETWEEN '{$newRecordBegin}' AND '{$newRecordEnd}') OR
              ('{$newRecordBegin}' BETWEEN begin AND end)

    Первая часть условия - начало какой-либо старой записи попадает в середину новой.
    Вторая часть - начало новой записи попадает в середину какой-либо старой .
    Если хоть одно условие выполнено - count(*) > 0, вставлять запись нельзя.
    Ответ написан
    Комментировать
  • Какой алгоритм использовать лля определения доступности временного промежутка?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    0. Пытаемся вставить новую запись newRecordStart, newRecordLength
    1. Получаем две ближайшие по времени записи, одну до (prevRecordStart, prevRecordLength) и одну после новой (nextRecordStart, nextRecordLength).
    2. Новая запись не должна пересекаться с предыдущей:
    (newRecordStart >= prevRecordStart+prevRecordLength)
    3. Новая запись не должна пересекаться со следующей:
    (newRecordStart+newRecordLength <= nextRecordStart)
    4. Если оба условия выполнены - можно вставлять запись.
    Ответ написан
    Комментировать
  • Анализ данных с термодатчиков и трубки Флейша?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    С температурами всё достаточно просто, графики без шумов. Можно брать локальные минимумы/максимумы, просто перебираете весь массив считая разницу между значениями в текущей и в следующей точках меняет знак, то записываете точку как локальный экстремум.

    d = V[1]-V[0];
    for (i = 1; i < N-1, i++) {
        d1 = V[i+1]-V[i];
        if (d < 0 && d1 > 0) {
            // Локальный минимум V[i]
        } else if (d > 0 && d1 < 0) {
            // Локальный максимум V[i]
        }
        d = d1;
    }

    Для объёма график с шумами, если уровень шумов заранее известен, то его можно исключить игнорируя разницу, попадающую в уровень шума. Для нахождения середины перегиба в этом случае можно анализировать два перехода - от повышения к нулю и от нуля к снижению (наоборот для нижнего перегиба) и брать значение в середине перегиба или среднее значение между крайними точками перегиба.

    noise = 2; // Уровень шума, поставить нужное значение
    t1 = 0; // Точка перехода к нулю
    upDown = 0; // Направление движения до нуля, > 0 - вверх, < 0 - вниз, 0 - начало графика
    d = V[1]-V[0];
    if (abs(d) < noise)
        d = 0;
    for (i = 1; i < N-1, i++) {
        d1 = V[i+1]-V[i];
        if (abs(d1) < noise)
            d1 = 0;
        if (d < 0 && d1 > 0) {
            // Локальный минимум V[i]
        } else if (d > 0 && d1 > 0) {
            // Локальный максимум V[i]
        } else if (d != 0 && d1 == 0) {
            t1 = i;
            upDown = d;
        } else if (d == 0 && d1 > 0 && upDown < 0) {
            // Локальный минимум V[(t1+i)/2] или (V[t1]+V[i])/2
        } else if (d == 0 && d1 < 0 && upDown > 0) {
            // Локальный максимум V[(t1+i)/2] или (V[t1]+V[i])/2
        }
        d = d1;
    }
    Ответ написан
    2 комментария