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 positifn≤1,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.