Trova i divisori positivi!


11

Definizione

Un numero è positivo se è maggiore di zero.

Un numero ( A) è il divisore di un altro numero ( B) se Apuò dividere Bsenza resto.

Ad esempio, 2è un divisore di 6perché 2può dividere 6senza resto.

Obbiettivo

Il tuo compito è quello di scrivere un programma / funzione che prende un numero positivo e quindi trovare tutti i suoi divisori.

Restrizione

  • Non è possibile utilizzare alcun built-in relativo a prime o fattorizzazione .
  • La complessità del tuo algoritmo non deve superare O (sqrt (n)) .

La libertà

  • L'elenco di output può contenere duplicati.
  • Non è necessario ordinare l'elenco di output.

punteggio

Questo è . Vince la soluzione più breve in byte.

Casi test

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

Probabilmente intendi divisore , non fattore . E immagino che tu voglia avere una complessità temporale di O(sqrt(n)).
flawr

Qual'è la differenza tra divisor e factor ?
Leaky Nun,

Parliamo di fattori, ad esempio un numero, se il prodotto di questi risulta nuovamente nel numero originale, ma i divisori sono di solito i numeri che dividono detto numero senza resto.
flawr

@flawr Aggiornato di conseguenza.
Leaky Nun,

2
Dovrebbero avere più esempi. 99 (1 3 9 11 33 99)
Brad Gilbert b2gills

Risposte:


4

PostgreSQL, 176 byte

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

Ingresso: (SELECT ...v)

Come funziona:

  • (SELECT ...v) - input
  • generate_series(1, sqrt(v)::int) - numeri da 1 a sqrt (n)
  • WHERE v%r=0 divisori del filtro
  • avvolgere con l'espressione di tabella comune per fare doppio riferimento
  • SELECT r FROM c UNION SELECT v/r FROM c generete il resto dei divisori e combinate
  • SELECT string_agg(r::text,',' ORDER BY r) produce un risultato separato da virgola finale

Inserisci come tabella:

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

Produzione:

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

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

Basato sulla soluzione C # di downrep_nation, ma ricorsivo e golfato più in basso utilizzando alcune nuove funzionalità di C # 6.

L'algoritmo di base è uguale a quello presentato da downrep_nation. Il for-loop viene trasformato in una ricorsione, quindi il secondo parametro. l'inizio della ricorsione viene eseguito dal parametro predefinito, quindi la funzione viene chiamata con il solo numero iniziale richiesto.

  • l'utilizzo di funzioni basate su espressioni senza blocco evita l'istruzione return
  • l'interpolazione di stringhe all'interno dell'operatore ternario consente di unire concatenazione e condizioni di stringhe

Poiché la maggior parte delle risposte qui (ancora) non seguono l'esatto formato di output degli esempi, lo tengo com'è, ma come svantaggio la funzione include una singola virgola finale nel risultato.


Bel primo post!
R


2

Matlab, 48 byte

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

Come funziona?
Leaky Nun,

Inoltre, hai ideato un algoritmo a cui non riuscivo a pensare ... Quanto sono stupido.
Leaky Nun,

Trovo tutti i divisori fino a, sqrt(n)quindi inserisco ogni divisore de n/dnella mia lista.
flawr

Aggiunte alcune regole. Forse potrebbe farti risparmiare qualche byte.
Leaky Nun,

1
Non ho ancora testato, ma non puoi usare b=~mod(n,a)per salvare 1 byte?
Luis Mendo,

2

J, 26 byte

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

Spiegazione

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

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

Non molto efficiente ma funziona! Esempio sotto:

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>


Benvenuti in PPCG!
Laikoni,

O(n)

1

MATL , 12 byte

tX^:\~ftGw/h

L'approccio è simile a quello nella risposta di @ flawr .

Provalo online!

Spiegazione

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

Mi chiedo spesso se il codice combinato di programmi scritto in MATL sarebbe un buon RNG.
flawr

@flawr Probabilmente questo vale per quasi tutte le lingue di golf del codice :-)
Luis Mendo

1

05AB1E , 14 12 byte

Codice:

ÐtLDŠÖÏDŠ/ï«

Spiegazione:

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

Utilizza la codifica CP-1252 . Provalo online! .


Vuoi fornire una spiegazione?
Leaky Nun

@KennyLau Aggiunto
Adnan

1

Python 2, 64 byte

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

Questa funzione anonima genera un elenco di divisori. I divisori sono calcolati dalla divisione di prova degli interi nell'intervallo [1, ceil(sqrt(n))], ovvero O(sqrt(n)). Se n % x == 0(equivalente a n%x<1), quindi entrambi xe n/xsono divisori di n.

Provalo online


1

Gelatina , 9 byte

½Rḍ³Tµ³:;

Come le altre risposte, questo è O (√n) se facciamo il presupposto (falso) che la divisione intera sia O (1) .

Come funziona

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

Provalo online!



1

Javascript, 47 byte

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


0

Mathematica, 50 byte

Simile alla soluzione di @ flawr .

Esegue pista di divisione per x da 1 fino alla radice quadrata di n e se scindibile, salva a un elenco come x e n / x .

(#2/#)~Join~#&@@{Cases[Range@Sqrt@#,x_/;x∣#],#}&
  • Si noti che richiede 3 byte per rappresentare in UTF-8, rendendo la stringa di 48 caratteri richiede 50 byte nella rappresentazione 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}

Bene, richiede 3 byte ...
Leaky Nun

@KennyLau Sì, mi sbagliavo, avrei dovuto ricontrollare
miglia

0

JavaScript (ES6), 66 62 byte

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

Ho pensato di scrivere una versione che restituiva un elenco deduplicato ordinato, e in realtà si è rivelato essere più corto di 4 byte ...


0

C #, 87 byte


golfed

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

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

Uscite

  • v1.0 - 87 bytes- Soluzione iniziale.

Appunti

  • Nel codice Golfed , uso var's e int' s anziché String's e Int32' s per accorciare il codice, mentre in Ungolfed Code e Full Code utilizzo String'e Int32' s per rendere il codice più leggibile.

Ho sentito che in forgenere è meglio di while.
Leaky Nun,

La tua soluzione ha una complessità di O (n) invece di O (sqrt (n)) ...
Leaky Nun

@KennyLau dipende dalla situazione, in questo caso avere un forloop avrebbe la stessa lunghezza del whileloop. In questo caso è irrilevante avere o avere l'altro.
auhmaan,

Ma in questo caso può farti risparmiare un byte ...
Leaky Nun

0

Lua, 83 byte

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

Purtroppo non ho potuto fare di meglio


1. benvenuto in PPCG, spero che questo sito ti piaccia! 2. è possibile modificare == 0 in <1 per salvare alcuni byte. 3. è possibile utilizzare la struttura ternaria anziché se poi fine, ma non so se salverà alcun byte. 4. la complessità del tuo algoritmo è O (n) che non soddisfa i requisiti.
Leaky Nun,

Tutto ok. L'elenco deve essere ordinato o formattato in modo appropriato?
user6245072,

"L'elenco di output può contenere duplicati. L'elenco di output non ha bisogno di essere ordinato."
Leaky Nun

Proprio lol. E devo stampare il risultato o un array che lo contiene è sufficiente?
user6245072,

Bene, o lo stampi o lo restituisci (all'interno di una funzione).
Leaky Nun,

0

Perl 6 , 40 byte

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

Spiegazione:

{
  # 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 byte

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

non so se questo funziona per tutti i numeri, sospetto che lo sia.

ma la complessità è giusta, quindi è già qualcosa che non lo è


0

Rubino, 56 byte

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

0

Codice macchina IA-32, 27 byte

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

Codice sorgente (sintassi di 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;

Il primo parametro ( ecx) è un puntatore all'output, il secondo parametro ( edx) è il numero. Non segna in alcun modo la fine dell'output; si dovrebbe precompilare l'array di output con zeri per trovare la fine dell'elenco.

Un programma C ++ completo che utilizza questo codice:

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

L'output presenta alcuni difetti, anche se segue le specifiche (non è necessario l'ordinamento; non è necessario unicità).


Ingresso: 69

Produzione:

69
1
23
3

I divisori sono in coppia.


Ingresso: 100

Produzione:

100
1
50
2
25
4
20
5
10
10

Per quadrati perfetti, l'ultimo divisore viene emesso due volte (è una coppia con se stesso).


Ingresso: 30

Produzione:

30
1
15
2
10
3
6
5
5
6

Se l'ingresso è vicino a un quadrato perfetto, l'ultima coppia viene emessa due volte. È a causa dell'ordine dei controlli nel ciclo: in primo luogo, verifica la presenza di "resto = 0" e delle uscite, e solo in questo caso verifica che "quoziente <divisore" esca dal ciclo.


0

SmileBASIC, 49 byte

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

Usa il fatto che D>N/D= D>sqrt(N)per numeri positivi


0

C, 87 81 byte

Migliorato da @ceilingcat , 81 byte:

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

Provalo online!


La mia risposta originale, 87 byte:

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

Compila gcc div.c -o div -lme corri con ./div <n>.


Bonus: una variante ancora più breve con O (n) complessità temporale e hardcoded n(46 byte + lunghezza di n):

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

Modifica: Grazie a @Sriotchilism O'Zaic per aver sottolineato che gli input non devono essere hardcoded, ho modificato la presentazione principale per prendere l'input tramite argv.


1
È nl'input? Mettere l'input in una variabile non è un modo accettato di fare input qui per una serie di ragioni. Puoi vedere di più sui nostri moduli di input e output accettati e non accettati qui: codegolf.meta.stackexchange.com/questions/2447/… . E se sei curioso di conoscere una lingua specifica (es. C) puoi guardare qui: codegolf.meta.stackexchange.com/questions/11924/… .
Ad Hoc Garf Hunter,

@ SriotchilismO'Zaic Sì, nè l'input. Proverò a modificarlo in modo che prenda l'input in un altro modo. Grazie per l'info!
OverclockedSanic il

0

APL (NARS), 22 caratteri, 44 byte

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

test:

  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 

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.