階乗数システムとの変換


27

階乗ナンバーシステムもfactoradic呼ばれるが、混合基数数字システムです。階乗は、数値の場所の値を決定します。

このシステムでは、右端の数字は0または1のいずれか、右から2番目の数字は0、1または2のようになります。これは、n桁因数分解が最大値を持つことができることを意味します(n + 1)!

たとえば、階乗数24201を10進数に変換するには、次のようにします。

2 * 5! = 240
4 * 4! = 96
2 * 3! = 12
0 * 2! = 0
1 * 1! = 1
240 + 96 + 12 + 0 + 1 = 349

したがって、階乗数24201349base 10です。

349例として)10進数を階乗数に変換するには、次のようにします。

数値よりも小さい最大の階乗を取る。この場合120、または5!です。

349 / 5! = 2 r 109
109 / 4! = 4 r 13
13 / 3! = 2 r 1
1 / 2! = 0 r 1
1 / 1! = 1 r 0

したがって、349base 10は階乗数24201です。

あなたの課題は、入力番号を他の基数に変換する最短のプログラムまたは関数を作成することです。

入力は、負でない整数の文字列表現になります。階乗数の前には!(例えば!24201)が付きますが、10進数の前には何も付きません。あなたは、最大入力がされると仮定することができる10! - 1- 3628799小数にして987654321factoradicに。これは、因数分解入出力に文字が表示されないことを意味します。

プログラムは!、因数分解出力にaを追加する必要はなく、文字列または整数を出力できます。入力は合理的な形式で行うことができます。


テストケース:

Input: 1234
Output: 141120

Input: 746
Output: 101010

Input: !54321
Output: 719

Input: !30311
Output: 381

回答:


10

APL、39 37文字

{A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}

例:

      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'1234'
141120
      {A B←(9⍴10)(⌽1+⍳9)⌽⍨'!'∊⍵⋄A⊥B⊤⍎⍵~'!'}'!54321'
719

1
に置き換え⍴⍵∩'!''!'∊⍵キャラクターを保存できると思います。
ボラティリティ

@Volatilityはい、できます。私も別のものを見つけました。
ハワード

11
スクリプトに「pwn」という単語が含まれているIMOは、追加の文字に値します。
ejrb

1
ejrbに同意します。これを分解してください。
タイタス

1
で置換~'!'∩⎕Dてキャラクターを保存します。
アダム

9

Python 2.7(163 157 152)

i=raw_input()
exec("b='';a=362880;j=int(i);x=9;"+'b+=`j//a`;j%=a;a/=x;x-=1;'*9,"a=x=1;b=0;"+'b+=a*int(i[-x]);x+=1;a*=x;'*~-len(i))['!'in i]
print int(b)

より読みやすいバージョン:

i=raw_input()
if'!'in i:a=x=1;b=0;c='b+=a*int(i[-x]);x+=1;a*=x;'*~-len(i)
else:b='';a=362880;j=int(i);x=9;c='b+=`j//a`;j%=a;a/=x;x-=1;'*9
exec c;print int(b)

壊す:

Factoradic -> Decimal, when i is in the form !(number)
a=1   #Factorial value (multiplied every iteration)
x=1   #Index value
b=0   #Output
iterate ~-len(i) times:    #PSEUDOCODE! bitwisenot(a) = ~a = -a-1
    b+=a*int(i[-x])        #add the value of the xth last character in the factoradic #
    x+=1                   #Increment x
    a*=x                   #Set a to x!, (x-1)! * x = x!

Decimal -> Factoradic
b=''                       #Output
a=362880                   #Factorial value, set to 9! here
j=int(i)                   #Integer value of the input
x=9                        #Index value
iterate 9 times:           #PSEUDOCODE! This block is in an exec() loop
    b+=`j/a`               #Add floor(j/a) to b
    j%=a                   #Take out all multiples of a in j
    a/=x                   #Set a to (x-1)!, x! / x = (x-1)!
    x-=1                   #Decrement x

1
いい解決策。に置き換え'!'==i[0]'!'in i使用できると思いますa=x=1。また、execステートメントを角括弧で囲む必要もありません。
-grc

1
また、置き換えることができ(len(i)-1)~-len(i)
ボラティリティ

@揮発性、GRC:ありがとう!ビット演算子を学ぶ必要があります:)
beary605

1
いい答えだ。私はifステートメントを(a,b)['!'in i]6文字に置き換えて自由に置き換えようとした。しかし、それは以前ほど読みやすくありません...
pastebin

@erjb:提案をありがとう!私は、2つのタプルをexec関数とインラインの文字列としてコードとともに使用しました。これにより、さらに2つの文字が保存されます:)
beary605

8

GolfScript(48 44 43文字)

.~\{1{):?\.?%\?/@}9*{*+}+9*}:^{:N,{^N=}?}if

これは自己完結型のプログラムです。factoriadic => decimal変換は、ベースの直接変換ではなくdecimal => factoriadic変換を使用して検索を行うため、非常に遅くなります。

入力形式では、非常に短いモード切り替えが可能です。.~入力文字列をコピーして評価します。したがって、入力が単なる数字である場合、たとえば"1234" 1234スタック上で終わり、!(論理ではなく、空ではない文字列が真実である)私たちは例えば0 30311スタック上で終わる。次に、スタックの一番下の値は、decimal => factoriadicの場合は真実であり、factoriadic => decimalの場合は偽です。


4

PHP <7.1 178 171 170 168 164 155 147 144138138126 123バイト

for($b=$j=1,$i=strlen($x=$argn);+$x?$b<=$x:--$i;$b*=++$j)$r+=$x[$i]*$b;if(+$x)for(;$j>1;$x%=$b)$r.=$x/($b/=$j--)|0;echo+$r;

でパイプとして実行する-r、オンラインでテストします

  • 拡張は不要です
  • サブ関数は必要ありません:階乗ベースが再利用されています(ループ内で増加/減少)
  • 純粋な整数と文字列の算術演算は、PHP 3でも動作するはずです(PHP 7でも動作します)。
  • decimal 0はの代わりに空の文字列を返します0(他のPHPの回答も両方行います。)それが受け入れられない場合は、余分な場合に+5を追加します。

なし:

// two loops in one: compute the decimal number from a factorial
// or find the first factorial larger than a decimal $x
// the latter inits $r with '0': $i=strlen -> $x[$i]=='' -> (int)$x[$i]==$x[$i]*$b==0
// $b is the current digit´s base; $j is the bases´ latest factor
for($b=$j=1,$i=strlen($x=$argn);+$x?$b<=$x:--$i;$b*=++$j)
    $r+=$x[$i]*$b;
// and now for dec->fact ...
if(+$x)
    for(;$j>1;$x%=$b)
        // both $b and $j are one step too far in the first iteration;
        // -> decrement must precede the actual loop body
        // -> can be merged into the digit calculation -> all braces golfed
        $r.=$x/($b/=$j--)|0;
        // now: go on with the remainder (see loop head)
echo+$r; // final type cast removes leading zeros (from the first loop)
    // and fixes the '0' result (no operations at all on that input!)

放棄されたゴルフのアイデア:

  • $b<=$x-> $b<$x(-1)
    は、純粋な10進数階乗(つまり、ゼロ以外の数字が1つだけの階乗数となる階乗)を分割します。JMPCのソリューションはこの問題を抱えています。HamZa´sはありません。
  • floor($x/$b)-> (int)($x/$b)
    少し速くなる可能性がありますが、型キャストは除算に先行するため、括弧が必要であり、バイトを取得しません。
    $x/$b|0トリックをします
  • fact-> decのループは、dec-> factのfactorial-findに似ています。同じ増分、ボディは重要ではありませんが、残念ながら異なるプリセットと異なる投稿条件。ダン; -21でゴルフできたかもしれません。
    解決策を見つけました。かなりのゴルフをしたが、さらに-4(いいえ:-9)切り落とし、すべてのバグ/抜け穴閉じた。

それ以上の可能性...または私はゴルフをしましたか?


@JörgHülsermannヒントをありがとう。
タイタス

1
+$r$r|01バイトを保存する代わりに。同じですif($x|0)
ヨルクヒュルザーマン

3

JavaScriptの(ES 6)139 137 122 113 111

配列マジックを使用して別のアプローチを試みました。しかし、私はそれで174 172バイトになりました:

f=x=>{if('!'==x[0]){a=x.split``.reverse();i=b=1;r=0;a.pop();a.map(d=>{r+=d*b;b*=++i})}else{t=[];for(i=b=1;b<=x;b*=++i){t.unshift(b)}r='';t.map(b=>{r+=x/b|0;x%=b})}return r}

ですから、PHPコードを取得して翻訳しました。すべての$sといくつかを削除でき;ますが、変数を初期化する必要性はその利点の一部を使い果たしました。しかし、ゴルフをうまくやると、両方の答えが少し下がります。

ゴルフをした

f=x=>{for(r=0,b=j=1,i=x.length;x|0?b<=x:--i;b*=++j)r+=x[i]*b;if(x|0)for(r='';j>1;x%=b)r+=x/(b/=j--)|0;return r}
  • 最初のバージョンは、10進数の0に対して ''を返します。+2を追加して修正
  • 2番目のバージョンでは文字列の入力が必要です
  • Firefox、Edge、Operaでテスト済み

食べない

f=x=>
{
    for(r=0,b=j=1,i=x.length;x|0?b<=x:--i;b*=++j)
        r+=x[i]*b;
    if(x|0)
        for(r='';j>1;x%=b)
            r+=x/(b/=j--)|0;
    return r
}

テストスイート

<table id=out border=1><tr><th>dec</th><th>result<th>expected</th><th>ok?</th></tr></table>
<script>
    addR=(r,s)=>{var d=document.createElement('td');d.appendChild(document.createTextNode(s));r.appendChild(d)}
    test=(x,e)=>{var y=f(x),r=document.createElement('tr');addR(r,x);addR(r,y);addR(r,e);addR(r,e==y?'Y':'N');document.getElementById('out').appendChild(r)}
    samples={'349':'24201','1234':'141120','746':'101010','719':'54321','381':'30311','24':'1000','0':'0'};
    for(d in samples){test(d,samples[d]);test('!'+samples[d],d)}
</script>

1
ES5には矢印表記IIRCがありません。そして、あなたはES6を使用するつもりなら、.split('')=>.split``
ザカリー

@ZacharýGna私がテストしたブラウザはおそらくFirefoxまたはOperaでした。ES 6?
タイタス

ええ、矢印表記はES6です。
ザカリー

1
ああ、それは不意を突かれました。一番上のコードブロックがあなたの解決策だと思いました!とにかく、あなたが言う必要はないと思いますf=。また、することr+=(x/(b/=j--)|0)ができますr+=x/(b/=j--)|0か?
ザカリー



1

Haskell、221文字

コードゴルフ

m v@(a:b)|a=='!'=(sum.zipWith(*)g.map(read.(:[])).reverse) b|True=(fst.until((<0).fst.snd)(\(s,(i,b))->(s*10+b`quot`f i,(i-1,b`rem`f i))).(\n->(0,((1+).last.takeWhile((n>=).f)$[1..], n))).read) v;g=scanl1(*)[1..];f=(g!!)

使用法

$ ghci factorial.hs
ghci> m "1234"
 141120
ghci> m "!54321"
 719

未ゴルフコード

parse v@(a:b) | a == '!' = to b
              | otherwise = from v

to = sum . zipWith (*) factorials . map (read . (:[])) . reverse

from = fst . until finished next . boostrap . read
    where finished = ((<0) . fst . snd)
          next (s,(i,r)) = (s * 10 + r `quot` factorial i, (i-1 ,r `rem` factorial i))
          bootstrap n = (0, (lastFact n, n))
          lastFact n = (1+) . last . takeWhile ((n>=) . factorial) $ [1..]

factorials = scanl1 (*) [1..]

factorial = (factorials!!)

最も読みやすいエントリ。ハスケルFTW!
ソーハムチョードリー

1

Mathematica 213 177 175

階乗数f[]は、入力でも出力でも、ラップされます。

g@{n_,j_,r_}:=If[j==0,FromDigits@r,g@{q=QuotientRemainder[n,j!];q[[2]],j-1,Append[r,q[[1]]]}]
z@n_:=If[!IntegerQ@n, g[{n[[1]],9,{}}], f@Tr@(p=1;# (p++)!&/@Reverse@IntegerDigits@n)]

使用法

z[24201]

f [349]

z[f[349]]

24201

階乗の10進数への変換QuotientRemainder[n,j!]階乗数の数字に左から右に再帰的に作用し、j各ステップで減少します。 QuotientRemainder[349, 5!]、たとえば、戻り値{2, 109}など。

10進数から階乗数への変換。右から左に移動すると、純関数、# (p++)! &は各桁に#適切な階乗を乗算します。


1

Python、128文字

これを実行するには約30分かかりますが、わずかです。

A=[`x`for x in xrange(10**9)if all(x/10**d%10<d+2 for d in range(9))]
i=raw_input()
print A.index(i[1:])if'!'in i else A[int(i)]

すべての<= 9桁の要因数のリストを数値順に作成し、ルックアップまたはインデックスを作成して変換します。

テストする場合は、6桁の可変数に置き換え10**910**6制限してください。

range(10**9)代わりにを使用して、技術的にキャラクターを保存できましたxrange(10**9)。自宅でこれを試さないでください。


何スペースが間必要とされていないd+2for
ザカリー

1

PHP 231 214 204

最新の回答

function g($x){return $x?$x*g($x-1):1;}function f($x,$e){if($x[0]=="!"){for($t=1;$t<$c=strlen($x);$t++){$e+=$x[$t]*g($c-$t);}}else{while(g(++$p)<=$x);while(--$p){$e.=floor($x/g($p));$x%=g($p);}}return$e;}

古い答え

 function f($n){if($n[0]=="!"){$n=str_split($n);$c=count($n);$f=$y=1;while($c-->1){$e+=($f*$n[$c]);$f*=++$y;}return$e;}else{for($i=$c=1;$i<$n;$i*=$c){$r[$c++]=$i;}foreach(array_reverse($r)as$t){$e.=floor($n/$t);$n=$n%$t;}return$e;}}

echo f('349')."\n"
    .f('!24201')."\n"
    .f('1234')."\n"
    .f('746')."\n"
    .f('!54321')."\n"
    .f('!30311');

出力

24201
349
141120
101010
719
381

2
新しい答えには214ではなく212を数えます。$ eは初期化を必要とせず(-6)foreach(range())、単純なforループに置き換えることができます(-9)。しかし、私はこのアイデアが好きです。
タイタス

2
純粋階乗の誤った結果。24返す必要があります1000返しますが400。修正:g(++$p)<$x-> g(++$p)<=$x(+1)
タイタス

@タイタス両方の返信ありがとうございます!回答を更新しました。あなたの回答がはるかに優れていると思われる場合、私の回答を改善するのを手伝ってくれてありがとう。
-JPMC

1
1)私はあなたよりも2つ少ない数を数えます。206ではなく204です。バイト数にWindowsの改行を含めますか?2)構文の構文エラーfor:3である,必要があり;ます。そのコードで20バイトを保存する別の7つの変更があります。それらが欲しいですか?
タイタス

2
まあ、実際には5つの変更だけですが、そのうちの1つには3つの部分があります。a)f()の廃止された2番目の引数(-3)b)関数gの廃止されたブランク(-1)c)真のブランチの廃止された中括弧(-4)d)真のブランチと偽のブランチを交換し、if条件を反転してから使用する私のセクシーな型はint(-6)にキャストされますが、これは10進0の結果には影響しません e)残りのforコンストラクトは非常に良い方法で書き換えることができますwhile(++$t<$c=strlen($x)):bodyの前にインクリメント-> $ tは初期化を必要としません(-6)
Titus

1

JELLY、5バイト

Æ!ŒṘ€

説明

Æ!ŒṘ€
Æ!     -Convert to factoriadic (list form)
  ŒṘ€  -Construct string

*ゼリーは質問の年齢よりも若いため、私の答えは競合していません。


1
PPCGへようこそ!Jellyはこの挑戦よりも若いと思うので、あなたはあなたの答えを非競合としてマークすべきです。
ライコニ

ああ、それがルールだとは知らなかった。しましょう。
DaggerOfMesogrecia

この課題に対する答えは、両方の方法で機能することを意味していませんか?これは一方向にしか機能しないようです。あなたはそれを修正したいかもしれません。(あなたはゼリーの整数と文字列の間の変換している場合は、別のノートで、それはいくつかの組み合わせを使用することは通常tersestだV。)

1

ゼリー、15バイト

ḊV€;0Æ¡µÆ!ṖḌƊ¬?

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

使い方

ḊV€;0Æ¡µÆ!ṖḌƊ¬?     Main link (monad). Input: integer or string
             ¬?  *) If the given input is a string, run 1); otherwise run 2)

ḊV€;0Æ¡  1) Factorial base -> integer
ḊV€         Remove "!" and map each char to number
   ;0       Append zero (this is needed to run the built-in correctly)
     Æ¡     Built-in conversion

Æ!ṖḌ  2) Integer -> factorial base
Æ!       Built-in conversion
  ṖḌ     Remove a zero at the end, and convert to decimal

なぜ*)機能するのか

¬要素単位の論理否定です。単一の整数を指定すると、単一のゼロになりますが、これは偽です。ただし、文字列を指定すると、各要素(文字)がゼロになり、結果全体が真のゼロの配列になります。

整数としてのゼロは特別な場合です。「階乗->整数」ルートを通りますが、それでも正しいゼロが得られます。

階乗ベースなし、25バイト

⁵R!µ³%Ḋ:ṖUḌ
⁵R!ḋḊUV€ƊµÇ¬?

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

使い方

⁵R!µ³%Ḋ:ṖUḌ  Aux. link (monad). Integer -> factorial base
⁵R!µ         Set (1..10)! as left argument
    ³%Ḋ:Ṗ    Compute each digit: (input % (2..10)!) // (1..9)!
         UḌ  Reverse and convert the digit array to decimal

⁵R!ḋḊUV€ƊµÇ¬?  Main link (monad).
         怪?  If the input is a string, apply the left chain;
               otherwise, apply the aux. link above
⁵R!            (1..10)!
   ḋ           Dot product with...
    ḊUV€Ɗ      Remove "!", reverse, map each character to digit

0

K、102

"I"$,/$*:'|:'{{(x-y*g),g:_(x:*x)%y:*/1+!y}\[x,0n;|1+!{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]]}

間違いなく改善される可能性があります。

k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 349
24201
k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 746
101010
k)"I"$,/$*:'|:'{{,[;g]x-y*g:_(x:*x)%y:*/1+!y}\[(x;0n);|1+!{{$[(x>(*/1+!y))&x<*/1+!y+1;y;.z.s[x;1+y]]}[x;0]}x]} 1234
141120

0

D(159文字)

int x(string n){import std.conv;int r,i=9,f=9*'鶀',d;if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}else{d=n.to!int;while(i){r=r*10+d/f;d%=f;f/=i--;}}return r;}

Ungolfedおよびプログラムエントリポイントあり

すべてのコマンドライン引数はとして出力され<original> -> <converted>ます。実際には、10進数からfactoradicのみが実装されていxます。もう1つの方法xは、結果が入力と等しくなるまで、すべての10進数(0 .. *)で呼び出します。これには、最大の入力(!987654321)で最大3秒かかります。

実行可能なオンラインバージョン:http : //dpaste.dzfl.pl/46e425f9

void main(string[] args) {
    import std.stdio;
    foreach (arg; args[1 .. $]) {
        writefln("%s -> %s", arg, x(arg));
    }
}

int x(string n) {
    import std.conv;
    int r, i=9, f=9*'鶀', d;  // 鶀's Unicode index equals 8*7*6*5*4*3*2*1

    // If the first character value is less than 48 ('0') it should be a '!'.
    if (n[0] < 48) {
        // Call x with different input (0..*) until it matches our n.
        // r.text.x is rewritten as x(text(r)).
        while (r.text.x < n[1..$].to!int) r++;
    } else {
        d = n.to!int;
        // Try d / 9!, d / 8!, etc. just as in the problem description.
        while (i) {
            r = r*10 + d/f;
            d %= f;
            f /= i--;
        }
    }
    return r;
}

に変更string nchar[]nて1バイトを保存することは可能かもしれません(私はここで遅れていることを知っています)。
ザカリー

また、2バイト節約if(n[0]<48){while(r.text.x<n[1..$].to!int)r++;}できるようになると思いif(n[0]<48)while(r.text.x<n[1..$].to!int)r++;ます。
ザカリー

0

VBA 225

助けてくれたTitusに感謝します!まだゴルフを楽しみにしています。

Sub a(b)
Set w=WorksheetFunction
e=Len(b)
If IsNumeric(b) Then
i=0
For d=0To 8
h=w.Fact(9-d)
g=b Mod h
If g<b+i Then
i=1
f=f &Int(b/h)
b=g
End If
Next
Else
For d=2To e
f=f+w.Fact(e-d-1)*Mid(b,d,1)
Next
End If
MsgBox f
End Sub

VBAを知りbませんが、最初の文字を比較する代わりに数値をチェックする方法はありますか?
タイタス

@Titus数値チェックがあり、ここで同等のものはになりますIf Not IsNumeric(b) Thenが、それはより多くの文字を取ります。今、私は入ってすべてのコードを再検討しませんでした。IsNumeric全体的にこれを行うには少し良い方法があるかもしれません。-修正、ここでわずかな改善があります。ありがとう!
ガフィ

:私は別の4つのバイトを見つけたFor d=9To 1Step-1Fact(d)> - For d=0To 8Fact(9-d)あなたが行う場合は、別の2 For d=2To eFact(e-d+1)*Mid(b,d,1)
タイタス

Intへの型キャストは別の方法で記述できますか?
タイタス

@Titusあなたを見て、私の周りを走り回っています。:)私は今調整しています... Int()に関しては、もっと単純な(より小さい)メソッドはないと思います。
ガフィ

0

PHP、124バイト

for($f=1;("$">$a=$argn)&&~$c=strrev($a)[$n];)$r+=$c*$f*=++$n;for(;$a>=$f*=++$i;);for(;~-$i;$a%=$f)$r.=0|$a/$f/=$i--;echo+$r;

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

延長

for($f=1;("$">$a=$argn)&&~$c=strrev($a)[$n];) # runs in case of "!" at the beginning
  $r+=$c*$f*=++$n; #reverse string multiply with the next factorial "!"*$f=0
for(;$a>=$f*=++$i;); # runs not in case of "!" at the beginning string comparing. search the factorial that is higher as input value
for(;~-$i;$a%=$f) # runs only when the second loop had runs
  $r.=0|$a/$f/=$i--; # concat the value of the division with the highest factorial used
echo+$r; # Output result

0

Perl 6、150バイト

{/^\!/??([+] [Z*] .comb.skip.reverse,[\*] 1..*)!!(reduce
->\a,\b{a[0]~a[1] div b,a[1]%b},("",+$_),|(first
*[*-1]>$_,[\,] [\*] 1..*).reverse[1..*])[0]}

0

APL(NARS)、36文字、72バイト

{⍵⊆⎕D:10⊥(9..2)⊤⍎⍵⋄t+.×⌽!⍳≢t←⍎¨,1↓⍵}

10⊥(9..2)⊤は再帰関数よりも優れているようです。これは、他のAPLソリューションのHowardのおかげです...(たとえ100%を理解していなくても)。「!」のない数字の入力 <10 !. テスト:

  u←{⍵⊆⎕D:10⊥(9..2)⊤⍎⍵⋄t+.×⌽!⍳≢t←⍎¨,1↓⍵}    
  u¨'1234' '746' '!54321' '!30311' '!24201'    
141120 101010 719 381 349 
  u '0'
0
  u '!0'
0
  u '9'
111
  u '!111'
9
  u '!9'
9
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.