Encontre os divisores positivos!


11

Definição

Um número é positivo se for maior que zero.

Um número ( A) é o divisor de outro número ( B) se Apuder dividir Bsem resto.

Por exemplo, 2é um divisor de 6porque 2pode dividir 6sem resto.

Objetivo

Sua tarefa é escrever um programa / função que receba um número positivo e depois encontrar todos os seus divisores.

Restrição

  • Você não pode usar nenhum built-in relacionado a prime ou fatoração .
  • A complexidade do seu algoritmo não deve exceder O (sqrt (n)) .

Liberdade

  • A lista de saída pode conter duplicatas.
  • A lista de saída não precisa ser classificada.

Pontuação

Isso é . A solução mais curta em bytes vence.

Casos de teste

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

Você provavelmente quer dizer divisor , não fator . E eu acho que você quer ter uma complexidade de tempoO(sqrt(n)) .
Flawr 01/05/19

Qual é a diferença entre divisor e fator ?
Freira vazando

Falamos sobre fatores de, por exemplo, um número, se o produto desses resultar no número original novamente, mas os divisores são geralmente os números que dividem o número sem deixar resto.
Flawr 01/05/19

@flawr Atualizado de acordo.
Leaky Nun

2
Deveria ter mais exemplos. 99 (1 3 9 11 33 99)
Brad Gilbert b2gills

Respostas:


4

PostgreSQL, 176 bytes

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

Entrada: (SELECT ...v)

Como funciona:

  • (SELECT ...v) - entrada
  • generate_series(1, sqrt(v)::int) - números de 1 a sqrt (n)
  • WHERE v%r=0 divisores
  • quebra automática com expressão de tabela comum para se referir duas vezes
  • SELECT r FROM c UNION SELECT v/r FROM c gerar resto de divisores e combinar
  • SELECT string_agg(r::text,',' ORDER BY r) produzir resultado separado por vírgula final

Entrada como tabela:

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

Resultado:

╔═════╦════════════════╗
║ 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 bytes

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

Baseado na solução C # de downrep_nation, mas recursivo e mais avançado, utilizando alguns novos recursos do C # 6.

O algoritmo básico é o mesmo que o apresentado por downrep_nation. O loop for é girado para uma recursão, portanto, o segundo parâmetro. O início da recursão é feito pelo parâmetro padrão, portanto, a função é chamada apenas com o número inicial necessário.

  • o uso de funções baseadas em expressão sem um bloco evita a instrução de retorno
  • interpolação de cadeia dentro do operador ternário permite juntar concatenação e condições de cadeia

Como a maioria das respostas aqui (ainda) não segue o formato de saída exato dos exemplos, eu o mantenho como está, mas, como desvantagem, a função inclui uma única vírgula no resultado.


Bom primeiro post!
Rɪᴋᴇʀ


2

Matlab, 48 bytes

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

Como é que isso funciona?
Leaky Nun

Além disso, você criou um algoritmo no qual eu não conseguia pensar ... Como sou burra.
Leaky Nun

Eu encontro todos os divisos até sqrt(n)e depois coloco cada divisor de n/dna minha lista.
Flawr 01/05/19

Adicionadas algumas regras. Talvez você possa economizar alguns bytes.
Leaky Nun

1
Não testei, mas você não pode usar b=~mod(n,a)para salvar 1 byte?
Luis Mendo

2

J, 26 bytes

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

Explicação

(],%)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 bytes

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

Não é muito eficiente, mas funciona! Exemplo abaixo:

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>


Bem-vindo ao PPCG!
Laikoni

O(n)

1

MATL , 12 bytes

tX^:\~ftGw/h

A abordagem é semelhante à da resposta do @ flawr .

Experimente online!

Explicação

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

Eu sempre me pergunto se o código combinado de programas escritos em MATL seria um bom RNG.
Flawr 01/05/19

@flawr Isso provavelmente se aplica a praticamente todas as línguas golf código :-)
Luis Mendo

1

05AB1E , 14 12 bytes

Código:

ÐtLDŠÖÏDŠ/ï«

Explicação:

Ð             # 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.

Usa a codificação CP-1252 . Experimente online! .


Gostaria de fornecer uma explicação?
Leaky Nun

@KennyLau Adicionado
Adnan

1

Python 2, 64 bytes

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

Essa função anônima gera uma lista de divisores. Os divisores são calculados pela divisão experimental de números inteiros no intervalo [1, ceil(sqrt(n))], que é O(sqrt(n)). Se n % x == 0(equivalente a n%x<1), então ambos xe n/xsão divisores de n.

Experimente online


1

Geléia , 9 bytes

½Rḍ³Tµ³:;

Como as outras respostas, este é O (√n) se fizermos a suposição (falsa) de que a divisão inteira é O (1) .

Como funciona

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

Experimente online!



1

Javascript, 47 bytes

d=(n,f=1,s='')=>n==f?s+n:d(n,f+1,n%f?s:s+f+',')


0

Mathematica, 50 bytes

Semelhante à solução da @ flawr .

Executa a divisão da trilha para x de 1 até a raiz quadrada de n e, se divisível, salva em uma lista como x e n / x .

(#2/#)~Join~#&@@{Cases[Range@Sqrt@#,x_/;x∣#],#}&
  • Observe que requer 3 bytes para representar em UTF-8, fazendo com que a cadeia de 48 caracteres exija 50 bytes na representação UTF-8.

Uso

  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}

Bem, isso requer 3 bytes ...
Leaky freira

@KennyLau Sim, eu estava errado, deveria ter verificado duas vezes
milhas

0

JavaScript (ES6), 66 62 bytes

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

Pensei em escrever uma versão que retornasse uma lista desduplicada classificada e que na verdade era 4 bytes mais curta ...


0

C #, 87 bytes


Golfe

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

Ungolfed

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

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

    o += "," + v;

    return o;
}

Código completo

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

Lançamentos

  • v1.0 - 87 bytes- Solução inicial.

Notas

  • No código Golfed , eu uso var's' e int's String' e Int32's para diminuir o código, enquanto no Código Ungolfed e Código Completo eu uso String' s Int32' e ' s para tornar o código mais legível.

Ouvi dizer que forgeralmente é melhor que while.
Leaky Nun

Sua solução tem uma complexidade de O (n) em vez de O (sqrt (n)) ...
Leaky Nun

@KennyLau depende da situação, nesse caso, ter um forloop teria o mesmo comprimento que o whileloop. Nesse caso, é irrelevante ter ou ter o outro.
Auhmaan

Mas, neste caso, você pode salvar um byte ...
Leaky Nun

0

Lua, 83 bytes

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

Infelizmente não consegui fazer melhor


1. bem-vindo ao PPCG, espero que você goste deste site! 2. você pode alterar == 0 para <1 para salvar alguns bytes. 3. Você pode usar a estrutura ternária em vez de se terminar, mas não sei se ela salvará bytes. 4. A complexidade do seu algoritmo é O (n) que não atende ao requisito.
Freira vazando

Tudo certo. A lista precisa ser solicitada ou formatada adequadamente?
User6245072

"A lista de saída pode conter duplicatas. A lista de saída não precisa ser classificada."
Leaky Nun

Certo, lol. E preciso imprimir o resultado ou uma matriz que o contenha é suficiente?
User6245072

Bem, você imprime ou devolve (dentro de uma função).
Leaky Nun

0

Perl 6 , 40 bytes

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

Explicação:

{
  # 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
  )
}

Uso:

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 bytes

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

Eu não sei se isso funciona para todos os números, eu suspeito que sim.

mas a complexidade é certa, então isso já é algo que não é


0

Ruby, 56 bytes

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

0

Código de máquina IA-32, 27 bytes

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

Código fonte (sintaxe do 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;

O primeiro parâmetro ( ecx) é um ponteiro para a saída, o segundo parâmetro ( edx) é o número. Não marca o final da saída de forma alguma; deve-se preencher previamente a matriz de saída com zeros para encontrar o final da lista.

Um programa C ++ completo que usa esse código:

#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';
}

A saída tem algumas falhas, apesar de seguir as especificações (sem necessidade de classificação; sem necessidade de exclusividade).


Entrada: 69

Resultado:

69
1
23
3

Os divisores estão em pares.


Entrada: 100

Resultado:

100
1
50
2
25
4
20
5
10
10

Para quadrados perfeitos, o último divisor é emitido duas vezes (é um par com ele mesmo).


Entrada: 30

Resultado:

30
1
15
2
10
3
6
5
5
6

Se a entrada estiver próxima de um quadrado perfeito, o último par será emitido duas vezes. É por causa da ordem das verificações no loop: primeiro, ele verifica "restante = 0" e as saídas e, somente então, verifica "quociente <divisor" para sair do loop.


0

SmileBASIC, 49 bytes

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

Usa o fato de que D>N/D= D>sqrt(N)para números positivos


0

C, 87 81 bytes

Melhorado por @ceilingcat , 81 bytes:

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

Experimente online!


Minha resposta original, 87 bytes:

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

Compile gcc div.c -o div -lme corra com ./div <n>.


Bônus: Uma variante ainda mais curta, com complexidade de tempo O (n) e codificada n(46 bytes + comprimento de n):

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

Edit: Obrigado a @Sriotchilism O'Zaic por apontar que as entradas não devem ser codificadas, modifiquei a submissão principal para receber a entrada via argv.


1
É na entrada? Colocar a entrada em uma variável não é uma maneira aceita de inserir aqui por vários motivos. Você pode ver mais sobre nossos formulários de entrada e saída aceitos e não aceitos aqui: codegolf.meta.stackexchange.com/questions/2447/… . E se você está curioso sobre um idioma específico (por exemplo, C), pode procurar aqui: codegolf.meta.stackexchange.com/questions/11924/… .
Post Rock Garf Hunter

@ SriotchilismO'Zaic Sim, né a entrada. Vou tentar modificá-lo para levar a entrada de outra maneira. Obrigado pela informação!
OverclockedSanic

0

APL (NARS), 22 caracteres, 44 bytes

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

teste:

  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 

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.