Найдите положительные делители!


11

Определение

Число положительно, если оно больше нуля.

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

Например, 2является делителем, 6потому что 2может делиться 6без остатка.

Цель

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

ограничение

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

свобода

  • Выходной список может содержать дубликаты.
  • Список вывода не нужно сортировать.

счет

Это . Самое короткое решение в байтах побеждает.

Testcases

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

Вы, вероятно, имеете в виду делитель , а не фактор . И я предполагаю , что вы хотите иметь временную сложность в O(sqrt(n)).
Flawr

В чем разница между делителем и фактором ?
Утренняя монахиня

Мы говорим о факторах, например, числа, если произведение этих результатов снова приводит к исходному числу, но делителями обычно являются числа, которые делят указанное число без остатка.
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

Matlab, 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!
Лайкони

О(N)

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

@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

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


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

Полный код

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's' и int's' вместо String's' и Int32's', чтобы сделать код короче, а в коде Ungolfed и полном коде я использую String's Int32' и 's', чтобы сделать код более читабельным.

Я слышал, что, forкак правило, лучше, чем while.
Утренняя монахиня

Ваше решение имеет сложность O (n) вместо O (sqrt (n)) ...
Leaky Nun

@KennyLau это зависит от ситуации, в этом случае forцикл будет иметь ту же длину, что и whileцикл. В этом случае не имеет значения иметь или иметь другого.
августа

Но в этом случае это может сэкономить вам байт ...
Leaky Nun

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. Вы можете использовать троичную структуру вместо if then end, но я не знаю, сохранит ли она какие-либо байты. 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

Если вход близок к идеальному квадрату, последняя пара выводится дважды. Это из-за порядка проверок в цикле: сначала он проверяет «remainder = 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

С, 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.