• Как найти 3 кратчайших пути в графе?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    В каждой вершине хранить не более трёх кратчайших путей до неё. В Дейкстре использовать очередь без модификации веса. Если очередной путь, взятый из очереди, лучше третьего по порядку пути, сохранённого в вершине, (или сохранено не более двух путей) - добавляем этот путь в вершину, а все его продолжения - в очередь.
    Проблема в том, что в путях могут появиться циклы. Например, для графа из двух вершин с тремя рёбрами
    (1,2, w=1)
    (1,2, w=3)
    (1,2, w=5)
    будут выданы пути 1-2 (по первому ребру), 1-2 (по второму ребру) и 1-2-1-2 (по первому ребру). Если циклы нежелательны - придётся возиться дольше
    Ответ написан
    Комментировать
  • Как можно порождать перестановки с дополнительными ограничениями для элементов итеративно?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    А чем не нравится goto? Вполне легальный оператор. В случае чего, от него легко избавиться, преобразовав код в конечный автомат (получится цикл с одним switch внутри). Хотя чаще хватает одной дополнительной логической переменной.
    И какого типа ограничения? И есть ли ограничение на порядок выдачи перестановок?

    UPD. Вот вариант решения на C#. Не самый эффективный, правда.
    class Program{
            static IEnumerable<int[]> Permutations(int N,Func<int,int,bool>Cond1,Func<int,int,int,int,bool> Cond2) {
                int[] res=new int[N];
                int k=0;
                res[0]=0;
                while(k>=0){
                    if(++res[k]<=N){
                        if(Cond1(k+1,res[k]) && GoodValue(res,k,Cond2)){
                            if(k==N-1) yield return res;
                            else res[++k]=0;
                        }
                    }else k--;
                }
            }
            static private bool GoodValue(int[] res,int k,Func<int,int,int,int,bool> Cond) {
                for(int i=0;i<k;i++) {
                    if(res[i]==res[k] || !Cond(i+1,res[i],k+1,res[k])) return false;
                }
                return true;
            }
    
            static int N=6;
            static bool Cond1(int a,int va) {
                if(a==1) return va==1;
                if(a==N) return va==N;
                return true;
            }
            static bool Cond2(int a,int va,int b,int vb) { 
                return Math.Abs(a-b)>1 || Math.Abs(va-vb)<=3;
            }
            static void Main(string[] args) {
                foreach(int[] perm in Permutations(N,Cond1,Cond2))
                    Console.WriteLine(String.Join(",",perm));
            }
        }

    Функции Permutations передаются два условия. Первое Cond1(a,va) проверяет, может ли элемент va находиться в позиции a, второе Cond2(a,va,b,vb) - могут ли одновременно находиться va в позиции a и vb в позиции b.
    В качестве примера - печать перестановок из задачи про лягушку из ProjectEuler: https://projecteuler.net/problem=490
    Для N=6 выдаёт ожидаемые 14 перестановок:
    1,2,3,4,5,6
    1,2,3,5,4,6
    1,2,4,3,5,6
    1,2,4,5,3,6
    1,2,5,3,4,6
    1,2,5,4,3,6
    1,3,2,4,5,6
    1,3,2,5,4,6
    1,3,4,2,5,6
    1,3,5,2,4,6
    1,4,2,3,5,6
    1,4,2,5,3,6
    1,4,3,2,5,6
    1,4,5,2,3,6


    Если не нравится конструкция yield return - вставьте вместо неё свою обработку перестановки, а функцию опишите, как void. Если из GoodValue yбрать проверку res[I]==res[k], то вместо перестановок будут печататься все N-элементные наборы из чисел 1..N, удовлетворяющие условию.
    Ответ написан
    4 комментария
  • Как имененить размер двумерного динамического массива?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    calloc должен заполнять нулями, это да. Но realloc не обязан заполнять нулями вновь захваченные элементы массива, это надо делать вручную.
    Ответ написан
    Комментировать
  • Какие есть алгоритмы численной минимизации функции одной переменной, заданной на всем пространстве?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Для непрерывной функции есть простой алгоритм поиска локальных минимумов.
    Допустим, что уже найдены точки a < b < c такие, что f(a) > f(b) < f(c).
    Добавляем точки d=(a+b)/2, e=(b+c)/2, и выбираем точку из b,d,e, значение на которой минимально. Она даст тройку (d,b,e), (a,d,b) или (b,e,c) соответственно, обладающую теми же свойствами, что и исходная тройка, но в 2 раза уже.
    Для поиска исходных точек надо просмотреть прямую с достаточно мелким шагом, чтобы впадина не могла спрятаться между точками. Шаг не обязан быть равномерным, поэтому даже для бесконечной прямой может хватить конечного числа точек.
    Ответ написан
    Комментировать
  • Как найти матрицу перехода по векторам?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Судя по названию View, вы работаете в терминах компьютерной графики, когда векторы - строки и умножаются на матрицу слева: v1' = v1*View.
    Берёте 4 линейно независимых вектора v1,v2,v3,v4, составляете из них матрицу M, в которой они записаны по строкам. Из соответствующих векторов v1',v2',v3',v4' строите матрицу M'. Тогда M' = M*View (это довольно очевидно - достаточно вспомнить, как перемножаются матрицы). Отсюда, View = Inverse(M)*M' (умножаем предыдущую формулу на Inverse(M) слева).
    Если пар больше 4, и соответствия только приближённые, то ситуация сложнее - придётся звать на помощь метод наименьших квадратов. Если на матрицу View есть какие-то ограничения, то тоже придётся ещё повозиться (потому что матрица, вычисленная по первым 4 векторам, может быть, например, не совсем ортогональной).
    Ответ написан
    3 комментария
  • Пример реализации односвязного списка на C#, Не понятно откуда берется свойство Netx Объекта Head?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Когда список пуст, Current и Head равны null. После добавления первого элемента Current и Head являются одним и тем же объектом, а при добавлении второго срабатывает строчка Current.Next = node; - и в этот момент устанавливается Head.Next (поскольку Current и Head совпадают).
    Ответ написан
    5 комментариев
  • Как сгенерировать окружности на сфере, что бы они оптимально перекрывали друг-друга?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Это известная проблема. Пока её решили до 10 кругов и ещё для некоторых чётных значений. Впрочем, всё это сведения 25-летней давности, свежих результатов найти не удаётся. Вот статья, где разбирается построение для 11 кругов (правда, я её не читал, и не знаю, есть ли там окончательное решение для этого случая):
    https://eudml.org/doc/141375
    Или у вас задача - "дан радиус сферы и радиус круга, найти минимальное число кругов"? Или можно задать примерный радиус (или примерное число кругов) и найти какое-нибудь решение, близкое к оптимальному, для этого случая?
    В общем, сейчас задача упирается в вопрос "а зачем?". Если нужно точное решение для написания докторской диссертации - то решайте. Если есть какая-нибудь практическая цель - напишите, какая, и будем искать реалистичные приближения.

    UPD. В общем, берёте икосаэдр, и каждую грань делите на маленькие правильные треугольники. Вершины этих треугольников и дадут центры кругов. Радиус придётся считать исходя из картинки вблизи вершины икосаэдра - там треугольники заметно искажаются. Возможно, радиальное расстояние между точками там придётся слегка уменьшить.
    Ответ написан
    7 комментариев
  • Почему не работает мой mergesort?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Видны две ошибки. Первая не должна влиять на результат, но может привести к выходу индекса за границу массива:
    if ((i < leftLen && left[i] < right[j]) || j >= rightLen) {

    В случае, когда j==rightLen, у вас будет проверяться элемент right[j]. Условия здесь надо поменять местами:
    if ( j >= rightLen || (i < leftLen && left[i] < right[j])) {

    Вторая - что элемент array[mid] не будет участвовать ни в первом, ни во втором рекурсивных вызовах mergeSort. Второй вызов надо было сделать
    mergeSort(array, mid, end);
    А чтобы не было бесконечной рекурсии, изменить условие в mergeSort на
    if (start < end-1) {
    (или на if(start < mid) ).

    Ну, и в классическом С невозможна конструкция

    int leftLen = mid - start,
          left[leftLen];

    Там массивы могут быть только фиксированной длины, а для динамического захвата приходится использовать malloc. Но если компилируется, значит, ваша версия компилятора такое позволяет.

    UPD. В С99 действительно возможны массивы переменной длины, и пишут, что gcc их поддерживает. Ну и ладно. Visual Studio такое не позволяет.
    Ответ написан
    1 комментарий
  • Как "вставить" биты в число?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если нужно сделать так, как в вашем примере (т.е. вставить биты 2048,1024,256,16), то так:
    y=((x&0xf00)<<4)+((x&0x80)<<2)+((x&0x70)<<1)+(x&0xf);

    Но так биты никто не нумерует. Обычно они нумеруются, начиная с младшего - иногда он считается за нулевой, иногда за первый.
    Ответ написан
    Комментировать
  • Перебор массива циклом или сверка значений проверкой?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    На С++ прямая проверка работает примерно вдвое быстрее, чем проверка циклом. Я проверял для массива из 10 элементов (проверял, входит ли число в первые 10 простых чисел). С циклом проблема ещё и в том, что для такого "if" трудно написать else-часть - нужно либо добавлять лишнюю логическую переменную, либо использовать goto.
    Ответ написан
    Комментировать
  • Можно ли одной bitwise операцией (без циклического сдвига) определить степень двойки(номер бита)?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Можно взять остаток от деления на 37, и дальше по табличке. Но это может оказаться дороже, чем цикл.
    Или за 5 операций AND:

    int n=0;
    if(x&0xffff0000) n+=16;
    if(x&0xff00ff00) n+=8;
    if(x&0xf0f0f0f0) n+=4;
    if(x&0xcccccccc) n+=2;
    if(x&0xaaaaaaaa) n++;

    Хотя через CLZ лучше.
    Ответ написан
    Комментировать
  • Как эффективней рисовать в 2d на C#?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Как насчёт Bitmap.LockBits()? Оно требует знания формата bitmap, но является самым быстрым способом редактирования.
    Ответ написан
  • PHP: как сгруппировать близкие по значению элементы массива?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Непонятная задача.
    Во-первых, решений может быть много. Например, пусть границы - abs(dx) <= 5, abs(dy) <= 5. Точки A=(0,0), B=(4,4), C=(7,7). Тогда решением будет и {A,B},{C} и {A},{B,C}. Из них правильно какое-то одно, или оба?
    А если точки A=(0,0), B=(4,4), C=(7,7), D=(11,11)? Годится ли решение {A},{B,C},{D}? В нём больше групп, чем в {A,B},{C,D}, но центральная группа плотнее.
    И наконец, является ли условие "posX && posY в группе отличаются каждая друг от друга не более чем на +\- какое-то значение" единственным? Если да - достаточно создать N групп, по одному элементу в каждой. Условие будет выполнено. А если нет - попытайтесь объяснить, почему конкретно это решение не годится. Сформулировать условие, которое нарушено. Может быть, тогда станет понятнее, что же это за задача. А пока это лишь пожелание "сделайте мне красиво".

    А если задача не формализована - ищите слово "кластеризация". Про неё много интересного написано.
    Ответ написан
    2 комментария
  • Как написать "Hello World" на машинном коде?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    На SO есть пример, как это сделать на ассемблере с использованием kernel32.lib:
    stackoverflow.com/questions/1023593/how-to-write-h...
    Можно попробовать начать оттуда, потом научиться переводить это в машинный код (например, посмотрев в листинг ассемблера).
    Ответ написан
    Комментировать
  • Для чего программисту нужно знать физику?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Этот же вопрос я задал себе неделю назад. После того, как исписал пару страниц физическими расчётами: нужно было определить направление оси вращения по показателям инклинометров, при неравномерном вращении прибора - т.е. с учётом центростремительного и тангенциального ускорений. Приступом не взялось, точность получилась порядка 0.01 градуса, а надо на порядок лучше... Надо дорабатывать модель. Так что, иногда физика требуется. И даже не обязательно в играх.
    Ответ написан
    Комментировать
  • Алгоритм поиска точки, максимально удалённой от границ фигуры на изображении?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Рассматриваем фигуру как граф: у каждой точки соседями считаются точки из небольшой окрестности (например, 7*7), а длиной ребра - евклидовы расстояния между точками. Тогда расстояние между двумя точками фигуры с хорошей точностью равно кратчайшему пути на этом графе. Осталось найти точку, самую далёкую от границы. Считается за O(S*log(S)), где S - площадь фигуры.
    Ответ написан
  • Как найти кратчайший путь в лабиринте?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Заведите ещё один массив и кладите в него направление, откуда пришли в данную клетку. Проще всего это направление передать параметром в FindPath. Потом пройдите по этим направлениям от финиша до старта.
    Другой вариант - на обратном проходе искать соседнюю клетку со значением tempMap на 1 меньшим, чем в данной клетке, и идти в неё. Это дольше писать и оно чуть медленнее работает, но требует меньше памяти.
    Лабиринт действительно на сетке из шестиугольников?
    Ответ написан
  • Как сформировать рёбра на основе списка вершин объекта?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Сначала найдите выпуклую оболочку. Она даст и рёбра, и грани. Провести плоскость через три точки одной грани - дело техники, а вот если граней нет, то задача вообще некорректна. По одному и тому же набору вершин можно построить много разных тел.
    Ответ написан
    1 комментарий
  • Как оценить статистическую погрешность соц. опроса в пределах одного города?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    От размера города погрешность не зависит, она определяется исключительно размером выборки (1 сигма не превосходит 1/(2*sqrt(n)) ). Так что для 200 человек пишите "ошибка (2*сигма) не превышает 7%".
    Но проблема будет с тем, кто же заходит в паблик и с какой вероятностью. Ведь, как известно, интернет-опросы показывают, что интернетом пользуется 100% населения... А если опрос добровольный - то с какой вероятностью представитель того или иного варианта захочет участвовать в опросе: возможно, что обладатели самых старых и самых новых версий будут хвастаться охотнее, чем "середняки".
    Ответ написан