找到正因数!


11

定义

如果数字大于零,则为正数。

如果数字(A)可以除以无余数,则它是另一个数字(B)的除数。AB

例如,26因的除数,2可以除以6余数。

目标

您的任务是编写一个带正数的程序/函数,然后找到所有除数。

限制

  • 您不得使用任何与prime factorization相关的内置函数
  • 算法的复杂度不得超过O(sqrt(n))

自由

  • 输出列表可能包含重复项。
  • 输出列表不需要排序。

计分

这是。以字节为单位的最短解决方案获胜。

测试用例

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

您可能是除数,而不是因子。而且我想您想将时间复杂度设置O(sqrt(n))
flawr

除数factor有什么区别?
Leaky Nun

我们讨论例如数字的因素,如果这些因素的乘积再次产生原始数字,但除数通常是所述数字而没有余数的数字。
瑕疵的

@flawr相应地更新。
Leaky Nun

2
应该有更多的例子。99 (1 3 9 11 33 99)
布拉德·吉尔伯特b2gills '16

Answers:


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

基于downrep_nation的C#解决方案,但使用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)]

这是如何运作的?
Leaky Nun

另外,您设计了一种我无法想到的算法...我多么愚蠢。
Leaky Nun

我找到所有sqrt(n)除数d,然后将每个除数和n/d放在我的列表中。
瑕疵的

添加了一些规则。也许可以为您节省一些字节。
Leaky Nun

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!
Laikoni '17

Øñ

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

05AB1E14 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编码。在线尝试!


愿意提供解释吗?
Leaky Nun

@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),则xn/x均为的除数n

在线尝试


1

果冻,9 字节

½Rḍ³Tµ³:;

另一个答案是,如果我们假设整数除法为O(1),则为O(√n )。

这个怎么运作

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

在线尝试!



1

Javascript,47个字节

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


0

Mathematica,50个字节

类似于@flawr的解决方案

x执行从1到n的平方根的路径除法,如果可除,将其另存为xn / x到列表中。

(#2/#)~Join~#&@@{Cases[Range@Sqrt@#,x_/;x∣#],#}&
  • 请注意,以UTF-8表示需要3个字节,因此以48个字符串以UTF-8表示需要50个字节。

用法

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

发布

  • 1.0 - 87 bytes-初始溶液。

笔记

  • Golfed代码中,使用var'和int'代替String'和Int32'使代码更短,而在Ungolfed代码完整代码中,我使用String'和Int32'使代码更具可读性。

我听说for通常比更好while
Leaky Nun

您的解决方案的复杂度为O(n)而不是O(sqrt(n))...
Leaky Nun

@KennyLau取决于情况,在这种情况下,具有for循环的长度将与while循环的长度相同。在这种情况下,与一个或另一个具有无关紧要。
auhmaan'5

但在这种情况下,它可以为您节省一个字节...
Leaky Nun

0

Lua,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),不符合要求。
Leaky Nun

好吧。列表是否需要订购或格式正确?
user6245072 '16

“输出列表可能包含重复项。不需要对输出列表进行排序。”
Leaky Nun

对吧 我是否需要打印结果或包含结果的数组就足够了?
user6245072

好吧,您可以打印它或将其返回(在函数内部)。
Leaky Nun

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

Ruby,56个字节

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

0

IA-32机器代码,27个字节

十六进制转储:

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”并输出,然后才检查“ quotient <除数”以退出循环。


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/…
Ad Hoc Garf Hunter,

@ SriotchilismO'Zaic是的,n是输入。我将尝试对其进行修改,以使其以其他方式使用输入。谢谢你的信息!
超频的

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 

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.