Quantas etapas são necessárias de n para 1 subtraindo o maior divisor?


50

Inspirado por esta pergunta em Matemática .


O problema

Let nSer um número natural ≥ 2. Pegue o maior divisor de n- que é diferente de nsi mesmo - e subtraia-o de n. Repita até você chegar 1.

A questão

Quantas etapas são necessárias para alcançar 1um determinado número n ≥ 2.

Exemplo Detalhado

Let n = 30.

O maior divisor de:

1.   30 is 15  -->  30 - 15 = 15
2.   15 is  5  -->  15 -  5 = 10
3.   10 is  5  -->  10 -  5 =  5
4.    5 is  1  -->   5 -  1 =  4
5.    4 is  2  -->   4 -  2 =  2
6.    2 is  1  -->   2 -  1 =  1

São necessários 6 passos para chegar 1.

Entrada

  • Entrada é um número inteiro n, onde n ≥ 2.
  • Seu programa deve oferecer suporte até o valor inteiro máximo do idioma.

Resultado

  • Basta imprimir o número de etapas, como 6.
  • Espaços em branco à esquerda / à direita ou novas linhas são bons.

Exemplos

f(5)        --> 3
f(30)       --> 6
f(31)       --> 7
f(32)       --> 5
f(100)      --> 8
f(200)      --> 9
f(2016^155) --> 2015

Exigências

  • Você pode obter entrada de STDINargumentos de linha de comando, como parâmetros de função ou do equivalente mais próximo.
  • Você pode escrever um programa ou uma função. Se for uma função anônima, inclua um exemplo de como invocá-la.
  • Este é o pelo que a resposta mais curta em bytes vence.
  • As brechas padrão não são permitidas.

Esta série também pode ser encontrada no OEIS: A064097

Um quase-logaritmo definido indutivamente por a(1) = 0e a(p) = 1 + a(p-1)se pé primo e a(n*m) = a(n) + a(m)se m,n > 1.


esclarecer o requisito de entrada em idiomas com números inteiros de precisão arbitrários?
Sparr

@ Sparr eu diria, você deve pelo menos apoiar-se 2^32 - 1. O resto é com você e seu sistema. Espero que seja isso que você quis dizer com sua pergunta.
insertusernamehere

3
Eu gosto de como o título resume tudo
Luis Mendo

Respostas:


20

Geléia , 9 bytes

ÆṪÐĿÆFL€S

Experimente online! ou verifique todos os casos de teste .

fundo

A definição da sequência A064097 implica que

definição

Pela fórmula do produto de Euler

Fórmula do produto de Euler

onde φ denota a função totiente de Euler ep varia apenas sobre os números primos.

Combinando ambos, deduzimos a propriedade

primeira propriedade

onde ω denota o número de fatores primos distintos de n .

Aplicando o resultante fórmula k + 1 vezes, onde k é grande o suficiente de modo que φ k + 1 (n) = 1 , obtemos

segunda propriedade

A partir dessa propriedade, obtemos a fórmula

Fórmula

onde a última igualdade é válida porque ω (1) = 0 .

Como funciona

ÆṪÐĿÆFL€S  Main link. Argument: n

  ÐĿ       Repeatedly apply the link to the left until the results are no longer
           unique, and return the list of unique results.
ÆṪ           Apply Euler's totient function.
           Since φ(1) = 1, This computes φ-towers until 1 is reached.
    ÆF     Break each resulting integer into [prime, exponent] pairs.
      L€   Compute the length of each list.
           This counts the number of distinct prime factors.
        S  Add the results.

Agora essa é uma abordagem super inteligente!
Abr001am

15

05AB1E , 13 11 bytes

Código:

[DÒ¦P-¼D#]¾

Explicação:

[        ]   # An infinite loop and...
       D#        break out of the loop when the value is equal to 1.
 D           # Duplicate top of the stack (or in the beginning: duplicate input).
  Ò          # Get the prime factors, in the form [2, 3, 5]
   ¦         # Remove the first prime factor (the smallest one), in order to get 
               the largest product.
    P        # Take the product, [3, 5] -> 15, [] -> 1.
     -       # Substract from the current value.
      ¼      # Add one to the counting variable.
          ¾  # Push the counting variable and implicitly print that value.

Usa a codificação CP-1252 . Experimente online! .


13
Remova o primeiro fator primo (o menor), a fim de obter o maior produto Que inteligente! :-)
Luis Mendo

Eu vejo, você é o desenvolvedor de linguagem
Sarge Borsch

@SargeBorsch Sim, isso é correto :)
Adnan

[¼Ñü-¤ÄD#]¾- Eu estava perto de raspar um byte com o par, oh bem ...
Magic Octopus Urn

-1 byte: [Ð#Ò¦P-¼]¾. Ðé melhor que DD.
Grimmy

11

Pitão, 11 bytes

fq1=-Q/QhPQ

Suíte de teste

Um loop direto de repetição até a verdade.

Explicação:

fq1=-Q/QhPQ
               Implicit: Q = eval(input())
f              Apply the following function until it is truthy,
               incrementing T each time starting at 1:
         PQ    Take the prime factorization of Q
        h      Take its first element, the smallest factor of Q
      /Q       Divide Q by that, giving Q's largest factor
    -Q         Subtract the result from Q
   =           Assign Q to that value
 q1            Check if Q is now 1.

esse é um truque muito legal com o ffiltro.
Maltysen

3
Não entendo por que isso gera o número de vezes que a função foi executada. Esse é um recurso não documentado f?
CorsiKa

@corsiKa fsem um segundo argumento itera sobre todos os números inteiros positivos a partir de 1e retorna o primeiro valor que é verdadeiro na instrução interna. Esse valor não é usado neste programa, portanto, ele retorna o número de vezes que foi executado. Não documentado, apenas não ortodoxo :) Se ajudar, você pode pensar nisso como um forloop como:for(int i=1; some_condition_unrelated_to_i; i++) { change_stuff_that_affects_condition_but_not_i;}
FryAmTheEggman

@corsiKa Está documentado na referência de personagem no lado direito do intérprete online. Com apenas um argumento ( f <l:T> <none>), fé a primeira entrada em que A(_)acabou[1, 2, 3, 4...] .
Dennis

Ah, eu entendo agora. Ele usa essa entrada, mas nunca usa a entrada no cálculo . Isso explica o comentário de @Maltysen sobre "esse é um truque muito bom", porque você se importa apenas com a contagem de iterações que não usa essa contagem em nenhum lugar do filtro. Eu amo esses momentos ah-ha !:)
corsiKa

7

Python 2, 50 49 bytes

f=lambda n,k=1:2/n or n%(n-k)and f(n,k+1)or-~f(k)

Isso não vai terminar o último caso de teste tão cedo ...

Como alternativa, aqui está um 48 bytes que retorna em Truevez de 1para n=2:

f=lambda n,k=1:n<3or n%(n-k)and f(n,k+1)or-~f(k)

6

Gelatina , 10 bytes

ÆfḊPạµÐĿi2

Experimente online! ou verifique a maioria dos casos de teste . Os últimos casos de teste são concluídos rapidamente localmente.

Como funciona

ÆfḊPạµÐĿi2  Main link. Argument: n (integer)

Æf          Factorize n, yielding a list of primes, [] for 1, or [0] for 0.
  Ḋ         Dequeue; remove the first (smallest) element.
   P        Take the product.
            This yields the largest proper divisor if n > 1, 1 if n < 2.
    ạ       Yield the abs. value of the difference of the divisor (or 1) and n.
     µ      Convert the chain to the left into a link.
      ÐĿ    Repeatedly execute the link until the results are no longer unique.
            Collect all intermediate results in a list.
            For each starting value of n, the last results are 2 -> 1 -> 0 (-> 1).
        i2  Compute the 1-based index of 2.

5

Retina , 12

  • 14 bytes salvos graças a @ MartinBüttner
(1 +) (? = \ 1 + $)

Isso pressupõe a entrada dada em unário e a saída fornecida em decimal. Se isso não for aceitável, podemos fazer isso por mais 6 bytes:

Retina , 18

  • 8 bytes salvos graças a @ MartinBüttner
. +
$ *
(1 +) (? = \ 1 + $)

Experimente online - 1ª linha adicionada para executar todos os casos de teste de uma só vez.

Infelizmente, isso é unário para os cálculos, portanto, a entrada de 2016 155 não é prática.

  • O primeiro estágio (2 linhas) simplesmente converte a entrada decimal em unária como uma sequência de 1s
  • O segundo estágio (1 linha) calcula o maior fator de n usando grupos correspondentes de regex e olha para trás e efetivamente o subtrai de n. Esse regex corresponderá ao número de vezes necessário para reduzir o número o máximo possível. O número de correspondências de regex será o número de etapas e é gerado neste estágio.

Eu não acho que você precise do \b.
Martin Ender


@ MartinBüttner Fantastic! Muito elegante - obrigado!
Digital Trauma

5

Pitão - 15 14 13 bytes

Invólucro especial 1está realmente me matando.

tl.u-N/Nh+PN2

Experimente online aqui .

tl                One minus the length of
 .u               Cumulative fixed point operator implicitly on input
  -N              N -
   /N             N /
    h             Smallest prime factor
     +PN2         Prime factorization of lambda var, with two added to work with 1

11
Uma coisa que eu sempre esqueço .... força bruta é muitas vezes a abordagem golfiest
Leaky Nun

O que você quer dizer com revestimento especial 1?
Adnan

11
@ Adnan, a principal fatoração de 1é [], o que causa um erro quando pego o primeiro elemento. Eu tenho um caso especial para fazê-lo retornar 1novamente, para que o .uponto fixo termine. Eu encontrei uma maneira melhor do que .xtentar, exceto que é o que me salvou esses 2 bytes.
Maltysen

Ele só precisa aceitar números> = 2 (> 1).
Solomon Ucko

@SolomonUcko você está entendendo mal, o .uponto fixo acabará alcançando 1todas as informações, e nesse ponto terá que ser revestido de maneira especial.
Maltysen

5

JavaScript (ES6), * 44 38

Editar 6 bytes salvos graças a l4m2

(* 4 marcado ainda é 4)

Função recursiva

f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0

Menos golfe

f=(n, d=n-1)=>{
  if (n>1)
    if(n % d != 0)
      return f(n, d-1) // same number, try a smaller divisor
    else
      return f(n-d)+1  // reduce number, increment step, repeat
  else
    return 0
}

Teste

f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0

console.log=x=>O.textContent+=x+'\n';

[5,30,31,32,100,200].forEach(x=>console.log(x+' -> '+f(x)))
<pre id=O></pre>


Bom, mas eu acho que você deve gastar os dois bytes necessários para fazer f (1) == 0.
Neil

@ Neil pensando novamente: não. "Seja n um número natural ≥ 2 ..."
edc65 11/11/16

Eu preciso de novos óculos.
Neil

Por que não f=(n,d=n)=>n>1?n%--d?f(n,d):f(n-d)+1:0?
L4m2 13/04/19

@ l4m2 certo, por que não? Graças
edc65

4

Mathematica, 36 bytes

f@1=0;f@n_:=f[n-Divisors[n][[-2]]]+1

Uma função sem nome usa os mesmos bytes:

If[#<2,0,#0[#-Divisors[#][[-2]]]+1]&

Essa é uma implementação muito direta da definição como uma função recursiva.


4

Oitava, 59 58 55 bytes

function r=f(x)r=0;while(x-=x/factor(x)(1));r++;end;end

Atualizado graças a Stewie Griffin, economizando 1 byte

Atualização adicional, economizando mais três bytes usando o resultado da fatoração na verificação durante a verificação.

Amostras de execuções:

octave:41> f(5)
ans =  3
octave:42> f(30)
ans =  6
octave:43> f(31)
ans =  7
octave:44> f(32)
ans =  5
octave:45> f(100)
ans =  8
octave:46> f(200)
ans =  9

é o último endnecessário na oitava?
Abr001am

Isto é. Percebi que não estava no matlab com as suas respostas, mas a Oitava espera isso (como aprendi ao experimentar as suas no Oitava).
Dcsohl

4

Haskell, 59 bytes

f 1=0;f n=1+(f$n-(last$filter(\x->n`mod`x==0)[1..n`div`2]))

Uso:

Prelude> f 30
Prelude> 6

Pode ser um pouco ineficiente para grandes números por causa da geração da lista.


11
Compreensão da lista e <1, em vez de ==0salvar alguns bytes: f 1=0;f n=1+f(n-last[a|a<-[1..ndiv2],mod n a<1])
Angs

4

Julia, 56 50 45 39 bytes

f(n)=n>1&&f(n-n÷first(factor(n))[1])+1

Esta é uma função recursiva que aceita um número inteiro e retorna um número inteiro.

Ungolfed:

function f(n)
    if n < 2
        # No decrementing necessary
        return 0
    else
        # As Dennis showed in his Jelly answer, we don't need to
        # divide by the smallest prime factor; any prime factor
        # will do. Since `factor` returns a `Dict` which isn't
        # sorted, `first` doesn't always get the smallest, and
        # that's okay.
        return f(n - n ÷ first(factor(n))[1]) + 1
    end
end

Experimente online! (inclui todos os casos de teste)

Economizou 6 bytes graças a Martin Büttner e 11 graças a Dennis!


3

PowerShell v2 +, 81 bytes

param($a)for(;$a-gt1){for($i=$a-1;$i-gt0;$i--){if(!($a%$i)){$j++;$a-=$i;$i=0}}}$j

Mais brutal da força bruta.

Recebe entrada $a, entra em um forloop até que $aseja menor ou igual a 1. Cada loop passamos por outro forloop que faz a contagem regressiva $aaté encontrarmos um divisor ( !($a%$i). Na pior das hipóteses, vamos encontrar $i=1como um divisor. Quando o fazemos, incrementa nosso contador $j, subtrai nosso divisor $a-=$ie define $i=0para sair do loop interno. Eventualmente, chegaremos a uma condição em que o loop externo é falso (ou seja, $aatingiu 1), portanto, produza $je sai.

Cuidado : Isso levará muito tempo em números maiores, especialmente números primos. A entrada de 100.000.000 leva ~ 35 segundos no meu laptop Core i5. Editar - apenas testei com [int]::MaxValue(2 ^ 32-1) e levou ~ 27 minutos. Não é tão ruim, suponho.


3

Matlab, 58 bytes

function p=l(a),p=0;if(a-1),p=1+l(a-a/min(factor(a)));end

3

Japt , 12 bytes (não concorrente)

@!(UµUk Å×}a

Teste online! Não concorrente porque usa vários recursos que foram adicionados após o lançamento do desafio.

Como funciona

@   !(Uµ Uk Å  ×   }a
XYZ{!(U-=Uk s1 r*1 }a
                       // Implicit: U = input integer
XYZ{               }a  // Return the smallest non-negative integer X which returns
                       // a truthy value when run through this function:
         Uk            //   Take the prime factorization of U.
            s1         //   Slice off the first item.
                       //   Now we have all but the smallest prime factor of U.
               r*1     //   Reduce the result by multiplication, starting at 1.
                       //   This takes the product of the array, which is the
                       //   largest divisor of U.
      U-=              //   Subtract the result from U.
    !(                 //   Return !U (which is basically U == 0).
                       //   Since we started at 0, U == 1 after 1 less iteration than
                       //   the desired result. U == 0 works because the smallest
                       //   divisor of 1 is 1, so the next term after 1 is 0.
                       // Implicit: output result of last expression

Essa técnica foi inspirada na resposta 05AB1E . Uma versão anterior usada ²¤(pressione 2, corte os dois primeiros itens) no lugar Åporque é um byte mais curto que s1 (observe o espaço à direita); Eu só percebi depois do fato de que, como isso acrescenta um 2 ao final da matriz e fatias desde o início , ele de fato falha em qualquer número composto ímpar, embora funcione em todos os casos de teste.


2

Python 3, 75, 70 , 67 bytes.

g=lambda x,y=0:y*(x<2)or[g(x-z,y+1)for z in range(1,x)if x%z<1][-1]

Esta é uma solução recursiva bastante direta. Demora MUITO tempo para os casos de teste de número elevado.


2

> <>, 32 bytes

<\?=2:-$@:$/:
1-$:@@:@%?!\
;/ln

Espera o número de entrada,, nna pilha.

Este programa constrói a sequência completa na pilha. Como o único número que pode levar a isso 1é 2, a construção da sequência pára quando 2é atingido. Isso também faz com que o tamanho da pilha seja igual ao número de etapas, em vez do número de etapas +1.


2

Ruby, 43 bytes

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

Encontre o menor número ique xdivide x-ie recorra até chegarmos 1.


2

Haskell, 67 bytes

Aqui está o código:

a&b|b<2=0|a==b=1+2&(b-1)|mod b a<1=1+2&(b-div b a)|1<2=(a+1)&b
(2&)

E aqui está uma razão pela qual Haskell é incrível:

f = (2&)

(-->) :: Eq a => a -> a -> Bool
(-->) = (==)

h=[f(5)        --> 3
  ,f(30)       --> 6
  ,f(31)       --> 7
  ,f(32)       --> 5
  ,f(100)      --> 8
  ,f(200)      --> 9
  ,f(2016^155) --> 2015
  ]

Sim, no Haskell você pode definir -->como equivalente ==.


2

Matlab, 107 bytes

a=input('');b=factor(a-isprime(a));c=log2(a);while(max(b)>1),b=max(factor(max(b)-1));c=c+1;end,disp(fix(c))
  • Não competitiva, essa não é a tradução iterativa da minha última submissão, apenas outro método algébrico direto, resume todos os logs binários de todos os fatores primários, meio ambíguo para ilustrar.
  • Vou jogar mais isso quando tiver tempo.

2

MATL, 17 16 bytes

`tttYfl)/-tq]vnq

Experimente Online

Explicação

        % Implicitly grab input
`       % Do while loop
    ttt % Make three copies of top stack element
    Yf  % Compute all prime factors
    l)  % Grab the smallest one
    /   % Divide by this to get the biggest divisor
    -   % Subtract the biggest divisor
    t   % Duplicate the result
    q   % Subtract one (causes loop to terminate when the value is 1). This
        % is functionally equivalent to doing 1> (since the input will always be positive) 
        % with fewer bytes
]       % End do...while loop
v       % Vertically concatenate stack contents (consumes entire stack)
n       % Determine length of the result
q       % Subtract 1 from the length
        % Implicitly display result

2

C99, 62 61 bytes

1 byte jogado fora por @Alchymist.

f(a,c,b)long*c,a,b;{for(*c=0,b=a;a^1;a%--b||(++*c,b=a-=b));}  

Chame como f (x, & y), onde x é a entrada e y é a saída.


Se você testar a% - b, poderá evitar eb no final. Uma economia de um byte inteiro.
Alchymist


2

Clojure, 116 104 bytes

(fn[n](loop[m n t 1](let[s(- m(last(filter #(=(rem m %)0)(range 1 m))))](if(< s 2)t(recur s (inc t))))))

-12 bytes, filtrando um intervalo para encontrar múltiplos e usando lastum para obter o melhor

Solução ingênua que basicamente resolve o problema, conforme descrito pelo OP. Infelizmente, encontrar o maior divisor sozinho ocupa metade dos bytes usados. Pelo menos eu deveria ter muito espaço para jogar golfe daqui.

Pré -olfo e teste:

(defn great-divider [n]
  ; Filter a range to find multiples, then take the last one to get the largest
  (last
     (filter #(= (rem n %) 0)
             (range 1 n))))

(defn sub-great-divide [n]
  (loop [m n
         step 1]
    (let [g-d (great-divider m) ; Find greatest divisor of m
          diff (- m g-d)] ; Find the difference
      (println m " is " g-d " --> " m " - " g-d " = " diff)
      (if (< diff 2)
        step
        (recur diff (inc step))))))

(sub-great-divide 30)

30  is  15  -->  30  -  15  =  15
15  is  5  -->  15  -  5  =  10
10  is  5  -->  10  -  5  =  5
5  is  1  -->  5  -  1  =  4
4  is  2  -->  4  -  2  =  2
2  is  1  -->  2  -  1  =  1
6

11
@insertusernamehere Não, infelizmente, porque todos esses são identificadores válidos. Eu removi todo o espaço em branco possível. Se eu quiser jogar mais, vou precisar refazer o algoritmo.
precisa saber é o seguinte

2

Perl 6 , 35 bytes

{+({$_ -first $_%%*,[R,] ^$_}...1)}

Experimente online!

Como funciona

{                                 }   # A bare block lambda.
                    [R,] ^$_          # Construct range from arg minus 1, down to 0.
        first $_%%*,                  # Get first element that is a divisor of the arg.
    $_ -                              # Subtract it from the arg.
   {                        }...1     # Do this iteratively, until 1 is reached.
 +(                              )    # Return the number of values generated this way.

1

Pitão, 17 16 bytes

L?tbhy-b*F+1tPb0

Experimente online! (O y.vfinal é para chamada de função)


17 bytes originais:

L?tb+1y-b*F+1tPb0

Experimente online! (O y.vfinal é para chamada de função)

(Na verdade, eu respondi a essa pergunta com este programa Pyth.)


Na verdade, eu não me incomodei em passar pelo seu programa, mas se você estiver usando a definição recursiva no OP, uprovavelmente será menor do que a recursão real.
Maltysen

1

Pyke, 11 bytes (não competitivo)

D3Phf-oRr;o

Isso usa um novo comportamento no qual, se houver uma exceção gerada após um goto, ele restaura o estado anterior ao goto (exceto definições de variáveis) e continua. Nesse caso, é equivalente ao seguinte código python:

# Implicit input and variable setup
inp = input()
o = 0
# End implicit
try:
    while 1:
        inp -= factors(inp)[0] # If factors is called on the value 1, it returns an empty
                               # list which when the first element tries to be accessed
                               # raises an exception
        o += 1 # Using `o` returns the current value of `o` and increments it
except:
    print o # This in effect gets the number of times the loop went

Tudo isso é possível usando o Pyke sem uma construção de loop while - yay goto!

Experimente aqui!


1

JavaScript (ES6), 70 54 bytes

f=(n,i=2)=>n<i?0:n%i?f(n,i+1):n>i?f(i)+f(n/i):1+f(n-1)

Implementação da fórmula recursiva fornecida, mas agora atualizada para usar a recursão para encontrar também o divisor.


1

Perl, 57 + 1 ( -psinalizador) = 58 bytes

$n=$_;$n-=$n/(grep!($n%$_),2..$n/2,$n)[0],$\++while$n>1}{

Uso:

> echo 31 | perl -pe '$n=$_;$n-=$n/(grep!($n%$_),2..$n/2,$n)[0],$\++while$n>1}{'

Ungolfed:

while (<>) {
# code above added by -p
    # $_ has input value
    # $\ has undef (or 0)
    my $n = $_;
    while ($n > 1) {
        my $d = 1;
        for (2 .. ($n / 2)) {
            if ($n % $_ == 0) {
                $d = $n / $_;
                last;
            }
        }
        $n -= $d;
        $\++;
    }
} {
# code below added by -p
    print;  # prints $_ (undef here) and $\
}

1

Clojure, 98 96 bytes

#(loop[n % i -1](if n(recur(first(for[j(range(dec n)0 -1):when(=(mod n j)0)](- n j)))(inc i))i))

usa for :whenpara encontrar o maior divisor, faz um loop até que nenhum valor maior que um seja encontrado.

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.