Retina , 530 220 210 202 201 193 191 187 185 (184) байт
Кредиты рандоме для сохранения 3 байта! (И прокладывает путь еще на пару.)
+`\.(\d)(.+)( .+)
$1.$2_$3_
\b
#
+`(\d*)#((((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|\w)
$1$1$1$1$1$1$1$1$1$1$3$4$5$6$7$8$9$10$11#
\d
11
(?=(1*)\1)[^.]
$1
^(1+)\.\1{90000}1+
Retina!
1.+
Trash!
Для подсчета байтов каждая строка идет в отдельном файле, но вы можете запустить приведенный выше код как один из одного файла, вызвав Retina с -s
флагом.
Это первое ожидает , что плотность (которая должна содержать десятичную точку, даже если это замыкающий один), а затем по ширине и высоте, то есть d w h
.
Это немного медленно. Я бы не стал пробовать большинство из приведенных тестов, потому что он будет работать целую вечность. Тем не менее, вы можете проверить, что он работает правильно с тестовыми примерами
19. 4096 2160 -> Trash!
1. 180 240 -> Trash!
1. 181 240 -> Retina!
1. 180 241 -> Retina!
0.04 10 10 -> Retina!
По сути, после умножения всех чисел на целые значения плотности не требуется, чтобы ширина и высота имели более 4 цифр.
Хотя это медленно, это совершенно точно ... нет проблем с плавающей запятой или что-то в этом роде. Вся арифметика использует (унарные) целые числа.
В принципе, я мог бы сбрить еще один байт: ^
опустить его можно, но это сделает Trash!
тестовые случаи ужасно медленными из-за чрезмерного количества возвратов.
объяснение
Во-первых, давайте изменим неравенство, чтобы избежать операций с плавающей запятой:
√(w2 + h2) / d > 300
√(w2 + h2) > 300 d
w2 + h2 > 90000 d2
Можно также заметить , что это инвариантно относительно умножения w
, h
и d
одним и тем же номером x
:
w2 + h2 > 90000 d2
(x w)2 + (x h)2 > 90000 (x d)2
x2 (w2 + h2) > 90000 x2 d2
w2 + h2 > 90000 d2
Есть несколько способов возвести в квадрат одинарное число, но мы будем использовать тождество
n2 = Σi=1..2n ⌊i/2⌋
Это дает нам возможность решить проблему, используя только целочисленную арифметику (представляющую целые числа в унарном).
Давайте пройдемся по коду. Каждая пара строк является подстановкой регулярного выражения.
+`\.(\d)(.+)( .+)
$1.$2_$3_
Это многократно перемещает десятичную точку в плотности вправо, умножая ширину и высоту на 10 ( x
выше). Это делается для того, чтобы все числа были целыми числами. Вместо добавления нулей я добавляю _
, что позже буду трактовать как ноль. (Это игра в гольф, потому что в противном случае мне нужно было бы написать, ...${3}0
чтобы избежать двусмысленности $30
.) +
Перед регулярным выражением перед Retina указывается повторять эту замену до тех пор, пока результат не перестанет изменяться (что является случаем, когда шаблон больше не совпадает) ,
\b
#
Мы готовим три числа для преобразования в унарный. В принципе, нам нужен маркер ( #
) перед каждым числом, но короче, чтобы добавить один к концу каждого числа, что не повлияет на шаг конвертации.
+`(\d*)#((((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|\w)
$1$1$1$1$1$1$1$1$1$1$3$4$5$6$7$8$9$10$11#
Это преобразование в унарный, используя трюк, разработанный dan1111 . По сути, я перевожу каждую цифру в саму повторную цифру, умножая существующие цифры на 10 (при этом перемещая #
маркер вправо). В этом двоичном представлении будет довольно много разных цифр, но общее число будет равно значению исходного целого числа. Обратите внимание \w
на конец - обычно это просто 0
, но мы также хотим трактовать _
как ноль (который в регулярном выражении считается символом слова).
\d
11
Мы превращаем каждую цифру в две 1
s, тем самым а) обеспечивая, чтобы все цифры были одинаковыми (что будет необходимо позже), и б) удваивая каждое из чисел.
(?=(1*)\1)[^.]
$1
Это делает две вещи: он возводит в квадрат все числа (или, точнее, половину каждого числа, вычисляя сумму над 2n
) и добавляет полученные квадраты ширины и высоты. Обратите внимание, что [^.]
соответствует 1
s, #
маркеры и пробелы. Если это #
или пробел, заглядывание не будет ничего захватывать, что означает, что все они просто удаляются, то есть результаты для ширины и высоты объединяются / добавляются. Десятичная точка .
остается отделить результат для d
тех. Если вместо этого [^.]
совпадает с a 1
, то предварительный просмотр гарантирует, что мы захватим половину 1
s после него (округлено) в группе 1
. Это вычисляет сумму, которую я упомянул выше, которая затем даст квадрат исходного числа.
^(1+)\.\1{90000}1+
Retina!
Строка теперь (в унарном), затем , затем (в унарном). Мы хотим знать, короче ли первое унарное число раз, чем второе. Мы можем легко сделать это умножение, используя группу захвата и синтаксис повторения. Мы используем (вместо ) впоследствии, чтобы убедиться, что второе число на самом деле больше , а не просто равно. Если это так, мы заменим все это на .d2
.
w2 + h2
90000
{n}
1+
1*
Retina!
1.+
Trash!
Если второе число не было достаточно большим, то предыдущий шаг ничего не изменит, и строка все равно будет начинаться с 1
. Если это так, мы просто заменим всю строку на Trash!
и все готово.