Основні фактори приятелів


21

Враховуючи ціле число N > 1, виведіть усі інші числа, прості розклади яких мають ті ж цифри, що і просте розкладанняN .

Наприклад, якщо N = 117, то вихід повинен бути [279, 939, 993, 3313, 3331], тому що

117 = 3 × 3 × 13

Таким чином, наявні цифри 1, 3, 3і 3і ми маємо

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

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

Якщо Nякісь - або з 117, 279, 939, 993, 3313або3331 , то вихід буде містити п'ять інших чисел: вони є головними факторами приятелями.

Ви не можете використовувати провідні нулі для отримання простих ліній, наприклад, для N = 107його єдиного друга 701(017 не вважається).

Вхідні та вихідні

  • Друзі вводу та виведення повинні прийматися та повертатися у десятковій основі.

  • 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]

Оцінка балів

Це , тому найкоротша відповідь у байтах виграє.

Відповіді:


4

Желе , 14 байт

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

Час виконання може бути вдвічі DFзамість, ніжV , але він по- , як і раніше завершує комбіновані тестові випадки у віці до тридцяти секунд.

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Як це працює

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

Я думаю, що це Ç€=$було б трохи швидше, ніж Ç€=Ç, враховуючи часові обмеження.
Ерік Аутгольфер

Дякую, але для введення 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і визначає function, f. Ця функція використовує накопичувальний пробний поділ для створення списку основних факторів. Він досить швидкий для невеликих входів, але, очевидно, виходить з ладу, якщо вхід великий. На щастя, всі тестові справи невеликі, тому цього достатньо.

Наступний рядок отримує fакторів $n, -splitз них на кожну цифру, ігноруючи порожні результати (це потрібно завдяки тому, як PowerShell проводить відповідність регулярного вирівнювання та як він переміщує вказівник через вхід і якийсь дратівливий для цілей гольфу), а потім sortрезультати у порядку зростання. Ми зберігаємо цей масив цифр $xі використовуємо це як вхід до |?{...}фільтра, щоб витягнути лише ті, які самі по собі є простими. Ці основні цифри зберігаються $yдля подальшого використання.

Потім ми розділилися $xна дві складові. Перша (тобто найменша) цифра зберігається $a, а решта передається в $b. Якщо є $xлише одна цифра, вона $bбуде порожньою / null. Потім нам потрібно повторно подати $aяк масив, тому ми використовуємо оператор комами швидко, як це зробити.

Далі нам потрібно побудувати всі можливі перестановки цифр. Це необхідно, щоб наші тести на поділ пізніше пропустили купу чисел і зробили все швидше в цілому.

Поки залишився елемент $b, ми знімаємо першу цифру $zі залишаємо решту $b. Тоді нам потрібно накопичити в $aрезультаті деяку нарізку рядків і виписування. Ми беремо $a+$yконкатенацію масиву, і для кожного елемента ми конструюємо нову рядок $c, потім пров'язуємо через $c's .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дійових осіб $i, sortїх, а вони -eqуал $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 Це лише 64 з 450, що дивно трохи на низький відсоток (14,22%) для відповідей PowerShell.
AdmBorkBork

8

CJam , 26 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

Тестовий набір .

Використовує те саме спостереження, що і з поста Мартіна .

Розширення:

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

Для цього використовується той же алгоритм, який використовували Мартін , Аднан , FryAmTheEggman та Денніс . Пропозиції з гольфу вітаються. Спробуйте в Інтернеті!

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

Ungolfing

          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

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