Знайдіть позитивних дільників!


11

Визначення

Число є позитивним, якщо воно більше нуля.

Число ( A) - дільник іншого числа ( B), якщо його Aможна розділити Bбез залишку.

Наприклад, 2є дільником 6тому, що 2може ділитися 6без залишку.

Мета

Ваше завдання - написати програму / функцію, яка приймає додатне число, а потім знайти всі її дільники.

Обмеження

  • Ви не можете використовувати будь-які вбудовані програми, пов’язані з праймером або факторизацією .
  • Складність вашого алгоритму не повинна перевищувати O (sqrt (n)) .

Свобода

  • Список вихідних даних може містити дублікати.
  • Список вихідних даних не потребує сортування.

Оцінка балів

Це . Найкоротше рішення в байтах виграє.

Тестові шафи

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

Ви, мабуть, маєте на увазі дільник , а не фактор . І я припускаю , що ви хочете мати тимчасову складність в O(sqrt(n)).
невдача

Яка різниця між дільником і фактором ?
Лина монашка

Ми говоримо про коефіцієнти, наприклад, число, якщо добуток цих результатів знову стає початковим числом, але дільниками, як правило, є числа, які ділять вказане число без залишку.
flawr

@flawr Оновлено відповідно.
Лина монашка

2
Повинно бути більше прикладів. 99 (1 3 9 11 33 99)
Бред Гілберт b2gills

Відповіді:


4

PostgreSQL, 176 байт

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

Вхід: (SELECT ...v)

Як це працює:

  • (SELECT ...v) - вхід
  • generate_series(1, sqrt(v)::int) - числа від 1 до sqrt (n)
  • WHERE v%r=0 -фільтрові дільники
  • обгортання із загальним виразом таблиці для позначення двічі
  • SELECT r FROM c UNION SELECT v/r FROM c генерете решту дільників і комбінуйте
  • SELECT string_agg(r::text,',' ORDER BY r) отримати остаточний результат, розділений комами

Введіть як таблицю:

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

Вихід:

╔═════╦════════════════╗
║ 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 байт

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

Заснований на C # рішенні downrep_nation, але рекурсивний і гольф далі вниз, використовуючи деякі нові функції від C # 6.

Базовий алгоритм такий самий, як алгоритм, представлений downrep_nation. Цикл for-циклу перетворюється на рекурсію, таким чином, другий параметр. запуск рекурсії здійснюється за параметром за замовчуванням, таким чином, функція викликається лише необхідним єдиним початковим номером.

  • використання функцій на основі вираження без блоку уникає оператора return
  • інтерполяція рядків всередині потрійного оператора дозволяє об'єднати об'єднання рядків і умови

Оскільки більшість відповідей тут (поки) не відповідають точному формату виведення з прикладів, я зберігаю його таким, яким він є, але як недолік функція включає в себе одну кінцеву кому в результаті.


Гарний перший пост!
Rɪᴋᴇʀ


2

Матлаб, 48 байт

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

Як це працює?
Лина монашка

Крім того, ви розробили алгоритм, про який я не міг придумати ... Як я дурний.
Лина монашка

Я знаходжу все divisos до , sqrt(n)а потім покласти кожен дільник dі n/dв моєму списку.
flawr

Додано кілька правил. Можливо, ви могли б заощадити кілька байт.
Лина монашка

1
Я не перевіряв, але ви не можете використати b=~mod(n,a)для збереження 1 байт?
Луїс Мендо

2

J, 26 байт

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

Пояснення

(],%)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 байт

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

Не дуже ефективно, але працює! Приклад нижче:

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>


Ласкаво просимо до PPCG!
Лайконі

О(н)

1

MATL , 12 байт

tX^:\~ftGw/h

Підхід схожий на відповідь у @ flawr .

Спробуйте в Інтернеті!

Пояснення

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

Мені часто цікаво, чи може комбінований код програм, написаних на MATL, зробити хорошим RNG.
невдача

@flawr Це, мабуть, стосується майже кожного коду мови для гольфу :-)
Луїс Мендо,

1

05AB1E , 14 12 байт

Код:

ÐtLDŠÖÏDŠ/ï«

Пояснення:

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

Використовує кодування CP-1252 . Спробуйте в Інтернеті! .


Хочете надати пояснення?
Лина монашка

@KennyLau Додано
Аднан

1

Python 2, 64 байти

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

Ця анонімна функція виводить список дільників. Дільники обчислюються пробним поділом цілих чисел у діапазоні [1, ceil(sqrt(n))], який є O(sqrt(n)). Якщо n % x == 0(еквівалентно n%x<1), то обидва xі n/xє дільниками n.

Спробуйте в Інтернеті


1

Желе , 9 байт

½Rḍ³Tµ³:;

Як і інші відповіді, це O (√n), якщо зробити (помилкове) припущення, що ціле ділення є O (1) .

Як це працює

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

Спробуйте в Інтернеті!




0

Математика, 50 байт

Подібно @ flawr в розчині .

Виконує поділ сліду для x від 1 до квадратного кореня n і, якщо ділиться, зберігає його до списку як x і n / x .

(#2/#)~Join~#&@@{Cases[Range@Sqrt@#,x_/;x∣#],#}&
  • Зауважте, що для представлення в UTF-8 потрібні 3 байти, тому 48-символьний рядок вимагає 50 байт у представленні UTF-8.

Використання

  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}

Ну, для цього потрібно 3 байти ...
Leaky Nun

@KennyLau Так, я помилявся, повинен був перевірити двічі
миль

0

JavaScript (ES6), 66 62 байт

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

Я думав, що напишу версію, яка повертає відсортований подвійний список, і він насправді виявився на 4 байти коротшим ...


0

C #, 87 байт


Гольф

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

Безумовно

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

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

    o += "," + v;

    return o;
}

Повний код

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

Релізи

  • v1.0 - 87 bytes- Початкове рішення.

Примітки

  • У коді Golfed я використовую var'і and int' s замість String's і Int32' s, щоб скоротити код, тоді як в коді Ungolfed та Full Code я використовую String's і Int32', щоб зробити код більш читабельним.

Я чув, що forце взагалі краще, ніж while.
Leaky Nun

Ваше рішення має складність O (n) замість O (sqrt (n)) ...
Leaky Nun

@KennyLau - це залежить від ситуації, і в цьому випадку forцикл матиме ту саму довжину, що і whileцикл. У цьому випадку не має значення іншого чи іншого.
auhmaan

Але в цьому випадку це може врятувати вас на байт ...
Лина монашка

0

Луа, 83 байти

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

На жаль, я не міг зробити кращого


1. Ласкаво просимо до PPCG, сподіваємось, вам сподобається цей сайт! 2. Ви можете змінити == 0 на <1, щоб зберегти кілька байт. 3. Ви можете використовувати потрійну структуру замість того, якщо потім закінчується, але я не знаю, чи збереже вона будь-які байти. 4. Складність вашого алгоритму - O (n), що не відповідає вимозі.
Лина монашка

Гаразд. Чи потрібно впорядкувати список чи форматувати його відповідним чином?
user6245072,

"Список вихідних даних може містити дублікати. Список вихідних даних не потрібно сортувати."
Leaky Nun

Право лол. І чи потрібно мені надрукувати результат або достатньо масиву, що містить його?
user6245072

Ну, або ви друкуєте його, або повертаєте його (всередині функції).
Лина монашка

0

Perl 6 , 40 байт

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

Пояснення:

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

Використання:

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 байт

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

я не знаю, чи працює це для всіх чисел, я підозрюю, що це так.

але складність правильна, так що це вже щось не так



0

Машинний код IA-32, 27 байт

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

Вихідний код (синтаксис 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;

Перший параметр ( ecx) - вказівник на вихід, другий параметр ( edx) - число. Це жодним чином не відзначає кінець випуску; слід попередньо заповнити вихідний масив нулями, щоб знайти кінець списку.

Повна програма C ++, яка використовує цей код:

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

Вихід має деякі збої, навіть не дивлячись на характеристики (немає необхідності в сортуванні; немає необхідності в унікальності).


Вхід: 69

Вихід:

69
1
23
3

Дільники складаються парами.


Вхід: 100

Вихід:

100
1
50
2
25
4
20
5
10
10

Для ідеальних квадратів останній дільник виводиться двічі (це пара з самим собою).


Вхід: 30

Вихід:

30
1
15
2
10
3
6
5
5
6

Якщо вхід близький до ідеального квадрата, остання пара виводиться двічі. Це через порядок перевірок у циклі: спочатку він перевіряє на "залишок = 0" та виводить, а вже потім перевіряє на "коефіцієнт <дільник", щоб вийти з циклу.


0

SmileBASIC, 49 байт

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

Використовує той факт, що D>N/D= D>sqrt(N)для додатних чисел


0

C, 87 81 байт

Покращено @ceilingcat , 81 байт:

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

Спробуйте в Інтернеті!


Моя оригінальна відповідь, 87 байт:

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

Компілюйте gcc div.c -o div -lmі запускайте ./div <n>.


Бонус: Ще коротший варіант із складною часовою складністю O (n) та жорстким кодом n(46 байт + довжина n):

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

Редагувати: Дякую @Sriotchilism O'Zaic за те, що він вказав, що входи не повинні бути жорстко кодованими, я змінив основне подання, щоб взяти вхід через argv.


1
Чи nє вхід? Розміщення введення змінною не є прийнятним способом введення тут даних з кількох причин. Більше про наші прийняті та неприйняті форми введення та виводу можна переглянути тут: codegolf.meta.stackexchange.com/questions/2447/… . А якщо вам цікаво певної мови (наприклад, C), ви можете подивитися тут: codegolf.meta.stackexchange.com/questions/11924/… .
Спеціальний мисливець на

@ SriotchilismO'Zaic Так, nце вхід. Я спробую модифікувати його, щоб це сприйняло інший спосіб. Дякую за інформацію!
OverclockedSanic

0

APL (NARS), 22 символи, 44 байти

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

тест:

  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 

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.