平方数の密度


17

数の平方数桁密度(SNDD)-自分で発明-は、連続した数字で見つかった平方数の数と数の長さの比です。たとえば、169は4つの正方形の数字(1、9、16、169)を含む3桁の数字であるため、4/3または1.33の正方形の数字の密度になります。4桁の数字1444には6つの正方形(1、4、4、4、144、1444)があるため、比率は6/4、つまり1.5です。前の例では、正方形の繰り返しが許可されていることに注意してください。また、441は番号1444内で連続して検出できないため、許可されません。

あなたの仕事は、与えられた範囲A-B(包括的)を検索して、最高の二乗数字桁密度を持つ数字を探すプログラムを書くことです。プログラムは、次の仕様に従う必要があります。

  • 入力A、Bを1〜1,000,000,000(10億)の範囲で受け取ります。例:sndd 50 1000
  • 結果として、最大のSNDDを持つ数値を返します。同点の場合、最小の数値を返します。
  • 0は、0、00、000など、どのような形式の正方形としてもカウントされません。049や0049など、0で始まる正方形もカウントされません。
  • 数値全体が正方である必要はないことに注意してください。

例:

sndd 14000 15000
Output: 14441

sndd 300 500
Output: 441

ボーナス:1から1,000,000,000の間で最大のSNDDを持つ数字は何ですか?これが可能な限り大きいのか、それともより大きな範囲がより高い範囲にあるのかを証明できますか?

現在のスコア:

  1. ルビー:142
  2. Windows PowerShell:153
  3. Scala:222
  4. Python:245

答えが選択されたので、ここにJavaScriptでの(変更されていない)リファレンス実装を示します:http ://jsfiddle.net/ywc25/2/

回答:


3

Ruby 1.9、142文字

$><<($*[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):タイの場合の出力を修正。

@Ventero:両方のテストケースに不合格。0 *で始まる正方形を
省く

@mellamokb:ここで失敗しません:$ ruby1.9 sndd.rb 14000 15000 => 14441x[0]>?00で始まる正方形をチェックします
。– Ventero

@mellamokb:ここでテストケースに合格します。
ナブ

@Ventero:うーん。ルビーのテスト環境に何か問題があるに違いない。私はRubyに詳しくありません。1.87があり、上記のコードをsndd.rbにコピー/貼り付け、ruby sndd.rb 14000 15000Windowsから実行すると
14000が

@mellamokb:Ruby 1.8では?0Fixnumですが、Ruby 1.8では文字列であるため、前述の比較はRubyのバージョンによって異なる意味を持ちます(実際には1.8で例外をスローするはずです)。そのため、タイトルでバージョン1.9を明示的に言及しました。
ヴェンテロ

8

ボーナスに答える:数値<1e9の最高スコアは5/3 = 1.666 ...で、144411449(および他の人も?)によって生成されます。

しかし、数字が大きいほど良い結果が得られます。通常、nのスコアがxの場合、nの2つのコピーを連結して同じスコアxを取得できます。幸運でnの最初と最後の数字が同じ場合、連結でそれらの数字の1つをドロップして、スコアをわずかに改善できます(1倍の数よりも小さく、1倍の数よりも少ない) 。

n = 11449441のスコアは1.625で、最初と最後の数字が同じです。その事実を使用して、次の一連のスコアを取得します。

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

これは、前の数字よりも厳密に(漸減的ではあるが)優れた数字の無限シーケンスを提供し、最初の2つを除くすべてが1e9未満の数字のベストスコアよりも優れています。

ただし、このシーケンスは全体的に最適ではない場合があります。有限スコア(12/7 = 1.714)に収束し、制限よりも良いスコアを持つ他の数値が存在する場合があります。

編集:より良いシーケンス、1.75に収束

1.600 14441
1.667 144414441
1.692 1444144414441
1.706 14441444144414441
1.714 144414441444144414441

面白い!このシーケンスが実際に無限であることを証明したかもしれません。
ESultanik

@ESultanik:そうではありません。全体の数が完全な正方形である必要はないためです。
mellamokb

@ESutanik:シーケンスが関連しているとは思いません。整数である必要があるので、私のシーケンスでは、誤って大きなサブシーケンスが存在しない限り、正方形は小さなサブシーケンス(<= 5桁)のみです。
キースランドール

また、リンクが余分な正方形を生成する無限シーケンスを生成することもできます。つまり、44で終了し1で始まるものはすべての組み合わせで441になります。簡単な例は、144、144144、144144144などのシーケンス
です。– mellamokb

@mellamokbうわー、数字が完全な正方形である必要はないことを完全に忘れていました。あなたが正しい。
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]

1バイト削減したVenteroに感謝します。

154バイトバージョンの説明:

$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

Python、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からのヒントのおかげで、引数解析コードを整理しました。

stdinコマンドライン引数とは対照的に、範囲が読み取られた場合、これははるかに短くなります。

編集:

ボーナスに関して、私の実験では次のことが示唆されています。

予想1すべてのnに対して ∈ℕ 、で数N最大SNDDとは、単に数字1,4、および9を含まなければなりません。

推測2.N ∈ℕ∀Iℕ∈ N:SNDD(N)≥SNDD(I)。

証明スケッチ。数字1、4、および9の正方形のセットはおそらく有限です。∎


試してくださいrange(*map(int,sys.argv[1:]))
キースランドール

1
シーケンスの後続の要素が永久にわずかに優れているため、私の答えの1.75収束シーケンスが最高のスコア(確かに大きい場合)を生成する場合、推測2は偽です。
キースランドール

SNDDの値を任意に大きくできるため、推測2は@Arntの答えでは偽です。
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が必要です。)


1

ボーナスの質問を考えてみましょう。範囲外では、可能な限り最高のSNDDは無限です。

少なくとも、質問を正しく読んだ場合、100(10 * 10)のような正方形はカウントされます。

番号275625を考慮すると、25、625、5625、75625、および275625はすべて正方形であるため、スコアは5/6です。

2つのゼロを追加すると、27562500のスコアが10/8になります。このシーケンスの制限は5/2 = 2.5です

同じ線に沿って、希望する任意の数の小さな正方形で終わる正方形を見つけることができます。私はこれを証明することができますが、おそらくあなたはアイデアを得るでしょう。

確かに、これはあまり良い解決策ではありませんが、SNDDに上限がないことを証明しています。


「 '同じ線に沿って、希望する任意の数の小さな正方形で終わる正方形を見つけることができます。これを証明することはできますが、おそらくあなたはアイデアを得るでしょう。 " この証明が開発されてほしい。25で終わる最大数列がすべて275625である、25で終わる最大数列を見ることができます。最初に別の正方形を見つけるために配置できる1-9の数字はありません。これを任意に大きくできると言っていますか?
mellamokb

はい、シーケンスを任意に大きくすることができます。証明は次のとおりです。a* a = bが開始番号である場合、cが十分に大きい場合、(a + 10 ^ c)*(a + 10 ^ c)もbで終了します。実際には、正方形を取るとbで終わる小さな数字があるかもしれません。この例では、18275625は正方形(4275 * 4275)です。
ARNT Veenstra

正方形を見つけるためのコード:jsfiddle.net/zVSuZ/2
mellamokb

@Arnt:このような(簡単な)シーケンス、5 ^ 2(1/2)、55 ^ 2(2/4)、5055 ^ 2(3/8)、50005055 ^ 2(4/16)などです。各加算は5 * 10 ^ nで、nは前のエントリの2倍です。各エントリのスコアは小さくなりますが、2を加算する00のルールを適用するときの制限はわずかに大きくなるため、制限は(1/2)、(2/2)、(3/2)、(4/2)などです。 。
mellamokb

はい、SNDDの値に到達できることを証明するアイデアです。
アーントヴェーンストラ

1

Clojure-185文字

おそらくさらに最適化できますが、次のとおりです。

(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))

2つのパラメーターを持つ関数として使用されます。

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

1

Jelly、21バイト、言語のポストデートチャレンジ

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

オンラインでお試しください!

説明

ヘルパー関数(入力の桁密度を計算):

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}

メインプログラム:

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

このプログラムは、おそらく1つではなくすべての最大密度数を返すことなく、間違いなくより興味深いものですが、仕様に準拠するために追加しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.