Trójkątna sekwencja deciDigits (KevinC)

19

Wejście:

Dodatnia liczba całkowita n, która wynosi 1 <= n <= 25000.

Wynik:

  1. W tej sekwencji zaczynamy od liczby dziesiętnej 1 / n .
  2. Następnie bierzemy sumę cyfr aż do n -tej cyfry po przecinku (indeks 1); następnie suma cyfr w górę do ( n -1), następnie ( n -2), itd. Kontynuuj, aż n będzie 1.
  3. Dane wyjściowe są sumą wszystkich tych razem.

Na przykład:

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

Zasady konkursu:

  • Jeśli po przecinku 1 / n nie ma n cyfr po przecinku, brakujące będą liczone jako 0 (tj 1/2 = 0.50 => (5+0) + (5) = 10.).
  • Bierzesz cyfry bez zaokrąglania (tzn. Cyfry 1/6166666i nie 166667)

Główne zasady:

  • Do odpowiedzi mają zastosowanie standardowe reguły , więc możesz używać STDIN / STDOUT, funkcji / metody z odpowiednimi parametrami, pełnych programów. Twoja decyzja.
  • Domyślne luki są zabronione.
  • Jeśli to możliwe, dodaj link z testem swojego kodu.
  • W razie potrzeby dodaj również wyjaśnienie.

Pierwsze 1–50 w sekwencji:

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

Ostatnie 24990 - 25000 w sekwencji:

1405098782, 1417995426, 1364392256, 1404501980, 1408005544, 1377273489, 1395684561, 1405849947, 1406216741, 1142066735, 99984
Kevin Cruijssen
źródło
8
Czy ktoś wspomniał moje imię?
Kevin

Odpowiedzi:

6

Galaretka , 9 bajtów

R⁵*:%⁵+\S

Raczej powolny, ale krótki. Wypróbuj online! lub sprawdź pierwsze 50 przypadków testowych .

Jak to działa

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.
Dennis
źródło
15

Mathematica, 42 bajty

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

lub

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

lub

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

Wyjaśnienie

Weź przykład ze specyfikacji wyzwania. Chcemy obliczyć:

  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

Zmiana układu to:

  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)

gdzie .jest iloczyn skalarny dwóch wektorów.

To prawie wszystko rozwiązanie.

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

Daje nam to pierwsze Ncyfry dziesiętne 1/N( #&@@wyodrębnia pierwszy element RealDigitswyniku, ponieważ zwraca również przesunięcie pierwszej cyfry, o którą nie dbamy).

Następnie otrzymujemy listę od Ndołu do 1albo za pomocą (#-Range@#+1)albo Range[#,1,-1], oba są krótsze niż Reverse@Range@#, i bierzemy iloczyn skalarny.

Zamiast tego alternatywne rozwiązanie Accumulateoblicza listę wszystkich sum prefiksów, a następnie sumuje te sumy prefiksów Tr.

Ponieważ jest to naprawdę szybkie nawet w przypadku dużych danych wejściowych, oto wykres rozproszenia sekwencji do N = 100,000(zrobienie ich wszystkich i wykreślenie ich zajęło jednak trochę czasu):

wprowadź opis zdjęcia tutaj
Kliknij, aby zobaczyć większą wersję.

Niebieska linia to naiwna górna granica 9 N (N+1) / 2(jeśli wszystkie cyfry dziesiętne były 9), a pomarańczowa linia to dokładnie połowa tej granicy. Nic dziwnego, że jest to bezpośrednio w głównej gałęzi wykresu, ponieważ statystycznie spodziewalibyśmy się, że średnia cyfra wyniesie 4,5.

Cienka linia punktów wykresu widoczna poniżej głównej gałęzi to ułamki, które kończą się ...3333..., ponieważ wszystkie leżą bardzo blisko siebie 3 N (N+1) / 2.

Martin Ender
źródło
Bardzo ładna odpowiedź i uwielbiam wykresy! To prawie niefortunne, że to nie jest najkrótszy i nie mogę zaakceptować tego jako odpowiedzi. :) Jeśli nie zapomnę, mogę w ciągu dwóch dni zarobić małą nagrodę za odpowiedź na coś więcej niż zwykłe zadanie, które podałem.
Kevin Cruijssen
1
@KevinCruijssen Thanks! :)
Martin Ender,
6

05AB1E , 12 11 bajtów

Di<ë°¹÷.pSO

Wypróbuj online! lub pakiet testowy dla pierwszych 50 numerów.

Wyjaśnienie

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

Bardziej wydajna wersja do wypróbowywania dużych liczb w TIO

Różnica w stosunku do krótszej wersji polega na tym, że sumujemy iloczyn cyfr i odwrócenie ich indeksu opartego na 1 zamiast sumowania cyfr w prefiksach.

Di<ë°¹÷SDgLR*O

Wypróbuj online!

Emigna
źródło
5

Java 8, 181 169 166 153 153 142 bajtów

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

Wyjaśnienie:

Wypróbuj tutaj.

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
Kevin Cruijssen
źródło
4

PHP, 66 65 bajtów

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

Na podstawie tej odpowiedzi (również przeze mnie): Podział niezbyt małych liczb i sugerowana edycja Jörga Hülsermanna. Użyj jak:

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

edycja: poprawiono błąd dla +1 bajtów i spasował przypisanie $ a do $ argv [1] dla -2 bajtów dla 1 bajta mniej netto.

użytkownik59178
źródło
3

Scala, 84 bajtów

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

Nie golfowany:

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

Wyjaśnienie:

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

Mógłbym zaoszczędzić kilka bajtów, wykorzystując sposób, w jaki kompilator tokenizuje: Wywołując argument &, możesz pisać 1 to&mapzamiast 1 to n map. Ta sama zasada dotyczy def?.

corvus_192
źródło
3

Galaretka , 11 bajtów

’aµR⁵*:µDFS

TryItOnline
First 50

Zbyt wolny dla dużych przypadków testowych.

W jaki sposób?

’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
Jonathan Allan
źródło
2
Nie sądzę, żebym kiedykolwiek widział odpowiedź na galaretkę, w której wyjaśnienie jest linią prostą ;-)
ETHproductions
Zrobiłem prawie umieścić R⁵*jako ekwiwalent od lewej do prawej, ale potem ten piękny prostą :)
Jonathan Allan
3

PHP, 76 bajtów

(Edytuj -1 bajtów - Dzięki użytkownik 59178 - Twoje rozwiązanie jest jeszcze lepsze)

for($c=substr(bcdiv(1,$a=$argv[1],$a),2);$i<$a;)$s+=($a-$i)*$c[$i++];echo$s;
Crypto
źródło
możesz zapisać bajt (średnik), przenosząc $c=blahdo pierwszej częścifor(;;)
user59178
2

MATL, 19 bajtów

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

Wypróbuj online!

Wyjaśnienie

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

Groovy, 87 bajtów

Było to mniej bolesne niż się spodziewałem i opiera się na mojej odpowiedzi tutaj :

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

Wyjaśnienie

1.0g - Użyj notacji BigDecimal dla tego jednego.

.divide(n, n, 1)+"" - Podziel przez n z dokładnością n (tylko funkcja BigDecimal) i przekonwertuj na str.

(...)[2..x+1].getChars() - Pobierz podciąg bieżącej iteracji jako tablicę znaków char.

.sum()-48*(x)- Zsumuj wartości ASCII znaków i zmniejsz o 48 dla każdego elementu. To zmienia wartość z cyfry ASCII na liczbę całkowitą, zasadniczo oszczędzając bajty *.toInteger().

(1..n).collect{...}.sum() - Iteruj po każdej cyfrze w podziale, wykonując tę ​​funkcję, umieść je wszystkie w jednej tablicy i sumie.

Zaoszczędzono 2 bajty i poświęcono wydajność ...

Jest to bardziej wydajna wersja, która nie przelicza BigDecimal przy każdej iteracji.

{n->i=1.0g.divide(n, n, 1)+"";(1..n).collect{x->i[2..x+1].getChars().sum()-48*(x)}.sum()}
Urna Magicznej Ośmiornicy
źródło
2

J, 27 bajtów

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

Stosowanie

Dane wejściowe to rozszerzona liczba całkowita.

   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

Wydajność jest dobra i wymaga tylko około 3 sekund na obliczenie dużych przypadków testowych.

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

Wyjaśnienie

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

Galaretka , 10 bajtów

⁵*:⁸D+\_ỊS

Nie najkrótsze podejście , ale dość wydajne. Wypróbuj online! lub zweryfikuj wszystkie przypadki testowe .

Jak to działa

⁵*:⁸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.
Dennis
źródło
1

Python 2, 90 bajtów

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

Niezbyt ładne, ale zrobione przez dzielenie zmiennoprzecinkowe, a następnie konwersję na ciąg, a następnie iteracyjny wybór indeksu ciągów, aby uzyskać trójkąt liczb, a następnie wykonać odczyt listy i przekonwertować każdy znak na liczbę całkowitą, a na końcu zsumować je wszystkie.

Zoo Zoo
źródło
1

JavaScript (ES6), 47 bajtów

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

Jak to działa

Ta odpowiedź pokazuje technikę obliczania c cyfr dziesiętnych a / b :

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

Będzie to doskonały punkt wyjścia do tego wyzwania. Najpierw możemy go nieco zmienić, aby obliczał b cyfry dziesiętne 1 / b , zmieniając kolejność parametrów i ustawiając wartości domyślne:

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

Następnie możemy to zmienić, tak aby obliczał sumę pierwszych b cyfr dziesiętnych, zamiast je łączyć (eliminuje to dparametr):

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

Jesteśmy prawie na rozwiązaniu; teraz musimy tylko pomnożyć każdą cyfrę przez c + 1 :

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

Hmm, to wydaje się trochę długie. Co jeśli zwiększymy c o 1 na początek?

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

To oszczędza jeden bajt. A oto sposób na uratowanie jeszcze jednego:

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

A teraz mamy naszą odpowiedź. f(7)to 103, f(11)to 270, f(1)to ... 2? Och, zapomnieliśmy wziąć pod uwagę przypadek, w którym a / b wynosi 1 przy pierwszej iteracji (tj. B wynosi 1). Zróbmy coś z tym:

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

1 mod b wynosi zawsze 1 , chyba że b wynosi 1 , w którym to przypadku będzie wynosić 0 . Nasz program jest teraz poprawny dla wszystkich danych wejściowych, przy 47 bajtach .

ETHprodukcje
źródło
1

Python 2, 49 bajtów

lambda n:sum(10**-~k/n%10*(n-k)for k in range(n))

Przetestuj na Ideone .

Dennis
źródło
0

C, 53 bajty

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

Poniżej głównej do wykonania testu ...

//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
źródło
Dlaczego ktoś tak głosuje? to dlatego, że jakiś błąd? czy to dlatego, że nie znajduję odpowiedniej minuty dla niego? Dla mnie ta liczba znaków jest wystarczająca i ok, cacel, i odpowiedź, podobnie jak druga, w której nie mogę mówić
RosLuP,
3
Jak inni skomentowali twoje inne odpowiedzi, celem golfa jest sprowadzenie kodu tak krótko, jak to możliwe , ale nadal dołączasz kilka makr bez powodu. f(n,i,x,s){while(i)x=10*(x%n),s+=i--*(x/n);return s;}ma tylko 53 bajty.
Dennis,