Retina or Trash?

Retina, 530 220 210 202 201 193 191 187 185 (184) bytes

Credits to randomra for saving 3 bytes! (And paving the way for a couple more.)

+`\.(\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!

For byte-counting purposes, each line goes in a separate file, but you can run the above code as is from a single file by invoking Retina with the -s flag.

This expects the density first (which must contain a decimal point, even if it's a trailing one), followed by width and height, i.e. d w h.

This is a bit slow. I wouldn't try most of the given test cases, because it will run for ages. However, you can check that it works correctly with the test cases

19. 4096 2160     -> Trash!
1. 180 240        -> Trash!
1. 181 240        -> Retina!
1. 180 241        -> Retina!
0.04 10 10        -> Retina!

Basically, after multiplying all numbers through to make the density an integer, you don't want the width and height to have more than 4 digits.

While this is slow, it is completely exact... there are no floating point issues or anything like that. All arithmetic is using (unary) integers.

In principle, I could shave off one more byte: the ^ can be omitted, but it will make Trash! test cases horribly slow due to excessive amounts of backtracking.

Explanation

First, let's rearrange the inequality to avoid floating point operations:

√(w2 + h2) / d > 300
√(w2 + h2) > 300 d
w2 + h2 > 90000 d2

We can also notice that this is invariant under multiplying w, h and d by the same number 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

There are several ways to square a unary number, but we'll be making use of the identity

n2 = Σi=1..2n ⌊i/2⌋

This gives us a way to solve the problem using only integer arithmetic (representing integers in unary).

Let's go through the code. Each pair of lines is a regex substitution.

+`\.(\d)(.+)( .+)
$1.$2_$3_

This repeatedly moves the decimal point in the density to the right while multiplying width and height by 10 (the x above). This is to ensure that all numbers are integers. Instead of appending zeroes, I'm appending _, which I'll be treating as zero later on. (This is a golfing trick, because otherwise I'd need to write ...${3}0 to avoid ambiguity with $30.) The + in front of the regex tells Retina to repeat this substitution until the result stops changing (which is the case when the pattern no longer matches).

\b
#

We're preparing the three numbers for conversion to unary now. In principle, we need a marker (the #) in front of each number, but it's shorter to add one to the end of each number as well, which won't affect the conversion step.

+`(\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#

This is the conversion to unary, using a trick that has been developed by dan1111. Essentially I'm translating each digit to a rep-digit of itself, while multiplying the existing digits by 10 (moving the # marker to the right in the process). This binary representation will be quite a jumble of different digits, but the total number will be equal to the value of the original integer. Note the \w at the end - normally this is just 0, but we want to treat _ as zero as well (which is considered a word character in regex).

\d
11

We turn each digit into two 1s, thereby a) ensuring all digits are the same (which will be necessary later) and b) doubling each of the numbers.

(?=(1*)\1)[^.]
$1

This does two things: it squares all numbers (or rather half of each number, by computing a sum over 2n), and adds the resulting squares of the width and the height. Notice that [^.] matches 1s, # markers and spaces. If it's a # or a space, the lookahead won't capture anything, which means all of those are simply removed, i.e. the results for the width and height are concatenated/added. The decimal point . remains to separate the result for d from those. If [^.] matches a 1 instead, then the lookahead ensures that we capture half of the 1s after it (rounded down) in group 1. This computes the sum I mentioned above, which will then yield the square of the original number.

^(1+)\.\1{90000}1+
Retina!

The string is now d2 (in unary), then ., then w2 + h2 (in unary). We want to know if the first unary number times 90000 is shorter than the second. We can easily do this multiplication using a capturing group and {n} repetition syntax. We use 1+ (instead of 1*) afterwards to ensure that the second number is actually greater than that and not just equal. If so, we replace all of that by Retina!.

1.+
Trash!

If the second number wasn't big enough, then the previous step won't have changed anything and the string will still start with a 1. If that's the case, we just replace the entire string by Trash! and are done.


Python, 49

lambda w,h,d:"RTertaisnha!!"[w*w+h*h<=9e4*d*d::2]

Uses string interleaving.

It turned out shorter to square both sides than to use the complex norm.

w*w+h*h<=9e4*d*d
abs(w+1j*h)<=300*d

CJam, 30 29 27 bytes

q~mh300/<"Retina""Trash"?'!

Requires input to be in form of diagonal width height

UPDATE: 1 byte saved thanks to Dennis!

Try it online here

Tags:

Code Golf