(KevinC's) Secuencia triangular de DeciDigits


19

Entrada:

Un entero positivo n que es 1 <= n <= 25000.

Salida:

  1. En esta secuencia comenzamos con el número decimal 1 / n .
  2. Luego tomamos la suma de los dígitos hasta el n -ésimo dígitos después de la coma (indexada 1); seguido de la suma de dígitos hasta el ( n -1) 'th, luego ( n -2)' th, etc. Continúe hasta que n sea ​​1.
  3. La salida es la suma de todos estos combinados.

Por ejemplo:

n = 7
1/7 = 0.1428571428...
7th digit-sum = 1+4+2+8+5+7+1 = 28
6th digit-sum = 1+4+2+8+5+7 = 27
5th digit-sum = 1+4+2+8+5 = 20
4th digit-sum = 1+4+2+8 = 15
3rd digit-sum = 1+4+2 = 7
2nd digit-sum = 1+4 = 5
1st digit     = 1
Output = 28+27+20+15+7+5+1 = 103

Reglas de desafío:

  • Si el decimal de 1 / n no tiene n dígitos después de la coma, los que faltan se contarán como 0 (es decir 1/2 = 0.50 => (5+0) + (5) = 10).
  • Toma los dígitos sin redondear (es decir, los dígitos de 1/6son 166666y no 166667)

Reglas generales:

  • Se aplican reglas estándar para su respuesta, por lo que puede usar STDIN / STDOUT, funciones / método con los parámetros adecuados, programas completos. Tu llamada.
  • Las lagunas predeterminadas están prohibidas.
  • Si es posible, agregue un enlace con una prueba para su código.
  • Además, agregue una explicación si es necesario.

Primero 1 - 50 en la secuencia:

0, 10, 18, 23, 10, 96, 103, 52, 45, 10, 270, 253, 402, 403, 630, 183, 660, 765, 819, 95, 975, 1034, 1221, 1500, 96, 1479, 1197, 1658, 1953, 1305, 1674, 321, 816, 2490, 2704, 4235, 2022, 3242, 2295, 268, 2944, 3787, 3874, 4097, 1980, 4380, 4968, 3424, 4854, 98

Últimos 24990 - 25000 en la secuencia:

1405098782, 1417995426, 1364392256, 1404501980, 1408005544, 1377273489, 1395684561, 1405849947, 1406216741, 1142066735, 99984

8
¿Alguien mencionó mi nombre?
Kevin

Respuestas:



15

Mathematica, 42 bytes

#&@@RealDigits[1/#,10,#,-1].(#-Range@#+1)&

o

#&@@RealDigits[1/#,10,#,-1].Range[#,1,-1]&

o

Tr@Accumulate@#&@@RealDigits[1/#,10,#,-1]&

Explicación

Tome el ejemplo de la especificación de desafío. Queremos calcular:

  1+4+2+8+5+7+1
+ 1+4+2+8+5+7
+ 1+4+2+8+5
+ 1+4+2+8
+ 1+4+2
+ 1+4
+ 1

Reorganizando, esto es:

  1*7 + 4*6 + 2*5 + 8*4 + 5*3 + 7*2 + 1*1
= (1, 4, 2, 8, 5, 7, 1) . (7, 6, 5, 4, 3, 2, 1)

donde .es el producto escalar de dos vectores.

Eso es prácticamente todo lo que hace la solución.

#&@@RealDigits[1/#,10,#,-1]

Esto nos da los primeros Ndígitos decimales de 1/N( #&@@extrae el primer elemento del RealDigitsresultado porque eso también devuelve el desplazamiento del primer dígito que no nos importa).

Luego obtenemos la lista de Nabajo a 1usar (#-Range@#+1)o Range[#,1,-1], los cuales son más cortos que Reverse@Range@#, y tomamos el producto escalar.

En cambio, la solución alternativa utiliza Accumulatepara calcular una lista de todas las sumas de prefijos y luego suma esas sumas de prefijos con Tr.

Dado que esto es realmente rápido incluso para entradas grandes, aquí hay un diagrama de dispersión de la secuencia N = 100,000( aunque hacerlas todas y trazarlas tomó un tiempo):

ingrese la descripción de la imagen aquí
Haga clic para una versión más grande.

La línea azul es el límite superior ingenuo de 9 N (N+1) / 2(si todos los dígitos decimales lo fueran 9) y la línea naranja es exactamente la mitad de eso. Como era de esperar, esto está justo dentro de la rama principal de la trama, ya que, estadísticamente, esperaríamos que el dígito promedio sea 4.5.

La delgada línea de puntos de trazado que puede ver debajo de la rama principal son fracciones que terminan en ...3333..., ya que todas se encuentran muy cerca 3 N (N+1) / 2.


Muy buena respuesta, ¡y me encanta el diagrama gráfico! Es casi desafortunado que este no sea el más corto y no puedo aceptarlo como respuesta. :) Si no lo olvido, podría hacer una pequeña recompensa en dos días por responder mucho más que la simple tarea que le di.
Kevin Cruijssen

1
@KevinCruijssen ¡Gracias! :)
Martin Ender

6

05AB1E , 12 11 bytes

Di<ë°¹÷.pSO

Pruébalo en línea! o un conjunto de pruebas para los primeros 50 números.

Explicación

              # implicit input n
Di<           # if n == 1 then 0
   ë          # else
    °¹÷       # 10^n // n
       .p     # get prefixes
         SO   # sum digits

Una versión más eficiente para probar grandes números en TIO

La diferencia con la versión más corta es que aquí sumamos el producto de los dígitos y la inversión de su índice basado en 1 en lugar de sumar dígitos en prefijos.

Di<ë°¹÷SDgLR*O

Pruébalo en línea!


5

Java 8, 181 169 166 153 142 bytes

import java.math.*;n->{int m=n+2,r=0,i;for(;m>2;)for(i=m--;i-->2;r+=(BigDecimal.ONE.divide(new BigDecimal(n),n,3)+"").charAt(i)-48);return r;}

Explicación:

Pruébalo aquí

import java.math.*;   // Required import for BigDecimal

n->{                  // Method with integer as both parameter and return-type
  int m=n+2,          //  Copy of the input-integer plus 2
      r=0,            //  Result-integer, starting at 0
      i;              //  Index-integer
  for(;m>2;)          //  Loop (1) as long as `m` is larger than 2
    for(i=m--;        //   Set index `i` to `m`, and decrease `m` by one afterwards
        i-->2;        //   Inner loop (2) from `m` down to 2 (inclusive)
      r+=             //    Add to the result-sum:
         (BigDecimal.ONE.divide(
                      //     1 divided by,
           new BigDecimal(n),
                      //     the input
           n,3)       //     With the minimal required precision
          +"")        //     Convert this to a String
          .charAt(i)  //     Take the character of this String at index `i`
          -48         //     And convert it to a number
     );               //   End of inner loop (2)
                      //  End of loop (1) (implicit / single-line body)
  return r;           //  Return result
}                     // End of method

4

PHP, 66 65 bytes

for($b=$c=$argv[$a=1];$c;)$o+=$c--*(($a=10*($a%$b))/$b^0);echo$o;

Adaptado de esta respuesta (también por mí): División de números no tan pequeños y edición sugerida de Jörg Hülsermann. Usar como:

php -r "for($b=$c=$argv[$a=1];$c;)$o+=$c--*(($a=10*($a%$b))/$b^0);echo$o;" 7

edit: corrigió un error por +1 bytes y dobló la asignación de $ a en $ argv [1] por -2 bytes por un neto de 1 byte menos.


3

Scala, 84 bytes

val b=BigDecimal
def?(& :Int)=1 to&map(x=>(""+b(1)/b(&))slice(2,x+2)map(_-48)sum)sum

Sin golf:

def f(n: Int)={
  val digits = ""+BigDecimal(1)/BigDecimal(n)
  (1 to n).map( x=>
    digits.slice(2, x+2).map(d => d - 48).sum
  ).sum

Explicación:

val b=BigDecimal   //define an alias for BigDecimal
def?(& :Int)=      //define a method called ? with an integer & as a parameter
  1 to &           //create a range from 1 to &
  map(x=>          //for each number x...
    (""+b(1)/b(&))   //calculate the fraction
    slice(2,x+2)     //and take the slice starting from the third element,
                     //(dropping the "1.") and containing x elements
    map(_-48)        //for each char, subtract 48 to get the integer value
    sum              //and sum them
  )sum             //and take the sum

Podría guardar algunos bytes explotando la forma en que el compilador se tokeniza: llamando al argumento &, puede escribir en 1 to&maplugar de 1 to n map. La misma regla se aplica a def?.


3

Jalea , 11 bytes

’aµR⁵*:µDFS

TryItOnline
First 50

Demasiado lento para los grandes casos de prueba.

¿Cómo?

’aµR⁵*:µDFS - Main link: n
’           - decrement
 a          - and (to handle special case where n=1, to return 0 rather than 10)
  µ         - monadic chain separation
   R        - range: [1,2,...n]
    ⁵       - literal 10
     *      - exponentiation: [10,100,...,10^n]
      :     - integer division: [10//n,100//n,...,10^n//n]
       µ    - monadic chain separation
        D   - cast to a decimal list [[digits of 10//n],[digits of 100//n],...]
         F  - flatten into one list
          S - sum

2
Creo que nunca antes había visto una respuesta de Jelly donde la explicación es una línea recta ;-)
ETHproductions

Casi puse el R⁵*equivalente de izquierda a derecha, pero luego vi la bonita línea recta :)
Jonathan Allan

3

PHP, 76 bytes

(Editar -1 byte - Gracias usuario59178 - su solución es aún mejor)

for($c=substr(bcdiv(1,$a=$argv[1],$a),2);$i<$a;)$s+=($a-$i)*$c[$i++];echo$s;

usted podría ahorrar un byte (un punto y coma) moviendo el $c=blahen la primera parte de lafor(;;)
user59178

2

MATL, 19 bytes

li/GEY$4LQ)!UYsG:)s

Pruébalo en línea!

Explicación

l       % Push a 1 literal to the stack
i/      % Grab the input (n) and compute 1/n
GE      % Grab the input again and multiply by 2 (2n)
Y$      % Compute the first 2n digits of 1/n after the decimal
4LQ)    % Get only the digits past the decimal point
!U      % Convert to numbers
Ys      % Compute the cumulative sum
G:)     % Get the first n terms
s       % Sum the result and implicitly display

2

Groovy, 87 bytes

Esto fue menos doloroso de lo que esperaba, y se basa en mi respuesta aquí :

{n->(1..n).collect{x->(1.0g.divide(n, n, 1)+"")[2..x+1].getChars().sum()-48*(x)}.sum()}

Explicación

1.0g - Utilice la notación BigDecimal para el uno.

.divide(n, n, 1)+"" - Divide entre n con n precisión (función BigDecimal solamente) y convierte a str.

(...)[2..x+1].getChars() - Obtenga la subcadena de la iteración actual como una matriz de caracteres.

.sum()-48*(x)- Suma los valores ASCII de los caracteres y reduce en 48 para cada elemento. Esto convierte el valor de un dígito ASCII en un número entero esencialmente guardando bytes *.toInteger().

(1..n).collect{...}.sum() - Iterar sobre cada uno de los dígitos en la división, haciendo esta función, obtenerlos en una sola matriz y sumar.

Se guardaron 2 bytes y se sacrificó la eficiencia ...

Esta es una versión más eficiente que no recalcula el BigDecimal en cada iteración.

{n->i=1.0g.divide(n, n, 1)+"";(1..n).collect{x->i[2..x+1].getChars().sum()-48*(x)}.sum()}

2

J, 27 bytes

1#.[:+/\-{.10#.inv%<.@*10^]

Uso

La entrada es un entero extendido.

   f =: 1#.[:+/\-{.10#.inv%<.@*10^]
   (,.f"0) (>: i. 50x) , 24990x + i. 11
    1          0
    2         10
    3         18
    4         23
    5         10
    6         96
    7        103
    8         52
    9         45
   10         10
   11        270
   12        253
   13        402
   14        403
   15        630
   16        183
   17        660
   18        765
   19        819
   20         95
   21        975
   22       1034
   23       1221
   24       1500
   25         96
   26       1479
   27       1197
   28       1658
   29       1953
   30       1305
   31       1674
   32        321
   33        816
   34       2490
   35       2704
   36       4235
   37       2022
   38       3242
   39       2295
   40        268
   41       2944
   42       3787
   43       3874
   44       4097
   45       1980
   46       4380
   47       4968
   48       3424
   49       4854
   50         98
24990 1405098782
24991 1417995426
24992 1364392256
24993 1404501980
24994 1408005544
24995 1377273489
24996 1395684561
24997 1405849947
24998 1406216741
24999 1142066735
25000      99984

El rendimiento es bueno y solo requiere unos 3 segundos para calcular los casos de prueba grandes.

   timex 'f 7x'
0.000119
   timex 'f 24999x'
3.8823
   timex 'f 25000x'
3.14903

Explicación

1#.[:+/\-{.10#.inv%<.@*10^]  Input: n
                          ]  Get n
                       10^   Raise 10 to the nth power
                  %          Get the reciprocal of n
                      *      Multiply (1/n) with (10^n)
                   <.@       Floor it
           10#.inv           Convert it to a list of base 10 digits
        -                    Negate n
         {.                  Take the last n values from the list of digits
                             (This is to handle the case for n = 1)
   [:  \                     For each prefix of the list of digits
     +/                        Reduce it using addition to get the sum
1#.                          Convert those sums as base 1 digits and return
                             (This is equivalent to taking the sum)

2

Jalea , 10 bytes

⁵*:⁸D+\_ỊS

No es el enfoque más corto , pero sí bastante eficiente. Pruébalo en línea! o verificar todos los casos de prueba .

Cómo funciona

⁵*:⁸D+\_ỊS  Main link. Argument: n (integer)

⁵*          Yield 10**n.
  :⁸        Divide 10**n by n (integer division).
    D       Convert the quotient to base 10.
     +\     Take the cumulative sum of the digits.
        Ị   Insignificant; yield (abs(n) <= 1).
       _    Subtract the resulting Boolean from each decimal digit.
            This takes care of edge case n = 1, which would return 2 otherwise.
         S  Take the sum.

1

Python 2, 90 bytes

lambda o:sum([sum([int(i)for i in s])for s in map(lambda x:str(1.0/o)[2:x],range(3,3+o))])

No es bonito, pero se hace mediante la división flotante y luego la conversión en una cadena y luego la selección iterativa del índice de cadena para obtener el triángulo de números, luego realizar la comprensión de la lista y convertir cada carácter en un int y finalmente sumarlos todos.


1

JavaScript (ES6), 47 bytes

f=(b,a=1%b,c=b+1)=>c&&(a/b|0)*c+f(b,a%b*10,c-1)

Cómo funciona

Esta respuesta demuestra una técnica para calcular c dígitos decimales de a / b :

f=(a,b,c,d=".")=>~c?(a/b|0)+d+f(a%b*10,b,c-1,""):d

Esto será un excelente punto de partida para este desafío. Primero podemos cambiarlo ligeramente para que calcule b dígitos decimales de 1 / b , reordenando los parámetros y configurando los valores predeterminados:

f=(b,a=1,c=b,d=".")=>~c?(a/b|0)+d+f(b,a%b*10,c-1,""):d

A continuación, podemos cambiar esto para que calcule la suma de los primeros dígitos decimales b , en lugar de concatenarlos (esto elimina el dparámetro):

f=(b,a=1,c=b)=>~c?(a/b|0)+f(b,a%b*10,c-1):0

Estamos casi en una solución; ahora solo necesitamos hacer que multiplique cada dígito por c + 1 :

f=(b,a=1,c=b)=>~c?(a/b|0)*-~c+f(b,a%b*10,c-1):0

Hmm, esto parece un poco largo. ¿Qué pasa si incrementamos c en 1 para empezar?

f=(b,a=1,c=b+1)=>c?(a/b|0)*c+f(b,a%b*10,c-1):0

Eso ahorra un byte. Y aquí hay una manera de guardar uno más:

f=(b,a=1,c=b+1)=>c&&(a/b|0)*c+f(b,a%b*10,c-1)

Y ahora tenemos nuestra respuesta. f(7)es 103, f(11)es 270, f(1)es ... 2? Oh, olvidamos dar cuenta del caso en el que a / b es 1 en la primera iteración (es decir, b es 1). Hagamos algo al respecto:

f=(b,a=1%b,c=b+1)=>c&&(a/b|0)*c+f(b,a%b*10,c-1)

1 mod b es siempre 1 , a menos que b sea 1 , en cuyo caso será 0 . Nuestro programa ahora es correcto para todas las entradas, a 47 bytes .



0

C, 53 bytes

f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}

Debajo del principal para hacer alguna prueba ...

//44,79
#define R return
#define F for
#define U unsigned
#define N int
#define B break
#define I if
#define L(i) for(;i-->0;)
#define J(a,b)  if(a)goto b
#define G goto
#define P printf
#define D double
#define C unsigned char
#define A getchar()
#define O putchar
#define M main
#define Y malloc
#define Z free
#define S sizeof
#define T struct
#define E else
#define Q static
#define X continue  
main()
{N  k, a=0, b=0, i;

 F(i=1;i<50;++i) 
       P("f(%u)=%u |", i, f(i,i,1,0));
 P("\n");
 F(i=24990;i<=25000;++i) 
       P("f(%u)=%u |", i, f(i,i,1,0));
 P("\n");
 R 0;
}

/*
f(1)=0 |f(2)=10 |f(3)=18 |f(4)=23 |f(5)=10 |f(6)=96 |f(7)=103 |f(8)=52 |f(9)=45
f(10)=10 |f(11)=270 |f(12)=253 |f(13)=402 |f(14)=403 |f(15)=630 |f(16)=183 |f(17)=660 
f(18)=765 |f(19)=819 |f(20)=95 |f(21)=975 |f(22)=1034 |f(23)=1221 |f(24)=1500
f(25)=96 |f(26)=1479 |f(27)=1197 |f(28)=1658 |f(29)=1953 |f(30)=1305 |f(31)=1674
f(32)=321 |f(33)=816 |f(34)=2490 |f(35)=2704 |f(36)=4235 |f(37)=2022 |f(38)=3242
f(39)=2295 |f(40)=268 |f(41)=2944 |f(42)=3787 |f(43)=3874 |f(44)=4097 |f(45)=1980
f(46)=4380 |f(47)=4968 |f(48)=3424 |f(49)=4854 |
f(24990)=1405098782 |f(24991)=1417995426 |f(24992)=1364392256 |f(24993)=1404501980
f(24994)=1408005544 |f(24995)=1377273489 |f(24996)=1395684561 |f(24997)=1405849947 
f(24998)=1406216741 |f(24999)=1142066735 |f(25000)=99984 
*/

¿Por qué alguien abajo vota esto? ¿Es porque algún error? ¿es porque no encuentro el min correcto para él o ella? Para mí, esa cantidad de char es suficiente y no dude en enviar esta respuesta también como la otra donde no puedo hablar
RosLuP

3
Como otros han comentado sobre otras respuestas suyas, el objetivo del código de golf es hacer que el código sea lo más corto posible , sin embargo, continúa incluyendo un montón de macros sin ninguna razón. f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}tiene solo 53 bytes de longitud.
Dennis
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.