数値の桁差の合計を計算する


39

8675309などの負でない整数を取り、隣接する数字のすべてのペア間の差の絶対値を計算することを検討してください。

以下のために8675309我々が得ます|8-6| = 2|6-7| = 1|7-5| = 2|5-3| = 2|3-0| = 3|0-9| = 9。これらの結果をつなぎ合わせると、別のより小さな非負整数が得られます212239。プロセスを繰り返すと、が得られます110160115これは、先行ゼロが書き込まれないという規則により、、またはに115なり、これ以上削減することはできません。これらすべての値を合計すると、が得られます。0448675309 + 212239 + 11016 + 115 + 4 = 8898683

Digit Difference Sum(またはDDS)を、数字の数字の差分を繰り返して新しい数字を作成し、結果の数字をすべて元の数字に追加するこの操作として定義しましょう。

以下は、対応するDDSシーケンスの最初の20個の値です。

N   DDS(N)
0   0
1   1
2   2
3   3
4   4
5   5
6   6
7   7
8   8
9   9
10  11
11  11
12  13
13  15
14  17
15  19
16  21
17  23
18  25
19  27

最初の10000個の値は次のとおりです。

DDS 10000プロット

特に、1000または100にプロットしても同じように見えるため、

DDS 1000プロット

DDS 100プロット

(私はそれを歯科医の階段と呼びます...)

チャレンジ

非負の整数を取り込んで、そのDDS値を出力または返すプログラムまたは関数を作成します。たとえば、入力がの場合、出力は8675309である必要があります8898683

バイト単位の最短コードが優先されます。


歯科医の階段?
マーティン

12
@MartijnR歯科医の階段。
カルビンの趣味

@ Calvin'sHobbies矯正歯科の階段?
ベータ崩壊

1
@BetaDecay Dentistの階段。
アレックスA.

回答:


11

Pyth、17

s.ui.aM-VJjNTtJTQ

ここで試してみるか、テストスイートを実行してください

説明:

s.u            Q   # Cumulative reduce, i.e. getting the intermediate values of each reduce
                     step and returning them as a list, then sum the list
   i ... T         # Convert the resulting list of numbers into a base 10 number
   .aM             # Get the absolute value of each element of ...
      -VJjNTtJ     # Perform vector subtraction on the lists given by
        JjNT       # assign J the number we currently have converted to its base 10 digits
            tJ     # and J[1:]. e.x. for 123 we get J = [1,2,3] then we do
                   # zip(J,J[1:]) which gives [[1,2],[2,3]] then element wise subtract
                   # to get [-1, -1]

これは何語ですか?とても不可解です!T_T
asgs

1
@asgs PPCGへようこそ:)これはPythと呼ばれ、そのGithubページでインタープリターといくつかのドキュメントを見つけることができます。この言語のユーザーのほとんどは、あなたがそれについて質問をしてお気軽にしているそうだとすれば、このサイト上でアクティブなチャット部屋はそれに捧げ :)
FryAmTheEggman

17

Python 2、73

幸いなことに、文字列操作を避けることができました。

t=lambda n:n>9and abs(n%10-n/10%10)+10*t(n/10)
g=lambda n:n and n+g(t(n))

g 答えを計算する関数です。


4
この黒魔術とは?!
ベータ崩壊

7
@BetaDecayそれは「数学」と呼ばれています。
リルトシアスト

Pythonを十分に理解できていませんが、残りの操作を1回のヒットで両方の用語に適用できますか?つまり(n-n/10)%10、と同じように動作しn%10-n/10%10ますか?それとも多分(9*n/10)%10
グレンO

Pythonの@GlenO %は、剰余ではなく真のモジュラス演算子であるため、機能しません。
feersum

15

MATLAB、101の105バイト

ifをpolyval代わりに使用することを提案してくれた@beakerに感謝しますbase2dec。それで私は

  • 4バイトを節約します。
  • 任意のベースへの一般化を大幅に簡素化し(以下を参照)、そこに22バイトを保存します。そして何よりも、
  • 一般的なケースのコードが間違っていることを理解するのに役立ちました(先頭のゼロは削除されていません)。コードとグラフが正しくなりました。

コード:

function y=f(y)
x=+num2str(y);while numel(x)>1
x=polyval(abs(diff(x)),10);y=y+x;x=+dec2base(x,10);end

例:

>> f(8675309)
ans =
     8898683

ボーナス:任意のベース

小さな一般化により、必ずしも10進数ではなく、任意の基数を使用できます。

  • 2~10から任意の塩基、108の 104バイト

    function y=f(y,b)
    x=+dec2base(y,b);while numel(x)>1
    x=polyval(abs(diff(x)),b);y=y+x;x=+dec2base(x,b);end
    

    これはのみにベース用に働く理由は、10MATLABのことであるdec2base関数が使用する数字01、...、 、、9 、...、および文字から(ASCII)コード中のジャンプがありますには。AB9A

  • 2から36までの任意のベース、124 146バイト

    以下からのジャンプ9へのAニーズの特別な治療上に言及。最大ベースは36、Matlabのdec2base関数に基づいています。

    function y=f(y,b)
    x=+dec2base(y,b);x(x>57)=x(x>57)-7;while numel(x)>1
    x=abs(diff(x));x=x(find(x,1):end);y=y+polyval(x,b);end
    

これは、歯科医の階段がさまざまなベースを探す方法です。

ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください


1
これは私がやったことです...別の答えを考える時間です笑 +1。
rayryeng-モニカの復元

@rayryeng :-)ありがとう
ルイスメンドー

@BetaDecayありがとう!:-)彼らは確かに
ルイスメンドー

11

CJam、22 21バイト

ri_{\s2ew::-:zsi_@+}h

このプログラムはデフォルト許可されているエラーで終了することに注意してください。

Javaインタープリターでは、STDERRを閉じることでエラーを抑制することができます。CJamインタープリターでこのコードをオンラインで試す場合、最後の行の前のすべての出力を無視します。

元のリビジョンのエラーを指摘してくれた@ Sp3000に感謝します。

1バイトのゴルフをしてくれた@MartinBüttnerに感謝します。

実行例

$ cjam digit-difference.cjam 2>&- <<< 8675309     
8898683

使い方

ri_   e# Read an integer (I) from STDIN and push a copy (A).
{     e# Do:
  \   e#   Swap I on top of A.
  s   e#   Cast I to string.
      e#   For example, 123 -> "123".
  2ew e#   Push the overlapping slices of length 2 (pair of adjacent digits).
  ::- e#   Replace each pair by its difference.
  :z  e#   Apply absolute value to each difference.
  si  e#   Cast to string, then to integer. This is the new I.
      e#   For example, [1 2 3] -> "123" -> 123.
  _   e#   Push a copy of I.
  @   e#   Rotate A on top of the copy of I.
  +   e#   Add I to A, updating A.
}h    e# While A is truthy, repeat the loop.

によってチェックされるとき、Aは常に真実hです。しかし、一度私は一桁の整数である、2ewそれがコールされた配列を消費した後にエラーで失敗します。これにより、目的の結果のみがスタックに残り、終了する前に出力されます。


2
7分前に投稿:O
カルバンの趣味

10

ラビリンス176 134 127 119 103 97の 88 82 79 76 72バイト

1バイトを節約し、さらに2バイトの道を開いてくれたSp3000に感謝します。

これはおそらく短縮できますが、Java Matlab Pythonに勝っています...

?
_
)/:}+{:`};!
9       "
_ :}-"" :_10
;;{: `" "  :
  {  (_:/=%}
  0+;`"

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

これはエラーで終了しますが、エラーメッセージはSTDERRに書き込まれます(これがTIOに表示されない理由です)。

実装はかなり簡単です。現在の値を積算合計に追加します。現在の値がより大きい場合9、10進数を計算し(div-modを繰り返して)、絶対差から新しい数値を形成します。我々が取得する場合9以下、我々は、実行中の合計を印刷します。

現在の番号の桁は、最上位の桁が最上位にある補助スタックに収集されます。

さて、abs(...)私がここで行った派手な実装は、新しいソリューションと比較してとんでもないほど複雑であることが判明しました。


5

Java-300バイト

ゴルフバージョン

static Long t=new Scanner(System.in).nextLong();static char[]c=t.toString().toCharArray();public static void main(String[]z){while(c.length>1)s();System.out.print(t);}static void s(){String s="";for(int i=0;i<c.length-1;)s+=Math.abs(c[i]-c[++i]);Long a=new Long(s);t+=a;c=a.toString().toCharArray();}

Ungolfed /フルバージョン

import java.util.Scanner;

public class DigitDifference {

    static Long t = new Scanner(System.in).nextLong();
    static char[] c = t.toString().toCharArray();

    public static void main(String[] args){
        while( c.length > 1 )
            s();
        System.out.print(t);
    }

    static void s(){
        String s="";
        for(int i = 0; i < c.length-1;)
            s += Math.abs(c[i]-c[++i]);
        Long a = new Long(s);
        t += a;
        c = a.toString().toCharArray();
    }
}

@Loovjo、乾杯..
コーダー

1
PPCGへようこそ!これはまだ多くのことができます。私はロジックをあまり見ていませんが、1)あなたは本当に別のもの(またはその問題のための完全なプログラム/クラス)を本当に必要としないので、1つすべてを1つの関数staticに引き出します2)引き出した後にs を取り除きます3)のそれら(a+"")は一般にと同じa.toString()ですが、より短いです4)スキャナーが単なる機能である場合、スキャナーは必要ありません。入力に長い時間がかかります。
ジオビット

2
例えば、作業の多くを変更し、ただ嫌なものを削除せずに、それは164の周りです:long f(long t){long a=t;char[]c;while((c=(a+"").toCharArray()).length>1){String s="";for(int i=0;i<c.length-1;)s+=Math.abs(c[i]-c[++i]);t+=a=new Long(s);}return t;}
Geobits

2
@Geobits、それは驚くべき仲間でした。私はCode Golfが初めてなので、コードの効率を改善しようと思います。Cherrs ..
コーダー

5

ジュリア、81 60バイト

n->(s=n;while n>9 s+=n=int(join(abs(diff(["$n"...]))))end;s)

ゴルフをしていない:

function f(n::Int)
    # Initialize a sum to the input
    s = n

    while n > 9
        # Get absolute values of the pairwise differences of the
        # digits of n, join as a string, convert it to an integer,
        # and reassign n
        n = int(join(abs(diff(["$n"...]))))

        # ["$n"...] actually splits n as a string into a vector
        # of its characters, but the difference between ASCII
        # codes is the same as the difference between the numbers
        # so it works as expected

        # Add the new n to the running sum
        s += n
    end

    # Return the sum
    return s
end

オンラインで試す

feersumとGlen Oのおかげで21バイト節約されました!


1
ndigits(n)>1と異なる理由はありn>9ますか?
feersum

提案:int(join(abs(diff(["$n"...]))))9バイトを節約します。n>9さらに9バイトを節約するために、feersumの提案に従って切り替えます。whileループで両方の割り当てを1ステップで実行することで、さらに3バイトを節約します(そして余分な、今では不要なセミコロンを削除します):n->(s=n;while n>9 s+=n=int(join(abs(diff(["$n"...]))))end;s)
グレンO

@feersumうーん、いや。ありがとう!
アレックスA.

@GlenO素晴らしい、ありがとう!
アレックスA.

5

OK37 32 24 23バイト

+/(10/{%x*x}1_-':.:'$)\

動作中:

  +/(10/{%x*x}1_-':.:'$)\8675309
8898683

  (+/(10/{%x*x}1_-':.:'$)\)'!20
0 1 2 3 4 5 6 7 8 9 11 11 13 15 17 19 21 23 25 27

K5にはこれに適したいくつかの機能があります。「エンコード」と「デコード」はベース変換を実行でき、各ペア(':)はリスト内の順次要素をペアにし、固定小数点スキャン(\)は停止するまで反復シーケンスを生成できます変化。ただし、プリミティブabs()が不足していると、の形で見苦しいバルクが発生し{(x;-x)x<0}'ます。

編集:

の代わりに{(x;-x)x<0}'、シーケンスの平方の平方根を(多少無駄に)取ることができます({%x*x}、5バイトを節約します。

編集2:

@maurinusのAPLソリューションに触発されて、「デコード」(((#$x)#10)\x)を数字の文字列表現の各文字の評価に置き換えることができます.:'$x。これにより、表現全体の暗黙の形式を使用して、追加の文字を保存することもできます。


4

Python 2、87バイト

f=lambda n:n and n+f(int('0'+''.join(`abs(int(a)-int(b))`for a,b in zip(`n`,`n`[1:]))))

現在の数を再帰的に追加し、数字の差を取ります。数字と文字列の間の変換がたくさん。おそらく改善することができます。


4

ジュリア、55 48バイト

h=n->(n>9&&h(int(join(abs(diff(["$n"...]))))))+n

ゴルフをしていない:

function h(n)
  if n>9
    # If multiple digits, find the digit difference...
    digitdiff=int(join(abs(diff(["$n"...]))))
    # ... recurse the function...
    downsum=h(digitdiff)
    # ... and return the sum so far (working up from the bottom)
    return downsum+n
  else
    # If single digit, no further recursion, return the current number
    return n
  end
end

基本的に、これは1桁のレベル(数字の差を実行できない場合)まで再帰し、レベルごとに再帰を終了するときに合計します。


3

Haskell、140バイト

d 仕事をします。

import Data.Char
d n=sum.m(read.m intToDigit).fst.span(/=[]).iterate s.m digitToInt.show$n
s l@(h:t)=snd$span(==0)$m abs$zipWith(-)l t
m=map

誰もが長い変換関数のインポートを避ける方法を知っていますか?


intToDigitでありtoEnum.(+48)digitToIntです(\i->fromEnum i-48)。リストコンテキストでsポイントフリーバージョンに 切り替えることもでき=<<ますs=snd.span(==0).m abs.(zipWith(-)=<<tail)。最後に、(==0)(<1)負ではない整数で作業しているためです。
nimi

...ああ、もしsポイントフリーであれば、名前を付ける必要はありません。直接呼び出す:iterate(snd.span ... tail))
nimi

...最初のコメントの間違いを訂正するのは、私=<<です。リストコンテキストではなく関数コンテキストで使用されています。ごめんなさい。
nimi

ブリリアント!また、ここでGHC拡張機能を使用するのは一般的な手順ですか?NoMonomorphismRestriction私もdポイントフリーになります。
レイフウィラーツ

1
chrとのord両方でData.Charあるため、を省略することはできませんimport。コンパイラフラグはバイトとしてカウントされ、あまりにも、そのNoMonomorphismRestriction25であなたのスコアを高める
nimi


3

APL(22)

{⍵≤9:⍵⋄⍵+∇10⊥|2-/⍎¨⍕⍵}

説明:

  • ⍵≤9:⍵:⍵≤9の場合、⍵をそのまま返します。
  • ⍎¨⍕⍵:⍵を文字列に変換してから、各文字を評価します
  • 2-/:隣接する2つの数値ごとに減算する
  • |:絶対値を取る
  • 10⊥:配列を基数10に変換します
  • ⍵+∇:この新しい値を使用して関数を再帰的に呼び出し、結果を入力に追加します

3

Mathematica、72 69 65バイト

Tr@FixedPointList[FromDigits@*Abs@*Differences@*IntegerDigits,#]&

ここで提案を受け付けています。


Tr@FixedPointList[FromDigits@*Abs@*Differences@*IntegerDigits,#]&
alephalpha

@alephalpha興味深いコンセプト、余分なゼロの作成...
LegionMammal978

2

JavaScript ES6、73バイト

t=n=>(b=10,M=Math).ceil(n&&n+t((j=n=>n>9&&M.abs(n%b-n/b%b)+b*j(n/b))(n)))

これは短くなりません:/もっとアプローチを試みますが、これはこれまでで最も短いものです


割り当てるのではなく匿名関数としてそのままにしておくと、tまだ有効であり、2バイト節約できます。
パトリックロバーツ

@PatrickRobertsはい、ただし再帰を使用しているため、名前を付ける必要があります
-Downgoat

ああ、それを逃した、十分に公正。
パトリックロバーツ

2

JavaScript(ES6)、69

EcmaScript 6に準拠したブラウザーで以下のスニペットを実行してテストします(ただし、スプレッド演算子をまだサポートしていないためChromeはそうではありません...)。

f=n=>n&&(n+=r='',[...n].map(d=>(r+=d>p?d-p:p-d,p=d),p=n[0]),+n+f(+r))

function test()
{
  var i=+I.value
  O.innerHTML = i+' -> '+f(i) + '\n' + O.innerHTML 
}
<input id=I value=8675309><button onclick=test()>-></button>
<pre id=O></pre>

代わりに、現在EcmaScript 2016(ES7)を対象とする配列内包表記を使用して、67バイト:

f=n=>n&&(n+=r='',p=n[0],[for(d of n)(r+=d>p?d-p:p-d,p=d)],+n+f(+r))

2

Python 3、125バイト

私はこの挑戦のためにそれを使用しようとするまで正規表現の短さが好きでした... re.findall('\d\d',s,overlapped=True)はオンではありません ;)

s=input()
p=int
x=p(s)
while p(s)>9:g=str(s);s=p(''.join(str(abs(p(g[i])-p(g[i+1])))for i in range(len(g)-1)));x+=s 
print(x)

乾杯@Todd :)


1
リストではなく整数に対してインプレース加算を実行できます。これにより、角括弧と最終合計が不要になります。's = p(input())'を使用すると、whileループのint変換とxへの割り当てを削除できます。また、gとg [1:]のzipをループすることを検討してください。
トッド

1

J、70バイト

 +/([:10&#.[:(2|@:-/\])[:10&(]#:~[#~[:>.[^.])])`]@.(11&>)^:a:".(1!:1)3

0

C 162バイト

ゴルフ:

main(int argc,char **argv){char *c=argv[1];int u=atoi(c),d;do{while(c[1]!=0){*c=abs(*c-*(c+1))+48;c++;}*c=0;c=argv[1];d=atoi(c);u+=d;}while(d>9);printf("%d",u);}

なし:

main(int argc, char **argv)
{
    char *c=argv[1];
    int u=atoi(c),d;

    do
    {
        while(c[1]!=0)
        {
            *c=abs(*c-*(c+1))+48;
            c++;
        }

        *c=0;
        c=argv[1];
        d=atoi(c);
        u+=d;
    }
    while(d>9);

    printf("%d\n",u);
}

0

R、134バイト

コード

f=function(x){z=x;while(z>9){n=seq(nchar(z));z=abs(diff(strtoi(substring(z,n,n))));z=sum(z*10**(rev(seq(length(z)))-1));x=x+z};cat(k)}

オンラインでテストします

非ゴルフ

f=function(x){
  z=x;
  while(z>9){
    n=seq(nchar(z));
    z=abs(diff(strtoi(substring(z,n,n))));
    z=sum(z*10**(rev(seq(length(z)))-1));
    x=x+z
  };
  cat(x)
}

これは、f(1)からf(1m)までの「数字の桁差の合計」シリーズの差のプロットです。diffが大好きだからです。

プロットコード

s <- seq(1,100000)
serie <- sapply(s,f)
plot(diff(ts(serie)),xlab="",ylab="")

0

MATLAB (141)(137)

編集: @Andrasのおかげで4バイト以下

function[s j]=n(T,b,c),if(T/b>9),u=fix(T/10);[x e]=n(T,b*10,0);y=n(u,b,0);[w z]=n(u,b,c);s=abs(x-y);j=s+e+10*c*z;else,s=mod(T,10);j=s;end
  • これは@LuisMendoの答えに勝るものではありませんが、少なくとも実行時間を短縮できました。
  • 私はそれをもっと減らすことができますが、時間を短くするにつれて、より多くのバイトを無駄にするので、ここに原則があります:

プログラムは、インライン化された数字の前に同じ行の数字を合計しています。これは、整数除算「n / 10」log_10(n)回のみを使用したことを意味し、複雑さはO(N)です。

もし n= a b c d

a          b           c           d
   |a-b|       |b-c|       |c-d|
    ||a-b|-|b-c|| ||b-c|-|c-d||
   ....

私のプログラムは以下を計算します:

a+|a-b| + | |a-b|-|b-c| |  +  |  | |a-b|-|b-c| | - | |b-c|-|c-d| |  |
+10*(
b+|b-c| + | |b-c|-|c-d| |
+10*(
c+|c-d|
+10*(
d
)
)
)

使用法:

  [a b]=n(13652,1,1)

a =

1

 b =

   16098

宣言のオプション,endを省略すると、4バイトを節約できますfunction
アンドラスDeak

投稿の文法を修正することを検討してください。あなたの言ったことをよく理解できません。
rayryeng-モニカを復活させる

0

プロローグ、143バイト

コード:

q(X,N):-X<9,N=0;A is abs(X mod 10-X//10 mod 10),Y is X//10,q(Y,M),N is A+M*10.
r(X,N):-X<9,N=X;q(X,Y),r(Y,M),N is X+M.
p(X):-r(X,N),write(N).

説明:

q(X,N):-X<9,N=0;                                                         % If only one digit, the difference is 0
        A is abs(X mod 10-X//10 mod 10),Y is X//10,q(Y,M),N is A+M*10.   % Else, the difference is the difference between the last 2 digits + the recursive difference of the number without the last digit
r(X,N):-X<9,N=X;                                                         % If we only have 1 digit the final answer is that digit
        q(X,Y),r(Y,M),N is X+M.                                          % Else, the final answer is the current number + the recursive difference of that number
p(X):-r(X,N),write(N).         

qは、数値をその数字の差に変換する計算を行います。
rqを再帰的に呼び出し、結果を合計して数字の差の合計を見つけます。
pはエントリポイントです。番号を取得し、rを呼び出して回答を出力します。

例:

>p(8675309).
8898683

こちらからオンラインでお試しください。


0

PHP-198バイト

<?$x=$t=$_GET['V'];function z($x){global$t;for($i=0;$i<strlen($x)-1;$i++){$z=str_split($x);$r.=str_replace('-','',$z[$i]-$z[$i+1]);}$r=ltrim($r,'0');$t+=$r;return strlen($r)>1?z($r):0;}z($x);echo$t;

非ゴルフ

<?
$x=$t=$_GET['V']; // Gets the value from input
function z($x){
    global$t;
    for($i=0;$i<strlen($x)-1;$i++){
        $z=str_split($x); //Turns the string into an array
        $r.=str_replace('-','',$z[$i]-$z[$i+1]); // Sums the two values and removes the minus signal
    }
    $r=ltrim($r,'0'); // Remove trailing zeroes
    $t+=$r; // Adds to global var
    return strlen($r)>1?z($r):0; // Checks the size of the string. If >1, calls the function again
}

z($x);
echo$t;

0

Perl 6、56バイト

{[+] $_,{+.comb.rotor(2=>-1)».map((*-*).abs).join}…0} # 56 bytes

使用法:

my &code = {...} # insert code from above

(180..190).map: &code;
# (259 258 259 260 261 262 263 264 265 266 280)

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