(КевінС) Трикутна послідовність децифрових цифр


19

Вхід:

Позитивне ціле число n, яке є 1 <= n <= 25000.

Вихід:

  1. У цій послідовності ми починаємо з десяткового числа 1 / n .
  2. Тоді ми візьмемо суму чисел аж до п "го знака після коми (1-індексований); з наступною сумою цифр до ( n -1) ', потім ( n -2)' й тощо. Продовжуйте, поки n не дорівнює 1.
  3. Вихід - це сума всіх цих об'єднаних.

Наприклад:

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

Правила виклику:

  • Якщо десятковий знак 1 / n не містить n цифр після коми, то пропущені вважатимуться як 0 (тобто 1/2 = 0.50 => (5+0) + (5) = 10).
  • Ви берете цифри без округлення (тобто цифри 1/6є, 166666а не 166667)

Загальні правила:

  • Для вашої відповіді застосовуються стандартні правила , тому вам дозволяється використовувати STDIN / STDOUT, функції / метод з відповідними параметрами, повноцінні програми. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду.
  • Також, будь ласка, додайте пояснення, якщо це необхідно.

Перші 1 - 50 в послідовності:

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

Останні 24990 - 25000 у послідовності:

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

8
Хтось згадав моє ім’я?
Кевін

Відповіді:


6

Желе , 9 байт

R⁵*:%⁵+\S

Досить повільний, але короткий. Спробуйте в Інтернеті! або перевірити перші 50 тестових випадків .

Як це працює

R⁵*:%⁵+\S  Main link. Argument: n

R          Range; yield [1, ..., n].
 ⁵*        10 power; yield [10**1, ..., 10**n].
   :       Divide each power by n.
    %⁵     Take each quotient modulo 10.
           This yields all desired decimal digits.
      +\   Take the cumulative sum of the digits.
        S  Take the sum.

15

Математика, 42 байти

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

або

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

або

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

Пояснення

Візьміть приклад із специфікації виклику. Ми хочемо обчислити:

  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

Переставляючи, це:

  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)

де .скалярний добуток двох векторів.

Це майже все рішення.

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

Це отримує нам перші Nдесяткові цифри 1/N(#&@@ витягує перший елемент RealDigitsрезультату, оскільки це також повертає зміщення першої цифри, про яку ми не піклуємося).

Потім ми Nпереходимо від списку до 1або використовуючи (#-Range@#+1)або Range[#,1,-1], обидва вони коротшіReverse@Range@# , і беремо скалярний продукт.

Альтернативне рішення натомість використовує Accumulateдля обчислення списку всіх префіксних сум, а потім додає ці суми префіксаTr .

Оскільки це дуже швидко навіть для великих входів, ось графік розсіяння послідовності до N = 100,000( все це робити і планувати їх зайняло певний час):

enter image description here
Клацніть для збільшення версії.

Синя лінія - це наївна верхня межа 9 N (N+1) / 2(якщо всі десяткові цифри були9 ), а помаранчева - точно половина. Не дивно, що це прямо у головній гілці сюжету, оскільки, статистично, ми очікуємо, що середня цифра становить 4,5.

Тонка лінія точок сюжету, яку ви бачите нижче основної гілки, - це дроби, які закінчуються ...3333..., оскільки всі вони лежать дуже близько 3 N (N+1) / 2.


Дуже приємна відповідь, і я люблю графік-сюжет! Майже шкода, що це не найкоротше, і я не можу прийняти це як відповідь. :) Якщо я не забуду, я міг би заробити невелику винагороду за два дні, щоб відповісти набагато більше, ніж просте завдання, яке я дав.
Кевін Кройсейсен

1
@KevinCruijssen Дякую! :)
Мартін Ендер

6

05AB1E , 12 11 байт

Di<ë°¹÷.pSO

Спробуйте в Інтернеті! або тестовий набір для перших 50 номерів.

Пояснення

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

Більш ефективна версія для спробу великих номерів на TIO

Відмінність від коротшої версії полягає в тому, що тут ми підсумовуємо добуток цифр та обернення їх 1-базисного індексу замість підсумовування цифр у префіксах.

Di<ë°¹÷SDgLR*O

Спробуйте в Інтернеті!


5

Java 8, 181 169 166 153 142 байт

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

Пояснення:

Спробуйте тут.

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 байт

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

Адаптований з цієї відповіді (також мною): Відділ не настільки малочисельних чисел і запропоновані Йоргом Гюльсерманом редагування до нього. Використовуйте як:

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

редагувати: виправлено помилку на +1 байт і склав призначення $ a на $ argv [1] на -2 байти за чистий на 1 байт менше.


3

Скала, 84 байти

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

Безголівки:

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

Пояснення:

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

Я міг би зберегти кілька байтів, використовуючи спосіб токенізації компілятора: Викликаючи аргумент &, ви можете писати 1 to&mapзамість 1 to n map. Це ж правило стосується і def?.


3

Желе , 11 байт

’aµR⁵*:µDFS

СпробуйтеItOnline
Перший 50

Занадто повільно для великих тестових випадків.

Як?

’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
Я не думаю, що я ніколи раніше не бачив відповіді Jelly, де пояснення є прямою лінією ;-)
ETHproductions

Я майже поставив R⁵* еквівалент зліва направо, але потім побачив хорошу пряму лінію :)
Джонатан Алан

3

PHP, 76 байт

(Редагувати -1 байт. Дякую користуваче59178 - ваше рішення ще краще)

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

ви можете зберегти байт (крапка з комою), перемістивши $c=blahв першу частинуfor(;;)
user59178

2

MATL, 19 байт

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

Спробуйте в Інтернеті!

Пояснення

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

Гроовий, 87 байт

Це було менш болісно, ​​ніж я передбачав, і ґрунтується на моїй відповіді тут :

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

Пояснення

1.0g - Використовуйте позначення BigDecimal для одного.

.divide(n, n, 1)+"" - Розділити на n з n точністю (лише функція BigDecimal) та перетворити на str.

(...)[2..x+1].getChars() - Отримайте підрядку поточної ітерації як масив char.

.sum()-48*(x)- Підсумуйте значення ASCII символів та зменшіть на 48 для кожного елемента. Це перетворює значення з цифри ASCII в цілий, по суті зберігаючи байти *.toInteger().

(1..n).collect{...}.sum() - Ітерайте над кожною з цифр у поділі, виконуючи цю функцію, зберіть їх усі в одному масиві та підсумовуйте.

Збережено 2 байти та ефективність жертви ...

Це більш ефективна версія, яка не перераховує кожну ітерацію BigDecimal.

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

2

J, 27 байт

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

Використання

Вхід - це розширене ціле число.

   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

Продуктивність хороша і для обчислення великих тестових випадків потрібно лише 3 секунди.

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

Пояснення

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

Желе , 10 байт

⁵*:⁸D+\_ỊS

Не найкоротший підхід , але досить ефективний. Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Як це працює

⁵*:⁸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 байт

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

Не дуже, але зроблено за допомогою поділу поплавця, потім перетворення на рядок, а потім ітераційний вибір індексу рядків, щоб отримати трикутник чисел, а потім виконати розуміння списку та перетворити кожну таблицю в цілий і, нарешті, підсумувати їх усі.


1

JavaScript (ES6), 47 байт

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

Як це працює

Ця відповідь демонструє техніку обчислення c десяткових цифр a / b :

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

Це стане чудовою відправною точкою для цього виклику. Спочатку ми можемо його трохи змінити, щоб він обчислював b десяткових цифр 1 / b шляхом переупорядкування параметрів та встановлення значень за замовчуванням:

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

Далі ми можемо змінити це так, щоб він обчислював суму перших b десяткових цифр, а не об'єднував їх (це усуває dпараметр):

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

Ми майже до рішення; тепер нам просто потрібно зробити так, щоб помножити кожну цифру на c + 1 :

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

Гм, це здається трохи довгим. Що робити, якщо ми зросли c на 1?

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

Це економить один байт. Ось такий спосіб зберегти ще один:

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

І ось ми маємо свою відповідь. f(7)це 103, f(11)це 270, f(1)це ... 2? О, ми забули врахувати випадок, коли a / b дорівнює 1 на першій ітерації (тобто b дорівнює 1). Зробимо щось з цього приводу:

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

1 mod b завжди дорівнює 1 , крім випадків, коли b дорівнює 1 , і в цьому випадку це буде 0 . Наша програма тепер правильна для всіх входів у 47 байт .



0

C, 53 байти

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

Нижче головного для того, щоб зробити тест ...

//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 
*/

Чому хтось за це проголосує? це тому, що якась помилка? це тому, що я не знаходжу потрібну хвилину для нього чи її? Для мене такої кількості знаків достатньо, і нормально почувайтеся вільними для кеселя і ця відповідь, як і інша, де я не можу говорити
RosLuP

3
Як інші прокоментували інші ваші відповіді, справа в коді гольфу полягає в тому, щоб зробити код якомога коротшим , але ви продовжуєте включати купу макросів без поважних причин. f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}всього 53 байти.
Денніс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.