Все мои проекты вплоть до этого момента, по-видимому, основывались на чрезвычайно математическом, алгоритмическом подходе к вещам, даже если на первый взгляд этот проект казался самым далеким от математики.

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

Этот проект, однако, казался менее математическим. Проблема была доведена до меня моим другом, адвокатом, который сказал что-то вроде:

Вы должны построить калькулятор для определения срока уголовного наказания. Многие барристеры используют калькуляторы на своих телефонах, что отнимает много времени и может быть неточным в более сложных случаях.

По правде говоря, проект показался мне слегка абсурдным, потому что я не особо понимал, что такого сложного в суммировании нескольких дат. Это казалось чем-то, что вы могли просто сделать в Excel. Но была одна загвоздка: понятия параллельных предложений и последовательных предложений. Когда мой друг рассказал мне о параллельных и последовательных предложениях, мой интерес пробудился.

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

Это легко сделать в тех случаях, когда обвиняемый имеет два или три обвинения в совершении преступления, но как насчет четырех, пяти или двадцати? Вот где появляется мотивация для приложения.

Калькулятор приговора — это готовый к использованию профессиональный помощник для юристов, позволяющий рассчитать продолжительность приговора, например, обвиняемому. В приведенном выше примере у подсудимого по тесту три преступления, соответственно, в течение одного года, двух месяцев и четырех месяцев. Таблица параллелизма составлена ​​таким образом, что пользователь может выбрать, какие преступления будут обслуживаться одновременно, и, если поле не выбрано, два преступления считаются последовательными. Следовательно, из счетов 2 и 3 счет 3 является большим числом из двух и, следовательно, «выигрывает» между ними. Счет 1 идет последовательно, поэтому результат равен (1 год) + (большее из 2 и 4 месяцев) = 16 месяцев.

Как я сказал в начале, мои проекты, кажется, предполагают несколько математических или алгоритмических тем, независимо от того, каков мой предполагаемый конечный результат. Итак, какую трудность мне нужно было преодолеть на этот раз? Что-то, что я назвал цепочкой параллелизма.

В начале моего приложения цепочка параллелизма была настолько серьезной проблемой, что я построил детектор всякий раз, когда это происходило, и вместо того, чтобы что-либо вычислять, я бы сказал, что предложение невозможно вычислить, пока пользователь не отрегулирует некоторые флажки в таблице параллелизма. .

Вот в чем проблема: таблица параллелизма добавляет одну строку и столбец для каждого добавляемого счетчика, назовем их от C[1] до C[n]. При построении таблицы и рассмотрении каждой пары отсчетов C[x] и C[y] мы хотим игнорировать все случаи, когда x=y и, где уже определена пара C[x]C[y], убедиться, что пара C[y]C[x] не возникает; это дубликат. В итоге таблица у нас выглядит так:

По мере создания флажков я создал для них HTML-классы. Первый класс будет count-${row}, а второй класс будет count-${column}. Поскольку мы старались не включать избыточные или повторяющиеся пары, классы каждого флажка уникальны. Например, флажок с классом count-2 count-4 будет в строке 2 столбца 4. Просто. Теперь, когда мы отмечаем поля count-1 count-2 и count-1 count-3, например, мы знаем, что C[1] совпадает с C[2] и что C[1] также совпадает с C[3]. Итак, если первое, второе и третье равны 1 году, 2 годам и 3 годам, то параллелизм соблюдается, и общее наказание составляет 3 года. Сначала рассчитывали следующим образом:

  1. Установленный флажок считывает свои HTML-классы.
  2. Для каждого класса значение количества дней извлекается из фактической длины предложения.
  3. Большее из двух предложений «выигрывает», после этого все предложения суммируются, как если бы они были последовательными, и значение проигравшего вычитается из суммы.
  4. Повторите для всех отмеченных флажков.

Но вот где цепочка параллелизма бросила гаечный ключ в работу: что, если C[1] параллельно с C[2], а C[2] параллельно с C[3]? Для простоты заменим термин «совпадает с» символом ^.

Мы знаем, что если a=b и b=c, то a=c — это транзитивная аксиома алгебры. Точно так же, если C[1]^C[2] и C[2]^C[3] следует, что C[1]^C[3]. Однако на примерах 2, 1 и 3 лет давайте проследим это по нашему алгоритму на данный момент.

  1. Читаются классы первого флажка: count-1 count-2.
  2. Читается количество дней для count-1 и count-2. Такая точность для этого не нужна, поэтому мы оставим пару равной 2 и 1 годам.
  3. Подсчет 1 побед, а проигравший (1 год) вычитается из общего количества (в настоящее время (2+1+3)-1
  4. Повторите для второй коробки. Читаются count-2 и count-3, счет 3 является победителем, меньший (2 года) вычитается из суммы (наконец (2+1+3)-1-1 = 4.

Это неверно, но неясно, что нужно сделать, чтобы появился правильный ответ 3. Есть много способов решить эту проблему, когда цепочка не является проблемой, например, преобразование «проигравших» в длину, равную 0. Это интуитивно понятно, но все равно постоянно приводит к неправильному ответу.

Таким образом, первоначальное решение, вызванное разочарованием, состояло в том, чтобы просто сообщить пользователю, что нет, они не могут просто сцепить параллелизмы таким образом. Мой друг, однако, попросил не согласиться, сказав, что, безусловно, есть способ сделать это возможным.

Итак, после многих часов тяжелого труда я создал функцию JavaScript под названием Gordon Evaluator, названную в честь друга, предложившего этот проект, чья логика выглядит следующим образом:

Во-первых: проверьте, были ли отмечены какие-либо флажки. Если нет, то верните максимальное предложение среди всех подсчетов. Если это так, продолжайте.

Во-вторых: извлеките все отмеченные флажки и передайте каждое из имен их классов в виде двухэлементного массива строк в массив с именем pairs.

Чтобы вернуться к нашему примеру, у нас будет массив, который выглядит так: [["count-1", "count-2"], ["count-2", "count-3"]]. Порядок важен.

Теперь, чтобы что-то было «приковано», помните, что мы полагаемся на структуру C[1]^C[2] и C[2]^C[3]. Имея это в виду, мы хотим теперь сделать следующее: если второй элемент пары равен первому элементу другой пары, то все четыре элемента(т.е. три уникальных элемента) равны прикован.

Итак, мы хотим перебрать второй элемент каждой пары и проверить этот элемент на соответствие первому элементу каждой другой пары. В этом случае наш алгоритм немедленно обнаруживает, что второй элемент пары 1 равен первому элементу пары 2. Затем мы можем сопоставить элементы обеих пар — count-1, count-2, count-3 — и вернуть наибольший из них. Затем соберите эти подсчеты в массив и обязательно вычтите проигравшие в конце. Что касается других отставших, добавьте их как обычные последовательные подсчеты.

Легко, верно?