Riduzione del divisore


21

Un divisore di un numero n è qualsiasi numero che divide uniformemente n , includendo 1 e n stesso. Il numero di divisori d (n) è quanti divisori ha un numero. Ecco d (n) per la prima coppia 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

Possiamo sottrarre ripetutamente il numero di divisori da un numero. Per esempio:

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

In questo caso sono stati necessari 5 passaggi per arrivare a 0.


Scrivi un programma o una funzione che, dato un numero non negativo n, restituisca il numero di passaggi necessari per ridurlo a 0 ripetendo la sottrazione del numero di divisori.

Esempi:

0, 0
1, 1
6, 2
16, 5
100, 19
100000, 7534

5
Collegamento OEIS obbligatorio: A155043
Sp3000,

Risposte:



6

Python, 49 byte

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

orlp ha contribuito a salvare un byte! E Sp3000 ne ha salvati altri due. Grazie!


1
Dovrebbe essere in grado di accorciare le cose spostando -~in n%-~ke rimuovendo il limite inferiore dell'intervallo.
orlp,

5

C, 52 byte

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

4

Pyth, 10 byte

tl.ulf%NTS

Suite di test.

Spiegazione

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.

3

Julia, 31 byte

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

Semplice implementazione ricorsiva.


2

MATL , 14 byte

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

Provalo online!

Spiegazione

`            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

2

JavaScript (ES6), 64 51 byte

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

Non chiedermi perché stavo usando inutilmente la ricorsione della coda.


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

3
Perché n=new Integer(100000)invece di n=100000?
user8397947

1

05AB1E, 12 10 byte

Codice:

[Ð>#Ñg-¼]¾

Spiegazione:

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

Provalo online

Modifica: 2 byte salvati e un bug con input 0 corretto grazie a @Adnan


Molto bella! Ho cercato di golf un po ', e ottenuto fino a 10 byte: [Ð>#Ñg-¼]¾. Ci deve essere un modo per accorciarlo però ...
Adnan,

@LuisMendo Sì, è perché la D0Q#parte è dopo l'incremento del contatore. Il [Ð>#Ñg-¼]¾codice dovrebbe funzionare 0anche se :).
Adnan,

@Adnan: ho provato una versione basata sulla generazione di tutti i conteggi fino a n, passando da un indice all'altro e indicando il conto alla rovescia, ma non sono riuscito ad accorciarlo in quel modo.
Emigna,


1

Mathcad, [tbd] byte

enter image description here


Lo schema di equivalenza dei byte di Mathcad deve ancora essere determinato. Utilizzando una grossolana equivalenza di battitura, il programma utilizza circa 39 "byte". Si noti che gli operatori while e per la programmazione eseguono solo un'operazione da tastiera ciascuna per immettere (ctl-] e ctl-shft- #, rispettivamente) - in effetti, possono essere immessi in questo modo solo dalla tastiera.

Quello che vedi è esattamente ciò che viene messo su un foglio di lavoro di Mathcad. Mathcad valuta le equazioni / i programmi e inserisce l'output sullo stesso foglio (ad esempio, dopo l'operatore di valutazione '=' o sul diagramma).


1

MATL, 13 byte

tX`t:\ztt]Nq&

Provalo online

Spiegazione:

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

1

Mathematica, 35 byte

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

Facendo uso del buon vecchio DivisorSigma. @ MartinBüttner osserva le seguenti alternative:

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

1

Hoon , 93 76 byte

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

Restituisce una funzione che riceve un atomo, r. Crea un valore intermedio che contenga tutti i progettisti di r(Crea elenco [1..n], mantieni solo gli elementi in cui (mod ri) ​​== 0). Se rè zero restituisce zero, altrimenti restituisce il valore incrementato della ricorrenza con r uguale r- (divisori di lunghezza).

Il codice così com'è richiede una stupida quantità di tempo per valutare n = 100.000, interamente perché trovare i progettisti di grandi numeri fa un elenco gigante e li mappa su di esso. Memorizzare i divisori ottiene l'output corretto per n = 10.000, ma non mi sono preoccupato di aspettare 100.000


1

Haskell, 43 40 39 byte

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

Semplice approccio ricorsivo. Esempio di utilizzo: g 16-> 5.

Modifica: @Lynn ha salvato 3 4 byte. Grazie!


Che ne dici g(sum$signum.mod n<$>[1..n])?
Lynn,

Oh, ed min 1è in realtà un byte più corto di signum, persino
Lynn,

1

PowerShell v2 +, 74 67 byte

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

Sembra piuttosto lungo rispetto ad alcune delle altre risposte ...

Accetta input $n, entra in un forloop con la condizione che $nè maggiore di 0. Ogni iterazione di loop che impostiamo helper $a, quindi cicla attraverso ogni numero 1fino a $n. Ogni ciclo interno controlliamo contro ogni numero per vedere se è un divisore e in tal caso incrementiamo il nostro helper $a(usando la negazione booleana e il cast implicito). Quindi, sottraggiamo quanti divisori abbiamo trovato $n-=$ae incrementiamo il nostro contatore $o++. Alla fine, abbiamo prodotto $o.

L' esecuzione richiede molto tempo, poiché è un costrutto for-loop significativo. Ad esempio, l'esecuzione n = 10,000sulla mia macchina (1 anno di età Core i5) richiede quasi 3 minuti.


1

Racchetta: 126 byte Fino a 98 byte 91 byte

Una soluzione estremamente ingenua - potrebbe probabilmente essere ridotta molto con un algoritmo decente e alcuni trucchi lisp che non conosco

(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))]))

Modifica: spiegazione su richiesta. Come ho detto, questa è una soluzione ricorsiva estremamente ingenua e può essere molto più breve.

(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

Modifica la versione 2: 98 byte con un algoritmo meno stupido (comunque piuttosto stupido e può essere più breve)

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

Spiegazione:

(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

Modifica 3: salvato 7 byte sostituendo (cdr(build-list x values))con(build-list x add1)

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

Ciao e benvenuto in PPCG! Ottimo post! Puoi spiegare la tua soluzione per favore? (PS I love Lisp!)
NoOneIsHere

@NoOneIsHere modificato in
kronicmage

0

> <> , 52 + 2 = 54 byte

Il numero di input deve essere presente nello stack all'avvio del programma, quindi ci sono +2 byte per il -vflag. Provalo online!

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

4 byte fastidiosi sprecati per problemi di allineamento. Bah.

Questo funziona costruendo la sequenza da na 0nello stack. Una volta che è stato raggiunto 0, aprilo e ottieni la lunghezza dello stack rimanente.

A proposito, corre in O(n^2)tempo, quindi non proverei n = 100000...


-vè un byte, non due.
NoOneIsHere

0

> <> , 36 + 3 = 39 byte

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

L'implementazione è relativamente semplice, essendo ogni iterazione sum(n%k>0 for k in range(1,n-1)). +3 byte per la -vbandiera, per meta .

Provalo online!


0

Rubino, 42 byte

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

C'è un errore di overflow dello stack nel caso di test più grande 100000, quindi ecco una versione iterativa entro 49 byte . Ci vuole un po ', però, considerando ilO(N^2) complessità.

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

0

Perl 5, 40 byte

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

L'input e l'output sono come elenchi del numero richiesto di copie di 1.


0

C #, 63 byte

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

0

In realtà, 17 byte

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

Provalo online! (nota: l'ultimo caso di test scade sul TIO)

Spiegazione:

";╗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)
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.