• Как найти из 4 чисел, где 3 равные между собой одно не равное, за один раз?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Надо уточнить - что считать, операции сравнения, или условные операторы. Считать написанные операции/операторы, или выполняющиеся.
    Возможные варианты решения:
    return a==b ? (a==c ? d : c) : (a==c ? b : a);
    int X[4];
    return X[(X[0]==X[2])+2*(X[0]==X[1])];

    int f(int p,int q,int r){
      return p==r ? q : p;
    }
    int g(int a,int b,int c,int d){
      return a==b ? f(c,d,a) : f(a,b,c);
    }

    int x=a^b,y=a^c;
    x=(x|-x)>>31; y=(y|-y)>>31;
    return ((a^b^c^d)&x&y)^((b^d)&x)^((c^d)&y)^d;

    (в последнем вообще нет сравнений и условных операторов).
    Ответ написан
    Комментировать
  • Теорема Кантора в программировании?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Применяется при поиске корня функции делением отрезка пополам. Для любой последовательности знаков f(x) для середин отрезка мы получаем некоторое число - корень уравнения. Конечно, в действительности мы делаем только конечное число шагов и получаем число из конечного множества, но сам факт, что метод работает, а корень существует, основан, в том числе, на континуальности отрезка. Если бы у нас были только рациональные числа, то уравнение x^2=2 корня бы не имело, и мы не имели бы права сказать, что мы находим его с нужной точностью.
    Ответ написан
    Комментировать
  • Когда ооп быстрее процедурного?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Про РНР не знаю, скажу на примере С/С++.

    Если виртуальными функциями не пользоваться, то C и C++ дадут одинаковую эффективность.
    Если пытаться один и тот же код, требующий run-time полиморфизма написать на C и на C++, то, вероятнее всего, код на C++ будет эффективней. Потому что у вас не хватит терпения аккуратно заполнять и использовать таблицы виртуальных функций, и получится код с большим количеством case, а то и if/else по тегам объектов. В конечном итоге, можно будет написать программу на C, эквивалентную программе на С++ (а потом её соптимизировать), но она будет сложной, непонятной, и практически нерасширяемой: добавление нового полиморфного метода в систему типов (с модификацией всех таблиц и всех методов, работающих с тегами) будет мучением.
    Ответ написан
    Комментировать
  • Как решить задачу с комплексными числами (не просьба решить, а подсказать)?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    1,2 - сначала умножаете числитель и знаменатель первой дроби на 1-i, а второй дроби - на 5i+2. Получатся две дроби, у которых в знаменателе вещественное число (у первой дроби 2, у другой -29). Теперь умножаете обе дроби на 58 (для этого числитель первой дроби умножается на 29, а второй - на -2). Получается число 29*(1-i)+2*5*(5*i+2). Раскрываете скобки и получаете ответ.
    3 - просто берёте формулу корней квадратного уравнения. Там всё видно.
    Ответ написан
    Комментировать
  • Как на основе расстояния Левенштейна вывести промежуточные слова?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Достаточно для каждого элемента массива запоминать последовательность действий - "как мы сюда попали". Например, в виде строки с 4 командами - "вставили символ X", "удалили символ X", "заменили X на Y" (X и Y могут совпадать).
    Если вторая строчка была "ABCD", то массив, соответствующий начальному состоянию D2, будет выглядеть так:
    {"","iA","iAiB","iAiBiC","iAiBiCiD"} - это команды, переводящие пустую строку в различные начальные подстроки этой второй строки.
    По мере пересчёта массивов строки будут удлиняться, и в итоге мы получим некоторую строку с командами, переводящими строку1 в строку2. Например, для перевода ASTRA в STARKA это может быть "dArSSrTTiArRRiKrAA".
    Дальше можно выполнить несколько первых команд и игнорировать остальные. Увеличивая число выполненных команд, получим промежуточные строки: ASTRA, STRA, STARA, STARKA
    Ответ написан
    Комментировать
  • Какую фантастику порекомендуете, где главный герой программист/инженер?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Владимир Савченко - "Открытие себя" и "Алгоритм успеха".
    В какой-то мере Стивенсон "Алмазный век" и Грег Иган "Permutation City"
    Ответ написан
    Комментировать
  • Отфильтровать шум в данных?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если хочется велосипеда, можно сделать так.
    1) вводите модель шума. Например, "с вероятностью 90% ошибка распределена по Гауссу с сигмой 15 м, а с вероятностью 10% точка может быть где угодно".
    2) для набора из 3, 4 или 5 последовательных точек (x,y,t) вводите критерий - насколько вероятно, что каждая из этих точек попала в 90% (с учётом технических возможностей автомобиля и возможной кривизны дороги). Определяете штраф, который тем больше, чем меньше вероятность. Определяете также штраф за то, что точка попала в 10%.
    3) просматриваете точки и перебираете варианты, какие точки попали в 90%, какие нет (динамическим программированием по маске последних попавших точек). Цель - найти вариант с наименьшим штрафом.
    4) к этому моменту точки разделены на хорошие (которые описываются гауссовым шумом) и плохие. Берёте хорошие точки и проходите по ним каким-нибудь сглаживающим фильтром. Правда, его придётся подбирать так, чтобы он учитывал возможность поворота под прямым углом.
    Это годится для точек, снятых с одной машины. Если точек много, они образуют широкую полосу, и информация, откуда они взялись, потеряна, то нужны какие-то другие методы.

    А если велосипед изобретать не хочется - изучайте, что такое фильтр Калмана. Может быть, вам повезёт. Лично я предпочту велосипед (кажется, конкретно эта или похожая модель называется методом Виттерби - но может быть, и нет).
    Ответ написан
    Комментировать
  • Каким алгоритмом или формулой можно выяснить, находится ли точка между паралельными прямыми?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Вычисляете (a1*x + b1*y + c1)*(a2*x + b2*y + c2). Если у него знак такой же, как у a1*a2+b1*b2, то точка принадлежит тупому углу между прямыми, если другой - то острому. В случае параллельных или почти параллельных прямых второй случай соответствует ситуации "лежит между", а первый - "нет".
    Ответ написан
    1 комментарий
  • Как можно найти вершинное покрытие графа за линейное время, если граф является деревом?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Рекурсия.
    Для каждого поддерева ищем два покрытия: P - минимальное покрытие вообще, и Q - минимальное покрытие, содержащее корень. Пусть T - наше дерево, X - его поддеревья, растущие из детей корня. Тогда
    Q(T)=1+sum(P(X))
    (корень включён, все рёбра, идущие к нему, учтены, в поддеревьях можно выбирать любые покрытия)
    P(T)=min(Q(T),sum(Q(X)))
    (либо корень не включён - и надо брать покрытия поддеревьев, содержащие корни, либо взять уже построенное покрытие Q).
    Для листьев P=0, Q=1.
    Ответ написан
    Комментировать
  • Как избавится от царапин на изображении?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если времени не жалко, то можно попробовать так:
    - берём все пары точек, находящихся на разных сторонах квадрата
    - каждую такую пару соединяем отрезком, и считаем среднюю яркость на нём (это примерно то же, что и преобразование Хафа, только более специализировано для задачи. И гораздо дольше)
    - получается функция от двух переменных. Ищем её максимум - это самая яркая царапина.
    - просматриваем параллельные прямые в окрестности, ищем ширину пика (ширина царапины)
    - заменяем точки на найденной царапине линейной интерполяцией ближайших точек, лежащих за её пределами. Или просто помечаем точки полосы как некорректные, и идём дальше.
    - убираем этот пик на двумерной функции, переходим к следующему максимуму.
    - после того, как удалили 10 (или 50, или 100) царапин, показываем картинку, и спрашиваем, продолжать ли.
    - если продолжать - пересчитываем функцию заново.
    Основным вопросом будет "как считать ширину пика". Я не знаю, надо смотреть конкретные графики.
    Ответ написан
    Комментировать
  • Стоит ли читать WEB-программисту книгу "Д.Е Кнут искусство программирования"?

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

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Видимо, задан ряд (в данном случае: -3, 6, -9, 12, -15, ...), и какое-то N. Надо найти сумму и произведение первых N элементов.
    В данном случае при N=4 сумма будет -3+6-9+12=6, а произведение - 1944.
    При N=5 сумма равна -9, а произведение -29160.
    Ответ написан
    Комментировать
  • Нужно преобразовать номерную емкость из одного формата в другой, кто может подсказать алгоритм?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Хорошая задача. На C# это бы выглядело так:
    long x0=9266070005,x1=9266099923;
                long n=1;
                x1++;
                while(x0<x1) {
                    if(x1-x0<n) n/=10;
                    else if((x0/n)%10==0 && x1-x0>=10*n) n*=10;
                    else{
                        Console.Write("{0}, ",x0/n);
                        x0+=n;
                    }
                }

    Можно ли это хорошо переписать на PHP, не знаю.
    Ответ написан
    1 комментарий
  • Как определить координаты тела, если оно движется по эллипсу?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Звезда не в центре, а в фокусе эллипса. Всё, что вам нужно знать (кроме ориентации эллипса в пространстве) - это то, что секторная скорость планеты постоянна. Ещё потребуется период обращения T и момент, когда планета проходила перигелий.
    Дальше просто. Пусть (a,b) - полуоси эллипса, звезда в фокусе (c,0), где c=sqrt(a^2-b^2), планета в точке X=(a*cos(x),b*sin(x)). Площадь сектора, "заметённого" планетой, равна S(x)=(a*b*x-c*b*sin(x))/2, а сектор, который она проходит за год - S(T)=a*b*pi. Поэтому, в точке X планета оказывается в момент t(x)=T*(x-c*sin(x)/a)/(2*pi). Решать уравнение, чтобы получить t(x), придётся численно.
    Ответ написан
    4 комментария
  • Нужен эвристический алгоритм заполнения таблицы или существует обычный?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Сразу можно сказать, что число столбцов в таблице - L=M*(N-1)/2+1, число строк - K=M*L/N. Оба этих числа должны быть целыми.
    В частном случае, когда N=q+1, M=2*(q+1), где q - простое число или степень простого, матрицу построить можно, в ней каждая строка будет встречаться дважды, а верхняя (и нижняя) половинка матрицы будет матрицей инцидентности конечной проективной плоскости. В остальных случаях - боюсь, что нужна эвристика, или вообще полный перебор. Всё-таки, это получается задача о покрытии - надо покрыть удвоенный набор рёбер полного графа с L вершинами непересекающимися графами с N вершинами. Свойство "в каждом столбце M ячеек" выполнится автоматически.
    Ответ написан
    Комментировать
  • Рефакторинг циклов возможен?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Вынести дублирующиеся тела циклов в отдельные функции. Циклов останется столько же, но они станут короче. Потом можно будет смотреть, что ещё можно исправить.
    Ответ написан
    Комментировать
  • Как найти максимальное значение без ?/switch/if?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Можно с битовыми операциями, в расчёте на 32-битную архитектуру:

    var arr=new int[]{1,2,3,4,5,6,98,65,190};
        int max=arr[0];
        foreach(int x in arr){
            int y=max-x;
            max-=y&(y>>31);
        }
    Ответ написан
    Комментировать
  • Как разбить множество на три подмножества с одинаковой суммой элементов?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Задача о рюкзаке, даже о двух :)
    Заводите массив M[0..S/3,0..S/3] (можно битовый, но лучше побольше - чтобы хранить обратные ссылки). В нём будут отмечены элементы M[a,b], такие, что из уже просмотренных элементов текущего набора можно выбрать непересекающиеся подмножества с суммами a и b.
    Когда приходит очередной элемент x - выполняете M[a,b]=M[a,b] | M[a-x,b] | M[a,b-x] для всех a,b начиная с конца (с больших a,b). Если при этом 0 сменился на 1 - помечаете в массиве обратных ссылок, из какого элемента вы сюда попали.
    Сложность - O(n*S^2). Можно ли сделать лучше, не знаю.

    Вот вариант кода - но он печатает только два множества. Как напечатать третье, разберётесь.
    spoiler
    static void Main(string[] args) {
                int[] dat=Array.ConvertAll(Console.ReadLine().Split(' '),int.Parse);
                int S=0;
                foreach(int x in dat) S+=x;
                if(S%3!=0) {
                    Console.WriteLine("-1"); return;
                }
                S/=3;
                int[,] M=new int[S+1,S+1];
                M[0,0]=-1;
                foreach(int x in dat) {
                    for(int a=S;a>=0;a--) {
                        for(int b=S;b>=0;b--) {
                            if(M[a,b]==0) {
                                if(a>=x && M[a-x,b]!=0) M[a,b]=x;  // back by set1
                                else if(b>=x && M[a,b-x]!=0) M[a,b]=-x;  // back by set2
                            }
                        }
                    }
                }
                if(M[S,S]==0) {
                    Console.WriteLine("-1"); return;
                }
                int u=S,v=S;
                string res1="",res2="";
                while(u!=0 || v!=0) {
                    if(M[u,v]>0) {
                        res1+=" "+M[u,v]; u-=M[u,v];
                    } else {
                        res2+=" "+(-M[u,v]); v+=M[u,v];
                    }
                }
                Console.WriteLine(res1);
                Console.WriteLine(res2);
            }

    Ответ написан
  • Существует ли какой-нибудь алгоритм склонения существительных во множественном числе?

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

    Mrrl
    @Mrrl
    Заводчик кардиганов
    А что-нибудь такого вида?
    var s=(i%3==0 ? "Fizz" : "")+(i%5==0 ? "Buzz" : "");
      console.log(s=="" ? i : s);
    Ответ написан
    Комментировать