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.