Redução de divisor

21

Um divisor de um número n é qualquer número que divida uniformemente n , incluindo 1 en . O número de divisores d (n) é quantos divisores um número possui. Aqui está d (n) para o primeiro casal n:

n    divisors    d(n)
1    1           1
2    1, 2        2
3    1, 3        2
4    1, 2, 4     3
5    1, 5        2
6    1, 2, 3, 6  4

Podemos subtrair repetidamente o número de divisores de um número. Por exemplo:

16                  = 16
16 - d(16) = 16 - 5 = 11
11 - d(11) = 11 - 2 = 9
 9 - d( 9) =  9 - 3 = 6
 6 - d( 6) =  6 - 4 = 2
 2 - d( 2) =  2 - 2 = 0

Nesse caso, foram necessárias 5 etapas para chegar a 0.


Escreva um programa ou função que, dado um número não negativo n, retorne o número de etapas necessárias para reduzi-lo a 0 por subtração repetida do número de divisores.

Exemplos:

0, 0
1, 1
6, 2
16, 5
100, 19
100000, 7534
orlp
fonte
5
Link obrigatório OEIS: A155043
Sp3000
Relacionado.
Martin Ender

Respostas:

1

Geléia, 10 9 bytes

1 byte graças a Dennis ♦ .

Porto da minha resposta em Pyth .

ÆDLạµÐĿL’

Experimente online!

Suíte de teste.

Explicação

_ÆDL$$ÐĿL’
      ÐĿ    Repeat the following until result no longer unique:
 ÆD             Yield the array of the divisors
   L            Yield the length of the array
_               Subtract that from the number
        L   Number of iterations
         ’  Minus one.
Freira Furada
fonte
6

Python, 49 bytes

f=lambda n:n and-~f(sum(n%~x<0for x in range(n)))

O orlp ajudou a salvar um byte! E o Sp3000 economizou mais dois. Obrigado!

Lynn
fonte
11
Deve ser capaz de encurtar as coisas movendo o -~para dentro n%-~ke removendo o limite inferior do intervalo.
Orlp 23/05
5

C, 52 bytes

g,o;l(f){for(g=o=f;o;f%o--||--g);return f?1+l(g):0;}
Lynn
fonte
4

Pitão, 10 bytes

tl.ulf%NTS

Suíte de teste.

Explicação

tl.ulf%NTS
tl.ulf%NTSNQ  implicit variables at the end
           Q  obtain the input number
  .u      N   repeat the following until result no longer unique:
         S        generate range from 1 to N
     f            filter for:
      %NT             T in that range, which N%T is truthy (not zero)
    l             length of that list
                  that means, we found the number of "non-divisors" of N
tl            number of iterations, minus 1.
Freira Furada
fonte
3

Julia, 31 bytes

f(n)=n<1?0:f(sum(n%(1:n).>0))+1

Implementação recursiva direta.

Sp3000
fonte
2

MATL , 14 bytes

`t~?x@q.]t:\zT

Experimente online!

Explicação

`            T  % Infinite loop
 t~?    ]       % Duplicate number. Is it non-zero?
    x@q.        % If so: delete number, push iteration index minus 1, break loop
         t:\    % Duplicate, range, modulo (remainder). Divisors give a 0 remainder
            z   % Number of non-zero elements; that is, of non-divisors
Luis Mendo
fonte
2

JavaScript (ES6), 64 51 bytes

f=n=>n&&[...Array(m=n)].map((_,i)=>m-=n%++i<1)|f(m)+1

Não me pergunte por que eu estava usando desnecessariamente a recursão da cauda.

Neil
fonte
2

Java, 147 93

a->{int k,i,n=new Integer(a),l=0;for(;n!=0;n-=k)for(l+=k=i=1;i<n;)if(n%i++==0)++k;return l;}
Esperançosamente útil
fonte
3
Por que ao n=new Integer(100000)invés de n=100000?
User8397947 de
1

05AB1E, 12 10 bytes

Código:

[Ð>#Ñg-¼]¾

Explicação:

[           # start infinite loop
 Ð          # triplicate current number
  >#        # increase by 1 and break if true
    Ñg      # get number of divisors
      -     # subtract number of divisors from number
       ¼    # increase counter
        ]   # end loop
         ¾  # print counter

Experimente online

Edit: 2 bytes salvos e um erro com a entrada 0 corrigido graças a @Adnan

Emigna
fonte
Muito agradável! Tentei golf um pouco, e tenho-o para baixo para 10 bytes: [Ð>#Ñg-¼]¾. Tem que haver uma maneira de obtê-lo mais curto embora ...
Adnan
@LuisMendo Sim, é porque a D0Q#parte é após o incremento do contador. O [Ð>#Ñg-¼]¾código deve funcionar 0embora :).
Adnan
@ Adnan: Tentei uma versão baseada na geração de todas as contagens até o índice e no valor no índice e na contagem, mas não consegui reduzi-lo dessa maneira.
Emigna
1

R, 50 bytes

Implementação bastante simples. Experimente online

z=scan();i=0;while(z>0){z=z-sum(z%%1:z<1);i=i+1};i
bouncyball
fonte
1

Mathcad, [tbd] bytes

insira a descrição da imagem aqui


O esquema de equivalência de bytes do Mathcad ainda está para ser determinado. Usando uma equivalência aproximada de pressionamento de tecla, o programa usa cerca de 39 "bytes". Observe que os operadores while e de programação levam apenas uma operação de teclado cada para inserir (ctl-] e ctl-shft- #, respectivamente) - na verdade, eles só podem ser inseridos dessa maneira a partir do teclado.

O que você vê é exatamente o que é colocado em uma planilha do Mathcad. O Mathcad avalia as equações / programas e coloca a saída na mesma folha (por exemplo, após o operador de avaliação '=' ou no gráfico).

Stuart Bruff
fonte
1

MATL, 13 bytes

tX`t:\ztt]Nq&

Experimente online

Explicação:

t               % Duplicate input
 X`      ]      % while loop, consumes 1 input
   t:\z         % calculates n-d(n), by counting number non-divisors
       tt       % dupe twice, for while loop condition, next iteration and to keep in stack
          Nq&   % get stack size, decrement, display that value
David
fonte
1

Mathematica, 35 bytes

If[#<1,0,#0[#-0~DivisorSigma~#]+1]&

Fazendo uso do bom e velho DivisorSigma. O @ MartinBüttner observa as seguintes alternativas:

If[#<1,0,#0[#-DivisorSum[#,1&]]+1]&
f@0=0;f@n_:=f[n-DivisorSum[n,1&]]+1
Sp3000
fonte
1

Hoon , 93 76 bytes

|=
r/@
?~
r
0
+($(r (sub r (lent (skim (gulf 1^r) |=(@ =(0 (mod r +<))))))))

Ungolfed:

|=  r/@
?~  r
  0
=+  (skim (gulf 1^r) |=(@ =(0 (mod r +<))))
+($(r (sub r (lent -))))

Retorna uma função que recebe um átomo r,. Crie um valor intermediário que contenha todos os desvisores de r(Make list [1..n], mantenha apenas os elementos em que (mod ri) ​​== 0). Se rfor zero, retorne zero, caso contrário, retorne o valor incrementado de recorrência com r igual a r- (divisores de comprimento).

O código como está leva uma quantidade estúpida de tempo para avaliar para n = 100.000, inteiramente porque encontrar os desvisores para grandes números faz uma lista gigante e mapeia sobre ele. Memoizar os divisores obtém a saída correta para n = 10.000, mas não me incomodei em esperar por 100.000

RenderSettings
fonte
1

Haskell, 43 40 39 bytes

g 0=0;g n=1+g(sum$min 1.mod n<$>[1..n])

Abordagem recursiva simples. Exemplo de uso: g 16-> 5.

Edit: @Lynn salvou 3 4 bytes. Obrigado!

nimi
fonte
Que tal g(sum$signum.mod n<$>[1..n])?
Lynn
Ah, e min 1é realmente um byte menor do que signum, mesmo
Lynn
1

PowerShell v2 +, 74 67 bytes

param($n)for($o=0;$n-gt0){$a=0;1..$n|%{$a+=!($n%$_)};$n-=$a;$o++}$o

Parece bastante demorado em comparação com algumas das outras respostas ...

Recebe entrada $n, entra em um forloop com a condição que $né maior que 0. Cada iteração de loop é definida como auxiliar e $a, em seguida, percorre todos os números de 1até $n. Cada loop interno é checado em relação a todos os números para ver se é um divisor e, nesse caso, incrementamos nosso auxiliar $a(usando negação booleana e conversão implícita implícita). Em seguida, subtraímos quantos divisores encontramos $n-=$ae incrementamos nosso contador $o++. Finalmente, nós produzimos $o.

Demora muito tempo para executar, pois é uma construção significativa para loop. Por exemplo, rodar n = 10,000na minha máquina (Core i5 de 1 ano) leva quase 3 minutos.

AdmBorkBork
fonte
1

Raquete - 126 bytes Até 98 bytes 91 bytes

Uma solução extremamente ingênua - provavelmente poderia ser reduzida com um algoritmo decente e alguns truques de cocô que eu não conheço

(define(g x[c 0][d 0][i 2])(cond[(= x 0)c][(= i x)(g d(+ 1 c))][(=(modulo x i)0)(g x c d(+ 1 i))][else(g x c(+ 1 d)(+ 1 i))]))

Editar: explicação por solicitação. Como eu disse, essa é uma solução recursiva extremamente ingênua e pode ser muito mais curta.

(define (g x [c 0] [d 0] [i 2]) ;g is the name of the function - arguments are x (input), c (counter for steps), d (non-divisor counter), i (iterator)
  (cond
    [(= x 0) c] ;once x gets to 0 c is outputted
    [(= i x) (g d (+ 1 c))] ;if iterator reaches x then we recurse with d as input and add 1 to c
    [(= (modulo x i) 0) (g x c d (+ 1 i))] ;checks if iterator is non divisor, then adds it to d and increments iterator
    [else(g x c (+ 1 d) (+ 1 i))])) ;otherwise just increments iterator

Editar versão 2: 98 bytes com um algoritmo menos burro (ainda bastante burro e pode ser mais curto)

(define(g x)(if(< x 1)0(+ 1(g(length(filter(λ(y)(>(modulo x y)0))(cdr(build-list x values))))))))

Explicação:

(define (g x) ;function name g, input x
  (if (< x 1)
      0 ;returns 0 if x < 1 (base case)
      (+ 1 ;simple recursion - adds 1 to output for each time we're looping
         (g (length ;the input we're passing is the length of... 
              (filter (λ (y) (> (modulo x y) 0)) ;the list where all numbers which are 0 modulo x are 0 are filtered out from...
                             (cdr (build-list x values)))))))) ;the list of all integers up to x, not including 0

Editar 3: salvou 7 bytes substituindo (cdr(build-list x values))por(build-list x add1)

(define(g x)(if(< x 1)0(+ 1(g(length(filter(λ(y)(>(modulo x y)0))(build-list x add1)))))))
kronicmage
fonte
Olá, e bem-vindo ao PPCG! Ótimo post! Você pode explicar sua solução, por favor? (PS Eu amo Lisp!)
NoOneIsHere
@NoOneIsHere Editado em
kronicmage
0

> <> , 52 + 2 = 54 bytes

O número de entrada precisa estar presente na pilha no início do programa, portanto, há +2 bytes para o -vsinalizador. Experimente online!

:0)?v~ln;>~$-]
03[}\::
@@:$<    v?=0:-1}+{~$?@@01%@:

4 bytes irritantes desperdiçados em questões de alinhamento. Bah.

Este funciona construindo a sequência de npara0 na pilha. Quando 0 for atingido, pop-lo e calcular o comprimento da pilha restante.

A propósito, ele corre no O(n^2)tempo, então eu não tentaria n = 100000...

Sok
fonte
-vé um byte, não dois.
NoOneIsHere
0

> <> , 36 + 3 = 39 bytes

:?v~ln; >~&
:}\0&
+&>1-:?!^:{:}$%0)&

A implementação é relativamente direta, com cada iteração sum(n%k>0 for k in range(1,n-1)). +3 bytes para o -vsinalizador, por meta .

Experimente online!

Sp3000
fonte
0

Ruby, 42 bytes

f=->n{n<1?0:1+f[n-(1..n).count{|i|n%i<1}]}

Há um erro de estouro de pilha no maior caso de teste 100000, então aqui está uma versão iterativa em 49 bytes . Demora um pouco, considerando a O(N^2)complexidade.

->n{c=0;c+=1 while 0<n-=(1..n).count{|i|n%i<1};c}
Value Ink
fonte
0

Perl 5, 40 bytes

sub f{@_?(1,f((1)x grep@_%$_,1..@_)):()}

Entrada e saída são como listas do número necessário de cópias de 1.

msh210
fonte
0

C #, 63 bytes

int F(int n)=>n<1?0:F(Enumerable.Range(1,n).Count(i=>n%i>0))+1;
RedLaser
fonte
0

Na verdade, 17 bytes

";╗R`╜%`░l;"£╬klD

Experimente online! (observação: o último caso de teste atinge o tempo limite no TIO)

Explicação:

";╗R`╜%`░l;"£╬klD
"          "£╬     while top of stack is truthy, call the function:
 ;╗                  push a copy of n to reg0
   R                 range(1,n+1) ([1,n])
    `  `░l             push the number of values where the following is truthy:
     ╜%                  k mod n
                       (this computes the number of non-divisors of n)
          ;            make a copy
              klD  push entire stack as list, count number of items, subtract 1
                   (the result is the number of times the function was called)
Mego
fonte