逆コロンビア関数


28

シーケンスを定義しましょう:n桁の加算シーケンス(n-DSS)は、nで始まるシーケンスです。最後の数がkの場合、次の数はk + digit-sum(k)です。最初のいくつかの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の場合、これはA004207です。ただし、定義がわずかに異なるため、最初の数桁は異なります。3の場合、A016052です。9、A016096の場合

今日の課題は、特定の数値が現れる最下位n桁の合計シーケンスを見つけることです。これは、「コロンビア逆関数」と呼ばれ、A036233です。1から始まる最初の20の用語は次のとおりです。

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

他のいくつかの良いテストケース:

117: 9
1008: 918

0より大きい整数のみを処理する必要があり、任意の標準形式で入出力を行うことができます。いつものように、これはなので、各言語で最短の回答が勝ちます。


回答:


12

Haskell104 64 63バイト

(H.PWizに-26に感謝、Sriotchilism O'Zaicに-14に感謝、コールに-1を感謝)

これは機能です。

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

オンラインでお試しください!


説明:

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

y + yのデジタル和を返す合成関数のシーケンス。最初に文字列に変換してから、いくつかのモナド体操を行って、文字と元の数字の合計を取得します(Coleに感謝)。

<*>このコンテキストの演算子には、タイプと定義があります

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

上記のように書くことができます

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

これによりaが数値にread . pure変換Charされるため(+) . read . pure :: Char -> Int -> Int、累積値に数字が追加されます。この値は、フォールド内の指定された数値に初期化されます。

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

until最初の引数の関数で指定された要件を満たすまで、結果(この場合はy + digital sum y)に関数を繰り返し適用します。これにより、x以上の最小のy-DSS要素が得られます。

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

最小のy-DSS要素> = xが実際にはxであるようなyの無限遅延リスト。Haskellのリスト内包表記法を使用します(これも完全に忘れてしまいました、ありがとうございました)。

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

そのリストの最初の要素。チャレンジの要件を満たす最小のyです。


1
ここに私がそれをゴルフした方法があります。
H.PWiz

1
@ H.PWiz これは同じでしょうか? 私はそう思うだろうが、fmapそもそもあなたの使用は私を少し混乱させる。
ウィートウィザード

1
OK、それは多くのfenanglingをとりましたが、私はシングルバイトを削るためにリーダーモナドを乱用しました。Woohooポイントフリーコード!TIO
コール

@ SriotchilismO'Zaicクール。私はちょうどそれについて考えずに、機械的にコードをgolfed
H.PWiz

1
モバイルでリクエストを編集する方法がわからないため、コードの説明で編集したばかりです。変更またはロールバックしてください。
コール


4

Perl 6、44バイト

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

オンラインでお試しください!

入力を含むシーケンスが見つかるまですべてのシーケンスをチェックする単純なソリューション

説明:

->\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バイト

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

オンラインでお試しください!または、最初の20個の値を確認します

説明

入力のi場合、これは-thシーケンスのn最初のi項がを含むまで増加し続けnますiiシーケンスが増加しているため、各シーケンスの用語をテストするだけで十分です。

`         % 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

Forth(gforth)、106バイト

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

オンラインでお試しください!

コードの説明

: 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バイト

fqQ.W<HQ+ssM`

ここで試してみるか、テストスイートをチェックしてください。


使い方

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
うまくできfqQ.W<HQ+sjZ10ました。14でした。整数から数字を取得する方法として `とsを忘れてしまいました。
ソク

3

ゼリー、9 バイト

DS+)i$ƬṖṪ

正の整数nを生成する正の整数を受け入れる単項リンクa(n)、の逆コロンビアn

オンラインでお試しください!または、テストスイートを参照してください。

どうやって

効果的に逆方向に作業を行い、値が見つからなくなるまで追加した値を繰り返し探します。

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例として使用しています...

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バイト

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

オンラインでお試しください!

これは、すべてのテストケース、およびOEISで指定されたすべての1..88エントリで確実に機能します。しかし、それが確かに正しいかどうかはまだよくわかりません。(これは、ユニットテストの教会に関する私の苦情の1つです)。


dバツバツCssC0=;Cs=Cs1+ΣdCs1バツ>1edバツe1edバツe0Σdバツ1

SCS=nΣdCs11<nSSSSna.index(n)

@Value Ink:ロジャー!それは完全に機能します。ありがとう!
チャスブラウン


2

MathGolf、13バイト

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

オンラインでお試しください!

素晴らしい挑戦です!MathGolfの暗黙的なポップ動作にいくつかのバグが見つかり、ソリューションに1〜2バイト追加されました。

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)

これが常に機能することを証明するn <= inputためinputに、inputthシーケンスの最初の要素であるため、簡単にわかります。このソリューションが常に有効であることを技術的に証明していませんが、テストしたすべてのテストケースに合格しています。



1

クリーン、86バイト

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

オンラインでお試しください!

拡張:

$ 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`
  ]

それdigitToInt dよりも長いのは気になりますtoInt d-48





1

Japt15 14バイト

input=output私を悩ませるケースを処理するための三者!

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

それを試してみてください

@Ç?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バイト

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

オンラインでお試しください!

説明

=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

Forth(gforth)、99バイト

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

オンラインでお試しください!

reffuの送信(106バイト)とほぼ同様。ゴルフパーツは次のとおりです。

  • 数字の合計の計算(-6)
  • ゴミを標準出力に出力することによる最終クリーンアップ(-1)。(結果はスタックの一番上に返されるため、問題はありません。)

使い方

: 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

、26バイト

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

オンラインでお試しください!リンクは、コードの詳細バージョンです。@ChasBrownのアルゴリズムを使用します。それが無効であることが判明した場合、29バイトの場合:

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

オンラインでお試しください!リンクは、コードの詳細バージョンです。各桁の合計シーケンスの最初のメンバーを計算することにより動作しますn。説明:

Nθ

入力n

W¬№υθ«

を含む数字の合計シーケンスが見つかるまでループしますn

≔⊕Lυη

次のシーケンスは、これまでのシーケンスの数よりも1つ多く始まります。

W‹ηθ

シーケンスのメンバーが未満の間にループしnます。

≧⁺Σηη

桁の合計を追加して、シーケンスの次のメンバーを取得します。

⊞υη

最後のメンバーをリストにプッシュします。

»ILυ

を含むリストが見つかるまで計算されたリストの数を出力しますn




0

ガイア、16バイト

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

オンラインでお試しください!

最小の整数を含むリストを返します。

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

ガイア、16バイト

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

オンラインでお試しください!

Xcoder氏の観察を使用します。他のものより短くはありませんが、それでもなお興味深いアプローチです。

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

ガイア、16バイト

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

オンラインでお試しください!

第三のアプローチを使用していないN-find#が、それでも中央のアプローチと同じ観察に頼ります。リストではなく整数を返します。


0

Clojure、106バイト

#(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)))))

オンラインでお試しください!

これは99バイトですが、大きな入力でスタックオーバーフローが発生します(JVMを調整すると役立つ場合があります)。

#((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

インク130 127バイト

-(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

オンラインでお試しください!

  • -3 bytes 単項入力を受け取る完全なプログラムに変換することにより。

これは長すぎてゴルフできないように感じます。

非ゴルフ

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.