Ответы пользователя по тегу C#
  • Где, когда и как лучше использовать лямбда-выражения?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Я использую лямбда-выражения в двух случаях:
    - когда это действительно "выражение", т.е. всё вычисление укладывается в одну формулу;
    - когда для вычислений нужно использовать значения переменных текущего метода.
    При этом я помню, что "под ковром" компилятор создаст для каждого контекста с лямбда-выражением отдельный класс, и захваченные переменные будут полями этого класса (а само лямбда-выражение - его методом). Причём они будут использоваться, как поля, не только для кода, вычисляющего это выражение, но и для всей работы с этими переменными. Так что, если в конкретном месте приходится думать об эффективности, то надо всё взвесить.
    Ответ написан
    1 комментарий
  • Нельзя изменять данные в структуре на прямую?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Предполагаю, что поле Company в объекте Im.Work описано тоже как свойство:
    public Company Company{ get; set; }

    В этом случае, когда вы пишете Im.Work.Company.CompanyName="Name", вызывается метод get для Company, возвращает копию структуры (потому что вернуть ссылку не может), и дальше вы пытаетесь в этой копии, никуда её не положив, поменять одно из полей. Оригинал от этого точно не изменится, и, по-видимому, компилятор не даёт выполнить заведомо бессмысленное действие (изменить объект, который сейчас будет уничтожен).
    Ответ написан
    8 комментариев
  • Как правильно реализовать регулярное выражение без конечных автоматов?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Как-нибудь так. Не очень эффективно, правда. И без скобок.
    static string FindReg(string src,string ptrn) {
                int LP=ptrn.Length,LS=src.Length;
                for(int i=0;i<LS;i++) {
                    int k=i;
                    bool ok=true;
                    for(int j=0;ok && j<LP;) {
                        int m=1;
                        bool plus=false;
                        char cur=ptrn[j++];
                        for(;j<LP;j++) {
                            if(ptrn[j]=='+') plus=true;
                            else if(ptrn[j]==cur) m++;
                            else break;
                        }
                        int s=0;
                        while(k+s<LS && src[k+s]==cur) s++;
                        if(s<m) {
                            ok=false; break;
                        } else if(plus) k+=s;
                        else k+=m;
                    }
                    if(ok) return src.Substring(i,k-i);
                }
                return null;
            }

    Но вообще, конечный автомат понадобится очень быстро. Уже для какого-нибудь a*b*ac без него трудно будет обойтись (если не писать страшную рекурсию).
    Ответ написан
    Комментировать
  • Как построить сложный алгоритм на комбинаторику?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    static int sstep;
           static void FindAll(int N,int sum,int step,bool ord){
                sstep=step;
                sum/=step;
                fill(new int[N],N,sum,sum-N+1,ord);
            }
            static void output(int[] A){
                  Console.Write("{0}",A[0]*sstep);
                  for(int i=1;i<A.Length;i++) Console.Write("/{0}",A[i]*sstep);
                  Console.WriteLine();
            }
    
            static void fill(int[] A,int N,int sum,int smax,bool ord) {
                if(N==0 && sum==0) {
                    output(A);
                    return;
                }
                if(N==0 || sum<N) return;
                int smin=ord ? 1 : (sum-1)/N+1;
                N--;
                for(A[N]=smin;A[N]<=smax;A[N]++) {
                    fill(A,N,sum-A[N],ord ? sum-N+1 : A[N],ord);
                }
            }

    Задаётся A=new int[N], и вызывается fill(A,N,sum,sum-N+1,ord), где N=6, sum=300, ord - true, если с учётом порядка и false, если без учёта. Я проверял для N=5, sum=10 - там число вариантов приемлемо. Насколько я понимаю, для (6,300,true) будет примерно 21 миллиард комбинаций (Comb(299,5)), а для (6,300,false) - не меньше 30 миллионов.
    Ответ написан
  • Как подсчитать объем?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Достаточно для каждой грани
    vertex x1 y1 z1
    vertex x2 y2 z2
    vertex x3 y3 z3
    посчитать величину Vj=(x1*(y2*z3-y3*z2)+x2*(y3*z1-y1*z3)+x3*(y1*z2-y2*z1))/6, и найти сумму этих величин (часть из них будет отрицательной, но это не страшно). Для замкнутой модели она и будет искомым объёмом.

    Работать проще с бинарным STL - там не нужно тратить силы на синтаксический разбор.
    Ответ написан
    6 комментариев
  • Закрасить часть фигуры "Инь-Янь" c#?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Проще всего чередовать рисование чёрным и белым - нарисовать чёрный полукруг, потом 4 круга и внешнюю окружность. Как-то так:

    private static void DrawYinYang(Graphics gr,int xctr,int yctr,int rmax,int rint,int ysmall,int rsmall) {
                Brush white=Brushes.White;
                Brush black=Brushes.Black;
                Pen BlackPen=new Pen(Color.Black,2*(rmax-rint));
    
                gr.FillPie(black,xctr-rmax,yctr-rmax,2*rmax,2*rmax,-90,180);
                gr.FillEllipse(white,xctr-rint/2,yctr-rint,rint,rint);
                gr.FillEllipse(black,xctr-rint/2,yctr,rint,rint);
                gr.FillEllipse(white,xctr-rsmall,yctr+ysmall-rsmall,2*rsmall,2*rsmall);
                gr.FillEllipse(black,xctr-rsmall,yctr-ysmall-rsmall,2*rsmall,2*rsmall);
                double rcircle=(rmax+rint)/2.0;
                gr.DrawEllipse(BlackPen,(float)(xctr-rcircle),(float)(yctr-rcircle),(float)(2*rcircle),(float)(2*rcircle));
            }

    Если же хочется именно закрасить криволинейную фигуру, надо изучать, что такое GraphicPath, и использовать FIllRegion. Но я так не пробовал.
    Ответ написан
    Комментировать