Compagni di fattori primi


21

Dato un numero intero N > 1, genera tutti gli altri numeri di cui le scomposizioni prime hanno le stesse cifre della decomposizione primaria di N.

Ad esempio, se N = 117, allora l'output deve essere [279, 939, 993, 3313, 3331], perché

117 = 3 × 3 × 13

di conseguenza, le cifre disponibili sono 1, 3, 3e 3e abbiamo

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

Questi sono gli unici altri numeri possibili, perché un'altra combinazione di queste cifre produce numeri interi non primi, che non possono essere il risultato della fattorizzazione in numeri primi.

Se Nè una delle 117, 279, 939, 993, 3313o 3331, allora l'uscita conterrà gli altri cinque numeri: sono fattori primi compagni.

Non è possibile utilizzare gli zeri iniziali per ottenere numeri primi, ad esempio perché il N = 107suo unico amico è 701( 017non è considerato).

Ingressi e uscite

  • I compagni di input e output devono essere presi e restituiti in base decimale.

  • Nsarà sempre strettamente maggiore di 1.

  • L'output può essere formattato piuttosto liberamente, purché contenga solo elementi sintattici di amici e separatori / elenchi.

  • L'ordinamento dell'output non è importante.

  • Puoi prendere l'input attraverso STDIN, come argomento di funzione o qualcosa di simile.

  • È possibile stampare l'output STDOUT, restituirlo da una funzione o qualcosa di simile.

Casi test

Il programma dovrebbe risolvere uno dei casi di test di seguito in meno di un minuto .

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]

punteggio

Questo è , quindi vince la risposta più breve in byte.

Risposte:


4

Gelatina , 14 byte

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

Il tempo di esecuzione potrebbe essere dimezzato DFinvece di V, ma completa comunque i casi di test combinati in meno di trenta secondi.

Provalo online! o verifica tutti i casi di test .

Come funziona

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

Penso che Ç€=$sarebbe un po 'più veloce di Ç€=Ç, dato il tempo limitato.
Erik the Outgolfer,

Grazie, ma per l'ingresso 117 , il tuo miglioramento significa che il collegamento helper verrà chiamato 3331 volte anziché 3332 volte, quindi l'accelerazione non è misurabile. Comunque, il TIO più recente (più veloce) non ha nemmeno bisogno di 20 secondi per i casi di test combinati .
Dennis,

16

PowerShell v3 +, 450 byte

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}

Finalmente!

PowerShell non ha alcun built-in per il controllo, la fattorizzazione o le permutazioni di primalità, quindi questo viene completamente eseguito manualmente. Ho lavorato su una serie di trucchi per l'ottimizzazione per cercare di ridurre la complessità temporale a qualcosa che si adatta alle restrizioni della sfida e sono felice di dire che alla fine ci sono riuscito -

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

Spiegazione

C'è molto da fare qui, quindi proverò a scomporlo.

La prima linea riceve l'input $ne definisce una function, f. Questa funzione utilizza la divisione di prova cumulativa per elaborare un elenco dei fattori primi. È abbastanza veloce per piccoli input, ma ovviamente si impantana se l'input è grande. Per fortuna tutti i casi di test sono piccoli, quindi questo è sufficiente.

La riga successiva ottiene i fattori $n, -splitli s su ogni cifra ignorando i risultati vuoti (ciò è necessario a causa di come PowerShell fa corrispondenza regex e come si sposta il puntatore attraverso l'ingresso ed è un pò fastidioso per scopi golf), allora sorts i risultati in ordine crescente. Memorizziamo quella matrice di cifre $xe la usiamo come input per un |?{...}filtro per estrarre solo quelli che sono essi stessi primi. Le cifre primi vengono archiviate $yper essere utilizzate in seguito.

Abbiamo quindi diviso $xin due componenti. La prima (cioè la più piccola) cifra viene memorizzata $a, mentre il resto viene passato $b. Se $xha solo una cifra, $bsarà vuoto / nullo. Abbiamo quindi bisogno di ripetere il cast $acome un array, quindi per fare ciò utilizziamo l'operatore virgola veloce.

Successivamente, dobbiamo costruire tutte le possibili permutazioni delle cifre. Ciò è necessario, quindi i nostri test di divisione in seguito saltano un sacco di numeri e rendono le cose più veloci nel complesso.

Finché rimane un elemento $b, stacciamo la prima cifra $ze lasciamo il resto $b. Quindi, dobbiamo accumularci nel $arisultato di alcune operazioni di taglio e taglio delle stringhe. Prendiamo $a+$ycome concatenazione di array e per ogni elemento costruiamo una nuova stringa $c, quindi passiamo in rassegna $c's' .lengthe li inseriamo $zin ogni posizione, inclusi anteporre $z$ce aggiungere $c$z, quindi selectsolo gli -uelementi di nicchia. Questo è di nuovo concatenato con array $ae nuovamente archiviato in $a. Sì, questo finisce per far succedere cose sciocche, come puoi ottenere 3333per input117, che in realtà non è una permutazione, ma è molto più breve del tentativo di filtrarle esplicitamente, assicura che otteniamo ogni permutazione ed è solo molto più lentamente.

Quindi, ora $aha una matrice di tutte le possibili (e quindi alcune) permutazioni delle cifre del fattore. Dobbiamo reimpostare $xil limite superiore dei possibili risultati |sortimmettendo le cifre in -desordine crescente e -joinreinserendole insieme. Ovviamente, nessun valore di output può essere maggiore di questo numero.

Abbiamo impostato il nostro array di helper $lcome un array di valori che abbiamo visto in precedenza. Successivamente, stiamo estraendo tutti i valori da $a(cioè, quelle permutazioni) che sono primi, ed entriamo in un ciclo che è il più grande spreco di tempo dell'intero programma ...

Ogni iterazione, eseguiamo il loop dal 0limite superiore $x, incrementando dell'elemento corrente $j. Finché il $ivalore che stiamo prendendo in considerazione non è un multiplo di un valore precedente (questa è la 0-notin($l|%{$i%$_})sezione), è un potenziale candidato per l'output. Se prendiamo gli fattori $i, sortloro, e -eqUAL $x, quindi aggiungere il valore alla pipeline. Alla fine del ciclo, aggiungiamo il nostro elemento corrente $jal nostro $larray per usarlo la prossima volta, poiché abbiamo già considerato tutti quei valori.

Infine, puntiamo |?{$_-ne$n}a estrarre quelli che non sono l'elemento di input. Sono tutti lasciati in cantiere e l'output è implicito.

Esempi

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

Questo è il maggior numero di dollari che abbia mai visto!
Fatalizza il

1
@Fatalize Sono solo 64 su 450, il che è sorprendentemente un po 'basso in percentuale (14,22%) per le risposte di PowerShell.
AdmBorkBork,

8

CJam , 26 23 byte

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

Provalo online

Spiegazione

Concatenare due numeri dà sempre un risultato più grande che moltiplicarli. Quindi il numero più grande che dovremmo eventualmente considerare è il numero più grande che possiamo formare dalle cifre della scomposizione in fattori primi dell'input, che è solo tutte le cifre ordinate in ordine decrescente. Per i numeri dati questo limite superiore è facilmente abbastanza piccolo da poter controllare in modo esaustivo ogni numero nell'intervallo per verificare se si tratta di un amico a fattore primo:

_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 byte

Codice:

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

Spiegazione:

Ò                  # 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

Utilizza la codifica CP-1252 . Provalo online!


4

Pyth, 17

LSjkPb-fqyTyQSs_y

Suite di test .

Utilizza la stessa osservazione del post di Martin .

Espansione:

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 byte

Modifica : è stato chiarito che un numero primo come 23 dovrebbe restituire [6] piuttosto un set di risultati vuoto. Ho salvato 5 byte rimuovendo una regola ormai inutile che - apposta - impediva che ciò accadesse.

L'ultimo caso di test viene commentato in modo che questo frammento venga eseguito abbastanza velocemente, anche se dovrebbe essere completato in meno di un minuto.

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 byte

potrebbe probabilmente essere più breve con un algoritmo che non è così dal libro.
(ma mi piace il conteggio dei byte corrente)

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

abbattersi

// 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

In realtà, 27 byte

Questo utilizza lo stesso algoritmo utilizzato da Martin , Adnan , FryAmTheEggman e Dennis . Suggerimenti di golf benvenuti. Provalo online!

`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 byte (versione 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)}

Nota: lo script risolve gli ultimi casi di test in meno di 3 minuti sul mio taccuino locale. Vedere la soluzione "prestazioni" di seguito.

Script di test meno golfato:

$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"
}

Produzione:

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 byte (versione "Performance")

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

Nota: credo che i requisiti di prestazione siano in conflitto con il principio GodeGolf. Ma poiché c'era una regola Your program should solve any of the test cases below in less than a minute, ho fatto due modifiche per soddisfare la regola:

  • -split'(.)'-ne''invece il codice funzione |% t*y;
  • una hashtable per incassare le stringhe.

Ogni modifica riduce della metà il tempo di valutazione. Per favore, non pensare di aver usato tutte le funzionalità per migliorare le prestazioni. Erano sufficienti quelli per soddisfare la regola.

Script di test meno golfato:

$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"
}

Produzione:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.