Numeri di Hamming


20

Dato un numero intero positivo, stampa tutti i numeri di martellamento , in ordine.

Regole:

  • L'input sarà un numero intero positivon1,000,000
  • L'output dovrebbe essere il primo n termini di https://oeis.org/A051037
  • Il tempo di esecuzione deve essere <1 minuto
  • Questo è ; vince il codice più breve

2
Quale obiettivo dovrebbe avere una risposta? Golf? Algoritmo più efficace? Stai solo cercando dei metodi di soluzione?
Nakilon,

Scusa per non essere specifico. Non l'ho risolto da solo, quindi non sono sicuro che i limiti che ho inserito siano ragionevoli. Per favore mi faccia sapere.
grokus,


3
1 è un numero di Hamming, quindi la stampa di 1.000.000 di 1s è conforme alle tue specifiche. Sarà anche in ordine, cioè non una sequenza non ordinata. :)
Will Ness,

Risposte:


7

Haskell, 101 97 92+ | n | personaggi

h=1:m 2h&m 3h&m 5h
m=map.(*)
c@(a:b)&o@(m:n)|a<m=a:b&o|a>m=m:c&n|0<1=a:b&n
main=print$take 1000000h

Calcola l'intero milione in 3,7 secondi sulla macchina su cui ho provato (varia di più se si desidera effettivamente archiviare l'output)

Ungolfed:

-- print out the first million Hamming numbers
main = print $ take 1000000 h

-- h is the entire Hamming sequence.
-- It starts with 1; for each number in the
-- sequence, 2n, 3n and 5n are also in.
h = 1 : (m 2 h) & (m 3 h) & (m 5 h)

-- helper: m scales a list by a constant factor
m f xs = map (f*) xs

-- helper: (&) merges two ordered sequences
a@(ha:ta) & b@(hb:tb)
    |    ha < hb = ha : ta & b
    |    ha > hb = hb :  a & tb
    |  otherwise = ha : ta & tb

Tutti Haskell è notoriamente bravo a: definire un elenco come una funzione pigra di se stesso, in un modo che funziona davvero.


1
Non ottieni il parametro intero positivo, che aggiunge più dimensioni al tuo codice
Zhen,

@Zhen Il parametro intero positivo è il penultimo token e la sua dimensione è dichiarata in uscita nell'intestazione.
JB

3

Personaggi di Python 181

h=[]        
h.append(1)
n=input()
i=j=k=0
while n:
    print h[-1]
    while h[i]*2<=h[-1]:
        i+=1
    while h[j]*3<=h[-1]:
        j+=1
    while h[k]*5<=h[-1]:
        k+=1
    h.append(min(h[i]*2,h[j]*3,h[k]*5))
    n-=1

Come sono 181 caratteri? Ho salvato questo in un file, rimuovendo lo spazio bianco dopo h=[], usando una distanza minima di tabulazione e interruzioni di riga di caratteri singoli e la dimensione del file finisce per essere 187 byte.
nitro2k01

1
Ottimizzazione Comunque ... Trivial: h=[1]. Inoltre, inserisci un numero direttamente nel codice sorgente, per salvare i caratteri per i numeri <1000000.
nitro2k01,

E oops, scusa, non ho realizzato che la risposta è super vecchia.
nitro2k01

@ nitro2k01, lo faccio 183 caratteri. (C'è un po 'di spazio bianco finale alla fine della prima riga e il rientro dovrebbe essere uno spazio per un livello e una scheda per due livelli).
Peter Taylor,

1

Rubino - 154 231 caratteri

def k i,n;(l=Math).log(i,2)*l.log(i,3)*l.log(i,5)/6>n end
def l i,n;k(i,n)?[i]:[i]+l(5*i,n)end
def j i,n;k(i,n)?[i]:[i]+j(3*i,n)+l(5*i,n)end
def h i,n;k(i,n)?[i]:[i]+h(2*i,n)+j(3*i,n)+l(5*i,n)end
puts h(1,n=gets.to_i).sort.first n

E ora è abbastanza veloce, ma sicuramente c'è ancora molto da giocare a golf.

→ time echo 1000000 | ruby golf-hamming.rb | wc
1000000 1000000 64103205
echo 1000000  0.00s user 0.00s system 0% cpu 0.003 total
ruby golf-hamming.rb  40.39s user 0.81s system 99% cpu 41.229 total
wc  1.58s user 0.05s system 3% cpu 41.228 total

1

Perl, 94 caratteri (ma troppo lento)

use List::Util min;
$\=$/;$h{1}=();delete$h{$_=min keys%h},print,@h{$_*2,$_*3,$_*5}=()for 1..<>

Ungolfed:

use List::Util 'min';
my %hamming;
my $up_to = <>;
$hamming{1} = (); # The value is undef, but the key exists!
for (1 .. $up_to) {
    my $next = min( keys %hamming );
    delete $hamming{$next}; # We're done with this one
    print $next, "\n";
    @hamming{ $next * 2, $next * 3, $next * 5 } = (); # Create keys for the multiples
} # Rinse, repeat

Impiega 11 minuti per calcolare i primi 100.000 numeri e non voglio nemmeno pensare a 1.000.000. Ottiene i primi 10.000 eseguiti in 3 secondi ordinati; è solo qualcosa che ricorda O (n ^ 2) :(


1

APL (Dyalog Classic) , 34 23 byte

{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡∘1

Provalo online!

n=1000000

{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡∘1     Monadic function:
{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5}         Define the following helper function g(⍺,⍵):
             ⍵∘.×⍳5             Make a multiplication table between  and (1 2 3 4 5).
                                (Including 4 is unnecessary but saves bytes.)
            ,                   Flatten the table into an array.
                               Keep unique elements.
    {⍵[⍋⍵]}                     Grade up the array and access it at those indices.
                                (This is the APL idiom to sort an array.)
 ⍺⍴                             Keep the first  elements; pad by repeating the array.
{⍺⍴{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡       Repeatedly apply g with some fixed left argument
                             until a fixed point is reached.
                             At this point we have a dyadic function that takes
                             n on the left and the starting value on the right,
                             and returns multiples of the n Hamming numbers.
                      1     Fix 1 as the right argument.

Mescolare le cose in giro ne salva quattro:1↓0 1{⍺↑{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡⍨1+⊢
Adám,

Cordiali saluti, {⍺⍴∧∪,⍵×⍀⍳5}`⍣≡∘1in esteso. (Backtick necessario a causa di un bug.)
Adám,

0

Haskell, 71

h n = drop n $ iterate (\(_,(a:t))-> (a,union t [2*a,3*a,5*a])) (0,[1])

Produzione

*Main> map fst $ take 20 $ h 1
[1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36]

Le specifiche richiedono la stampa, pertanto è necessario contare il codice da stampare. Ciò consente anche un confronto equo con l'altra implementazione di Haskell.
Peter Taylor,

@PeterTaylor Quanti personaggi pensi che dovrei aggiungere?
Timtech,

0

Ursala, 103

#import std
#import nat
smooth"p" "n" = ~&z take/"n" nleq-< (rep(length "n") ^Ts/~& product*K0/"p") <1>

Uscita permain = smooth<2,3,5>* nrange(1,20)

<1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36>

0

Mathematica, 54 byte

Sort[1##&@@@({2,3,5}^#&/@Tuples[0~Range~#,3])]~Take~#&

Funzione pura inefficiente ma breve. Calcola tutti i prodotti del modulo 2^i * 3^j * 5^kper 0 <= i, j, k <= #( #è il primo argomento della funzione), quindi Sortli e Takesolo il primo #.


1
In qualche modo non credo che l'esecuzione di calcoli 1e18 avverrà tra meno di un minuto.
Jonathan Allan,

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.