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


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.