Funzione colombiana inversa


28

Definiamo una sequenza: la sequenza sommatoria di n cifre (n-DSS) è una sequenza che inizia con n . Se l'ultimo numero era k , il numero successivo è k + cifra-somma (k) . Ecco i primi 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...

Per 1, questo è A004207 , sebbene le prime cifre siano diverse a causa di una definizione leggermente diversa. Per 3, è A016052 ; per 9, A016096 .

La sfida di oggi è trovare la sequenza di somma n più bassa in cui appare un determinato numero. Questa è chiamata "Funzione colombiana inversa" ed è A036233 . I primi venti termini, a partire da 1 sono:

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

Alcuni altri buoni casi di test:

117: 9
1008: 918

Devi solo gestire numeri interi maggiori di 0 e puoi accettare input e output in qualsiasi formato standard. Come al solito, si tratta di , quindi vince la risposta più breve in ogni lingua.


Risposte:


12

Haskell , 104 64 63 byte

(-26 grazie a H.PWiz, ulteriori -14 grazie allo Sriotchilism O'Zaic, ulteriori -1 grazie a Cole)

Questa è una funzione

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

Provalo online!


Spiegazione:

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

Sequenza di funzioni composte che restituisce y + somma digitale di y. Prima si converte in corda, poi fa un po 'di ginnastica in monade per ottenere la somma dei personaggi e il numero originale (grazie a Cole).

L' <*>operatore in questo contesto ha tipo e definizione

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

così possiamo scrivere quanto sopra come

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

Questo read . pureconverte a Charin un numero, quindi (+) . read . pure :: Char -> Int -> Intaggiunge una cifra a un valore accumulato. Questo valore viene inizializzato sul numero indicato nella piega.

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

untilapplica ripetutamente una funzione al suo risultato (in questo caso, la y + somma digitale y) fino a quando non soddisfa un requisito specificato da una funzione nel primo argomento. Ciò fornisce l'elemento y-DSS più piccolo che è maggiore o uguale a x.

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

Elenco pigro infinito di y tale che l'elemento y-DSS più piccolo> = x sia effettivamente x. Usa la notazione di comprensione dell'elenco di Haskell (di cui mi ero anche completamente dimenticato, grazie a tutti).

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

Primo elemento di tale elenco, che è il più piccolo y che soddisfa il requisito della sfida.


1
Ecco come l'ho giocato a golf.
H.Piz,

1
@ H.PWiz Questo dovrebbe essere lo stesso no? Penserei di sì, ma il tuo uso fmapin primo luogo mi confonde un po '.
Wheat Wizard il

1
OK, ci sono voluti molti tentativi ma ho abusato della monade del lettore per radere via un singolo byte. Woohoo codice gratuito! TIO
Cole

@ SriotchilismO'Zaic Cool. Ho appena giocato a golf il codice meccanicamente, senza pensarci
H.Piz,

1
Non sono sicuro di come modificare la richiesta sul cellulare, quindi ho appena modificato una spiegazione del mio codice: sentiti libero di cambiare o ripristinare.
Cole


4

Perl 6 , 44 byte

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

Provalo online!

Soluzione ingenua che controlla ogni sequenza fino a quando non trova quella che contiene l'input

Spiegazione:

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

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

Provalo online! Oppure verifica i primi 20 valori .

Spiegazione

Per l'input i, questo continua ad aumentare nfino a quando i primi itermini della n-esima sequenza includono i. È sufficiente testare i itermini per ogni sequenza perché la sequenza è in aumento.

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

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

Provalo online!

Spiegazione del codice

: 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 byte

fqQ.W<HQ+ssM`

Provalo qui o controlla la suite di test .


Come funziona

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
Ben fatto, l'ho fatto fqQ.W<HQ+sjZ10per 14. Continuo a dimenticare `e s come un modo per ottenere cifre da un numero intero!
Ho

3

Gelatina , 9 byte

DS+)i$ƬṖṪ

Un collegamento monadico che accetta un numero intero positivo nche produce un numero intero positivo a(n), il colombiano inverso di n.

Provalo online! Oppure vedi la suite di test .

Come

In effetti, lavoriamo all'indietro, cercando ripetutamente il valore aggiunto fino a quando non riusciamo a trovarne uno:

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 13come esempio ...

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 byte

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

Provalo online!

Questo sicuramente funziona per tutti i casi di test, oltre a tutte le voci 1..88 fornite a OEIS; ma non sono ancora sicuro che sia dimostrabilmente corretto. (Questa è una delle mie lamentele riguardo la Church Of Unit Testing :)).


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 Ink: Roger! Funziona totalmente. Grazie!
Chas Brown,


2

MathGolf , 13 byte

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

Provalo online!

Grande sfida! Mi ha fatto trovare alcuni bug all'interno del comportamento pop implicito di MathGolf, che ha aggiunto 1-2 byte alla soluzione.

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)

Per dimostrare che funzionerà sempre, è facile vederlo n <= input, perché inputè il primo elemento della inputsequenza. Tecnicamente non ho dimostrato che questa soluzione sia sempre valida, ma supera tutti i casi di test che ho testato.



1

Pulito , 86 byte

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

Provalo online!

Allargato:

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

Mi dà fastidio che digitToInt dsia più lungo ditoInt d-48



1

JavaScript, 65 byte

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

Provalo online!


Funziona anche come C, ma costa un byte in più

C (gcc) , 66 byte

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

Provalo online!



1

Japt , 15 14 byte

Il ternario per gestire i casi in cui input=outputmi dà fastidio!

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

Provalo

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

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

Provalo online!

Spiegazione

=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 byte

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

Provalo online!

In gran parte simile alla presentazione di reffu (106 byte) . Le parti golfate sono:

  • Calcolo somma cifre (-6)
  • Pulizia finale (-1) stampando della spazzatura su stdout. (Nessun problema perché il risultato viene restituito nella parte superiore dello stack.)

Come funziona

: 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

Carbone , 26 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Utilizza l'algoritmo di ChasBrown. Se ciò risulta non valido, per 29 byte:

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Funziona calcolando il primo membro di ogni sequenza sommatoria di cifre non inferiore a n. Spiegazione:

Nθ

Input n.

W¬№υθ«

Ripeti finché non troviamo una sequenza di somma delle cifre contenente n.

≔⊕Lυη

La sequenza successiva inizia con una in più rispetto al numero di sequenze finora.

W‹ηθ

Effettua il ciclo mentre il membro della sequenza è inferiore a n.

≧⁺Σηη

Aggiungi la somma delle cifre per ottenere il membro successivo della sequenza.

⊞υη

Sposta il membro finale nell'elenco.

»ILυ

Stampa il numero di elenchi calcolati fino a quando non ne abbiamo trovato uno contenente n.




0

Gaia , 16 byte

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

Provalo online!

Restituisce un elenco contenente il numero intero più piccolo.

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 byte

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

Provalo online!

Usa l'osservazione fatta da Mr. Xcoder . Non è più breve dell'altro, ma è comunque un approccio 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 byte

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

Provalo online!

Il terzo approccio non utilizza N-find, #ma si basa ancora sulla stessa osservazione dell'approccio di mezzo. Restituisce un numero intero anziché un elenco.


0

Clojure , 106 byte

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

Provalo online!

Si tratta di 99 byte, ma si traduce in Stack Overflow su input più grandi (forse sarebbe utile modificare la 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

inchiostro , 130 127 byte

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

Provalo online!

  • -3 bytes convertendolo in un programma completo che accetta input unari.

Sembra troppo lungo per non essere golfabile.

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)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.