Kare Sayısı Rakam Yoğunluğu


17

Kendim tarafından icat edilen bir sayının kare sayı basamak yoğunluğu (SNDD), art arda basamaklarda bulunan kare sayılarının sayısının sayının uzunluğuna oranıdır. Örneğin 169, 4 kare sayısı - 1, 9, 16, 169 - içeren 3 basamaklı bir sayıdır ve bu nedenle kare sayısı basamak yoğunluğu 4/3 veya 1,33'tür. 4 haneli 1444 sayısı 6 kareye - 1, 4, 4, 4, 144, 1444 - ve dolayısıyla 6/4 veya 1.5 oranına sahiptir. Önceki örnekte, karelerin tekrarlanmasına izin verildiğine dikkat edin. Ayrıca, 441'e izin verilmez, çünkü 1444 sayısının içinde art arda bulunamaz.

Göreviniz, en yüksek kare sayısı basamak yoğunluğuna sahip sayı için belirli bir A - B aralığını (dahil) araştıran bir program yazmaktır. Programınız aşağıdaki özelliklere uymalıdır:

  • A, B girişini 1 ila 1.000.000.000 (1 milyar) aralığında alın. Misal:sndd 50 1000
  • Sonuç olarak en büyük SNDD'ye sahip sayıyı döndürün. Beraberlik durumunda, en küçük sayıyı döndürün.
  • 0, 0, 00, 000 vb. Şeklinde herhangi bir kare olarak sayılmaz. 0 ile başlayan, 049 veya 0049 gibi kareler de yoktur.
  • Sayının tamamının kare sayı olması gerekmediğini unutmayın.

Örnekler:

sndd 14000 15000
Output: 14441

sndd 300 500
Output: 441

Bonus: 1 ile 1.000.000.000 arasında en büyük SNDD'ye sahip sayı nedir? Bunun mümkün olan en büyük olup olmadığını veya daha yüksek bir aralıkta daha büyük bir tane olduğunu kanıtlayabilir misiniz?

Güncel Skorlar:

  1. Yakut: 142
  2. Windows PowerShell: 153
  3. Scala: 222
  4. Python: 245

Bir yanıt seçildiğine göre, JavaScript'teki (ungolfed) referans uygulamam: http://jsfiddle.net/ywc25/2/

Yanıtlar:


3

Yakut 1.9, 142 karakter

$><<($*[0]..$*[1]).map{|a|n=0.0;(1..s=a.size).map{|i|n+=a.chars.each_cons(i).count{|x|x[0]>?0&&(r=x.join.to_i**0.5)==r.to_i}};[-n/s,a]}.min[1]
  • (139 -> 143): Beraberlik durumunda sabit çıkış.

@Ventero: Her iki test vakasında başarısız olur. Sanırım 0 * ile başlayan kareleri terk etmeyi unutuyorsun
mellamokb

@mellamokb: onları burada başarısız yok: $ ruby1.9 sndd.rb 14000 15000 => 14441. x[0]>?00 ile başlayan kareleri kontrol eder.
Ventero

@mellamokb: Test örneklerini burada geçiyor.
Nabb

@Ventero: Hmm .. yakut test ortamımda bir şeyler yanlış olmalı. Ruby'ye aşina değilim. Sanırım 1.87 ve yukarıdaki kodu kopyaladım / yapıştırdım sndd.rb, sonra ruby sndd.rb 14000 15000Windows ile çalıştırın , ben 14000 olsun.
mellamokb

@mellamokb: Ruby 1.8'de ?0bir Fixnum, Ruby 1.8'de ise bir dize, bu yüzden bahsettiğim karşılaştırma Ruby sürümüne bağlı olarak farklı bir anlama sahip (aslında 1.8'de bir istisna atmalı). Bu yüzden başlıkta 1.9 sürümünden açıkça bahsetmiştim.
Ventero

8

Bonusu cevaplamak için: <1e9 rakamları için en iyi puan 144411449 (ve belki de diğerleri?) Tarafından oluşturulan 5/3 = 1.666 ... 'dır.

Ancak daha büyük sayılarla daha iyisini yapabilirsiniz. Genellikle n'nin x puanı varsa, n'nin iki kopyasını birleştirebilir ve aynı puanı x elde edebilirsiniz. Eğer şanslıysanız ve n aynı ilk ve son basamağa sahipse, bu basamaklardan birini birleştirme içinde bırakabilir ve puanınızı hafifçe artırabilirsiniz (karelerin sayısının iki katından az ve basamak sayısının iki katından az). .

n = 11449441, 1.625 puanına sahiptir ve aynı ilk ve son basamağa sahiptir. Bu gerçeği kullanarak, aşağıdaki puan dizisini elde ederiz:

1.625 for 11449441
1.666 for 114494411449441
1.682 for 1144944114494411449441
1.690 for 11449441144944114494411449441
1.694 for 114494411449441144944114494411449441

bu da önceki sayılardan kesinlikle (azalan olmasına rağmen) daha iyi olan ve ilk 2 hariç tümü <1e9 sayıları için en iyi puandan daha iyi olan sonsuz bir sayı dizisi verir.

Bununla birlikte, bu dizi genel olarak en iyi olmayabilir. Sonlu bir puana yaklaşır (12/7 = 1.714) ve limitten daha iyi skorlara sahip başka sayılar olabilir.

Düzenleme : daha iyi bir sıra, 1,75'e yakınsar

1.600 14441
1.667 144414441
1.692 1444144414441
1.706 14441444144414441
1.714 144414441444144414441

İlginç! Bu dizinin aslında sonsuz olduğunu kanıtlamış olabilirsiniz .
ESultanik

@ESultanik: Pek değil, çünkü burada toplam sayının mükemmel bir kare olması gerekmiyor.
mellamokb

@ESutanik: Dizinin ilişkili olduğunu düşünmüyorum, çünkü tüm sayının kare olmasını istiyorlar - dizimde sadece kareler küçük dizilerdir (<= 5 basamak), eğer kazara daha büyük bir tane olmadıkça.
Keith Randall

Ayrıca bağlantının fazladan bir kare oluşturduğu sonsuz bir sıra oluşturabilirsiniz, yani 44 ile biten ve 1 ile başlayan bir şey her kombinasyonda 441 yapar. Önemsiz bir örnek, 144, 144144, 144144144 vb.
Dizidir

@mellamokb Vay be, sayının mükemmel bir kare olması gerekmediğini tamamen özledim. Haklısın.
ESultanik

3

Windows PowerShell, 153 154 155 164 174

$a,$b=$args
@($a..$b|sort{-(0..($l=($s="$_").length)|%{($c=$_)..$l|%{-join$s[$c..$_]}}|?{$_[0]-48-and($x=[math]::sqrt($_))-eq[int]$x}).Count/$l},{$_})[0]

Ventero sayesinde bir baytlık bir azalma için kendimi bulamayacak kadar aptaldım.

154 baytlık sürüm açıkladı:

$a,$b=$args   # get the two numbers. We expect only two arguments, so that
              # assignment will neither assign $null nor an array to $b.

@(   # @() here since we might iterate over a single number as well
    $a..$b |  # iterate over the range
        sort {   # sort
            (   # figure out all substrings of the number
                0..($l=($s="$_").length) | %{  # iterate to the length of the
                                               # string – this will run off
                                               # end, but that doesn't matter

                    ($c=$_)..$l | %{       # iterate from the current position
                                           # to the end

                        -join$s[$c..$_]    # grab a range of characters and
                                           # make them into a string again
                    }
                } | ?{                     # filter the list
                    $_[0]-48 -and          # must not begin with 0
                    ($x=[math]::sqrt($_))-eq[int]$x  # and the square root
                                                     # must be an integer
                }

            ).Count `  # we're only interested in the count of square numbers
            / $l       # divided by the length of the number
        },
        {-$_}  # tie-breaker
)[-1]  # select the last element which is the smallest number with the
       # largest SNDD

2

Piton, 245 , 256

import sys
def t(n,l):return sum(map(lambda x:int(x**0.5+0.5)**2==x,[int(n[i:j+1])for i in range(l)for j in range(i,l)if n[i]!='0']))/float(l)
print max(map(lambda x:(x,t(str(x),len(str(x)))),range(*map(int,sys.argv[1:]))),key=lambda y:y[1])[0]
  • 256 → 245: Keith Randall'ın bir ipucu sayesinde argüman ayrıştırma kodu temizlendi .

Aralık stdin, komut satırı bağımsız değişkenlerinin aksine okunduysa bu çok daha kısa olabilir .

Düzenle:

Bonus ile ilgili olarak, deneylerim şunları önermektedir:

Konjektif 1 . Her n ∈ ℕ için , en büyük SNDD'ye sahipn rakamı yalnızca 1, 4 ve 9 rakamlarını içermelidir.

Sanısı 2.n ∈ ℕ ∀ i ℕ ∈ N : SNDD ( n ) ≥ SNDD ( i ).

Kanıt kroki . 1, 4 ve 9 basamaklı kareler kümesi muhtemelen sonludur . ∎


Denerange(*map(int,sys.argv[1:]))
Keith Randall

1
Cevabımdaki 1.75 yakınsak dizi, en iyi skorları (kabul edilirse, büyükse) üretirse, dizinin sonraki elemanları sonsuza dek marjinal olarak daha iyi olduğundan, konjektif 2 yanlıştır.
Keith Randall

Konjektif 2 @ Arnt'ın cevabı tarafından yanlıştır, çünkü SNDD'nin değeri keyfi olarak büyütülebilir.
mellamokb

2

Scala, 222

object O extends App{def q(i: Int)={val x=math.sqrt(i).toInt;x*x==i}
println((args(0).toInt to args(1).toInt).maxBy(n=>{val s=n+""
s.tails.flatMap(_.inits).filter(x=>x.size>0&&x(0)!='0'&&q(x.toInt)).size.toFloat/s.size}))}

(Scala 2.9 gerekir.)


1

Bonus sorusu göz önüne alındığında: Aralık dışında mümkün olan en yüksek SNDD sınırsızdır.

En azından soruyu doğru okursam 100 (10 * 10) gibi bir kare sayılır.

275625 sayısını düşünürseniz, skor 5/6'dır, çünkü 25, 625, 5625, 75625 ve 275625'in hepsi karedir.

2 sıfır eklenmesi: 27562500, puanı 10/8. Bu dizinin sınırı 5/2 = 2,5'tir.

Aynı çizgiler boyunca, istediğiniz sayıda daha küçük kareyle sonuçlanan kareler bulabilirsiniz. Bunu kanıtlayabilirim, ama muhtemelen fikri anlarsın.

Kuşkusuz, bu çok hoş bir çözüm değil, ancak SNDD'nin üst sınırı olmadığını kanıtlıyor.


"Aynı çizgiler boyunca, istenilen sayıda daha küçük kareyle biten kareler bulabilirsiniz. Bunu kanıtlayabilirim, ama muhtemelen fikri anlıyorsunuz." Bu kanıtın geliştiğini görmek istiyorum. 25 ile biten en büyük diziyi 25 ile biten her sayının bir kare olduğu 275625 olduğunu görebiliyorum. Başka bir kare bulmak için başlangıçta yerleştirebileceğiniz 1-9 basamağı yok. Bunun keyfi olarak yapılabileceğini mi söylüyorsunuz, eğer öyleyse nasıl ve neden?
mellamokb

Evet, dizi keyfi olarak büyütülebilir. Kanıt şudur: a * a = b başlangıç ​​numaranızsa, c yeterince büyükse (a + 10 ^ c) * (a + 10 ^ c) de b ile biter. Pratikte kareyi alırsanız b ile biten daha küçük sayılar olabilir. Örneğin, 18275625 bir karedir (4275 * 4275).
Arnt Veenstra

Kareleri bulmak için kod: jsfiddle.net/zVSuZ/2
mellamokb

@Arnt: İşte böyle (önemsiz) bir dizi, 5 ^ 2 (1/2), 55 ^ 2 (2/4), 5055 ^ 2 (3/8), 50005055 ^ 2 (4/16), vb. burada her ekleme 5 * 10 ^ n'dir, burada n bir önceki girdinin iki katıdır. Her bir giriş skor olarak küçülür, ancak iki 00'ın eklenmesi kuralını uygularken sınır marjinal olarak büyür, bu nedenle limitler (1/2), (2/2), (3/2), (4/2) vb. .
mellamokb

Evet, SNDD için herhangi bir değerin kanıtlandığını gösteren fikir budur.
Arnt Veenstra

1

Clojure - 185 karakter

Muhtemelen daha da optimize edilebilir, ancak işte gidiyor:

(fn[A,B]((first(sort(for[r[range]n(r A(inc B))s[(str n)]l[(count s)]][(/(count(filter #(=(int%)(max 1%))(for[b(r(inc l))a(r b)](Math/sqrt(Integer/parseInt(subs s a b))))))(- l))n])))1))

İki parametreli bir işlev olarak kullanılır:

(crazy-function-as-above 14000 15000)
=> 14441

1

Jelly , 21 bayt, dil postdates zorluğu

DµẆ1ị$ÐfḌƲS÷L
rµÇÐṀḢ

Çevrimiçi deneyin!

açıklama

Yardımcı işlevi (girişinin basamak yoğunluğunu hesaplar):

DµẆ1ị$ÐfḌƲS÷L
Dµ              Default argument: the input's decimal representation
  Ẇ             All substrings of {the decimal representation}
      Ðf        Keep only those where
   1ị$          the first digit is truthy (i.e. not 0)
        Ḍ       Convert from decimal back to an integer
         Ʋ     Check each of those integers to see if it's square
           S    Sum (i.e. add 1 for each square, 0 for each nonsquare)
            ÷L  Divide by the length of {the decimal representation}

Ana program:

rµÇÐṀḢ
rµ              Range from the first input to the second input
  ÇÐṀ           Find values that maximize the helper function
     Ḣ          Choose the first (i.e. smallest)

Program tartışmasız daha ilginç olmadan - bu şekilde, sadece bir değil, tüm maksimum yoğunluklu sayıları döndürür - ancak spesifikasyona uymak için ekledim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.