主要因素伙伴


21

给定一个整数N > 1,输出素数分解与素数分解相同的所有其他数字N

例如,如果为N = 117,则输出必须为[279, 939, 993, 3313, 3331],因为

117 = 3 × 3 × 13

因此,现有的数字是1333我们有

279  = 3 × 3 × 31
939  = 3 × 313
993  = 3 × 331
3313 = 3313
3331 = 3331

这些是唯一可能的其他数字,因为这些数字的其他组合会产生非素数整数,而这不是素数分解的结果。

如果N是任意的11727993999333133331,然后输出将包含五个其他数字:他们是首要因素好友。

您不能使用前导零来获取素数,例如,对于N = 107,它的唯一伙伴是701017不考虑)。

输入和输出

  • 输入和输出伙伴必须以十进制为基础并返回。

  • N将始终严格大于1

  • 只要只包含伙伴和分隔符/列表语法元素,就可以相当自由地格式化输出。

  • 输出的顺序并不重要。

  • 您可以通过接受输入STDIN,作为函数参数或类似的参数。

  • 您可以将输出打印到STDOUT,从函数返回它或类似的东西。

测试用例

您的程序应在不到一分钟的时间内解决以下任何测试用例。

N        Buddies
2        []
4        []
8        []
15       [53]
16       []
23       [6]
42       [74, 146, 161]
126      [222, 438, 483, 674, 746, 851, 1466, 1631, 1679]
204      [364,548,692,762,782,852,868,1268,1626,2474,2654,2921,2951,3266,3446,3791,4274,4742,5426,5462,6233,6434,6542,7037,8561,14426,14642,15491,15833,22547]

计分

这是,因此最短的答案以字节为单位。

Answers:


4

果冻,14 字节

ÆfVṢṚḌ
ÇÇ€=ÇTḟ

可以使用DF代替来将执行时间减半V,但是仍然可以在不到30秒的时间内完成组合的测试用例。

在线尝试!验证所有测试用例

怎么运行的

ÆfVṢṚḌ   Helper link. Argument: k (integer)

Æf       Decompose k into an array of primes with product k.
  V      Eval. Eval casts a 1D array to string first, so this computes the integer
         that results of concatenating all primes in the factorization.
   Ṣ     Sort. Sort casts a number to the array of its decimal digits.
    Ṛ    Reverse. This yields the decimal digits in descending order.
     Ḍ   Undecimal; convert the digit array from base 10 to integer.


ÇÇ€=ÇTḟ  Main link. Argument: n (integer)

Ç        Call the helper link with argument n.
         This yields an upper bound (u) for all prime factorization buddies since
         the product of a list of integers cannot exceed the concatenated integers.
 ǀ      Apply the helper link to each k in [1, ..., u].
    Ç    Call the helper link (again) with argument n.
   =     Compare each result to the left with the result to the right.
     T   Truth; yield all 1-based indices of elements of [1, ..., u] (which match
         the corresponding integers) for which = returned 1.
      ḟ  Filter; remove n from the indices.

考虑到时间限制,我认为这Ç€=$会快一些Ç€=Ç
暴民埃里克(Erik the Outgolfer)'17年

谢谢,但是对于输入117,您的改进意味着助手链接将被调用3331次而不是3332次,因此无法测量提速。无论如何,更新(更快)的TIO甚至不需要20秒就可以完成组合测试用例。
丹尼斯

16

PowerShell v3 +,450字节

param($n)function f{param($a)for($i=2;$a-gt1){if(!($a%$i)){$i;$a/=$i}else{$i++}}}
$y=($x=@((f $n)-split'(.)'-ne''|sort))|?{$_-eq(f $_)}
$a,$b=$x
$a=,$a
while($b){$z,$b=$b;$a=$a+($a+$y|%{$c="$_";0..$c.Length|%{-join($c[0..$_]+$z+$c[++$_..$c.Length])};"$z$c";"$c$z"})|select -u}
$x=-join($x|sort -des)
$l=@();$a|?{$_-eq(f $_)}|%{$j=$_;for($i=0;$i-le$x;$i+=$j){if(0-notin($l|%{$i%$_})){if(-join((f $i)-split'(.)'|sort -des)-eq$x){$i}}}$l+=$j}|?{$_-ne$n}

最后!

PowerShell没有用于素数检查,因数分解或置换的任何内置函数,因此这是完全手动完成的。我通过努力一堆优化技巧的尝试和减少时间复杂度降低到东西,将适合在挑战的限制,我很高兴地说,我终于成功了-

PS C:\Tools\Scripts\golfing> Measure-Command {.\prime-factors-buddies.ps1 204}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 27
Milliseconds      : 114
Ticks             : 271149810
TotalDays         : 0.000313830798611111
TotalHours        : 0.00753193916666667
TotalMinutes      : 0.45191635
TotalSeconds      : 27.114981
TotalMilliseconds : 27114.981

说明

这里有很多事情,所以我会尽力分解。

第一行获取输入$n和定义的functionf。此功能使用累积试验划分得出主要因素的列表。对于小的输入来说,这是相当快的,但是如果输入很大,显然会陷入困境。幸运的是,所有测试用例都很小,因此就足够了。

下一行获取的factor $n-split使它们的每个数字都忽略任何空结果(由于PowerShell如何进行正则表达式匹配以及如何将指针移动通过输入,并且对于打高尔夫球的目的有点烦人,所以需要这样做),然后sort生成结果升序排列。我们将该数字数组存储到中$x,并将其用作|?{...}过滤器的输入,以仅提取本身就是质数的那些。这些素数被存储起来$y以备后用。

然后,我们$x分为两个部分。第一个(即最小的)数字存储到中$a,其余的则传递到中$b。如果$x只有一位,$b则为空/空。然后,我们需要将其重新广播$a为数组,因此我们使用类似于逗号的运算符来快速转换。

接下来,我们需要构造所有可能的数字排列。这是必要的,这样我们的事业部测试后跳过一串数字让事情变的更快的整体。

只要有剩余元素$b,我们就将第一个数字剥离掉$z,剩下的保留在中$b。然后,我们需要累加$a一些字符串切片和切块的结果。我们采取$a+$y的阵列串联,对于每个元素,我们构建一个新的字符串$c,然后依次通过$c.length,并插入$z到每一个位置,包括前面加上$z$c并追加$c$z,那么select只有荷兰国际集团的-uNIQUE元素。再次将其$a与数组串联,然后重新存储回$a。是的,确实会发生一些愚蠢的事情,例如您可以获取3333输入117,它实际上不是一个排列,但是比尝试显式过滤掉它们要短得多,这可以确保我们得到每个排列,并且速度非常慢。

因此,现在$a有了该因子数字的所有可能(然后是一些)排列的数组。我们需要重新设置$x为可能结果的上限,方法|sort是按-des升序排列数字并将-join它们重新组合在一起。显然,任何输出值都不能大于该数字。

我们将帮助程序数组$l设置为以前看到的值的数组。接下来,我们从$a质数中提取每个值(即那些排列),并进入一个循环,该循环是整个程序的最大耗时...

每次迭代,我们都循环0到上限$x,以当前元素递增$j。只要$i我们考虑的值不是先前值的倍数(这是该0-notin($l|%{$i%$_})部分),它就可能是输出的候选者。如果我们采取f的行动者$isort他们,他们-eqUAL $x,然后将值添加到管道。在循环的最后,我们已经将当前元素添加$j$l数组中以供下次使用,因为我们已经考虑了所有这些值。

最后,我们|?{$_-ne$n}着手提取那些不是输入元素的内容。它们全部留在管道上,输出是隐式的。

例子

PS C:\Tools\Scripts\golfing> 2,4,8,15,16,23,42,117,126,204|%{"$_ --> "+(.\prime-factors-buddies $_)}
2 --> 
4 --> 
8 --> 
15 --> 53
16 --> 
23 --> 6
42 --> 74 146 161
117 --> 279 939 993 3313 3331
126 --> 222 438 674 746 1466 483 851 1679 1631
204 --> 782 2921 3266 6233 3791 15833 2951 7037 364 868 8561 15491 22547 852 762 1626 692 548 1268 2654 3446 2474 5462 4742 5426 4274 14426 6542 6434 14642

那是我见过的最多的钱!
致命

1
@Fatalize在450个表中,它只有64个,对于PowerShell答案,这是令人惊讶的偏低百分比(14.22%)。
AdmBorkBork

8

CJam26 23字节

{_mfs$:XW%i){mfs$X=},^}

在线尝试

说明

连接两个数字总是比将它们相乘产生更大的结果。因此,我们可能需要考虑的最大数字是我们可以从输入素数分解的数字中形成的最大数字,该数字只是所有数字以降序排列。对于给定的数字,此上限很容易足够小,我们可以详尽地检查范围内的每个数字是否是主要因素好友:

_mf    e# Duplicate input N and get a list of its prime factors.
s$     e# Convert the list to a (flattened) string and sort it.
:X     e# Store this in X for later.
W%     e# Reverse it. This is now a string repesentation of the largest 
       e# possible output M.
i)     e# Convert to integer and increment.
{      e# Get a list of all integers i in [0 1 ... M] for which the following
       e# block gives a truthy result.
  mf   e#   Get list of prime factors of i.
  s$   e#   Get a sorted list of the digits appearing in the factorisation.
  X=   e#   Check for equality with X.
},
^      e# Symmetric set difference: removes N from the output list.

6

05AB1E,17个字节

码:

ÒJ{©RƒNÒJ{®QN¹Ê*–

说明:

Ò                  # Get the factorization with duplicates, e.g. [3, 3, 13]
 J                 # Join the array, e.g. 3313
  {©               # Sort and store in ©, e.g. 1333
    R              # Reverse the number, e.g. 3331. This is the upperbound for the range
     ƒ             # For N in range(0, a + 1), do...
      NÒ           # Push the factorization with duplicates for N
        J          # Join the array
         {         # Sort the string
          ®Q       # Check if equal to the string saved in ©
            N¹Ê    # Check if not equal to the input
               *   # Multiply, acts as a logical AND
                –  # If 1, print N

使用CP-1252编码。在线尝试!


4

佩斯,17岁

LSjkPb-fqyTyQSs_y

测试套件

使用与Martin的文章相同的观察结果。

扩张:

LSjkPb        ##  Define a function y(b) to get the sorted string of digits
              ##  of the prime factors of b
    Pb        ##  prime factors
  jk          ##  join to a string with no separator
 S            ##  Sort

-fqyTyQSs_yQQ ##  Auto-fill variables
         _yQ  ##  get reversed value of y(input)
       Ss     ##  convert that string to a list [1 ... y(input)]
 fqyTyQ       ##  keep numbers T from the list that satisfy y(T)==y(input)
-           Q ##  remove the input from the result

3

的JavaScript(ES6),163个 158字节

编辑:已经阐明,诸如23的质数应返回[6]而不是空结果集。删除了一个现在无用的规则,从而避免了这种情况的发生,从而节省了5个字节。

对最后一个测试用例进行了注释,以使此代码段运行得足够快,尽管它也应该在不到一分钟的时间内完成。

let f =

n=>[...Array(+(l=(p=n=>{for(i=2,m=n,s='';i<=m;n%i?i++:(s+=i,n/=i));return s.split``.sort().reverse().join``})(n))+1)].map((_,i)=>i).filter(i=>i&&i-n&&p(i)==l)

console.log(JSON.stringify(f(2)));
console.log(JSON.stringify(f(4)));
console.log(JSON.stringify(f(8)));
console.log(JSON.stringify(f(15)));
console.log(JSON.stringify(f(16)));
console.log(JSON.stringify(f(23)));
console.log(JSON.stringify(f(42)));
console.log(JSON.stringify(f(126)));
//console.log(JSON.stringify(f(204)));


1

PHP 486字节

书中可能没有的算法可能会更短一些。
(但我喜欢当前的字节数)

function p($n){for($i=1;$i++<$n;)if($n%$i<1&&($n-$i?p($i)==$i:!$r))for($x=$n;$x%$i<1;$x/=$i)$r.=$i;return $r;}function e($s){if(!$n=strlen($s))yield$s;else foreach(e(substr($s,1))as$p)for($i=$n;$i--;)yield substr($p,0,$i).$s[0].substr($p,$i);}foreach(e(p($n=$argv[1]))as$p)for($m=1<<strlen($p)-1;$m--;){$q="";foreach(str_split($p)as$i=>$c)$q.=$c.($m>>$i&1?"*":"");foreach(split("\*",$q)as$x)if(0===strpos($x,48)|p($x)!=$x)continue 2;eval("\$r[$q]=$q;");}unset($r[$n]);echo join(",",$r);

分解

// find and concatenate prime factors
function p($n)
{
    for($i=1;$i++<$n;)  // loop $i from 2 to $n
        if($n%$i<1      // if $n/$i has no remainder
            &&($n-$i    // and ...
                ?p($i)==$i  // $n!=$i: $i is a prime
                :!$r        // $n==$i: result so far is empty ($n is prime)
            )
        )
            for($x=$n;      // set $x to $n
                $x%$i<1;    // while $x/$i has no remainder
                $x/=$i)     // 2. divide $x by $i
                $r.=$i;     // 1. append $i to result
    return $r;
}

// create all permutations of digits
function e($s)
{
    if(!$n=strlen($s))yield$s;else  // if $s is empty, yield it, else:
    foreach(e(substr($s,1))as$p)    // for all permutations of the number w/o first digit
        for($i=$n;$i--;)            // run $i through all positions around the other digits
            // insert removed digit at that position and yield
            yield substr($p,0,$i).$s[0].substr($p,$i);
}

// for each permutation
foreach(e(p($n=$argv[1]))as$p)
    // create all products from these digits: binary loop through between the digits
    for($m=1<<strlen($p)-1;$m--;)
    {
        // and insert "*" for set bits
        $q="";
        foreach(str_split($p)as$i=>$c)$q.=$c.($m>>$i&1?"*":"");
        // test all numbers in the expression
        foreach(split("\*",$q)as$x)
            if(
                0===strpos($x,48)   // if number has a leading zero
                |p($x)!=$x          // or is not prime
            )continue 2; // try next $m
        // evaluate expression and add to results (use key to avoid array_unique)
        eval("\$r[$q]=$q;");
    }

// remove input from results
unset($r[$n]);

// output
#sort($r);
echo join(",",$r);

1

其实是27个位元组

它使用与MartinAdnanFryAmTheEggmanDennis所使用的算法相同的算法。欢迎打高尔夫球。在线尝试!

`w"i$n"£MΣSR≈`╗╜ƒ;╝R`╜ƒ╛=`░

开球

          Implicit input n.
`...`╗    Define a function and store it in register 0. Call the function f(x).
  w         Get the prime factorization of x.
  "..."£M   Begin another function and map over the [prime, exponent] lists of w.
    i         Flatten the list. Stack: prime, exponent.
    $n        Push str(prime) to the stack, exponent times.
               The purpose of this function is to get w's prime factors to multiplicity.
  Σ         sum() the result of the map.
             On a list of strings, this has the same effect as "".join()
  SR≈       Sort that string, reverse it and convert to int.
╜ƒ        Now push the function stored in register 0 and call it immediately.
           This gives the upper bound for any possible prime factor buddy.
;╝        Duplicate this upper bound and save a copy to register 1.
R         Push the range [0..u]
`...`░    Filter the range for values where the following function returns a truthy.
           Variable k.
  ╜ƒ        Push the function in register 0 and call it on k.
  ╛=        Check if f(k) == f(n).
          Implicit return every value that is a prime factor buddy with n, including n.

1

Powershell,147个字节(CodeGolf版本)

param($n)filter d{-join($(for($i=2;$_-ge$i*$i){if($_%$i){$i++}else{"$i"
$_/=$i}}if($_-1){"$_"})|% t*y|sort -d)}2..($s=$n|d)|?{$_-$n-and$s-eq($_|d)}

注意:该脚本在我的本地笔记本上不到3分钟即可解决最后的测试用例。请参阅下面的“性能”解决方案。

少打高尔夫的测试脚本:

$g = {

param($n)
filter d{                       # in the filter, Powershell automatically declares the parameter as $_
    -join($(                    # this function returns a string with all digits of all prime divisors in descending order
        for($i=2;$_-ge$i*$i){   # find all prime divisors
            if($_%$i){
                $i++
            }else{
                "$i"            # push a divisor to a pipe as a string
                $_/=$i
            }
        }
        if($_-1){
            "$_"                # push a last divisor to pipe if it is not 1
        }
    )|% t*y|sort -d)            # t*y is a shortcut to toCharArray method. It's very slow.
}
2..($s=$n|d)|?{                 # for each number from 2 to number with all digits of all prime divisors in descending order
    $_-$n-and$s-eq($_|d)        # leave only those who have the 'all digits of all prime divisors in descending order' are the same
}

}

@(
    ,(2   ,'')
    ,(4   ,'')
    ,(6   ,23)
    ,(8   ,'')
    ,(15  ,53)
    ,(16  ,'')
    ,(23  ,6)
    ,(42  ,74, 146, 161)
    ,(107 ,701)
    ,(117 ,279, 939, 993, 3313, 3331)
    ,(126 ,222, 438, 483, 674, 746, 851, 1466, 1631, 1679)
    ,(204 ,364,548,692,762,782,852,868,1268,1626,2474,2654,2921,2951,3266,3446,3791,4274,4742,5426,5462,6233,6434,6542,7037,8561,14426,14642,15491,15833,22547)
) | % {
    $n,$expected = $_

    $sw = Measure-Command {
        $result = &$g $n
    }

    $equals=$false-notin(($result|%{$_-in$expected})+($expected|?{$_-is[int]}|%{$_-in$result}))
    "$sw : $equals : $n ---> $result"
}

输出:

00:00:00.0346911 : True : 2 --->
00:00:00.0662627 : True : 4 --->
00:00:00.1164648 : True : 6 ---> 23
00:00:00.6376735 : True : 8 --->
00:00:00.1591527 : True : 15 ---> 53
00:00:03.8886378 : True : 16 --->
00:00:00.0441986 : True : 23 ---> 6
00:00:01.1316642 : True : 42 ---> 74 146 161
00:00:01.0393848 : True : 107 ---> 701
00:00:05.2977238 : True : 117 ---> 279 939 993 3313 3331
00:00:12.1244363 : True : 126 ---> 222 438 483 674 746 851 1466 1631 1679
00:02:50.1292786 : True : 204 ---> 364 548 692 762 782 852 868 1268 1626 2474 2654 2921 2951 3266 3446 3791 4274 4742 5426 5462 6233 6434 6542 7037 8561 14426 14642 15491 15833 22547

Powershell,215字节(“性能”版本)

param($n)$p=@{}
filter d{$k=$_*($_-le3e3)
($p.$k=-join($(for($i=2;!$p.$_-and$_-ge$i*$i){if($_%$i){$i++}else{"$i"
$_/=$i}}if($_-1){($p.$_,"$_")[!$p.$_]})-split'(.)'-ne''|sort -d))}2..($s=$n|d)|?{$_-$n-and$s-eq($_|d)}

注意:我认为性能要求与GodeGolf原则相抵触。但是既然有规则Your program should solve any of the test cases below in less than a minute,我做了两处更改以满足该规则:

  • -split'(.)'-ne''代替短代码|% t*y;
  • 用于兑现字符串的哈希表。

每次更改都会使评估时间减少一半。请不要以为我已经使用了所有功能来提高性能。那些足以满足规则。

少打高尔夫的测试脚本:

$g = {

param($n)
$p=@{}                          # hashtable for 'all digits of all prime divisors in descending order'
filter d{                       # this function returns a string with all digits of all prime divisors in descending order
    $k=$_*($_-le3e3)            # hashtable key: a large hashtable is not effective, therefore a key for numbers great then 3000 is 0
                                # and string '-le3e3' funny
    ($p.$k=-join($(             # store the value to hashtable
        for($i=2;!$p.$_-and$_-ge$i*$i){
            if($_%$i){$i++}else{"$i";$_/=$i}
        }
        if($_-1){
            ($p.$_,"$_")[!$p.$_] # get a string with 'all digits of all prime divisors in descending order' from hashtable if it found
        }
    )-split'(.)'-ne''|sort -d)) # split each digit. The "-split'(.)-ne''" code is faster then '|% t*y' but longer.
}
2..($s=$n|d)|?{                 # for each number from 2 to number with all digits of all prime divisors in descending order
    $_-$n-and$s-eq($_|d)        # leave only those who have the 'all digits of all prime divisors in descending order' are the same
}

}

@(
    ,(2   ,'')
    ,(4   ,'')
    ,(6   ,23)
    ,(8   ,'')
    ,(15  ,53)
    ,(16  ,'')
    ,(23  ,6)
    ,(42  ,74, 146, 161)
    ,(107 ,701)
    ,(117 ,279, 939, 993, 3313, 3331)
    ,(126 ,222, 438, 483, 674, 746, 851, 1466, 1631, 1679)
    ,(204 ,364,548,692,762,782,852,868,1268,1626,2474,2654,2921,2951,3266,3446,3791,4274,4742,5426,5462,6233,6434,6542,7037,8561,14426,14642,15491,15833,22547)
) | % {
    $n,$expected = $_

    $sw = Measure-Command {
        $result = &$g $n
    }

    $equals=$false-notin(($result|%{$_-in$expected})+($expected|?{$_-is[int]}|%{$_-in$result}))
    "$sw : $equals : $n ---> $result"
}

输出:

00:00:00.0183237 : True : 2 --->
00:00:00.0058198 : True : 4 --->
00:00:00.0181185 : True : 6 ---> 23
00:00:00.4389282 : True : 8 --->
00:00:00.0132624 : True : 15 ---> 53
00:00:04.4952714 : True : 16 --->
00:00:00.0128230 : True : 23 ---> 6
00:00:01.4112716 : True : 42 ---> 74 146 161
00:00:01.3676701 : True : 107 ---> 701
00:00:07.1192912 : True : 117 ---> 279 939 993 3313 3331
00:00:07.6578543 : True : 126 ---> 222 438 483 674 746 851 1466 1631 1679
00:00:50.5501853 : True : 204 ---> 364 548 692 762 782 852 868 1268 1626 2474 2654 2921 2951 3266 3446 3791 4274 4742 5426 5462 6233 6434 6542 7037 8561 14426 14642 15491 15833 22547

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.