Retornar o enésimo dígito da sequência de séries de alíquotas


20

0. DEFINIÇÕES

Uma sequência é uma lista de números.
Uma série é a soma de uma lista de números.
O conjunto de números naturais contém todos os "números inteiros não negativos maiores que zero".
Um divisor (neste contexto) de um número natural j é um número natural i , de modo que j ÷ i também é um número natural.

1. PREÂMBULO

Algumas outras perguntas neste site mencionam o conceito de alíquota, ou a sequência de divisores de um número natural a que são menores que a . A determinação de números amigáveis envolve o cálculo da soma desses divisores, denominada soma de alíquotas ou série de alíquotas. Todo número natural tem sua própria soma de alíquotas, embora o valor da soma de alíquotas de um número não seja necessariamente exclusivo desse número. ( Exemplo : todo número primo tem uma soma alíquota de 1.)

2. DESAFIO

Dado um número natural n, retorne o ndígito da sequência de somas de alíquotas. As primeiras várias séries na sequência, começando pela série para 1, são:

{0, 1, 1, 3, 1, 6, 1, 7, 4, 8, 1, 16, 1, 10, 9, 15, 1, 21, 1, 22, 11, 14, 1, 36, 6, 16, 13}

Concatenadas, elas se parecem com:

0113161748116110915121122111413661613

A entrada pode ser indexada em zero ou indexada em um, de acordo com sua preferência. As soluções devem ser programas ou funções capazes de retornar o 10.000 dígito (entrada até 9999ou 10000). A solução de trabalho mais curta vence.

3. CASOS DE ENSAIO

Os pares de entrada-saída corretos devem incluir, entre outros, o seguinte:

   0 or     1    ->    0
   4 or     5    ->    1
  12 or    13    ->    6
9999 or 10000    ->    7

O número que precede o "ou" é indexado em 0; o número a seguir é indexado em 1.
Casos de teste adicionais podem ser fornecidos mediante solicitação.

4. REFERÊNCIAS

OEIS possui uma lista de números e suas somas de alíquotas.


2
Bom primeiro desafio, aliás. :)
Martin Ender

1
se o idioma não pode gerenciar 10k chars strings ?? (por exemplo, o terrível limite do Oracle SQL 4k ) é a resposta válida se for o limite de idioma?
Giacomo Garabello

@MartinEnder, obrigado! E obrigado por esse link; foi esclarecedor. Existe alguma coisa lá fora que explica como tratar respostas em idiomas com limitações? Não consegui encontrar nada, mas sei que isso não significa que não esteja lá. :)
Joe

Talvez eu esteja sendo completamente grossa, mas como são calculados os números dessa série?
Tom Carpenter

@ TomCarpenter: para o primeiro elemento, pegue todos os divisores de 1 que sejam menores que 1 e adicione-os. (1 é o único divisor de 1, portanto o primeiro elemento acaba sendo zero.) Segundo elemento, os divisores de 2 que são menores que 2 (apenas 1 se ajusta a isso); terceiro, divisores de 3 (ainda apenas 1); e assim por diante. Os divisores de 4 são {1, 2}, e 1 + 2 == 3, de modo que o quarto elemento é 3. Levei um tempo para descobrir isso também;)
Joe

Respostas:


6

05AB1E , 14 11 10 bytes

Calcule n = 9999 em cerca de 15 segundos. Código:

ÌL€Ñ€¨OJ¹è

Explicação:

Ì           # Increment implicit input by 2
 L          # Generate the list [1 .. input + 2]
  ۄ        # For each, get the divisors
    ۬      # For each, pop the last one out
      O     # Sum all the arrays in the array
       J    # Join them all together
        ¹è  # Get the nth element

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


6

Mathematica, 51 bytes

Array[##&@@IntegerDigits[Tr@Divisors@#-#]&,#][[#]]&

Uma função sem nome que pega e retorna um número inteiro e usa indexação baseada em 1. Lida com a entrada 10000instantaneamente.

Explicação

Esta é uma implementação muito direta da definição, fazendo uso do fato de que as nsomas do primeiro divisor são sempre suficientes para determinar o nth dígito. Como sempre, a ordem de leitura do Mathematica jogado no golfe é um pouco engraçada:

Array[...&,#]...&

Isso gera uma lista com todos os resultados da aplicação da função sem nome à esquerda em todos os valores ide 1para ninclusivo.

...Tr@Divisors@#-#...

Começamos calculando os divisores de i, somando-os Tre subtraindo i-os para que seja apenas a soma dos divisores menor que i.

...IntegerDigits[...]...

Isso transforma o resultado em uma lista de seus dígitos decimais.

##&@@...

E isso remove o cabeçalho "list", para que todas as listas de dígitos sejam automaticamente concatenadas no resultado de Array. Para mais detalhes sobre como ##funciona, consulte a seção "Sequências de argumentos" nesta postagem .

...[[#]]

Por fim, selecionamos o ndígito th do resultado.


4

Braquilog , 40 bytes

:2-I,?:?:1yrc:Im.;0.
:1e:2f+.
>.>0,?:.%0

É indexado em 1, leva cerca de 0,15 segundos por N = 100, 15 segundos por N = 1000. No momento, estou concorrendo N = 10000, informarei o tempo de execução assim que terminar (se minha estimativa estiver correta, levará cerca de 8 horas)

Edit : corrigindo a propagação prematura de restrições no Brachylog, agora (em um código de 3 bytes a mais) leva cerca de 2.5minutos para, 10000mas retorna um out of global stackerro.

Explicação

  • Predicado principal: Input = N

    :2-I,                 I = N - 2
         ?:?:1y           Find the N first valid outputs of predicate 1 with input N
               rc         Reverse and concatenate into a single number
                 :Im.     Output is the Ith digit of that number
                     ;    Or (I strictly less than 0)
                      0.  Output is 0
    
  • Predicado 1: calcula a soma dos divisores

    :1e                   Get a number between N and 1
       :2f                Find all valid outputs of predicate 2 with that number as input
          +.              Output is the sum of those outputs
    
  • Predicado 2: unifica a saída com um divisor da entrada

    >.>0,                 Output is a number between Input and 0
         ?:.%0            Input is divisible by Output
    

1
Você pode alocar mais pilha global com a -Gopção O padrão é apenas 128M. Você pode usar, por exemplo: swipl -G2Gpara usar 2 GO.
mat

4

Pitão, 26 21 20 15 bytes

@sm`sf!%dTtUdSh

Experimente online. Suíte de teste.

Usa indexação baseada em 0. O programa é O (n²) e termina para n = 9999 em cerca de 14 minutos na minha máquina de 2008.


O que há com essa pesquisa complicada de divisores? f!%dTr1dé muito mais curto (mas também mais lento)
Jakube

Opa, @Jakube, modificou a versão errada para a solução de 20 bytes.
PurkkaKoodari

f!%TYtUTé o que eu costumava ter.
PurkkaKoodari

@Jakube eu mudei para isso. Ainda está em execução para n = 9999, já faz mais de 5 minutos: \
PurkkaKoodari

4

Geléia, 13 11 10 bytes

2 bytes graças a @Adnan e mais 1 graças a @Dennis.

ÆDṖSDµ€Fị@

Experimente online!

Usa indexação baseada em 1. Conclui por n = 10000 em menos de 2 segundos online.


ÆDṖSDµ€Fị@salva um byte.
Dennis

@Dennis, isso aplica a toda a primeira cadeia?
PurkkaKoodari

@ Pietu1998: Sim, exatamente: em geral, no momento da análise, é aplicado chain.pop() if chain else chains.pop(). A cadeia iniciada recentemente está vazia; portanto, a última cadeia finalizada é usada.
Lynn

3

PHP, 90 bytes

0 indexado

<?php for(;strlen($s)<=$a=$argv[1];$s.=$n)for($n=0,$j=++$i;--$j;)$i%$j||$n+=$j;echo$s[$a];

Absolutamente não sutil ou com uma maneira inteligente de abordá-lo.
Além disso, como sempre, produz três avisos que são ignorados.


3

J , 34 bytes

{[:;1<@":@(-~>:@#.~/.~&.q:)@+i.@>:

O índice é zero e usa a fórmula abaixo para calcular as somas do divisor.

Fórmula

Explicação

{[:;1<@":@(-~>:@#.~/.~&.q:)@+i.@>:  Input: n
                                >:  Increment n
                             i.@    Create the range [0, 1, ..., n]
    1                       +       Add one to each to get [1, 2, ..., n+1]
          (               )@        For each value
                        q:            Get the prime factors
                   /.~&.              For each group of equal prime factors
                #.~                     Raise the first to the first power, the second
                                        squared and so on, and sum them
             >:@                        Increment that sum
                      &.q:            Reduce the groups using multiplication
           -~                         Subtract the initial value from that sum
       ":@                            Convert each to a string
     <@                               Box each
 [:;                                Unbox each and concatenate the strings
{                                   Select the character from that string at index n
                                    and return it

2

MATL , 16 15 bytes

:"@@q:\~fsV]vG)

A indexação é baseada em 1.

O último caso de teste atinge o tempo limite no compilador online, mas fornece o resultado correto com o compilador offline, em cerca de 15 segundos.

Experimente online!

:         % Take input n. Push [1 2 ... n]
"         % For each k in [1 2 ... n]
  @       %   Push k
  @q:     %   Push [1 2 ... k-1]
  \       %   Modulo. Zero values correspond to divisors
  ~f      %   Indices of zeros. These are the divisors
  s       %   Sum
  V       %   Convert to string
]         % End for each
v         % Concatenate all stack contents vertically
G)        % Take n-th digit. Implicitly display

2

Haskell, 52 bytes

(([1..]>>= \n->show$sum[m|m<-[1..n-1],mod n m<1])!!)

Exemplo de uso: (([1..]>>= \n->show$sum[m|m<-[1..n-1],mod n m<1])!!) 12-> 6.

É uma implementação direta da definição: foreach nsoma seus divisores e converte-o em uma string. Concatene todas essas cadeias e escolha o elemento no índice solicitado. A preguiça de Haskell leva apenas ns da lista infinita, [1..]conforme necessário.


1

Python 3.5, 103 93 92 bytes:

R=range;A=lambda f:''.join([str(sum([j for j in R(1,i)if i/j%1==0]))for i in R(1,f+1)])[f-1]

Implementação bastante direta do método descrito no post.

Experimente Online! (Ideona)

Não termina nos 5 segundos alocados no compilador online para entrada 10000, mas termina na minha máquina para a mesma entrada em cerca de 8,5 segundos.


1

Oitava, 71 bytes

Este é apenas oitava. Não vai funcionar no MATLAB. É criada uma função virtual que funciona em números indexados em 1. Provavelmente pode ser simplificado um pouco mais. Vai dar uma olhada esta noite.

@(x)c((c=num2str(arrayfun(@(n)sum(b(~rem(n,b=(1:n-1)))),1:x)))~=' ')(x)

Você pode tentar online aqui .

Simplesmente execute o comando acima, prefixado com a=ou o que quer que seja (apenas para que você possa usá-lo várias vezes) e, em seguida, faça a(10000)ou o que for. Demora cerca de 7 segundos para calcular que o 10000º dígito é um 7.


1

Java 8, 220 bytes

import java.util.stream.IntStream;
char a(int n){return IntStream.range(1,n+2).map(i->IntStream.range(1,i).filter(k->i%k==0).sum()).mapToObj(Integer::toString).collect(java.util.stream.Collectors.joining("")).charAt(n);}

Bem, pelo menos é rápido. A média é de 0,3 segundos para obter o elemento 9999/10000 na minha máquina. Ele gera apenas tantas somas de alíquotas quanto o índice que você especificou. Isso significa que a string será um pouco mais longa que o seu índice na maioria dos casos, já que algumas somas de alíquotas têm 2 ou mais dígitos, mas na maioria das vezes, ela gera apenas o comprimento de uma string necessária.

Uso:

public static void main(String[] args) {
    System.out.println(a(0));
    System.out.println(a(4));
    System.out.println(a(12));
    System.out.println(a(9999));
}

Ungolfed:

public static void main(String[] args) {
    System.out.println(all(0));
    System.out.println(all(4));
    System.out.println(all(12));
    System.out.println(all(9999));
}

static int aliquotSum(int n) {
    return IntStream.range(1, n).filter(k -> n % k == 0).sum();
}

static IntStream sums(int n) {
    return IntStream.range(1, n + 2).map(i -> aliquotSum(i));
}

static String arraycat(IntStream a) {
    return a.mapToObj(Integer::toString).collect(java.util.stream.Collectors.joining(""));
}

static char all(int index) {
    return arraycat(sums(index)).charAt(index);
}
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.