Redukcja dzielnika

21

Dzielnikiem liczby n jest dowolna liczba, która równomiernie dzieli n , w tym 1 i n samo. Liczba dzielników d (n) to liczba dzielników, które ma liczba. Oto d (n) dla pierwszej pary 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

Możemy wielokrotnie odejmować liczbę dzielników od liczby. Na przykład:

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

W tym przypadku zajęło 5 kroków, aby uzyskać 0.


Napisz program lub funkcję, która podając nieujemną liczbę n zwraca liczbę kroków, które należy wykonać, aby zmniejszyć ją do zera przez wielokrotne odejmowanie liczby dzielników.

Przykłady:

0, 0
1, 1
6, 2
16, 5
100, 19
100000, 7534
orlp
źródło
5
Obowiązkowe łącze OEIS: A155043
Sp3000
Związane z.
Martin Ender

Odpowiedzi:

1

Galaretka, 10 9 bajtów

1 bajt dzięki Dennisowi ♦ .

Port mojej odpowiedzi w Pyth .

ÆDLạµÐĿL’

Wypróbuj online!

Zestaw testowy.

Wyjaśnienie

_Æ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.
Leaky Nun
źródło
6

Python, 49 bajtów

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

orlp pomógł uratować bajt! Sp3000 zaoszczędził jeszcze dwa. Dzięki!

Lynn
źródło
1
Powinien być w stanie skrócić rzeczy, przesuwając -~do n%-~ki usuwając dolną granicę zakresu.
lub
5

C, 52 bajty

g,o;l(f){for(g=o=f;o;f%o--||--g);return f?1+l(g):0;}
Lynn
źródło
4

Pyth, 10 bajtów

tl.ulf%NTS

Zestaw testowy.

Wyjaśnienie

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.
Leaky Nun
źródło
3

Julia, 31 bajtów

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

Prosta implementacja rekurencyjna.

Sp3000
źródło
2

MATL , 14 bajtów

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

Wypróbuj online!

Wyjaśnienie

`            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
źródło
2

JavaScript (ES6), 64 51 bajtów

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

Nie pytaj mnie, dlaczego niepotrzebnie korzystałem z rekurencji ogona.

Neil
źródło
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;}
Mam nadzieję, że jest pomocna
źródło
3
Dlaczego n=new Integer(100000)zamiast n=100000?
user8397947
1

05AB1E, 12 10 bajtów

Kod:

[Ð>#Ñg-¼]¾

Wyjaśnienie:

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

Wypróbuj online

Edycja: 2 bajty zapisane i błąd z wejściem 0 naprawiony dzięki @Adnan

Emigna
źródło
Bardzo dobrze! Próbowałem go trochę w golfa, a dostał go w dół do 10 bajtów: [Ð>#Ñg-¼]¾. Musi istnieć sposób, aby go skrócić ...
Adnan
@LuisMendo Tak, to dlatego, że D0Q# część jest za przyrostem licznika. [Ð>#Ñg-¼]¾Kod powinien pracować 0chociaż :).
Adnan
@Adnan: Próbowałem wersji opartej na generowaniu wszystkich zliczeń do n i przechodzeniu od indeksu do wartości przy indeksie i zliczaniu, ale nie udało mi się skrócić go w ten sposób.
Emigna
1

R, 50 bajtów

Dość prosta implementacja. Wypróbuj online

z=scan();i=0;while(z>0){z=z-sum(z%%1:z<1);i=i+1};i
Odbijająca się piłka
źródło
1

Mathcad, [tbd] bajty

enter image description here


Schemat równoważności bajtów Mathcada nie został jeszcze ustalony. Korzystając z przybliżonej równoważności klawiszy, program używa około 39 „bajtów”. Zauważ, że operatorzy while i dla programowania wykonują tylko jedną operację klawiatury, aby wprowadzić (odpowiednio ctl-] i ctl-shft- #) - w rzeczywistości można je wprowadzić tylko z klawiatury.

To, co widzisz, jest dokładnie tym, co zostaje zapisane w arkuszu Mathcad. Mathcad ocenia równania / programy i umieszcza dane wyjściowe na tym samym arkuszu (np. Za operatorem oceny „=” lub na wykresie).

Stuart Bruff
źródło
1

MATL, 13 bajtów

tX`t:\ztt]Nq&

Wypróbuj online

Wyjaśnienie:

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
źródło
1

Mathematica, 35 bajtów

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

Wykorzystując stare dobre DivisorSigma. @ MartinBüttner zauważa następujące alternatywy:

If[#<1,0,#0[#-DivisorSum[#,1&]]+1]&
f@0=0;f@n_:=f[n-DivisorSum[n,1&]]+1
Sp3000
źródło
1

Hoon , 93 76 bajtów

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

Nie golfowany:

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

Zwraca funkcję, która pobiera atomu r. Utwórz wartość pośrednią, która zawiera wszystkich twórców r(Make list [1..n], zachowaj tylko te elementy, gdzie (mod ri) ​​== 0). Jeśli rzero wynosi zero, w przeciwnym razie zwraca wartość przyrostu rekurencji z r równym r- (dzielniki długości).

Kod „tak jak jest” zajmuje głupią ilość czasu na ocenę n = 100 000, całkowicie dlatego, że znalezienie twórców dużych liczb tworzy ogromną listę i mapy nad nią. Zapamiętywanie dzielników daje prawidłową moc wyjściową dla n = 10.000, ale nie zawracałem sobie głowy czekaniem na 100.000

RenderSettings
źródło
1

Haskell, 43 40 39 bajtów

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

Proste podejście rekurencyjne. Przykład użycia: g 16-> 5.

Edycja: @ Lynn zapisał 3 4 bajty. Dzięki!

nimi
źródło
Jak o g(sum$signum.mod n<$>[1..n])?
Lynn
Aha, i min 1jest o jeden bajt krótszy niż signumnawet
Lynn
1

PowerShell v2 +, 74 67 bajtów

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

Wydaje się dość długi w porównaniu do niektórych innych odpowiedzi ...

Pobiera dane wejściowe $n, wchodzi w forpętlę z warunkiem $nwiększym niż 0. W każdej iteracji pętli ustawiamy pomocnika $a, a następnie zapętlamy każdą liczbę od 1do $n. Każdą wewnętrzną pętlę sprawdzamy względem każdej liczby, aby sprawdzić, czy jest to dzielnik, a jeśli tak, zwiększamy naszego pomocnika $a(używając logicznej negacji i niejawnego rzutowania na int). Następnie odejmujemy liczbę znalezionych dzielników $n-=$ai zwiększamy licznik $o++. Wreszcie produkujemy $o.

Wykonanie zajmuje dużo czasu, ponieważ jest to znacząca konstrukcja dla pętli for. Na przykład uruchomienie n = 10,000na moim komputerze (1-letni Core i5) zajmuje prawie 3 minuty.

AdmBorkBork
źródło
1

Rakieta - 126 bajtów Do 98 bajtów 91 bajtów

Niezwykle naiwne rozwiązanie - prawdopodobnie można by je znacznie ograniczyć dzięki porządnemu algorytmowi i niektórym sztuczkom seplenienia, których nie znam

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

Edycja: wyjaśnienie na żądanie. Jak powiedziałem, jest to wyjątkowo naiwne rozwiązanie rekurencyjne i może być znacznie krótsze.

(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

Edytuj wersję 2: 98 bajtów z mniej głupim algorytmem (wciąż dość głupi i może być krótszy)

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

Wyjaśnienie:

(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

Edycja 3: Zapisano 7 bajtów, zastępując (cdr(build-list x values))je(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
źródło
Witaj i witaj w PPCG! Wspaniały post! Czy możesz wyjaśnić swoje rozwiązanie? (PS Kocham Lisp!)
NoOneIsHere
@NoOneIsHere Edytowano w
kronicmage
0

> <> , 52 + 2 = 54 bajtów

Numer wejściowy musi być obecny na stosie przy starcie programu, więc jest +2 bajty dla -vflagi. Wypróbuj online!

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

4 irytujące bajty zmarnowane na problemy z wyrównaniem. Bah.

Ten działa poprzez budowanie sekwencji od ndo 0na stosie. Po osiągnięciu 0, wciśnij go i wypisz długość pozostałego stosu.

Nawiasem mówiąc, działa w O(n^2)czasie, więc nie próbowałbym n = 100000...

Sok
źródło
-vto jeden bajt, a nie dwa.
NoOneIsHere
0

> <> , 36 + 3 = 39 bajtów

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

Implementacja jest stosunkowo prosta, z każdą iteracją sum(n%k>0 for k in range(1,n-1)). +3 bajty dla-v flagi na meta .

Wypróbuj online!

Sp3000
źródło
0

Rubin, 42 bajty

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

Wystąpił błąd przepełnienia stosu w największym przypadku testowym 100000, więc oto iteracyjna wersja w obrębie 49 bajtów . Jednak zajmuje to trochę czasu, biorąc pod uwagę O(N^2)złożoność.

->n{c=0;c+=1 while 0<n-=(1..n).count{|i|n%i<1};c}
Wartość tuszu
źródło
0

Perl 5, 40 bajtów

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

Dane wejściowe i wyjściowe są listami wymaganej liczby kopii 1.

msh210
źródło
0

C #, 63 bajty

int F(int n)=>n<1?0:F(Enumerable.Range(1,n).Count(i=>n%i>0))+1;
RedLaser
źródło
0

Właściwie 17 bajtów

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

Wypróbuj online! (uwaga: limit czasu ostatniego testu w TIO)

Wyjaśnienie:

";╗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
źródło