Mật độ số chữ số


17

Mật độ chữ số số vuông (SNDD) của một số - do tôi tự phát minh - là tỷ lệ của số lượng các số vuông được tìm thấy trong các chữ số liên tiếp với độ dài của số. Chẳng hạn, 169 là một số có 3 chữ số chứa 4 số vuông - 1, 9, 16, 169 - và do đó có mật độ chữ số số là 4/3 hoặc 1,33. Số có 4 chữ số 1444 có 6 ô vuông - 1, 4, 4, 4, 144, 1444 - và do đó tỷ lệ là 6/4 hoặc 1,5. Lưu ý trong ví dụ trước rằng hình vuông được phép lặp lại. Ngoài ra, 441 không được phép, bởi vì nó không thể được tìm thấy liên tiếp bên trong số 1444.

Nhiệm vụ của bạn là viết một chương trình tìm kiếm một phạm vi A - B (đã bao gồm) cho số có mật độ chữ số cao nhất. Chương trình của bạn phải tuân theo các thông số kỹ thuật sau:

  • Lấy đầu vào A, B trong phạm vi 1 đến 1.000.000.000 (1 tỷ). Thí dụ:sndd 50 1000
  • Trả về kết quả là số có SNDD lớn nhất. Trong trường hợp hòa, trả lại số nhỏ nhất.
  • 0 không được tính là một hình vuông dưới mọi hình thức, 0, 00, 000, v.v. Không phải hình vuông bắt đầu bằng 0, chẳng hạn như 049 hoặc 0049.
  • Lưu ý rằng toàn bộ số không phải là số vuông.

Ví dụ:

sndd 14000 15000
Output: 14441

sndd 300 500
Output: 441

Tiền thưởng: Con số nào có SNDD lớn nhất trong khoảng từ 1 đến 1.000.000.000? Bạn có thể chứng minh liệu đây là lớn nhất có thể, hoặc có thể có một cái lớn hơn trong phạm vi cao hơn?

Điểm hiện tại:

  1. Hồng ngọc: 142
  2. Windows PowerShell: 153
  3. Scala: 222
  4. Con trăn: 245

Bây giờ, một câu trả lời đã được chọn, đây là triển khai tham chiếu (chưa được chỉnh sửa) của tôi trong JavaScript: http://jsfiddle.net/ywc25/2/

Câu trả lời:


3

Ruby 1.9, 142 ký tự

$><<($*[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): Đầu ra cố định trong trường hợp hòa.

@Ventero: Thất bại cả hai trường hợp thử nghiệm. Tôi nghĩ rằng bạn đang quên để lại các ô vuông bắt đầu bằng 0 *
mellamokb

@mellamokb: Không thất bại ở đây : $ ruby1.9 sndd.rb 14000 15000 => 14441. x[0]>?0kiểm tra các ô vuông bắt đầu bằng 0.
Ventero

@mellamokb: Nó vượt qua các trường hợp thử nghiệm ở đây.
Nabb

@Ventero: Hmm .. có gì đó không ổn với môi trường thử nghiệm ruby ​​của tôi. Tôi không quen thuộc với Ruby. Tôi có 1,87 tôi nghĩ và tôi đã sao chép / dán mã ở trên vào sndd.rb, sau đó chạy với ruby sndd.rb 14000 15000Windows, tôi nhận được 14000.
mellamokb

@mellamokb: Trong Ruby 1.8, ?0là một Fixnum, trong khi trong Ruby 1.8 là một chuỗi, do đó, so sánh tôi đã đề cập có một ý nghĩa khác tùy thuộc vào phiên bản Ruby (thực ra nó nên đưa ra một ngoại lệ trong 1.8). Đó là lý do tại sao tôi đề cập rõ ràng phiên bản 1.9 trong tiêu đề.
Ventero

8

Trả lời phần thưởng: điểm số tốt nhất cho các số <1e9 là 5/3 = 1.666 ..., được tạo bởi 144411449 (và có thể các số khác?).

Nhưng bạn có thể làm tốt hơn với số lượng lớn hơn. Thông thường nếu n có điểm x, thì bạn có thể ghép hai bản sao của n và nhận được cùng số điểm x. Nếu bạn may mắn và n có cùng một chữ số đầu tiên và cuối cùng, thì bạn có thể bỏ một trong những chữ số đó vào phần ghép và cải thiện điểm số của bạn một chút (một ít hơn gấp đôi số lượng hình vuông và một ít hơn gấp đôi số chữ số) .

n = 11449441 có số điểm là 1.625 và có cùng chữ số đầu tiên & cuối cùng. Sử dụng thực tế đó, chúng tôi nhận được chuỗi điểm sau:

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

cung cấp một chuỗi vô hạn các số hoàn toàn (mặc dù Tăng) tốt hơn các số trước đó và tất cả trừ 2 số đầu tốt hơn số điểm tốt nhất cho các số <1e9.

Trình tự này có thể không phải là tổng thể tốt nhất, mặc dù. Nó hội tụ đến một số điểm hữu hạn (12/7 = 1.714) và có thể có những số khác có điểm tốt hơn giới hạn.

Chỉnh sửa : trình tự tốt hơn, hội tụ đến 1,75

1.600 14441
1.667 144414441
1.692 1444144414441
1.706 14441444144414441
1.714 144414441444144414441

Hấp dẫn! Bạn có thể vừa chứng minh rằng chuỗi này thực sự là vô hạn.
ESultanik

@ESultanik: Không thực sự, bởi vì không có yêu cầu nào ở đây rằng tổng số là một hình vuông hoàn hảo.
mellamokb

@ESutanik: Tôi không nghĩ chuỗi đó có liên quan, vì chúng yêu cầu toàn bộ số phải là một hình vuông - trong chuỗi của tôi, các ô vuông duy nhất là các dãy nhỏ (<= 5 chữ số), trừ khi tình cờ có một số lớn hơn.
Keith Randall

Bạn cũng có thể tạo một chuỗi vô hạn trong đó liên kết tạo ra một hình vuông thừa, nghĩa là, một cái gì đó kết thúc bằng 44 và bắt đầu bằng 1 sẽ tạo ra 441 với mọi kết hợp. Một ví dụ tầm thường sẽ là chuỗi 144, 144144, 144144144, v.v.
mellamokb

@mellamokb Wow, tôi hoàn toàn nhớ rằng con số không phải là một hình vuông hoàn hảo. Bạn đúng.
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]

Cảm ơn Ventero về việc giảm một byte tôi đã quá ngu ngốc khi thấy mình.

Phiên bản 154 byte giải thích:

$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

Con trăn, 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: Làm sạch mã phân tích đối số nhờ một mẹo từ Keith Randall .

Điều này có thể ngắn hơn rất nhiều nếu phạm vi được đọc từ stdintrái ngược với các đối số dòng lệnh.

Biên tập:

Đối với phần thưởng, các thí nghiệm của tôi đề xuất như sau:

Phỏng đoán 1 . Đối với mỗi n ∈ ℕ , số lượng trongn với SNDD lớn nhất phải chứa chỉ các chữ số 1, 4 và 9.

Phỏng đoán 2.n ∈ ℕ ∀ i ℕ ∈ n : SNDD ( n ) ≥ SNDD ( i ).

Bằng chứng phác thảo . Tập hợp các hình vuông có chữ số 1, 4 và 9 có khả nănghữu hạn . ■


Hãy thửrange(*map(int,sys.argv[1:]))
Keith Randall

1
Phỏng đoán 2 là sai nếu chuỗi hội tụ 1,75 trong câu trả lời của tôi tạo ra điểm số tốt nhất (lớn nếu, thừa nhận), vì các yếu tố tiếp theo của chuỗi sẽ tốt hơn một chút, mãi mãi.
Keith Randall

Phỏng đoán 2 là sai bởi câu trả lời của @ Arnt, bởi vì giá trị của SNDD có thể được làm lớn tùy ý.
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}))}

(Yêu cầu Scala 2.9.)


1

Xem xét câu hỏi tiền thưởng: Ngoài phạm vi, SNDD cao nhất có thể là vô hạn.

Ít nhất, nếu tôi đọc chính xác câu hỏi, một hình vuông như 100 (10 * 10) sẽ được tính.

Nếu bạn xem xét số 275625, điểm số là 5/6, vì 25, 625, 5625, 75625 và 275625 đều là hình vuông.

Thêm 2 số 0 cho: 27562500, có điểm 10/8. Giới hạn của chuỗi này là 5/2 = 2,5

Dọc theo cùng một dòng, bạn có thể tìm thấy các hình vuông kết thúc bằng bất kỳ số lượng hình vuông nhỏ hơn mong muốn. Tôi có thể chứng minh điều này, nhưng bạn có thể có được ý tưởng.

Phải thừa nhận rằng, đây không phải là một giải pháp hay, nhưng nó chứng minh rằng không có giới hạn trên đối với SNDD.


"'Dọc theo cùng một dòng, bạn có thể tìm thấy các hình vuông kết thúc bằng bất kỳ số lượng hình vuông nhỏ hơn mong muốn. Tôi có thể chứng minh điều này, nhưng bạn có thể có ý tưởng." Tôi muốn thấy bằng chứng này được phát triển. Tôi có thể thấy dãy lớn nhất kết thúc bằng 25 trong đó mỗi số kết thúc bằng 25 là một hình vuông là 275625. Không có chữ số 1-9 nào bạn có thể đặt ở đầu để tìm một hình vuông khác. Bạn đang nói điều này có thể được thực hiện lớn tùy ý, và nếu vậy, làm thế nào và tại sao?
mellamokb

Có, trình tự có thể được thực hiện lớn tùy ý. Bằng chứng là đây: Nếu a * a = b là số bắt đầu của bạn, thì (a + 10 ^ c) * (a + 10 ^ c) cũng kết thúc bằng b nếu c đủ lớn. Trong thực tế có thể có số nhỏ hơn kết thúc bằng b nếu bạn lấy hình vuông. Ví dụ, 18275625 là một hình vuông (4275 * 4275).
Arnt Veenstra

Mã để tìm hình vuông: jsfiddle.net/zVSuZ/2
mellamokb

@Arnt: Đây là một chuỗi (tầm thường) như vậy, 5 ^ 2 (1/2), 55 ^ 2 (2/4), 5055 ^ 2 (3/8), 50005055 ^ 2 (4/16), v.v. trong đó mỗi lần thêm là 5 * 10 ^ n, trong đó n là hai lần mục trước. Mỗi mục tăng nhỏ hơn về điểm số, nhưng giới hạn khi áp dụng quy tắc thêm hai 00 tăng lên một chút, do đó các giới hạn là (1/2), (2/2), (3/2), (4/2), v.v. .
mellamokb

Vâng, đó là ý tưởng chứng minh bất kỳ giá trị nào cho SNDD có thể đạt được.
Arnt Veenstra

1

Clojure - 185 ký tự

Có lẽ có thể được tối ưu hóa hơn nữa nhưng ở đây đi:

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

Được sử dụng như một hàm với hai tham số:

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

1

Jelly , 21 byte, thách thức ngôn ngữ

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

Hãy thử trực tuyến!

Giải trình

Hàm trợ giúp (tính mật độ chữ số của đầu vào):

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}

Chương trình chính:

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

Chương trình thú vị hơn nhiều nếu không có - theo cách đó, nó trả về tất cả các số mật độ tối đa thay vì chỉ một - nhưng tôi đã thêm nó để tuân thủ thông số kỹ thuật.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.