Ters Kolombiyalı Fonksiyonu


28

Bir dizi tanımlayalım: n basamaklı toplama dizisi (n-DSS) n ile başlayan bir dizidir . Son sayı k ise , bir sonraki sayı k + digit-sum (k) olur . İşte ilk n-DSS:

1-DSS: 1, 2, 4, 8, 16, 23, 28, 38, 49, 62, 70...
2-DSS: 2, 4, 8, 16, 23, 28, 38, 49, 62, 70, 77...
3-DSS: 3, 6, 12, 15, 21, 24, 30, 33, 39, 51, 57...
4-DSS: 4, 8, 16, 23, 28, 38, 49, 62, 70, 77, 91...
5-DSS: 5, 10, 11, 13, 17, 25, 32, 37, 47, 58, 71...
6-DSS: 6, 12, 15, 21, 24, 30, 33, 39, 51, 57, 69...
7-DSS: 7, 14, 19, 29, 40, 44, 52, 59, 73, 83, 94...
8-DSS: 8, 16, 23, 28, 38, 49, 62, 70, 77, 91, 101...
9-DSS: 9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99...

1 için, bu A004207 , ilk birkaç rakam biraz farklı bir tanım nedeniyle farklı olmasına rağmen. 3 için A016052 ; 9 için, A016096 .

Bugünün zorluğu, belirli bir sayının göründüğü en düşük n basamaklı toplam diziyi bulmaktır. Buna "Ters Kolombiya Fonksiyonu" denir ve A036233'tür . 1 ile başlayan ilk yirmi terim:

1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 5, 3, 5, 7, 3, 1, 5, 9, 7, 20

Bazı diğer iyi test durumları:

117: 9
1008: 918

Yalnızca 0'dan büyük tam sayıları işlemeniz gerekir ve herhangi bir standart biçimde girdi ve çıktı alabilirsiniz. Her zamanki gibi, bu , her dilde en kısa cevap kazanıyor.


Yanıtlar:


12

Haskell , 104 64 63 bayt

(-26 H.PWiz sayesinde, Sriotchilism O'Zaic sayesinde ek olarak -14, kola sayesinde ek -1)

Bu bir fonksiyondur.

f x=[y|y<-[1..],x==until(>=x)(foldr((+).read.pure)<*>show)y]!!0

Çevrimiçi deneyin!


Açıklama:

(foldr((+).read.pure)<*>show)

Y + sayısal y toplamını döndüren birleşik fonksiyonların sırası. Önce dizeye dönüştürür, sonra karakterlerin ve orijinal sayıların toplamını elde etmek için bazı monad jimnastikleri yapar (Cole sayesinde).

<*>Bu bağlamda kullanıcı tipi ve bir tanıma sahip

(<*>) :: (a -> b -> c) -> (a -> b) -> c
f <*> g = \x -> f x (g x)

bu yüzden yukarıdaki gibi yazabiliriz

\x -> foldr ((+) . read . pure) x (show x)

Bu, read . purea'yı Charsayıya dönüştürür , bu nedenle (+) . read . pure :: Char -> Int -> Intbirikmiş bir değere bir rakam ekler. Bu değer, katmanda verilen numaraya sıfırlanır.

until (>=x) {- digital sum function -} y

untililk argümandaki bir fonksiyon tarafından belirtilen bir gereksinimi yerine getirinceye kadar (bu durumda y + dijital toplamı y) sonucuna bir fonksiyon tekrar tekrar uygular. Bu, x'e eşit veya daha büyük olan en küçük y-DSS öğesini verir.

[y | y<-[1..]; x == {- smallest y-DSS element >= x -} ]

Y'nin sonsuz tembel listesi, en küçük y-DSS elemanı> = x aslında x olur. Haskell'in liste anlama gösterimini kullanır (ki ben de tamamen unutmuşum, hepinize teşekkür ederim).

f x = {- aforementioned list -} !! 0

Bu listenin ilk elemanı, meydan okuma şartını yerine getiren en küçük y.


1
İşte nasıl golf oynadım.
H.PWiz

1
@ H.PWiz Bu aynı olmalı mı? Öyle düşünürdüm ama fmapilk etapta kullanımınız beni biraz şaşırtıyor.
Buğday Sihirbazı

1
Tamam, çok fazla fenangling aldı, ancak okuyucu monad'i tek bir baytı tıraş etmek için suistimal ettim. Woohoo nokta kodu! TIO
cole

@ SriotchilismO'Zaic Cool. Kodu düşünmeden mekanik olarak
golf oynamıştım

1
Mobilde isteği nasıl düzenleyeceğimi bilmediğim için kodumun açıklamasında sadece bir düzenleme yaptım - değişiklik yapmaktan veya geri almaktan çekinmeyin.
cole


4

Perl 6 , 44 bayt

->\a{+(1...{a∈($_,{$_+.comb.sum}...*>a)})}

Çevrimiçi deneyin!

Girdi içeren bir tane bulana kadar her diziyi kontrol eden saf çözüm

Açıklama:

->\a{                                    }  # Anonymous code block taking input as a
     +(1...{                           })   # Find the first number
            a∈(                       )     # Where the input is an element of
                                ...         # The sequence
               $_,                          # Starting with the current number
                  {            }   # Where each element is
                   $_+             # Is the previous element plus
                      .comb.sum    # The digit sum
                                   *>a      # Until the element is larger than the input



3

MATL , 18 bayt

`@G:"ttFYAs+]vG-}@

Çevrimiçi deneyin! Veya ilk 20 değeri doğrulayın .

açıklama

Girişi için i, bu increqsing tutan nbirinci kadar ikoşulları ninci dizisine dahil i. iHer bir dizi için terimleri test etmek yeterlidir, çünkü dizi artmaktadır.

`         % Do...while
  @       %   Push iteration index, n. This is the firsrt term of the n-th sequence
  G:      %   Push [1 2 ... i], where i is the input
  "       %   For each (i.e., do the following i times)
    tt    %     Duplicate twice
    FYA   %     Convert to digits
    s     %     Sum
    +     %     Add to previous term. This produces a new term of the n-th sequence
  ]       %   End
  v       %   Concatenate all terms into a column vector
  G-      %   Subtract i, element-wise. This is the do...while loop condition (*).
}         % Finally (this is executed right before exiting the loop)
  @       %   Push current n. This is the output, to be displayed
          % End (implicit). A new iteration will start if all terms of (*) are nonzero
          % Display (implicit)

3

İleri (gforth) , 106 bayt

: f
>r 0 begin 1+ dup begin dup i < while dup begin 10 /mod >r + r> ?dup 0= until repeat i = until rdrop
;

Çevrimiçi deneyin!

Kod Açıklaması

: f                \ start a new word definition
  >r               \ store the input on the return stack for easy access
  0                \ set up a counter
  begin            \ start an indefinite loop
    1+ dup         \ add 1 to the counter and duplicate
    begin          \ start a 2nd indefinite loop
      dup i <      \ check if current value is less than the input value
    while          \ if it is, continue with the inner loop
      dup          \ duplicate the current value
      begin        \ innermost loop, used to get the digit-wise sum of a number
        10 /mod    \ get quotient and remainder of dividing by 10
        >r + r>    \ add remainder to current list value
        ?dup 0=    \ check if quotient is 0
      until        \ end the innermost loop if it is
    repeat         \ go back to the beginning of the 2nd loop
    i =            \ check if the "last" value of the current list = the input value
  until            \ if it does, we're done
  rdrop            \ remove the input value from the return stack
;                  \ end the word definition    

3

Pyth , 13 bayt

fqQ.W<HQ+ssM`

Burada deneyin veya test odasına bakın .


Nasıl çalışır

fqQ.W<HQ+ssM`     Full program. Takes input Q from STDIN, writes to STDOUT.
f{...}            Loop over 1,2,3,... and find the first number to yield truthy results when
                     applying the function {...} (whose variable is T = the current integer).
 qQ.W<HQ+ssM`     The function {...}, which will be analysed separately.
   .W             Functional while. While condition A is true, do B.
     <HQ          Cond. A (var: H - starts at T): Checks if H is less than Q.
        +ssM`     Func. B (var: G - G & H are the same): If A, G & H become G+digit sum(G)
                  The last value of this functional while will be the least possible number N
                  in the T-DSS that is greater than or equal to Q.
                  If N = Q, then Q ∈ T-DSS. Else (if N > Q), then Q ∉ T-DSS.
 q                That being said, check whether N == Q. 

nk1nnnk


1
Güzel, ben fqQ.W<HQ+sjZ1014 için vardı . Ben `ve 's bir tamsayı rakam almak için bir yol olarak unutmaya devam ediyorum!
Sok

3

Jöle , 9 bayt

DS+)i$ƬṖṪ

Ters Kolombiyalı, npozitif bir tamsayı üreten pozitif bir tamsayıyı kabul eden bir monadik Bağlantı .a(n)n

Çevrimiçi deneyin! Veya test odasına bakın .

Nasıl

Etkili bir şekilde geriye doğru çalışıyoruz, bir tane bulamadıkça art arda kattığımız değeri arıyoruz:

DS+)i$ƬṖṪ - Link: integer n
      Ƭ   - Repeat until a fixed point, collecting up:
     $    -   last two links as a monad - f(n):
   )      -     left links as a monad for each - [g(x) for x in [1..n]]:
D         -       decimal digits of x
 S        -       sum
  +       -       add x
    i     -     first (1-indexed) index of n in that list, or 0 if no found
       Ṗ  - pop of the rightmost value (the zero)
        Ṫ - tail

13Örnek olarak kullanmak ...

D  )  = [[1],[2],[3],[4],[5],[6],[7],[8],[9],[1,0],[1,1],[1,2],[1,3]]
 S    = [  1,  2,  3,  4,  5,  6,  7,  8,  9,    1,    2,    3,    4]
  +   = [  2,  4,  6,  8, 10, 12, 14, 16, 18,   11,   13,   15,   17]
    i 13 = .......................................... 11
    i 11 = .................................... 10
    i 10 = ............... 5
    i 5 = not found = 0 
    i 0 = not found = 0
    Ƭ -> [13, 11, 10, 5, 0]
    Ṗ =  [13, 11, 10, 5]
    Ṫ =               5

2

Python 2,85 bayt

f=lambda n,a=[]:n in a and a.index(n)or f(n,[k+sum(map(int,`k`))for k in a]+[len(a)])

Çevrimiçi deneyin!

Bu kesinlikle tüm test durumlarında ve OEIS'te verilen tüm 1..88 kayıtların hepsinde işe yarar; ama yine de oldukça bu kadar emin değilim kanıtlanabilir doğru. (Bu, Kilise Birim Testine ilişkin şikayetlerimden biri :).


d(x)xCi(s)isCi(0)=i;Ci(s)=Ci(s1)+Σd(Ci(s1))x>1ed(x)(e1)ed(x)(e0)Σd(x)1

S(i)Ci(S(i))=nΣd(Ci(s1))1i<inS(i),S(i)S(i)S(i)iiinia.index(n)

@ Değer Mürekkep: Roger! Bu tamamen işe yarıyor. Teşekkürler!
Chas Brown


2

MathGolf , 13 bayt

╒môk(É∙Σ+=k/)

Çevrimiçi deneyin!

Büyük zorluk! Bu, çözüme 1-2 bayt ekleyen MathGolf'un gizli pop davranışı içinde birkaç hata bulmama neden oldu.

3

╒               range(1,n+1) ([1, 2, 3])
 mô             explicit map using 6 operators
   k(           push input-1 to TOS
     É          start block of length 3 (repeat input-1 times)
      ∙Σ+       triplicate TOS, take digit sum of top copy, and add that to second copy
                This transforms the array items to their respective sequences instead
                Array is now [1, 2, 4, 2, 4, 8, 3, 6, 12]
         =      get index of element in array (the index of 3 is 6)
          k/    divide by input (gives 2)
            )   increment (gives the correct answer 3)

Bunun her zaman işe yarayacağını kanıtlamak için bunu görmek kolaydır n <= input, çünkü th sırasının inputilk elemanıdır input. Teknik olarak bu çözümün her zaman geçerli olduğunu ispat etmedim, ancak test ettiğim her test vakasını geçiyor.



1

Temiz , 86 bayt

import StdEnv
$n=hd[i\\i<-[1..]|n==while((>)n)(\j=j+sum[toInt d-48\\d<-:toString j])i]

Çevrimiçi deneyin!

Expanded:

$ n                    // function `$` of `n` is
 = hd [                // the first
   i                   // integer `i`
  \\                   // for
   i <- [1..]          // each integer from 1 upwards
  |                    // where 
   n ==                // `n` is equal to
   while ((>) n) (     // the highest value not more than `n` from
    \j = j + sum [     // `j` plus the sum of
      toInt d - 48     // the digital value
     \\                // for each
      d <-: toString j // digit in the string form of `j`
     ]                 // where `j` is the previous term
    )                  // of the sequence
   i                   // starting with term `i`
  ]

Daha digitToInt duzun olan beni rahatsız ediyortoInt d-48



1

JavaScript, 65 bayt

n=>eval('for(i=p=1;n-p;p=p>n?++i:p)for(j=p;j;j=j/10|0)p+=j%10;i')

Çevrimiçi deneyin!


Aynı zamanda C olarak da çalışır, ancak bir bayt daha maliyeti

C (gcc) , 66 bayt

i,p,j;f(n){for(i=p=1;n-p;p=p>n?++i:p)for(j=p;j;j/=10)p+=j%10;n=i;}

Çevrimiçi deneyin!



1

Japt , 15 14 bayt

input=outputBeni rahatsız eden davaları halletme üçlü !

@Ç?X±ìx:XÃøU}a

Dene

@Ç?X±ìx:XÃøU}a     :Implicit input of integer U
@                  :A function taking an integer X as its argument
 Ç                 :  Map each Z in the range [0,U)
  ?                :    If Z>0
   X±              :      Increment X by
     ì             :      Convert X to digit array
      x            :      Reduce by addition
       :X          :    Else X
         Ã         :  End map
          øU       :  Contains U
            }      :End function
             a     :Return the first integer that returns true when passed through that function

1

cQuents , 18 bayt

#|1:#bN;A
=A?Z+UDZ

Çevrimiçi deneyin!

açıklama

=A?Z+UDZ      second line - helper function
               first input = A
               second input = n
=A            first term is A
  ?           mode=query, return true if n in sequence, false if n not in sequence
              each term in the sequence equals
   Z+          previous term +
     U   )                     sum (                          )
      D )                            digits (               )
       Z                                      previous term

#|1:#bN;A     main program
               first input = A  (user input)
               second input = n
#|1           n = 1
   :          mode=sequence, return the nth term in the sequence
    #     )   conditional - next term equals next N that evaluates to true
              N increments, any terms that evaluate to true are added to the sequence
               conditional (                      )
     b   )                   second line (      )
      N;A                                  N, A

1

İleri (gforth) , 99 bayt

: f >r 0 begin 1+ dup begin dup i < while dup 20 for 10 /mod >r + r> next + repeat i = until r> . ;

Çevrimiçi deneyin!

Reffu'nun gönderimine büyük ölçüde benzer (106 bayt) . Golf parçaları:

  • Rakam toplamı hesaplaması (-6)
  • Son temizlik (-1), bazı atıkları stdout'a yazdırarak. (Sonuç yığının üstüne getirildiği için sorun değil.)

Nasıl çalışır

: dsum ( n -- n+digitsum ) \ Sub-function. Given n, add its digit sum to n.
  dup                      \ Copy n to form ( n m ) -> extract digits from m and add to n
  20 for                   \ Repeat 20 times (a 64-bit int is at most 20 digits)
    10 /mod >r + r>        \   n += m%10, m = m/10
  next + ;                 \ End loop and discard 0

: f ( n -- ans )    \ Main function.
  >r                \ Move n to the return stack, so it can be referenced using `i`
  0 begin 1+        \ Initialize counter and loop starting from 1
    dup begin       \   Copy the counter (v) and loop
      dup i < while \     break if v >= n
      dsum          \     v += digit sum of v
    repeat          \   End loop
  i = until         \ End loop if n == v
  r> . ;            \ Cleanup the return stack so the function can return correctly
                    \ `r> .` is one byte shorter than `rdrop`

0

Kömür , 26 bayt

NθW¬№υθ«UMυ⁺κΣκ⊞υ⊕Lυ»I⊕⌕υθ

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. @ ChasBrown'un algoritmasını kullanır. Bunun geçersiz olduğu ortaya çıkarsa, 29 bayt için:

NθW¬№υθ«≔⊕LυηW‹ηθ≧⁺Σηη⊞υη»ILυ

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. Her rakam toplama dizisinin ilk üyesini en az değil hesaplayarak çalışır n. Açıklama:

Nθ

Giriş n.

W¬№υθ«

İçinde bir rakam toplama dizisi bulana kadar döngü n.

≔⊕Lυη

Bir sonraki dizi, şimdiye kadarki dizi sayısından bir tanesiyle başlar.

W‹ηθ

Dizinin üyesi daha küçükken döngü n.

≧⁺Σηη

Sıralamanın bir sonraki üyesini almak için rakam toplamını ekleyin.

⊞υη

Son üyeyi listeye itin.

»ILυ

Bir tane bulana kadar hesaplanan liste sayısını yazdırın n.




0

Gaia , 16 bayt

1⟨⟨:@<⟩⟨:Σ+⟩↺=⟩#

Çevrimiçi deneyin!

En küçük tam sayıyı içeren bir liste döndürür.

1⟨	      ⟩#	% find the first 1 positive integers where the following is truthy:
	     =		% DSS equal to the input?
  	    ↺		% while
  ⟨:@<⟩			% is less than the input
       ⟨:Σ+⟩		% add the digital sum to the counter

Gaia , 16 bayt

1⟨w@⟨:):Σ++⟩ₓĖ⟩#

Çevrimiçi deneyin!

Bay Xcoder tarafından yapılan gözlemi kullanır . Diğerinden daha kısa değil, ancak yine de ilginç bir yaklaşım.

1⟨	      ⟩#	% find the first 1 integers z where:
  	     Ė		% the input (n) is an element of
  w@⟨:):Σ++⟩ₓ		% the first n terms of the z-th Digital Sum Sequence

Gaia , 16 bayt

┅ẋ⟨@⟨:):Σ++⟩ₓĖ⟩∆

Çevrimiçi deneyin!

Üçüncü yaklaşım kullanmıyor N-find, #fakat orta yaklaşımla aynı gözlemlemeye dayanıyor. Bir liste yerine bir tamsayı döndürür.


0

Clojure , 106 bayt

#(loop[j 1 i 1](if(= j %)i(if(< j %)(recur(apply + j(for[c(str j)](-(int c)48)))i)(recur(inc i)(inc i)))))

Çevrimiçi deneyin!

Bu 99 bayttır, ancak daha büyük girdilerde Yığın Taşması ile sonuçlanır (belki JVM'nin ayarını değiştirebilir):

#((fn f[j i](if(= j %)i(if(< j %)(f(apply + j(for[c(str j)](-(int c)48)))i)(f(inc i)(inc i)))))1 1)



0

mürekkep , 130 127 bayt

-(l)
+(i)[+]->l
*(w)[{i}]
~temp n=w
-(o){n<i:
~n+=s(n)
->o
}{n>i:->w}{w}
==function s(n)
{n>9:
~return n%10+s(n/10)
}
~return n

Çevrimiçi deneyin!

  • -3 bytes unary girdi alan tam bir programa dönüştürerek.

Bu golf oynamak için çok uzun.

Ungolfed

// This program takes unary input. It passes through the same choice prompt as long as it recieves 1, and execution begins when it recieves 2
-(input_loop)
+(input_value)[+] -> input_loop                 // When this option (option 1) is selected, its read count is incremented. We can access this via the "input_value" variable. We then return to the prompt by going back to the "input_loop" gather
*(which_sequence)[{i}]                          // When this option (option 2) is selected, execution begins. Its read count also serves to keep track of which DSS we're checking.
~temp current_value = which_sequence            // The initial value for the n-DSS is n, of course.
-(sequence)                                     //
{current_value < input_value:                   // If we're still below the value we're looking for, we might find it.
    ~ current_value += digit_sum(current_value) // To get the next number, we add the current number's digit sum
    -> sequence                                 // Then we loop
}
{n > i: -> which_sequence}                      // If we get here, we're at or above our target number. If we're above it, we know it's the wrong sequence and move on to the next one by going back up to option 2. This increments its read count.
{which_sequence}                                // If we get here, we've found the target number, so we output the sequence's number.
// End of main stitch, program ends.

// A function to calculate the digit sum of a number
== function digit_sum(n) ==
{n > 9: // If given a number greater than 9, recurse
    ~ return (n % 10) + digit_sum(n / 10)
}
~ return n // Otherwise, return the input (it's a single digit)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.