Inverse kolumbianische Funktion


28

Definieren wir eine Sequenz: Die n-stellige Summierungssequenz (n-DSS) ist eine Sequenz, die mit n beginnt . Wenn die letzte Zahl k war , dann ist die nächste Zahl k + Ziffernsumme (k) . Hier sind die ersten paar 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...

Für 1 ist dies A004207 , obwohl sich die ersten Ziffern aufgrund einer leicht abweichenden Definition unterscheiden. Für 3 ist es A016052 ; für 9, A016096 .

Die heutige Herausforderung besteht darin, die niedrigste n-stellige Summenfolge zu finden, in der eine bestimmte Zahl vorkommt. Dies wird als "Inverse Colombian Function" bezeichnet und lautet A036233 . Die ersten zwanzig Begriffe, beginnend mit 1, sind:

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

Einige andere gute Testfälle:

117: 9
1008: 918

Sie müssen nur Ganzzahlen verarbeiten, die größer als 0 sind, und Sie können Eingaben und Ausgaben in jedem Standardformat vornehmen. Wie üblich ist dies , daher gewinnt die kürzeste Antwort in jeder Sprache.


Antworten:


12

Haskell , 104 64 63 Bytes

(-26 danke an H.PWiz, zusätzlich -14 danke an Sriotchilism O'Zaic, zusätzlich -1 danke an cole)

Dies ist eine Funktion.

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

Probieren Sie es online!


Erläuterung:

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

Folge von zusammengesetzten Funktionen, die y + digitale Summe von y zurückgeben. Konvertiert zuerst in eine Saite und macht dann eine Monadenturnung, um die Summe der Zeichen und der ursprünglichen Zahl zu erhalten (danke an Cole).

Der <*>Operator hat in diesem Zusammenhang Typ und Definition

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

so können wir das oben genannte als schreiben

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

Dies read . purewandelt a Charin eine Zahl um und (+) . read . pure :: Char -> Int -> Intaddiert somit eine Ziffer zu einem akkumulierten Wert. Dieser Wert wird auf die angegebene Nummer im Falz initialisiert.

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

untilWendet wiederholt eine Funktion auf das Ergebnis an (in diesem Fall y + digitale Summe y), bis eine Anforderung erfüllt ist, die im ersten Argument durch eine Funktion angegeben ist. Dies ergibt das kleinste y-DSS-Element, das größer oder gleich x ist.

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

Unendlich faule Liste von ys, so dass das kleinste y-DSS-Element> = x tatsächlich x ist. Verwendet die Listenverständnisnotation von Haskell (die ich auch völlig vergessen habe, danke).

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

Erstes Element dieser Liste, das kleinste y, das die Anforderung der Herausforderung erfüllt.


1
Hier ist, wie ich es Golf gespielt habe.
H.PWiz

1
@ H.PWiz Das sollte doch gleich sein nein? Ich denke schon, aber Ihre Verwendung von fmapin erster Linie verwirrt mich ein bisschen.
Weizen-Assistent

1
OK, es hat eine Menge Fenangling gekostet, aber ich habe die Lesermonade missbraucht, um ein einzelnes Byte zu entfernen. Woohoo pointfree Code! TIO
Cole

@ SriotchilismO'Zaic Cool. Ich habe den Code nur mechanisch gespielt, ohne darüber nachzudenken
H.PWiz

1
Ich bin mir nicht sicher, wie ich eine Anfrage auf dem Handy bearbeiten soll, daher habe ich sie nur in einer Erklärung meines Codes bearbeitet. Sie können sie jederzeit ändern oder zurücksetzen.
Cole


4

Perl 6 , 44 Bytes

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

Probieren Sie es online!

Naive Lösung, die jede Sequenz überprüft, bis eine gefunden wird, die die Eingabe enthält

Erläuterung:

->\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-}@

Probieren Sie es online! Oder überprüfen Sie die ersten 20 Werte .

Erläuterung

Für die Eingabe iist dies so lange erforderlich, nbis die ersten iTerme der n-ten Sequenz enthalten sind i. Es ist ausreichend, iTerme für jede Sequenz zu testen , da die Sequenz zunimmt.

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

Viertens (gviertens) , 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
;

Probieren Sie es online!

Code-Erklärung

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

fqQ.W<HQ+ssM`

Probieren Sie es hier aus oder schauen Sie sich die Testsuite an .


Wie es funktioniert

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
Gut gemacht, ich hatte fqQ.W<HQ+sjZ10für 14. Ich vergesse immer wieder über `und s als eine Möglichkeit, Ziffern von einer ganzen Zahl zu bekommen!
Sok

3

Gelee , 9 Bytes

DS+)i$ƬṖṪ

Ein monadischer Link, der eine positive Ganzzahl akzeptiert, die eine positive Ganzzahl nergibt a(n), der inverse Kolumbianer von n.

Probieren Sie es online! Oder sehen Sie sich die Testsuite an .

Wie

Wir arbeiten effektiv rückwärts und suchen wiederholt nach dem Wert, den wir hinzugefügt haben, bis wir keinen mehr finden:

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

Am 13Beispiel ...

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

Probieren Sie es online!

Dies funktioniert auf jeden Fall für alle Testfälle sowie für alle 1..88 Einträge bei OEIS. Aber ich bin mir nicht ganz sicher, ob es nachweislich richtig ist. (Dies ist eine meiner Beschwerden bezüglich der 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! Das funktioniert total. Vielen Dank!
Chas Brown


2

MathGolf , 13 Bytes

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

Probieren Sie es online!

Große Herausforderung! Es führte dazu, dass ich einige Fehler im impliziten Pop-Verhalten von MathGolf fand, die der Lösung 1-2 Bytes hinzufügten.

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)

Um zu beweisen, dass dies immer funktioniert, ist dies leicht zu erkennen n <= input, da inputes sich um das erste Element der inputdritten Sequenz handelt. Ich habe technisch nicht bewiesen, dass diese Lösung immer gültig ist, aber sie besteht jeden Testfall, den ich getestet habe.



1

Sauber , 86 Bytes

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

Probieren Sie es online!

Erweitert:

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

Mich stört das digitToInt dlänger alstoInt d-48





1

Japt , 15 bis 14 Bytes

Die ternären Fälle zu behandeln, wo input=outputmich nervt!

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

Versuch es

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

Probieren Sie es online!

Erläuterung

=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

Viertens (gviertens) , 99 Bytes

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

Probieren Sie es online!

Weitgehend ähnlich zu reffus Submission (106 Bytes) . Die Golfplätze sind:

  • Ziffernsummenberechnung (-6)
  • Endgültige Bereinigung (-1) durch Drucken von Müll nach stdout. (Kein Problem, da das Ergebnis oben im Stapel zurückgegeben wird.)

Wie es funktioniert

: 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

Holzkohle , 26 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Verwendet den @ ChasBrown-Algorithmus. Wenn sich herausstellt, dass das ungültig ist, dann für 29 Bytes:

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Berechnet das erste Glied jeder Ziffernsummierungssequenz mit mindestens n. Erläuterung:

Nθ

Eingabe n.

W¬№υθ«

Schleife, bis wir eine Ziffernsummierungsfolge finden, die enthält n.

≔⊕Lυη

Die nächste Sequenz beginnt mit eins mehr als die Anzahl der Sequenzen.

W‹ηθ

Schleife, während das Mitglied der Sequenz kleiner als ist n.

≧⁺Σηη

Addieren Sie die Ziffernsumme, um das nächste Mitglied der Sequenz zu erhalten.

⊞υη

Schieben Sie das letzte Mitglied in die Liste.

»ILυ

Gibt die Anzahl der berechneten Listen aus, bis wir eine gefunden haben, die enthält n.




0

Gaia , 16 Bytes

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

Probieren Sie es online!

Gibt eine Liste mit der kleinsten Ganzzahl zurück.

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@⟨:):Σ++⟩ₓĖ⟩#

Probieren Sie es online!

Verwendet die Beobachtung von Herrn Xcoder . Es ist nicht kürzer als das andere, aber es ist trotzdem ein interessanter Ansatz.

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

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

Probieren Sie es online!

Dritter Ansatz, der nicht verwendet N-findwird #, sich jedoch auf dieselbe Beobachtung stützt wie der mittlere Ansatz. Gibt eine Ganzzahl anstelle einer Liste zurück.


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

Probieren Sie es online!

Dies sind 99 Bytes, führt jedoch bei größeren Eingaben zu einem Stapelüberlauf (möglicherweise hilft das Optimieren der 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

Tinte , 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

Probieren Sie es online!

  • -3 bytes durch Konvertieren in ein vollständiges Programm, das unäre Eingaben benötigt.

Das fühlt sich zu lang an, um nicht golfen zu können.

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)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.