哥伦比亚函数逆


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。以20开头的前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的整数,就可以采用任何标准格式进行输入和输出。像往常一样,这是,因此每种语言的最短答案都会获胜。


Answers:


12

Haskell104 64 63字节

(感谢H.PWiz,感谢-26,感谢奥利奇主义的-14,感谢科尔感谢的-1)

这是一个功能。

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

在线尝试!


说明:

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

返回y + y的数字和的复合函数序列。首先转换为字符串,然后进行一些monad体操以获得字符和原始数字的总和(感谢Cole)。

<*>在这种情况下,运算符具有类型和定义

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

所以我们可以这样写

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

read . pure会将a Char转换为数字,因此(+) . read . pure :: Char -> Int -> Int将一个数字添加到累加值中。该值被初始化为折叠中的给定数字。

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

until重复将函数应用于其结果(在本例中为y +数字和y),直到满足第一个参数中函数指定的要求为止。这给出了大于或等于x的最小y-DSS元素。

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

y的无限懒惰列表,使得最小的y-DSS元素> = x实际上是x。使用Haskell的列表理解表示法(我也完全忘记了,谢谢大家)。

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

该列表的第一个元素,是满足挑战要求的最小y。


1
是我打高尔夫球的方式。
H.PWiz

1
@ H.PWiz 这应该是一样的吗? 我会这样认为,但是您的使用fmap首先使我感到困惑。
小麦巫师

1
好的,这花了很多苦头,但是我滥用了读者monad来剃除一个字节。Woohoo毫无意义的代码!TIO
科尔

@ SriotchilismO'Zaic酷。我只是机械地打了代码,没有考虑它
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,这一直递增,n直到第i- n个序列的第一个项包括为止i。测试i每个序列的术语就足够了,因为该序列正在增加。

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

第四(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+sjZ1014岁。我一直忘记将`和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条目;但我依然不能肯定它是可证明是正确的。(这是我对单元测试教堂的投诉之一)。


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)

@Value墨水:罗杰!那完全有效。谢谢!
Chas Brown


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它是第inputn个序列的第一个元素。从技术上讲,我尚未证明此解决方案始终有效,但它确实通过了我测试过的每个测试用例。



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

JavaScript,65个字节

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

在线尝试!


它也可以用作C,但是要多花一个字节

C(gcc),66个字节

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

在线尝试!



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

第四(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)
  • 通过将一些垃圾输出到stdout进行最终清理(-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υη

下一个序列比到目前为止的序列数多一个。

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)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.