Задать вопрос
  • Взаимное уничтожение слагаемых - что это?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Это то, из-за чего (a+b)*(a^2-a*b+b^2)=a^3-b^3. Четыре слагаемых - a^2*b, -a^2*b, a*b^2, -a*b^2 в сумме дали 0, и в итоговой формуле их не видно. Как того суслика.
    Ответ написан
    Комментировать
  • Программируете ли вы в свободное время?

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

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Множественный return, а также операторы break, continue, switch и throw - это не более, чем маскировки оператора goto, с которым несколько последних десятилетий идёт борьба. Так что, если вы не боитесь goto - то пользуйтесь на здоровье.
    Ответ написан
  • Как найти центральный угол сектора, если известны значения двух углов прямых, окружности относительно оси x?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если это не прямые, а лучи, и направления a,b, лежащие от 0 до 360, то
    min( abs(a-b), 360-abs(a-b) )
    Ответ написан
    1 комментарий
  • Какие методы Вы используете, чтобы быстро найти участок в проекте с сотней тысяч строк?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Go to definition и Find all references в Visual Studio. Реже - поиск имени функции или строки по всему solution.
    Ответ написан
    Комментировать
  • Как построить модель цилиндрической волны?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если достаточно приближенной модели, можно сделать так:
    r1=sqrt(x^2+y^2)
    a=A*p/sqrt(p^2+x^2+y^2)
    z=a*sin(k*r1-w*t)
    где p - размер области в окрестности нуля с насильственно ограниченной амплитудой,
    A - максимальная амплитуда (в нуле)
    k - пространственная частота (т.е. 2*pi/k - расстояние между волнами)
    w - временнАя частота (2*pi/w - период).
    w/k - скорость распространения.
    Ответ написан
    Комментировать
  • Как описать квадратом окружность, имея координаты точки и радиус?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Так и не решили? Интересная задачка.
    Предположим, что Земля шарообразная и её радиус RE. Радиус нашей окружности R, координаты точки выражены в радианах.
    Определим r=R/RE (это радиус в радианах).
    Расстояние от центра окружности до вершины описанного квадрата - a=arctg(sqrt(2)*tg(r)) (под квадратом понимается правильный сферический 4-угольник?)
    Теперь нам надо отступить от нашей точки на расстояние a под углом 45 гр к меридиану.
    Пусть P - северный полюс, O - центр окружности, A - вершина квадрата на северо-востоке.
    У треугольника AOP длина стороны OP=pi/2-Lat, AO=a, угол POA=pi/4. Отсюда, по 1-й теореме косинусов,
    AP=arccos(cos(AO)*cos(OP)+sin(AO)*sin(OP)*cos(AOP))=arccos(cos(a)*sin(Lat)+sqrt(0.5)*sin(a)*cos(Lat)). Получаем h1=pi/2-AP - широта точки A.
    Угол APO найдём по теореме синусов: sin(APO)/sin(AO)=sin(AOP)/sin(AP), откуда APO=d1=arcsin(sin(a)*sqrt(0.5)/cos(h1)). Долгота точки A будет Lon+d1, а координаты северо-западной вершины D - (h1,Lon-d1).
    С южными вершинами поступаем аналогично (только там угол будет 135 гр):
    BP=arccos(cos(a)*sin(Lat-sqrt(0.5)*sin(a)*cos(Lat)), h2=pi/2-BP.
    BPO=d2=arcsin(sin(a)*sqrt(0.5)/cos(h2)).
    Координаты точек B и C - (h2,Lon+d2) и (h2,Lon-d2).
    Если надо учитывать сплюснутость Земли, или под квадратом понималось нечто иное, то нужны более конкретные условия.
    Кстати, если радиус окружности будет больше четверти экватора, то вершины описанного квадрата окажутся внутри круга. Такая уж сферическая геометрия.
    Ответ написан
    Комментировать
  • Задача про стену и кирпичи. Как решить?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Строите матрицу перехода между рядами (43х43, как описано в ответе Andy_U ), потом возводите её в 9-ю степень (поскольку у нас 9 переходов) и считаете сумму всех элементов (поскольку первый и последний ряд могут быть любыми). Всё.
    Работает для любого числа рядов, хоть для триллиона :) Только потребуется быстрое возведение в степень.
    Но это будет число способов построить стену. Если имелось в виду число наборов кирпичей (сколько может быть кирпичей 3x1 и сколько 4x1), то надо подумать, как сделать проще всего.
    Ответ написан
  • Как разделить "пик" функции на два простых пика?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Сумма двух парабол - это тоже парабола. Как и сумма любых двух многочленов - многочлен той же степени.
    Возможно, график удастся представить в виде суммы двух нормальных распределений:
    f(x)=a1*exp((x-b1)^2/c1)+a2*exp((x-b2)^2/c2).
    Получается 6 неизвестных. Записываете функцию F(a1,b1,c1,a2,b2,c2)=sum((f(x_i)-y_i)^2) и ищете её минимум. Например, методом градиентного спуска.
    Ответ написан
    1 комментарий
  • Как построить задачу поиска оптимальной точки?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Я бы её решал как точку пересечения трёх сфер в пространстве с последующей проекцией на плоскость ABC, а потом на поверхность Земли:
    Пусть радиусы равны RA, RB, RC, а расстояния между точками - AB,AC,BC.
    Вычислим величины
    u=((RA^2-RB^2)/AB^2+1)/2
    v=((RA^2-RC^2)/AC^2+1)/2
    Это будут проекции точки пересечения сфер на отрезки AB и AC, выраженные в длинах этих отрезков.
    Пусть a - угол в вершине А треугольника АВС (найдём по теореме косинусов).
    Если Q - проекция точки пересечения сфер на плоскость ABC, то
    AQ=(AB*(u-v*cos(a))+AC*(v-u*cos(a)))/(sin(a)^2),
    т.е. Q=A*(1-(u+v)/(1+cos(a)))+B*((u-v*cos(a))/sin(a)^2)+C*((v-u*cos(a))/sin(a)^2),
    где A,B,C - трёхмерные координаты точек. Тогда Q*(R/|OQ|) - искомая точка (|OQ| - расстояние от Q до центра Земли, R - радиус Земли).
    Формулы не проверялись :(
    Ответ написан
    Комментировать
  • Как улучшить скорость функции?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Записать условие в виде (a+1)*(b+1) == n*(n+1)/2+1 = N, и для чисел a от (n+1)/2 до n проверить, делится ли N на a+1. Если делится, то b=N/(a+1)-1. На всякий случай, проверить, что b < n+1.
    При желании, перебор можно сократить примерно в 12 раз. Но тогда вместо проверки делимости надо будет быстро проверять, является ли число полным квадратом - что может быть не очень просто.
    Ответ написан
    2 комментария
  • Как наличие одинаковых элементов в сортируемой последовательности влияет на быструю сортировку?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Смотря как писать сортировку - здесь всё зависит от мелких деталей.
    Если не помнить, что элементы могут быть одинаковыми, легко свалиться в O(n^2).
    Можно написать так, что число сравнений не изменится, но одинаковые элементы будут вхолостую переставляться друг с другом.
    Можно на каждом шагу бояться, что могут встретиться одинаковые элементы, и делить массив на три части - меньше опорного, равные ему и большие его. Тогда при большом количестве одинаковых элементов будет работать быстро, но когда одинаковых элементов нет - то число сравнений будет в 1.6 раза больше.
    Можно при разделении смотреть, был ли хоть один элемент равен опорному, и отделять равные только если был. Тогда будет плохо, когда каждый элемент встречается ровно два раза.
    Есть и другие способы. И всё это будет quicksort. Если всё написать правильно, то чем больше одинаковых элементов, тем быстрее будет сортировка.
    Ответ написан
    1 комментарий
  • Как назвать класа элемента библиотеки (той где книги и журналы)?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Paper, Publication
    Ответ написан
    Комментировать
  • Как работает данный алгоритм?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Страшноватый алгоритм...
    Сначала создаём строку, содержащую всю информацию из списка (то есть, нас вообще не волнует, что где-то была структура "список" - мы его убиваем, чтобы потом построить заново из сырых данных)...
    Потом превращаем строку в массив из строк! С помощью Split, разделяя её по пробелам!!! Зачем? Почему сразу не заполнить массив строк? А если строки в списке будут сами содержать пробелы, как "Новый список:"?
    Потом разворачиваем этот массив! Зачем? А потому, что нас не научили вставлять элементы в конец списка, мы можем вставить их только в начало. Проходить массив в обратном порядке, вероятно, тоже не умеем.
    Потом, уже при построении списка, у нас вызывается загадочная функция addNode(). Что она делает - неизвестно, поскольку, если бы она вставляла новый элемент после current - её бы вызвали ещё в двух местах кода, а не писали бы её код в развёрнутом виде.
    И, наконец, независимо от того, что делает addNode(), элемент tt[n+1] будет вставлен в список дважды.
    static Node SwapFirst(Node c) {
        if(c==null || c.next==null) return c;
        Node result=c.next;
        c.next=result.next;
        result.next=c;
        return result;
    }
    public static Node reverseMyList (Node c,int n) {
       if(n==0) return SwapFirst(c);
       Node d=c;
       for(;n>1 && d.next!=null;n--) d=d.next;
       if(n==1) d.next=SwapFirst(d.next);
       return c;
    }
    Ответ написан
    Комментировать
  • Кто-нибудь может доходчиво объяснить, что такое иерархическая временнАя последовательность физических величин?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Судя по всему, иерархическая последовательность - это последовательность последовательностей последовательностей... Раз временнАя - значит, каждый её член соответствует какому-то моменту прошлого или будущего, сам он является последовательностью - значит, от него растёт новая ветка истории и т.д. Таким образом, иерархическая последовательность описывает изменение физической величины в ветвящейся Вселенной (из теории множественных миров Эверетта). Пожалуй, сеть, способная обрабатывать такие последовательности, действительно должна быстро обучаться. Этакая квантовая нейронная сеть, какой, по мнению Пенроуза, является и наш мозг. Возможно, это и есть недостающее звено на пути к искусственному разуму.
    Ответ написан
    Комментировать
  • Какая математика нужна GameDev'у?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Ведь игры это не обязательно 3D-графика?
    В зависимости от типа игр могут потребоваться:
    - вся математика, до которой сможете дотянуться
    - комбинаторика
    - теория вероятностей
    - теория графов
    - начала искусственного интеллекта
    - матан, диффуры и теоретическая механика
    - вообще ничего, кроме программирования
    Ответ написан
    Комментировать
  • Как определить винрейт?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Никак. Возможно, результаты Б против С хуже потому, что Б готовилась к игре против А. А А - наоборот, к игре против С. Тогда может получиться, что А будет всегда проигрывать Б. А может быть и наоборот - когда А знает слабое место Б, которого не знает С. Тогда А будет выигрывать, возможно, даже чаще, чем в 80% случаев.
    Чтобы можно было что-то сказать, нужна модель - по возможности, однопараметрическая.
    Ответ написан
    7 комментариев
  • Знаете ли вы хороший сервис по изучению математики?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Игра в Евклида почему-то закрылась. Есть вот такой задачник: sciencevsmagic.net/geo/# но он, судя по всему, не о том. Но если поискать "interactive geometry problems", то много чего выдаёт, можно покопаться в результатах.
    Ответ написан
    1 комментарий
  • Как расписать циклы через goto, а потом преобразовать в state-машину?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Возьмём программу, в которой есть и циклы, и goto. Например, проверка, есть ли в матрице нулевая строка:
    void Check(int M[5][5]){
      for(int a=0;a<5;a++){
        for(int b=0;b<5;b++){
          if(M[a][b]!=0) goto L1;
       }
       goto L2;
    L1: continue;
      }
      printf("No\n"); return;
    L2:
      printf("Yes\n"); 
    }

    Опишем все переменные в начале, а циклы распишем прямо по определению.
    Кроме того, return превратим в goto на метку Return в конце функции:
    void Check(int M[5][5]){
      int a,b;
      a=0;
      goto Loop1_Check;
    Loop1_Body:
      b=0;
      goto Loop2_Check;
    Loop2_Body:
          if(M[a][b]!=0) goto L1;
          b++;
    Loop2_Check:
          if(b<5) goto Loop2_Body;  
       goto L2;
    L1: 
    Loop1_End:
       a++;
    Loop1_Check:  
      if(a<5) goto Loop1_Body;
      printf("No\n"); goto Return;
    L2:
      printf("Yes\n"); 
    Return: ;
    }

    Теперь между любыми двумя метками у нас находится линейная последовательность, в которой могут встретиться конструкции if(condition) goto label;
    Заводим переменную state.
    Каждой метке присваиваем какое-нибудь значение этой переменной, и вместо goto label пишем state=label; а вместо if(condition) goto label; - if(condition) state=label; else{ остаток кода до следующей метки }. Если перед какой-нибудь меткой label не было безусловного goto, пишем перед ней state=label;
    void Check(int M[5][5]){
      const int Return=0;
      const int Loop1_Check=1;
      const int Loop1_Body=2;
      const int Loop2_Check=3;
      const int Loop2_Body=4;
      const int L1=5;
      const int L2=6;
    
      int state;
      int a,b;
      a=0;
      state=Loop1_Check;
    Loop1_Body:
      b=0;
     state=Loop2_Check;
    Loop2_Body:
          if(M[a][b]!=0) state=L1;
          else{
             b++;
             state=Loop2_Check;
          }
    Loop2_Check:
          if(b<5) state=Loop2_Body;  
          else state=L2;
    L1: 
          a++;
          state=Loop1_Check;
    Loop1_Check:  
      if(a<5) state=Loop1_Body;
      else{
          printf("No\n"); 
          state=Return;
      }
    L2:
      printf("Yes\n"); 
      state=Return;
    Return: ;
    }

    (это преобразование было неэквивалентным).
    Теперь перед первой меткой вставляем while(state!=Return){ switch(state){
    а каждую метку label: заменяем на break; case label:
    break; перед первой меткой убираем, а case Return: меняем на } }
    void Check(int M[5][5]){
      const int Return=0;
      const int Loop1_Check=1;
      const int Loop1_Body=2;
      const int Loop2_Check=3;
      const int Loop2_Body=4;
      const int L1=5;
      const int L2=6;
    
      int state;
      int a,b;
      a=0;
      state=Loop1_Check;
      while(state!=Return){
        switch(state){
          case Loop1_Body:
            b=0;
            state=Loop2_Check;
            break;
          case Loop2_Body:
            if(M[a][b]!=0) state=L1;
            else{
              b++;
              state=Loop2_Check;
            }
            break;
          case Loop2_Check:
            if(b<5) state=Loop2_Body;  
            else state=L2;
            break;
          case L1: 
            a++;
            state=Loop1_Check;
            break;
          case Loop1_Check:  
             if(a<5) state=Loop1_Body;
             else{
                printf("No\n"); 
                state=Return;
             }
             break;
           case L2:
              printf("Yes\n"); 
              state=Return;
              break;
         }
      }
      ;
    }

    Всё.
    Ответ написан
    4 комментария
  • Как использовать метод Гаусса для итерационного метода Ньютона?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Итак, у вас есть система: F(X)=0. В точке X=(x1,x2,...,xn) её матрица Якоби равна J, а значение F(X)=Y. Шаг метода Ньютона с обратной матрицей выглядел бы как
    X'=X-J-1Y.
    Обозначим dX=J-1Y. Тогда J*dX=Y. А это - линейная система из n уравнений. Её действительно проще решить методом Гаусса, чем искать обратную матрицу и умножать на вектор. Так что находите dX и вычитаете из X.
    Ответ написан
    Комментировать