Numéros de Hamming


20

Étant donné un entier positif, imprimez autant de nombres parasites , dans l'ordre.

Règles:

  • L'entrée sera un entier positifn1,000,000
  • La sortie doit être les n premiers termes de https://oeis.org/A051037
  • Le temps d'exécution doit être <1 minute
  • C'est ; le code le plus court gagne

2
Quel objectif devrait avoir une réponse? Le golf? Algorithme le plus efficace? Vous cherchez simplement des méthodes de solution?
Nakilon

Désolé de ne pas être précis. Je n'ai pas résolu cela moi-même, donc je ne sais pas si les limites que je mets sont raisonnables. S'il vous plaît, faites-moi savoir.
grokus


3
1 est un nombre de Hamming, donc l'impression de 1 000 000 1s est conforme à vos spécifications. Il sera également en ordre, c'est-à-dire pas une séquence non ordonnée. :)
Will Ness

Réponses:


7

Haskell, 101 97 92+ | n | personnages

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

Calcule le million entier en 3.7s sur la machine sur laquelle j'ai testé (de manière variable si vous voulez réellement que la sortie soit stockée)

Non golfé:

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

Tout Haskell est notoirement doué pour: définir une liste comme une fonction paresseuse d'elle-même, d'une manière qui fonctionne réellement.


1
Vous n'obtenez pas le paramètre entier positif, qui ajoute plus de taille à votre code
Zhen

@Zhen Le paramètre entier positif est l'avant-dernier jeton, et sa taille est déclarée outfront dans l'en-tête.
JB

3

Python 181 caractères

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

Comment sont ces 181 caractères? J'ai enregistré cela dans un fichier, en supprimant les espaces après h=[], en utilisant une distance de tabulation minimale et des sauts de ligne d'un seul caractère, et la taille du fichier finit par être de 187 octets.
nitro2k01

1
Quoi qu'il en soit l' optimisation ... Trivial: h=[1]. Donnez également un nombre directement dans le code source, pour enregistrer des caractères pour les nombres <1000000.
nitro2k01

Et oups, désolé, je n'avais pas réalisé que la réponse était super vieille.
nitro2k01

@ nitro2k01, je le fais 183 caractères. (Il y a un espace de fin à la fin de la première ligne, et l'indentation doit être un espace pour un niveau et une tabulation pour deux niveaux).
Peter Taylor

1

Ruby - 154 231 caractères

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

Et maintenant c'est assez rapide, il y a certainement beaucoup de golf qui peut encore arriver.

→ 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 caractères (mais trop lent)

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

Non golfé:

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

Prend 11 minutes pour calculer les 100 000 premiers chiffres, et je ne veux même pas penser à 1 000 000. Il obtient les 10 000 premiers faits en 3 secondes bien rangées; c'est juste quelque chose qui ressemble à O (n ^ 2) :(


1

APL (Dyalog Classic) , 34 23 octets

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

Essayez-le en ligne!

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.

Mélanger les choses autour en sauve quatre:1↓0 1{⍺↑{⍵[⍋⍵]}∪,⍵∘.×⍳5}⍣≡⍨1+⊢
Adám

FYI, {⍺⍴∧∪,⍵×⍀⍳5}`⍣≡∘1dans Extended. (Backtick nécessaire en raison d'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])

Production

*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]

La spécification vous demande d'imprimer, donc le code à imprimer doit être compté. Cela permet également une comparaison équitable avec l'autre implémentation de Haskell.
Peter Taylor

@PeterTaylor Combien de caractères pensez-vous que je devrais ajouter?
Timtech

0

Ursala, 103

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

Sortie pourmain = 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 octets

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

Fonction pure inefficace mais courte. Calcule tous les produits de la forme 2^i * 3^j * 5^kpour 0 <= i, j, k <= #( #est le premier argument de la fonction), puis Sorts eux et Takes seulement le premier #.


1
D'une manière ou d'une autre, je ne pense pas que l'exécution de calculs 1e18 se produira dans moins d'une minute.
Jonathan Allan

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.