Densità cifre numeri quadrati


17

La densità delle cifre dei numeri quadrati (SNDD) di un numero - inventato da me stesso - è il rapporto tra il numero di numeri quadrati trovati in cifre consecutive e la lunghezza del numero. Ad esempio, 169 è un numero di 3 cifre contenente 4 numeri quadrati - 1, 9, 16, 169 - e quindi ha una densità di cifre quadrate di 4/3 o 1,33. Il numero a 4 cifre 1444 ha 6 quadrati - 1, 4, 4, 4, 144, 1444 - e quindi un rapporto di 6/4 o 1,5. Si noti nell'esempio precedente che i quadrati possono essere ripetuti. Inoltre, 441 non è consentito, poiché non può essere trovato consecutivamente all'interno del numero 1444.

Il tuo compito è scrivere un programma che cerchi in un determinato intervallo A - B (incluso) il numero con la più alta densità di cifre in numeri quadrati. Il tuo programma dovrebbe rispettare le seguenti specifiche:

  • Prendi input A, B nell'intervallo da 1 a 1.000.000.000 (1 miliardo). Esempio:sndd 50 1000
  • Restituisce di conseguenza il numero con il più grande SNDD. In caso di pareggio, restituire il numero più piccolo.
  • 0 non conta come un quadrato in nessuna forma, 0, 00, 000, ecc. Né i quadrati iniziano con 0, come 049 o 0049.
  • Si noti che l'intero numero non deve essere un numero quadrato.

Esempi:

sndd 14000 15000
Output: 14441

sndd 300 500
Output: 441

Bonus: qual è il numero con il più grande SNDD tra 1 e 1.000.000.000? Puoi provare se questo è il più grande possibile o se ce ne potrebbe essere uno più grande in un intervallo più alto?

Punteggi attuali:

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

Ora che è stata selezionata una risposta, ecco la mia implementazione di riferimento (non golfizzata) in JavaScript: http://jsfiddle.net/ywc25/2/

Risposte:


3

Ruby 1.9, 142 caratteri

$><<($*[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): uscita fissa in caso di pareggio.

@Ventero: fallisce entrambi i casi di test. Penso che ti stai dimenticando di lasciare fuori i quadrati che iniziano con 0 *
mellamokb,

@mellamokb: non li fallire qui: $ ruby1.9 sndd.rb 14000 15000 => 14441. x[0]>?0controlla i quadrati che iniziano con 0.
Ventero,

@mellamokb: passa qui i casi di test.
Nabb,

@Ventero: Hmm .. qualcosa deve essere sbagliato nel mio ambiente di test ruby. Non ho familiarità con Ruby. Ho 1.87 penso, e ho copiato / incollato il codice sopra in sndd.rb, quindi eseguito con ruby sndd.rb 14000 15000da Windows, ottengo 14000.
mellamokb

@mellamokb: In Ruby 1.8, ?0è un Fixnum, mentre in Ruby 1.8 è una stringa, quindi il confronto che ho citato ha un significato diverso a seconda della versione di Ruby (in realtà dovrebbe generare un'eccezione in 1.8). Ecco perché ho citato esplicitamente la versione 1.9 nel titolo.
Ventero,

8

Risposta al bonus: il miglior punteggio per i numeri <1e9 è 5/3 = 1.666 ..., generato da 144411449 (e forse altri?).

Ma puoi fare di meglio con numeri più grandi. Generalmente se n ha un punteggio di x, puoi concatenare due copie di n e ottenere lo stesso punteggio x. Se sei fortunato e n ha la stessa prima e ultima cifra, puoi rilasciare una di quelle cifre nella concatenazione e migliorare leggermente il tuo punteggio (uno in meno del doppio del numero di quadrati e uno in meno del doppio del numero di cifre) .

n = 11449441 ha un punteggio di 1.625 e ha la stessa prima e ultima cifra. Usando questo fatto, otteniamo la seguente sequenza di punteggi:

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

che fornisce una sequenza infinita di numeri che sono strettamente (anche se in modo decrescente) migliori dei numeri precedenti, e tutti tranne i primi 2 migliori del miglior punteggio per i numeri <1e9.

Questa sequenza potrebbe non essere la migliore in assoluto, comunque. Converge in un punteggio finito (12/7 = 1.714) e potrebbero esserci altri numeri con punteggi migliori del limite.

Modifica : una sequenza migliore, converge a 1,75

1.600 14441
1.667 144414441
1.692 1444144414441
1.706 14441444144414441
1.714 144414441444144414441

Interessante! Potresti aver appena dimostrato che questa sequenza è in realtà infinita.
ESultanik,

@ESultanik: Non proprio, perché qui non è necessario che il numero complessivo sia un quadrato perfetto.
mellamokb,

@ESutanik: Non penso che la sequenza sia correlata, poiché richiedono che l'intero numero sia un quadrato - nella mia sequenza gli unici quadrati sono piccole sottosequenze (<= 5 cifre), a meno che per caso non ce ne sia una più grande.
Keith Randall,

Potresti anche generare una sequenza infinita in cui il link genera un quadrato extra, cioè qualcosa che termina in 44 e che inizia con 1 farebbe un 441 con ogni combinazione. Un esempio banale sarebbe la sequenza 144, 144144, 144144144, ecc.
mellamokb,

@mellamokb Wow, mi mancava del tutto che il numero non dovesse essere un quadrato perfetto. Hai ragione.
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]

Grazie a Ventero per una riduzione di un byte ero troppo stupido per ritrovarmi.

Spiegazione della versione a 154 byte:

$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: ripulito l'argomento analizzando il codice grazie a un suggerimento di Keith Randall .

Questo potrebbe essere molto più breve se l'intervallo fosse letto stdinrispetto agli argomenti della riga di comando.

Modificare:

Per quanto riguarda il bonus, i miei esperimenti suggeriscono quanto segue:

Congettura 1 . Per ogni n ∈ ℕ , il numero inn con il più grande SNDD deve contenere esclusivamente le cifre 1, 4 e 9.

Congettura 2.n ∈ ℕ ∀ i ∈ ℕ n : SNDD ( n ) ≥ SNDD ( i ).

Schizzo di prova . L'insieme dei quadrati con le cifre 1, 4 e 9 è probabilmente finito . ∎


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

1
La congettura 2 è falsa se la sequenza convergente di 1,75 nella mia risposta produce i punteggi migliori (un grande se, certo,), poiché gli elementi successivi della sequenza sono marginalmente migliori, per sempre.
Keith Randall,

La congettura 2 è falsa dalla risposta di @Arnt, perché il valore di SNDD può essere reso arbitrariamente grande.
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 richiesta.)


1

Considerando la domanda bonus: al di fuori dell'intervallo il SNDD più alto possibile è infinito.

Almeno, se ho letto correttamente la domanda, conta un quadrato come 100 (10 * 10).

Se si considera il numero 275625, il punteggio è 5/6, poiché 25, 625, 5625, 75625 e 275625 sono tutti quadrati.

Aggiungendo 2 zero si ottiene: 27562500, che ha un punteggio di 10/8. Il limite di questa sequenza è 5/2 = 2.5

Sulla stessa linea, puoi trovare i quadrati che terminano in qualsiasi numero di quadrati più piccoli desiderati. Posso provarlo, ma probabilmente avrai l'idea.

Certo, questa non è una soluzione molto bella, ma dimostra che non c'è limite superiore a SNDD.


"'Sulla stessa linea, puoi trovare quadrati che finiscono in qualsiasi numero di quadrati più piccoli desiderati. Posso dimostrarlo, ma probabilmente avrai l'idea." Mi piacerebbe vedere questa dimostrazione sviluppata. Vedo la sequenza più grande che termina con 25 dove ogni numero che termina con 25 è un quadrato è 275625. Non c'è una cifra 1-9 che puoi posizionare all'inizio per trovare un altro quadrato. Stai dicendo che questo può essere reso arbitrariamente grande, e se sì, come e perché?
mellamokb,

Sì, la sequenza può essere resa arbitrariamente grande. La prova è questa: se a * a = b è il tuo numero iniziale, allora (a + 10 ^ c) * (a + 10 ^ c) termina anche in b se c è sufficientemente grande. In pratica potrebbero esserci numeri più piccoli che terminano in b se si prende il quadrato. Ad esempio, 18275625 è un quadrato (4275 * 4275).
Arnt Veenstra,

Codice per trovare i quadrati: jsfiddle.net/zVSuZ/2
mellamokb

@Arnt: Ecco una sequenza (banale), 5 ^ 2 (1/2), 55 ^ 2 (2/4), 5055 ^ 2 (3/8), 50005055 ^ 2 (4/16), ecc. dove ogni aggiunta è 5 * 10 ^ n, dove n è il doppio della voce precedente. Ogni voce diventa più piccola di punteggio, ma il limite quando si applica la regola di aggiunta due 00 aumenta leggermente più grande, quindi i limiti sono (1/2), (2/2), (3/2), (4/2), ecc. .
mellamokb

Sì, questa è l'idea che dimostra che è possibile raggiungere qualsiasi valore per SNDD.
Arnt Veenstra,

1

Clojure - 185 caratteri

Probabilmente potrebbe essere ulteriormente ottimizzato, ma qui va:

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

Utilizzato come una funzione con due parametri:

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

1

Gelatina , 21 byte, sfida postdatati in lingua

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

Provalo online!

Spiegazione

Funzione helper (calcola la densità delle cifre del suo input):

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}

Programma principale:

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

Probabilmente il programma è più interessante senza - in questo modo, restituisce tutti i numeri a densità massima anziché solo uno - ma l'ho aggiunto per soddisfare le specifiche.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.