Trouvez les diviseurs positifs!


11

Définition

Un nombre est positif s'il est supérieur à zéro.

Un nombre ( A) est le diviseur d'un autre nombre ( B) s'il Apeut se diviser Bsans reste.

Par exemple, 2est un diviseur de 6car 2peut se diviser 6sans reste.

Objectif

Votre tâche consiste à écrire un programme / une fonction qui prend un nombre positif, puis à trouver tous ses diviseurs.

Restriction

  • Vous ne pouvez pas utiliser de fonction intégrée liée à l' amorçage ou à la factorisation .
  • La complexité de votre algorithme ne doit pas dépasser O (sqrt (n)) .

Liberté

  • La liste de sortie peut contenir des doublons.
  • La liste de sortie n'a pas besoin d'être triée.

Notation

C'est du . La solution la plus courte en octets gagne.

Cas de test

input    output
1        1
2        1,2
6        1,2,3,6
9        1,3,9

Vous voulez probablement dire un diviseur , pas un facteur . Et je suppose que vous voulez avoir une complexité temporelle de O(sqrt(n)).
flawr

Quelle est la difference entre diviseur et factor ?
Leaky Nun

Nous parlons de facteurs, par exemple un nombre, si le produit de ces résultats donne à nouveau le nombre d'origine, mais les diviseurs sont généralement les nombres qui divisent ledit nombre sans reste.
flawr

@flawr Mis à jour en conséquence.
Leaky Nun

2
Devrait avoir plus d'exemples. 99 (1 3 9 11 33 99)
Brad Gilbert b2gills

Réponses:


4

PostgreSQL, 176 octets

WITH c AS(SELECT * FROM(SELECT 6v)t,generate_series(1,sqrt(v)::int)s(r)WHERE v%r=0)
SELECT string_agg(r::text,',' ORDER BY r)
FROM(SELECT r FROM c UNION SELECT v/r FROM c)s

SqlFiddleDemo

Contribution: (SELECT ...v)

Comment ça fonctionne:

  • (SELECT ...v) - contribution
  • generate_series(1, sqrt(v)::int) - nombres de 1 à sqrt (n)
  • WHERE v%r=0 -filtres diviseurs
  • envelopper avec une expression de table commune pour faire référence deux fois
  • SELECT r FROM c UNION SELECT v/r FROM c reste de diviseurs et combiner
  • SELECT string_agg(r::text,',' ORDER BY r) produire un résultat final séparé par des virgules

Entrée sous forme de tableau:

WITH c AS(SELECT * FROM i,generate_series(1,sqrt(v)::int)s(r)WHERE v%r=0)
SELECT v,string_agg(r::text,',' ORDER BY r)
FROM(SELECT v,r FROM c UNION SELECT v,v/r FROM c)s
GROUP BY v

SqlFiddleDemo

Production:

╔═════╦════════════════╗
║ v   ║   string_agg   ║
╠═════╬════════════════╣
║  1  ║ 1              ║
║  2  ║ 1,2            ║
║  6  ║ 1,2,3,6        ║
║  9  ║ 1,3,9          ║
║ 99  ║ 1,3,9,11,33,99 ║
╚═════╩════════════════╝

3

C # 6, 75 octets

string f(int r,int i=1)=>i*i>r?"":r%i==0?$"{i},{n(r,i+1)}{r/i},":n(r,i+1);

Basé sur la solution C # de downrep_nation, mais récursif et golfé plus bas en utilisant certaines nouvelles fonctionnalités de C # 6.

L'algorithme de base est le même que celui présenté par downrep_nation. La boucle for est transformée en récursivité, donc le deuxième paramètre. le début de récursivité est effectué par le paramètre par défaut, ainsi la fonction est appelée avec le seul numéro de départ requis.

  • l'utilisation de fonctions basées sur des expressions sans bloc évite l'instruction return
  • l'interpolation de chaînes dans l'opérateur ternaire permet de joindre la concaténation de chaînes et les conditions

Comme la plupart des réponses ici (encore) ne suivent pas le format de sortie exact des exemples, je le garde tel quel, mais comme inconvénient, la fonction inclut une seule virgule de fin au résultat.


Bon premier post!
Rɪᴋᴇʀ


2

Matlab, 48 octets

n=input('');a=1:n^.5;b=mod(n,a)<1;[a(b),n./a(b)]

Comment cela marche-t-il?
Leaky Nun

De plus, vous avez conçu un algorithme auquel je ne pouvais pas penser ... Comme je suis stupide.
Leaky Nun

Je trouve tous les diviseurs jusqu'à sqrt(n)puis place chaque diviseur det n/ddans ma liste.
flawr

Ajout de quelques règles. Peut-être pourriez-vous économiser quelques octets.
Leaky Nun

1
Je n'ai pas testé, mais ne pouvez-vous pas utiliser b=~mod(n,a)pour enregistrer 1 octet?
Luis Mendo

2

J, 26 octets

(],%)1+[:I.0=]|~1+i.@<.@%:

Explication

(],%)1+[:I.0=]|~1+i.@<.@%:  Input: n
                        %:  Sqrt(n)
                     <.@    Floor(Sqrt(n))
                  i.@       Get the range from 0 to Floor(Sqrt(n)), exclusive
                1+          Add 1 to each
             ]              Get n
              |~            Get the modulo of each in the range by n
           0=               Which values are equal to 0 (divisible by n), 1 if true else 0
       [:I.                 Get the indices of ones
     1+                     Add one to each to get the divisors of n less than sqrt(n)
   %                        Divide n by each divisor
 ]                          Get the divisors
  ,                         Concatenate them and return

2

JavaScript (ES6) - 48 octets

f=n=>[...Array(n+1).keys()].filter(x=>x&&!(n%x))

Pas très efficace mais fonctionne! Exemple ci-dessous:

let f=n=>[...Array(n+1).keys()].filter(x=>x&&!(n%x));
document.querySelector("input").addEventListener("change", function() {
  document.querySelector("output").value = f(Number(this.value)).join(", ");
});
Divisors of <input type="number" min=0 step=1> are: <output></output>


Bienvenue chez PPCG!
Laikoni

O(n)

1

MATL , 12 octets

tX^:\~ftGw/h

L'approche est similaire à celle de la réponse de @ flawr .

Essayez-le en ligne!

Explication

t      % take input N. Duplicate.
X^:    % Generate range from 1 to sqrt(N)
\      % modulo (remainder of division)
~f     % indices of zero values: array of divisors up to sqrt(N)
tGw/   % element-wise divide input by those divisors, to produce rest of divisors
h      % concatenate both arrays horizontally

Je me demande souvent si le code combiné de programmes écrits en MATL ferait un bon RNG.
flawr

@flawr Cela s'applique probablement à presque tous les langages de golf de code :-)
Luis Mendo

1

05AB1E , 14 12 octets

Code:

ÐtLDŠÖÏDŠ/ï«

Explication:

Ð             # Triplicate input.
 tL           # Push the list [1, ..., sqrt(input)].
   D          # Duplicate that list.
    Š         # Pop a,b,c and push c,a,b.
     Ö        # Check for each if a % b == 0.
      Ï       # Only keep the truthy elements.
       D      # Duplicate the list.
        Š     # Pop a,b,c and push c,a,b
         /ï   # Integer divide
           «  # Concatenate to the initial array and implicitly print.

Utilise l' encodage CP-1252 . Essayez-le en ligne! .


Voulez-vous fournir une explication?
Leaky Nun

@KennyLau Ajouté
Adnan

1

Python 2, 64 octets

lambda n:sum([[x,n/x]for x in range(1,int(n**.5+1))if n%x<1],[])

Cette fonction anonyme génère une liste de diviseurs. Les diviseurs sont calculés par division d'essai d'entiers dans la plage [1, ceil(sqrt(n))], qui est O(sqrt(n)). Si n % x == 0(équivalent à n%x<1), alors les deux xet n/xsont des diviseurs de n.

Essayez-le en ligne


1

Gelée , 9 octets

½Rḍ³Tµ³:;

Comme les autres réponses, c'est O (√n) si nous faisons l'hypothèse (fausse) que la division entière est O (1) .

Comment ça fonctionne

½Rḍ³Tµ³:;  Main link. Argument: n

½          Compute the square root of n.
 R         Construct the range from 1 to the square root.
  ḍ³       Test each integer of that range for divisibility by n.
    T      Get the indices of truthy elements.
     µ     Begin a new, monadic chain. Argument: A (list of divisors)
      ³:   Divide n by each divisor.
        ;  Concatenate the quotients with A.

Essayez-le en ligne!




0

Mathematica, 50 octets

Similaire à la solution de @ flawr .

Effectue la division de traînée pour x de 1 jusqu'à la racine carrée de n et si divisible, l'enregistre dans une liste sous les noms x et n / x .

(#2/#)~Join~#&@@{Cases[Range@Sqrt@#,x_/;x∣#],#}&
  • Notez que nécessite 3 octets pour représenter en UTF-8, ce qui fait que la chaîne de 48 caractères nécessite 50 octets en représentation UTF-8.

Usage

  f = (#2/#)~Join~#&@@{Cases[Range@Sqrt@#,x_/;x∣#],#}&
  f[1]
{1, 1}
  f[2]
{2, 1}
  f[6]
{6, 3, 1, 2}
  f[9]
{9, 3, 1, 3}

Eh bien, cela nécessite 3 octets ...
Leaky Nun

@KennyLau Oui, je me trompais, j'aurais dû revérifier
miles

0

JavaScript (ES6), 66 62 octets

f=(n,d=1)=>d*d>n?[]:d*d-n?n%d?f(n,d+1):[d,...f(n,d+1),n/d]:[d]

Je pensais que j'écrirais une version qui renvoyait une liste dédupliquée triée, et elle s'est avérée en fait 4 octets plus courte ...


0

C #, 87 octets


Golfé

String m(int v){var o="1";int i=1;while(++i<=v/2)if(v%i==0)o+=","+i;o+=","+v;return o;}

Non golfé

String m( Int32 v ) {
    String o = "1";
    Int32 i = 1;

    while (++i <= v / 2)
        if (v % i == 0)
            o += "," + i;

    o += "," + v;

    return o;
}

Code complet

using System;
using System.Collections.Generic;

namespace N {
    class P {
        static void Main( string[] args ) {
            List<Int32> li = new List<Int32>() {
                1, 2, 6, 9,
            };

            foreach (Int32 i in li) {
                Console.WriteLine( i + " »> " + m( i ) );
            }

            Console.ReadLine();
        }

        static String m( Int32 v ) {
            String o = "1";
            Int32 i = 1;

            while (++i <= v / 2)
                if (v % i == 0)
                    o += "," + i;

            o += "," + v;

            return o;
        }
    }
}

Communiqués

  • v1.0 - 87 bytes- Solution initiale.

Remarques

  • Dans le code Golfed , j'utilise var«et int» au lieu de String«et Int32» pour raccourcir le code, tandis que dans le code non golfé et le code complet, j'utilise String«et Int32» pour rendre le code plus lisible.

J'ai entendu dire que c'était forgénéralement mieux que while.
Leaky Nun

Votre solution a une complexité de O (n) au lieu de O (sqrt (n)) ...
Leaky Nun

@KennyLau cela dépend de la situation, dans ce cas, avoir une forboucle aurait la même longueur que la whileboucle. Dans ce cas, il n'est pas pertinent d'avoir l'un ou l'autre.
auhmaan

Mais dans ce cas, cela peut vous faire économiser un octet ...
Leaky Nun

0

Lua, 83 octets

s=''x=io.read()for i=1,x do if x%i==0 then s=s..i..', 'end end print(s:sub(1,#s-2))

Je ne pouvais pas faire mieux, malheureusement


1. Bienvenue sur PPCG, j'espère que vous apprécierez ce site! 2. vous pouvez changer == 0 en <1 pour économiser quelques octets. 3. vous pouvez utiliser la structure ternaire à la place de if then end, mais je ne sais pas si elle permettra d'économiser des octets. 4. la complexité de votre algorithme est O (n) qui ne répond pas à l'exigence.
Leaky Nun

D'accord. La liste doit-elle être commandée ou formatée de manière appropriée?
user6245072

"La liste de sortie peut contenir des doublons. La liste de sortie n'a pas besoin d'être triée."
Leaky Nun

Bon lol. Et dois-je imprimer le résultat ou un tableau le contenant suffit?
user6245072

Eh bien, soit vous l'imprimez, soit vous le renvoyez (à l'intérieur d'une fonction).
Leaky Nun

0

Perl 6 , 40 octets

{|(my@a=grep $_%%*,^.sqrt+1),|($_ X/@a)}

Explication:

{
  # this block has an implicit parameter named $_

  # slip this list into outer list:
  |(

    my @a = grep
                 # Whatever lambda:
                 # checks if the block's parameter ($_)
                 # is divisible by (%%) this lambda's parameter (*)

                 $_ %% *,

                 # upto and exclude the sqrt of the argument
                 # then shift the Range up by one
                 ^.sqrt+1
                 # (0 ..^ $_.sqrt) + 1

                 # would be clearer if written as:
                 # 1 .. $_.sqrt+1
  ),
  # slip this list into outer list
  |(

    # take the argument and divide it by each value in @a
    $_ X/ @a

    # should use X[div] instead of X[/] so that it would return
    # Ints instead of Rats
  )
}

Usage:

my &divisors = {|(my@a=grep $_%%*,^.sqrt+1),|($_ X/@a)}

.say for (1,2,6,9,10,50,99)».&divisors
(1 1)
(1 2 2 1)
(1 2 3 6 3 2)
(1 3 9 3)
(1 2 10 5)
(1 2 5 50 25 10)
(1 3 9 99 33 11)

0

c #, 87 octets

void f(int r){for(int i=1;i<=Math.Sqrt(r);i++){if(r%i==0)Console.WriteLine(i+" "+r/i);}

je ne sais pas si cela fonctionne pour tous les numéros, je pense que oui.

mais la complexité est bonne, donc c'est déjà quelque chose


0

Rubis, 56 octets

->n{a=[];(1..Math.sqrt(n)).map{|e|a<<e<<n/e if n%e<1};a}

0

Code machine IA-32, 27 octets

Hexdump:

60 33 db 8b f9 33 c0 92 43 50 f7 f3 85 d2 75 04
ab 93 ab 93 3b c3 5a 77 ec 61 c3

Code source (syntaxe MS Visual Studio):

    pushad;
    xor ebx, ebx;
    mov edi, ecx;
myloop:
    xor eax, eax;
    xchg eax, edx;
    inc ebx;
    push eax;
    div ebx;
    test edx, edx;
    jnz skip_output;
    stosd;
    xchg eax, ebx;
    stosd;
    xchg eax, ebx;
skip_output:
    cmp eax, ebx;
    pop edx;
    ja myloop;
    popad;
    ret;

Le premier paramètre ( ecx) est un pointeur vers la sortie, le deuxième paramètre ( edx) est le nombre. Cela ne marque en aucun cas la fin de la sortie; il faut pré-remplir le tableau de sortie avec des zéros pour trouver la fin de la liste.

Un programme C ++ complet qui utilise ce code:

#include <cstdint>
#include <vector>
#include <iostream>
#include <sstream>
__declspec(naked) void _fastcall doit(uint32_t* d, uint32_t n) {
    _asm {
        pushad;
        xor ebx, ebx;
        mov edi, ecx;
    myloop:
        xor eax, eax;
        xchg eax, edx;
        inc ebx;
        push eax;
        div ebx;
        test edx, edx;
        jnz skip_output;
        stosd;
        xchg eax, ebx;
        stosd;
        xchg eax, ebx;
    skip_output:
        cmp eax, ebx;
        pop edx;
        ja myloop;
        popad;
        ret;
    }
}
int main(int argc, char* argv[]) {
    uint32_t n;
    std::stringstream(argv[1]) >> n;
    std::vector<uint32_t> list(2 * sqrt(n) + 3); // c++ initializes with zeros
    doit(list.data(), n);
    for (auto i = list.begin(); *i; ++i)
        std::cout << *i << '\n';
}

La sortie a quelques problèmes, même si elle suit la spécification (pas besoin de tri; pas besoin d'unicité).


Entrée: 69

Production:

69
1
23
3

Les diviseurs sont par paires.


Entrée: 100

Production:

100
1
50
2
25
4
20
5
10
10

Pour des carrés parfaits, le dernier diviseur est émis deux fois (c'est une paire avec lui-même).


Entrée: 30

Production:

30
1
15
2
10
3
6
5
5
6

Si l'entrée est proche d'un carré parfait, la dernière paire est sortie deux fois. C'est à cause de l'ordre des vérifications dans la boucle: tout d'abord, il vérifie "reste = 0" et les sorties, puis seulement il vérifie que "quotient <diviseur" pour quitter la boucle.


0

SmileBASIC, 49 octets

INPUT N
FOR D=1TO N/D
IF N MOD D<1THEN?D,N/D
NEXT

Utilise le fait que D>N/D= D>sqrt(N)pour les nombres positifs


0

C, 87 81 octets

Amélioré par @ceilingcat , 81 octets:

i,j;main(n,b)int**b;{for(;j=sqrt(n=atoi(b[1]))/++i;n%i||printf("%u,%u,",i,n/i));}

Essayez-le en ligne!


Ma réponse d'origine, 87 octets:

i;main(int n,char**b){n=atoi(b[1]);for(;(int)sqrt(n)/++i;n%i?:printf("%u,%u,",i,n/i));}

Compilez avec gcc div.c -o div -lmet exécutez avec ./div <n>.


Bonus: une variante encore plus courte avec une complexité temporelle O (n) et codée en dur n(46 octets + longueur de n):

i,n=/*INSERT VALUE HERE*/;main(){for(;n/++i;n%i?:printf("%u,",i));}

Edit: Merci à @Sriotchilism O'Zaic d'avoir souligné que les entrées ne doivent pas être codées en dur, j'ai modifié la soumission principale pour prendre l'entrée via argv.


1
Est-ce nl'entrée? Placer l'entrée dans une variable n'est pas une manière acceptée de faire l'entrée ici pour un certain nombre de raisons. Vous pouvez en savoir plus sur nos formulaires d'entrée et de sortie acceptés et non acceptés ici: codegolf.meta.stackexchange.com/questions/2447/… . Et si vous êtes curieux au sujet d'une langue spécifique (par exemple C), vous pouvez regarder ici: codegolf.meta.stackexchange.com/questions/11924/… .
Ad Hoc Garf Hunter

@ SriotchilismO'Zaic Oui, nc'est l'entrée. Je vais essayer de le modifier pour qu'il prenne l'entrée d'une autre manière. Merci pour l'info!
OverclockedSanic

0

APL (NARS), 22 caractères, 44 octets

{v∪⍵÷v←k/⍨0=⍵∣⍨k←⍳⌊√⍵}

tester:

  f←{v∪⍵÷v←k/⍨0=⍵∣⍨k←⍳⌊√⍵}
  f 1
1 
  f 2
1 2 
  f 6
1 2 6 3 
  f 9
1 3 9 
  f 90
1 2 3 5 6 9 90 45 30 18 15 10 

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.