Dyalog APL ( 75 73 69 68 знаков)
Вот еще одна и пятая попытка (скорее всего, моя последняя); Я потратил весь день на то, чтобы написать какой-нибудь фрагмент кода длиной менее 80 символов и полностью соответствовать правилам. Этот вызов сделал мой день!
Я наконец-то получил строку APL, состоящую из 75 символов, работающую с Dyalog APL (но не на странице онлайн-переводчика, так как использует функцию ⍎
execute ), которая выглядит следующим образом:
(N,D)÷D∨N←(⍎'0',1↓I/⍨2=+\P)+(⍎'0',I/⍨2>+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I← '1.2.3'
Конечно, я мог бы сделать это немного короче, но в особых случаях, когда одно, два или три поля отсутствуют. Мой код может даже обрабатывать ..
случай ввода.
Я знаю, что APL трудно читать, и поскольку людям нравится понимать, как на самом деле работает фрагмент кода, вот некоторые объяснения. По сути, я вычисляю последний знаменатель в переменной D и последний числитель в переменной N.
APL анализируется справа налево.
- Во-первых, строка хранится в переменной I (
I←
).
- Затем он сопоставляется с вектором логических значений, указывающих, где находится точка, и этот вектор называется P (
P←'.'=
). Например, '1.2.3' будет отображено на 0 1 0 1 0.
- Этот вектор является цифрой в базе 10 (
10⊥
); сейчас «1.2.3» составляет 1010.
- Затем 1 вычитается из этого числа (либо с,
1-⍨
либо с ¯1+
, здесь я выбрал второе). Теперь «1.2.3» - это 1009.
- Затем это число преобразуется в строку (
⍕
), удаляются две начальные цифры ( 2↓
), что составляет 09 из нашего первоначального примера 1.2.3; строка перевернута ( ⌽
).
- Здесь, в качестве особого случая, я добавляю начальный символ 0 перед строкой; мне грустно использовать четыре символа,
'0',
но я сделал это, чтобы избежать ошибки, когда второе и третье поля пусты. Строка преобразуется обратно в число ( ⍎
) и сохраняется в D, который является знаменателем, за исключением случаев, когда оба последних поля пусты, потому что в этом случае D равно 0.
D←D+0=
Кусок кода множества D 1 , если она в настоящее время нулевой, а теперь D содержит знаменатель (до НОД разделения однако).
- Этот знаменатель умножается (
×
) на содержание исходной строки I до второй точки, с (⍎'0',I/⍨2>+\P)
которой снова начинается с P (0 1 0 1 0 в моем примере), добавляет последовательные числа, накапливая их (что составляет 0 1 1 2 2 в моем примере), проверьте, какие значения меньше 2 (делая логический вектор 1 1 1 0 0), и принимая соответствующие символы в I; еще один 0 добавляется перед строкой для предотвращения другой ловушки (если два начальных поля пусты), и все преобразуется в число.
- Последняя часть входной строки добавляется к предыдущему продукту с помощью
(⍎'0',1↓I/⍨2=+\P)
, которая снова принимает P, добавляет путем кумуляции снова, проверяет, какие значения равны 2 (см. Предыдущее объяснение), берет символы-символы, удаляет первый, который является точкой , добавляет начальный нулевой символ и преобразует в число.
- Этот продукт с последующей суммой хранится в N, который является числителем.
- Наконец, GCD вычисляется с помощью D∨N, и оба числа делятся на этот GCD.
изменить: вот исправление для 73 символов:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I←
Идея этого взлома состоит в том, чтобы сначала вычислить случай, когда накопленное сложение имеет значения, равные 2, сохранить их для последующего использования и инвертировать эту побитовую маску для получения первого случая; таким образом, для вычисления следующего случая требуется меньше символов.
редактировать: вот еще одно исправление для 69 символов:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽2↓⍕¯1+10⊥P←'.'=I←
Идея этого взлома состоит в том, чтобы встроить наиболее сложный частный случай в виде кода APL в строку, которая должна быть оценена (на этапе преобразования строки в число).
редактировать: вот еще одно исправление для 68 символов:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽3↓⍕1-10⊥P←'.'=I←
Идея этого хака состоит в том, чтобы заменить добавление -1 к значению для вычитания 1 к этому значению операцией, вычтя это значение к 1, а затем удалить вначале еще один символ в начале (что будет знаком минус).
изменить: косметическое изменение:
(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←1⌈⍎'0',⌽3↓⍕1-10⊥P←'.'=I←
Нет улучшения в размере, но более удовлетворен, чтобы получить максимальную функцию из кода, подлежащего оценке.
9/99
?