Função Colombiana Inversa


28

Vamos definir uma sequência: a seqüência de soma de n dígitos (n-DSS) é uma sequência que começa com n . Se o último número for k , o próximo número será k + soma dos dígitos (k) . Aqui estão os primeiros 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...

Para 1, esse é A004207 , embora os primeiros dígitos sejam diferentes devido a uma definição ligeiramente diferente. Para 3, é A016052 ; para 9, A016096 .

O desafio de hoje é encontrar a menor seqüência de soma de n dígitos em que um determinado número aparece. Isso é chamado de "Função Colombiana Inversa" e é A036233 . Os primeiros vinte termos, começando com 1, são:

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

Alguns outros bons casos de teste:

117: 9
1008: 918

Você só precisa manipular números inteiros maiores que 0 e pode receber entrada e saída em qualquer formato padrão. Como sempre, esse é o , e a resposta mais curta em cada idioma vence.


Respostas:


12

Haskell , 104 64 63 bytes

(-26 graças a H.PWiz, -14 graças a Sriotchilism O'Zaic, -1 adicionais a cole)

Esta é uma função.

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

Experimente online!


Explicação:

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

Sequência de funções compostas que retornam y + soma digital de y. Converte primeiro a string e depois faz ginástica de mônada para obter a soma dos caracteres e o número original (graças a Cole).

O <*>operador neste contexto possui tipo e definição

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

para que possamos escrever o acima como

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

Isso read . pureconverte a Charem número e, portanto, (+) . read . pure :: Char -> Int -> Intadiciona um dígito a um valor acumulado. Este valor é inicializado para o número especificado na dobra.

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

untilaplica repetidamente uma função ao seu resultado (nesse caso, y + soma digital y) até atender a um requisito especificado por uma função no primeiro argumento. Isso fornece o menor elemento y-DSS maior ou igual a x.

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

Lista preguiçosa infinita de y, de modo que o menor elemento y-DSS> = x seja realmente x. Usa a notação de compreensão de lista de Haskell (que eu também esqueci totalmente, obrigado a todos).

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

Primeiro elemento dessa lista, que é o menor y que satisfaz os requisitos do desafio.


1
Aqui está como eu jogava golfe.
H.PWiz 23/07

1
@ H.PWiz Este deve ser o mesmo não? Eu acho que sim, mas seu uso fmapem primeiro lugar me confunde um pouco.
Wheat Wizard

1
OK, foi preciso muita discussão, mas eu abusei da mônada do leitor para cortar um único byte. Woohoo código pointfree! TIO
cole

@ SriotchilismO'Zaic Cool. Eu apenas joguei o código mecanicamente, sem pensar nisso
H.PWiz 23/07

1
Não tenho certeza de como editar a solicitação no celular, então acabei de editar uma explicação do meu código - fique à vontade para alterar ou reverter.
cole


4

Perl 6 , 44 bytes

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

Experimente online!

Solução ingênua que verifica todas as seqüências até encontrar uma que contenha a entrada

Explicação:

->\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 bytes

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

Experimente online! Ou verifique os 20 primeiros valores .

Explicação

Para entrada i, isso continua aumentando naté que os primeiros itermos da n-ésima sequência sejam incluídos i. É suficiente testar itermos para cada sequência porque a sequência está aumentando.

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

Quarto (gforth) , 106 bytes

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

Experimente online!

Código Explicação

: 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

Pitão , 13 bytes

fqQ.W<HQ+ssM`

Experimente aqui ou confira a suíte de testes .


Como funciona

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
Bem feito, eu tinha fqQ.W<HQ+sjZ10por 14. Eu continuo esquecendo `es como uma maneira de obter dígitos de um número inteiro!
Sok

3

Geléia , 9 bytes

DS+)i$ƬṖṪ

Um link monádico que aceita um número inteiro positivo nque gera um número inteiro positivo a(n), o colombiano inverso de n.

Experimente online! Ou veja a suíte de testes .

Quão

Efetivamente, trabalhamos para trás, procurando repetidamente o valor que agregamos até não encontrarmos um:

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

Usando 13como exemplo ...

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 bytes

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

Experimente online!

Isso certamente funciona para todos os casos de teste, além de todas as 1..88 entradas fornecidas no OEIS; mas ainda não tenho certeza de que seja comprovadamente correto. (Essa é uma das minhas reclamações sobre a Igreja de testes de unidade :)).


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)

Valor @ Ink: Roger! Isso funciona totalmente. Obrigado!
Chas Brown


2

MathGolf , 13 bytes

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

Experimente online!

Grande desafio! Isso me levou a encontrar alguns bugs no comportamento pop implícito do MathGolf, que adicionou 1-2 bytes à solução.

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)

Para provar que isso sempre funcionará, é fácil ver isso n <= input, porque inputé o primeiro elemento da inputquinta sequência. Tecnicamente, não provei que esta solução é sempre válida, mas passa em todos os casos de teste que testei.



1

Limpo , 86 bytes

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

Experimente online!

Expandido:

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

Incomoda-me que digitToInt dseja mais do quetoInt d-48



1

JavaScript, 65 bytes

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

Experimente online!


Também funciona como C, mas custa mais um byte

C (gcc) , 66 bytes

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

Experimente online!



1

Japonês , 15 14 bytes

O ternário para lidar com casos em que input=outputestá me irritando!

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

Tente

@Ç?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 bytes

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

Experimente online!

Explicação

=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

Quarto (gforth) , 99 bytes

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

Experimente online!

Muito semelhante ao envio de reffu (106 bytes) . As peças golfadas são:

  • Cálculo da soma dos dígitos (-6)
  • Limpeza final (-1) imprimindo algum lixo no stdout. (Não há problema porque o resultado é retornado na parte superior da pilha.)

Como funciona

: 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

Carvão , 26 bytes

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

Experimente online! Link é a versão detalhada do código. Usa o algoritmo do @ ChasBrown. Se isso for inválido, então para 29 bytes:

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

Experimente online! Link é a versão detalhada do código. Funciona calculando o primeiro membro de cada sequência de soma de dígitos não inferior a n. Explicação:

Nθ

Entrada n.

W¬№υθ«

Faça um loop até encontrarmos uma sequência de soma de dígitos contendo n.

≔⊕Lυη

A próxima sequência começa com uma mais que o número de seqüências até agora.

W‹ηθ

Loop enquanto o membro da sequência é menor que n.

≧⁺Σηη

Adicione a soma dos dígitos para obter o próximo membro da sequência.

⊞υη

Envie o membro final para a lista.

»ILυ

Imprima o número de listas calculadas até encontrarmos uma que contenha n.




0

Gaia , 16 bytes

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

Experimente online!

Retorna uma lista contendo o menor número inteiro.

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 bytes

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

Experimente online!

Usa a observação feita pelo Sr. Xcoder . Não é mais curto que o outro, mas é uma abordagem interessante.

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 bytes

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

Experimente online!

Terceira abordagem não usando N-find, #mas ainda contando com a mesma observação que a abordagem do meio. Retorna um número inteiro em vez de uma lista.


0

Clojure , 106 bytes

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

Experimente online!

São 99 bytes, mas resultam em estouro de pilha em entradas maiores (talvez ajustar a JVM ajudaria):

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

tinta , 130 127 bytes

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

Experimente online!

  • -3 bytes convertendo para um programa completo que requer entrada unária.

Parece muito tempo para não ser jogável.

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)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.