Fatorações parciais de um número inteiro positivo


23

Uma coleção de números inteiros positivos d_1 d_2 ... d_ké uma fatoração de um número inteiro positivo nse

d_1 * d_2 * ... * d_k = n

Cada número inteiro positivo possui uma fatoração primária única , mas em geral eles também possuem fatorações nas quais alguns dos termos são compostos. Por exemplo

12 = 6 * 2 = 4 * 3 = 3 * 2 * 2

Escreva um programa, função, verbo ou similar que tenha como entrada um único número inteiro positivo e retorne ou imprima uma lista completa de suas fatorações distintas. As fatorações podem ser produzidas em qualquer ordem, e seus termos podem estar em qualquer ordem, mas não duas devem ser permutações uma da outra. As fatorações podem não incluir 1duas exceções: para entrada, nvocê pode fornecer a fatoração em n*1vez de n; e para entrada, 1você pode dar a fatoração em 1vez da lista vazia.

Você pode assumir que a entrada estará no intervalo de um número inteiro de 32 bits assinado. Se a saída for como uma sequência, deve haver uma distinção clara entre a delimitação de números dentro de uma fatoração e a delimitação das fatorações, mas não é necessário (por exemplo) que os fatores sejam unidos a um *.

Seu código deve ser capaz de lidar com qualquer entrada válida em 10 minutos em uma máquina de desktop razoável.

Exemplos

1                  [[]]
                or [[1]]
                or [[1 1]]

7                  [[7]]
                or [[7 1]]
                or [[1 7]]

12                 [[12] [6 2] [4 3] [2 3 2]]
                or variants

16                 [[2 2 2 2] [2 2 4] [2 8] [4 4] [16]]
                or variants

901800900          a list of 198091 factorisations

1338557220         a list of 246218 factorisations

Você pode postar a lista de fatorações 901800900e em 1338557220algum lugar onde podemos verificá-las? Meu código está me fornecendo 2048 e 1024 fatorações para esses números, respectivamente, e não sei por que.
Sherlock9

@ Sherlock9, fará isso quando eu chegar em casa. O que posso fazer com um gerador on-line é fornecer uma saída válida para 5336100 .
Peter Taylor

3
Isso me lembra um desafio do ProjectEuler (infelizmente não me lembro qual). Mas era preciso contar o número de fatorações em vez de listá-las.
flawr

OEIS relacionado: A001055
Sherlock9

Respostas:


12

Haskell, 56 bytes

_!1=[[]]
i!n=[j:f|j<-[i..n],mod n j<1,f<-j!div n j]
(2!)

(2!)(1338557220::Int)imprime em cinco minutos no meu laptop, quando compilado ghc -O3.

Haskell, 62 bytes, mas muito mais rápido

i!n|i*i>n=[[n]]|0<1=[i:f|mod n i<1,f<-i!div n i]++(i+1)!n
(2!)

(2!)(1338557220::Int)imprime em um quarto de segundo no meu laptop, quando compilado ghc -O3.


Como faço para testar isso? ghcdá-me Parse error: naked expression at top levele ghcidá-meparse error on input `='
Peter Taylor

@PeterTaylor Substitua a função (2!) pelo programa main = print ((2!) (1338557220::Int)), compile com ghc -O3 factor.hse execute com ./factor.
Anders Kaseorg 29/07

7

Pitão, 29 bytes

Msam+Ldgd/Hdf!%HT>S@H2tG]]Hg2

M                                def g(G, H):
                   @H2             square root of H
                  S                1-indexed range up to floor
                 >    tG           all but first G − 1 elements
            f                      filter for elements T such that:
              %HT                    H mod T
             !                       is false (0)
   m                               map for elements d:
       gd/Hd                         g(d, H/d)
    +Ld                              prepend d to each element
  a                     ]]H        append [[H]]
 s                                 concatenate
                           g2Q   print g(2, input)

Experimente online

É executado em vinte segundos 1338557220no meu laptop.


@PeterTaylor A maneira usual: pyth factor.pyth(ou pyth -c 'Msam+Ldgd/Hdf!%HT>S@H2tG]]Hg2'), fornecendo 16stdin. Verifique se você está usando uma versão atual do Pyth; implícito Qfoi adicionado em março. Não consigo imaginar como você pode estar conseguindo a divisão por zero, no entanto.
Anders Kaseorg 29/07

Arrrrgh. Eu estava usando em "vez de ', e bash estava expandindo o !%para outra coisa.
Peter Taylor

6

Python , 252 313 312 311 145 141 137 135 103 84 83 bytes

Isso se baseia amplamente na resposta Pyth de Anders Kaseorg . Todas as sugestões de golfe são bem-vindas. Experimente online!

Edit: 19 bytes jogados de golfe graças a Dennis. Corrigido um erro de digitação no código e adicionado um link TIO.

g=lambda n,m=2:[[n]]+[j+[d]for d in range(m,int(n**.5)+1)if n%d<1for j in g(n/d,d)]

Ungolfed:

def g(n, m=2):
    a = [[n]]
    s = int(n**.5) + 1
    for d in range(m, s):
        if n%d == 0:
            for j in g(n/d, d):
                a.append([d]+j)
    return a

1
**.5se livra da importação.
Dennis

4

JavaScript (ES6), 83 bytes

f=(n,a=[],m=2,i=m)=>{for(;i*i<=n;i++)n%i<1&&f(n/i,[...a,i],i);console.log(...a,n)}

Apenas emprestei o truque de raiz quadrada do @ AndersKaseorg porque acabou me salvando bytes em geral. Imprime 1para uma entrada de 1, caso contrário, não imprime 1s.


1

Ruby 1.9+, 87 89 87 bytes

Esta resposta é baseada na resposta Pyth de Anders Kaseorg . Esse código funciona apenas para versões após o Ruby 1.9, já que as lambdas stabby ->foram introduzidas apenas no 1.9. Todas as sugestões de golfe são bem-vindas.

g=->n,m=2{(m..Math.sqrt(n)).select{|i|n%i<1}.flat_map{|d|g[n/d,d].map{|j|[d]+j}}+[[n]]}

Ungolfed:

def g(n, m=2)
  a = [[n]]
  s = (m..Math.sqrt(n))
  t = s.select{|i|n%i<1}
  t.each do |d|
    g[n/d,d].each do |j|
      a.push([d]+j)
    end
  end
  return a
end

Isso requer uma versão específica do Ruby? Com 1.8.7, recebo uma reclamação sobre g[n/d,d]:wrong number of arguments (0 for 1)
Peter Taylor

Aparentemente, lambdas stabby ->foram introduzidas no Ruby 1.9. Vou editar a resposta para mostrar o número da versão necessária.
Sherlock9

Ok obrigado. Ainda estou curioso g[n/d,d]. g(n/d,d)é mais compatível com versões anteriores.
Peter Taylor

1
Ah, f[n]é necessário chamar lambdas stabby e ruby ​​lambdas em geral. f(n)e f nchamadas exigem defe end. Mais informações aqui e aqui
Sherlock9

1

J, 52 bytes

[:~.q:<@/:~@(*//.)"$~#@q:_&(;@]<@(,~"{~0,#\@~.)"1)}:

Não é tão eficiente quanto poderia ser, pois algumas fatorações podem ser repetidas e uma passagem final deve ser feita após a classificação de cada fatoração e a eliminação da duplicação.

Experimente online! (Mas tente manter os valores de entrada pequenos).

Na minha área de trabalho, os horários são

   f =: [:~.q:<@/:~@(*//.)"$~#@q:_&(;@]<@(,~"{~0,#\@~.)"1)}:
   timex 'r =: f 1338557220'
3.14172
   # r
246218
   timex 'r =: f 901800900'
16.3849
   # r
198091

Explicação

Esse método depende da geração de todas as partições definidas para os fatores primos do número inteiro de entrada n . O desempenho é melhor quando n é livre de quadrados, caso contrário, fatorações duplicadas serão criadas.

[:~.q:<@/:~@(*//.)"$~#@q:_&(;@]<@(,~"{~0,#\@~.)"1)}:  Input: integer n
                                                  }:  Curtail, forms an empty array
                       q:                             Prime factorization
                     #@                               Length, C = count prime factors
                         _&(                     )    Repeat that many times on x = []
                                 (            )"1       For each row
                                            ~.            Unique
                                         #\@              Enumerate starting at 1
                                       0,                 Prepend 0
                                  ,~"{~                   Append each of those to a
                                                          copy of the row
                               <@                         Box it
                            ;&]                         Set x as the raze of those boxes
                                                      These are now the restricted growth
                                                      strings of order C
    q:                                                Prime factorization
            (    )"$~                                 For each RGS
               /.                                       Partition it
             */                                         Get the product of each block
        /:~@                                            Sort it
      <@                                                Box it
[:~.                                                  Deduplicate
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.