Retina , 530 220 210 202 201 193 191 187 185 (184) bayt
3 byte tasarruf için randomra için Kredi! (Ve bir çiftin yolunu açıyor.)
+`\.(\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!
Bayt sayma amacıyla, her satır ayrı bir dosyaya gider, ancak yukarıdaki kodu tek bir dosyadan olduğu gibi Retina'yı -s
bayrakla çalıştırarak çalıştırabilirsiniz .
Bu, önce yoğunluğu ( izleyen olsa bile ondalık bir nokta içermesi gerekir ) önce genişliğini ve yüksekliğini bekler d w h
.
Bu biraz yavaş. Verilen test vakalarının çoğunu denemem, çünkü uzun yıllar sürecek. Ancak, test durumlarıyla doğru çalıştığını kontrol edebilirsiniz.
19. 4096 2160 -> Trash!
1. 180 240 -> Trash!
1. 181 240 -> Retina!
1. 180 241 -> Retina!
0.04 10 10 -> Retina!
Temel olarak, yoğunluğu bir tamsayı yapmak için tüm sayıları çarptıktan sonra, genişliğin ve yüksekliğin 4 basamaktan daha fazla olmasını istemezsiniz.
Bu yavaş olsa da, tamamen kesin ... kayan nokta sorunu veya bunun gibi bir şey yok. Tüm aritmetik (unary) tamsayılar kullanıyor.
Prensip olarak, bir bayt daha tıraş ^
edebilirim : ihmal edilebilir, ancak Trash!
aşırı geri izleme nedeniyle test durumlarını çok yavaşlatır.
açıklama
İlk önce, kayan nokta işlemlerinden kaçınmak için eşitsizliği yeniden düzenleyelim:
√(w2 + h2) / d > 300
√(w2 + h2) > 300 d
w2 + h2 > 90000 d2
Biz de bu değişmez çarparak altında olduğunu fark edebilirsiniz w
, h
ve d
aynı sayısına göre 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
Tek bir sayının karesini almanın birkaç yolu vardır, ancak kimliği kullanacağız.
n2 = Σi=1..2n ⌊i/2⌋
Bu bize sorunu sadece tamsayı aritmetiği kullanarak (tekli tamsayıları temsil eden) çözmenin bir yolunu verir.
Hadi koddan geçelim. Her bir çizgi çifti bir regex ikamesidir.
+`\.(\d)(.+)( .+)
$1.$2_$3_
Bu, genişlik ve yüksekliği 10 ( x
yukarıdaki) ile çarparken, yoğunluktaki ondalık noktayı tekrar tekrar sağa kaydırır . Bu, tüm sayıların tam sayı olmasını sağlamak içindir. _
Sıfır eklemek yerine, daha sonra sıfır olarak kullanacağım, ekliyorum . (Bu bir golf oyunudur, çünkü aksi takdirde ...${3}0
belirsizlikten kaçınmak için yazmam gerekir $30
.) +
Regex'in önünde, Retina'ya, bu değişimin bitinceye kadar (desen artık uyuşmadığında olduğu gibi) bu değişikliği tekrar etmesini söyler. .
\b
#
Şimdi üç sayıyı unary'e çevirmeye hazırlıyoruz. Prensip olarak, #
her sayının önünde bir işaretleyiciye ( ) ihtiyacımız vardır , ancak her sayının sonuna bir tane eklemek daha kolaydır, bu da dönüşüm adımını etkilemez.
+`(\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#
Bu, dan1111 tarafından geliştirilen bir numara kullanarak , birliğe dönüşüyor . Temelde, mevcut haneleri 10 ile çarparken her basamağı kendi basamağının diline çeviriyorum (işlem sırasında #
işaretçiyi sağa doğru hareket ettirerek ). Bu ikili gösteriliş, farklı basamaklarda oldukça karışık olacaktır, ancak toplam sayı, orijinal tamsayının değerine eşit olacaktır. Not \w
sonunda - normalde bu sadece 0
, ama biz tedavi etmek istiyorum _
(bir kelime regex karakter olarak kabul edilir) hem de sıfır olarak.
\d
11
Her basamağı iki 1
s'ye çeviririz, böylece a) tüm basamakların aynı olmasını sağlamak (daha sonra gerekli olacak) ve b) sayıların her birini iki katına çıkarmak.
(?=(1*)\1)[^.]
$1
Bu iki şey yapar: tüm sayıları kareler (veya her sayının yarısını, toplamı hesaplayarak 2n
) kareler ve genişliğin ve yüksekliğin sonuç karelerini ekler. S, işaretleyiciler ve boşluklarla [^.]
eşleşen dikkat edin . Eğer bu bir boşluk ya da boşluk ise, bakış açısı hiçbir şeyi yakalamaz, bu da bunların hepsinin basitçe kaldırıldığı anlamına gelir, yani genişlik ve yükseklik için sonuçlar birleştirilir / eklenir. Ondalık nokta sonucu onlardan ayırmak için kalır . Eğer maçları bir yerine, ardından ileri yönlü olmasını sağlar bunun biz yakalama yarım s bununla (yuvarlak aşağı) grubunda sonra . Bu yukarıda belirtilen toplamı hesaplar ve bu daha sonra orijinal sayının karesini verir.1
#
#
.
d
[^.]
1
1
1
^(1+)\.\1{90000}1+
Retina!
Dize şimdi (unary içinde), sonra , sonra (unary içinde). İlk unary sayı sürelerinin ikinciden daha kısa olup olmadığını bilmek istiyoruz . Bir yakalama grubu ve tekrarlama sözdizimi kullanarak bu çarpımı kolayca yapabiliriz . İkinci sayının aslında ondan daha büyük olmasını ve sadece eşit olmasını sağlamak için (yerine ) kullanırız . Eğer öyleyse, hepsini değiştiririz .d2
.
w2 + h2
90000
{n}
1+
1*
Retina!
1.+
Trash!
İkinci sayı yeterince büyük değilse, önceki adım hiçbir şeyi değiştirmez ve dize yine de bir ile başlar 1
. Bu durumda, dizenin tamamını değiştiririz Trash!
ve yapılır.