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
Freira Furada
fonte
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 ║
╚═════╩════════════════╝
lad2025
fonte
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.

jongleur
fonte
Bom primeiro post!
Rɪᴋᴇʀ
3

R , 36 31 bytes

n=scan();c(d<-1:n^.5,n/d)^!n%%d

Experimente online!

-5 bytes graças a Robin Ryder

Giuseppe
fonte
32 bytes com em n^.5vez de sqrt(n).
Robin Ryder
Você pode diminuir para 31 bytes duplicando 1várias vezes.
Robin Ryder
@RobinRyder clever! Obrigado.
Giuseppe
2

Matlab, 48 bytes

n=input('');a=1:n^.5;b=mod(n,a)<1;[a(b),n./a(b)]
flawr
fonte
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
milhas
fonte
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>

Kamila Skonieczna
fonte
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
Luis Mendo
fonte
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! .

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

Mego
fonte
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!

Dennis
fonte
1

Javascript, 47 bytes

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

Paulo
fonte
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}
milhas
fonte
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 ...

Neil
fonte
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.
auhmaan
fonte
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

user6245072
fonte
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)
Brad Gilbert b2gills
fonte
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 é

downrep_nation
fonte
0

Ruby, 56 bytes

->n{a=[];(1..Math.sqrt(n)).map{|e|a<<e<<n/e if n%e<1};a}
Value Ink
fonte
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.

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

12Me21
fonte
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.

OverclockedSanic
fonte
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 
RosLuP
fonte