Shortlexのその数字は何ですか?


15

ほとんどのコンピューターは整数をバイナリで保存しますが、10進数で出力します。ただし、10進数は単なる1つの表現であり、たまたまそれが便利であることがわかりました。

この課題は、整数値をshortlex decimalで出力するためのコードを書くことです。

あれは何でしょう?
http://en.wikipedia.org/wiki/Shortlex_order

Shortlexは、一連の数字の長さを値の主要な記号として受け取ります。ゼロを表す空の文字列から始まるシーケンスは...

ε,0,1,...,8,9,00,01,...98,99,000,001,...,998,999,0000,...

(Excelの列を考えますが、10進数のみを使用します。)

整数を受け入れ、上記のようにその整数のshortlex-decimal表現に対応する文字列を返すプログラムまたは関数を作成します。

テスト値:

0→「」(空の文字列)
1→「0」
10→「9」
11→「00」
42→「31」
100→「89」
800→「689」
1060→「949」
10270→「9159」
100501→ 「89390」


2
19, 20, 21, 2210進数のシーケンス08, 09, 10, 11がshortlexにマッピングされることに注意することが重要です。だから混乱して使用したの100 -> 89です!
ショーンレイサム14


6
数字の「ショートレックス10進数」と呼んでいるものは、全単射 10進数でもあり、記号{0,1,2,3,4,5,6,7,8,9}が通常の数字{1,2,3,4,5,6,7,8,9、A}。たとえば、通常の全単射10進表記の2014年は1A14であり、ショートレックス10進数では0903です。
14

回答:


34

JavaScript(ES6)42 74

n=>(n-~(n+'').replace(/./g,8)+'').slice(1)

FireFoxコンソールでテストする

;[0,1,10,11,42,100,800,1060,10270,100501]
.forEach(x => console.log(x +" -> '" + S(x) + "'"))

出力

0 -> ''
1 -> '0'
10 -> '9'
11 -> '00'
42 -> '31'
100 -> '89'
800 -> '689'
1060 -> '949'
10270 -> '9159'
100501 -> '89390'

これをどう思いましたか?

固定桁数を指定すると、出力シーケンスは単純に昇順になるため、入力と出力の間には固定デルタがあります。ご覧ください:

  1..10 -> 0..9 (delta -1)
 11..110 -> 00..99 (delta -11)
111..1110 -> 000..999 (delta -111) mmm there's a pattern here...

ただし、先頭の0は管理が難しいため、標準的なトリックを使用して、最初の数字を追加し、モジュロで動作します(つまり、出力の最初の数字を切り取ります)。-1-> + 9、-11-> + 89、-111-> +889など。
最後のステップ:最初の桁が何であるかは気にしないので、iinput番号が111より小さいかどうかを確認する必要はありません...(正直、試行錯誤でこれを見つけました)

テスト

var F=
n=>(n-~(n+'').replace(/./g,8)+'').slice(1)

function update()
{
  var i=+I.value
  O.textContent = F(i)
}


update()
<input id=I value=99 type=number oninput='update()'><pre id=O></pre>


8
これがなぜ機能するのかわかりません。
マーティンエンダー14

なぜあなたはn-~(n+'')ただの代わりに行うのですn-~nか?
クラウディウ

@Claudiu it (n+'').replace(...)、replaceは数字ではなく文字列で動作します。
edc65

@ edc65:はい Dayumこれは非常に素晴らしいです
クラウディウ

3
@Dennisは自由に移植できます。あなたは既に勝っている
edc65

13

Marbelous 177 173 170

@0@6000000@5
}0&0&0&0&0
>0@6&3
\\--\/&2
@0/\@4\/&1!!
@4@1..@2@5@3
IIIIIIIIIIII
FF&1FF&2FF&3
@1OO@2OO@3OO
:I
}1..}10001F7
=9&1++..&1&0
&0}0&1&0{1{1
{>\/{0//
:O
}0
+Z
+C
{0

Marbelousは8ビット言語であるため、256未満の値に対してのみ機能します。

使い方

Marbelousは、8ビットのビー玉で表される値を持つ2D言語であり、デバイスが落下を防止しない限り、各ティックで1つのセルに落下します。このMarbelousプログラムは3つのボードで構成されています。最も簡単なものから始めましょう:

:O
}0
+Z
+C
{0

:Oはボードの名前です(正確にはOは名前で、:はこの行が名前であることを解釈します。ボードに名前を付けると、他のボードはそれら}0を入力デバイスとして呼び出す ことができ、これはこのセルの引数は、関数が呼び出されたときに入力大理石(値)に置き換えられます。 +Z通過する大理石に35を追加し、通過させます。+C同じことを行いますが、12を追加します。{0が、、大理石がこのセルに到達すると、関数は終了し、この出力デバイスに値を返します。

したがって、このボードは1つの値を取り、47を加算します。これは、1桁の数字を数字-1のASCIIコードに変換することを意味します(もちろん10でも機能します)。

:I
}1 .. }1 00 01 F7
=9 &1 ++ .. &1 &0
&0 }0 &1 &0 {1 {1
{> \/ {0 //

このボードはもう少し複雑に見えます。:Iボードの名前として識別でき、入力デバイスと出力デバイスをいくつか見つけているはずです。2つの異なる入力デバイスとが}0あり}1ます。これは、この関数が2つの入力を取ることを意味します。また、}1デバイスには2つのインスタンスがあることに気付くでしょう。関数を呼び出すと、これらのセルの両方に同じ値が含まれます。}0入力装置は、Aの真上にあります\/このゴミ箱として作用し、すぐにそれに当たる任意の大理石を削除し、デバイス。

}1入力デバイスによってボードに入れられたビー玉の1つに何が起こるか見てみましょう。

}1
=9 &1
&0
{>

最初のティックで落ち、=9デバイスにヒットします。これは、大理石の値oifを9と比較し、ステートメントが=9評価された場合に大理石を通過させます。そうでない場合、大理石は右に押されます。&0そして、&1シンクロしています。それらは、他のすべての&nシンクロナイザーが同様に満たされるまで、それらの上に落ちるビー玉を保持します。ご想像のとおり、これはボードの他の部分で条件付きで異なる動作をトリガーします。

}1 00 01 F7
++ .. &1 &0
&1 &0 {1 {1
{0 //

それ++がインクリメンターであると言えば、あなたはすでに異なるシンクロナイザーが何で満たされるかを伝えることができるはずです。左側&1には入力値}1+ 1 が含まれ、その&0隣には0が含まれます(0016進数で表される言語リテラルです)。2番目&1には値1が含まれ、右側に&0はが入力されF7ます。Marbelousでの加算は256を法とするため、値から9を減算します。

// はデフレクターデバイスで、大理石を落下させる代わりに左に押します。

これをすべてまとめると、これが得られます。大理石}1が9の場合、&0シンクロナイザーがいっぱいになります。これにより、値0が{0出力およびF7(または-9)に{1出力されます。}19以外の場合は{0}1+ 1 で埋められ、1 {0が含まれます。{>デバイスもあります。これは、ボードの下ではなくビー玉を出力する特別な出力です。これは、}19に等しい場合に満たされます。

@0 @6 00 00 00 @5
}0 &0 &0 &0 &0
>0 @6 &3
\\ -- \/ &2
@0 /\ @4 \/ &1 !!
@4 @1 .. @2 @5 @3
II II II II II II
FF &1 FF &2 FF &3
@1 OO @2 OO @3 OO

さて、今は大きなものです。このボードはファイルのメインボードであるため、明示的な名前はありません。暗黙の名前はMbです。いくつかの細胞を認識できるはずです。入力デバイス、いくつかの言語リテラル(00およびFF)があります。シンクロナイザーとディフレクターがあります。このピースを1つずつステップスルーできます。

@0 @6
}0 &0
>0 @6
\\ --
@0 /\ @4

したがって、入力値(これはメインボードであるためコマンドライン入力)は、}0配置されている上から2番目のセルから始まります。落下して、>0別の比較デバイスであるデバイスに到達します。0より大きい大理石はすべて通過し、他の大理石は右に押されます。(Marbelous変数は符号なしなので、正確に0だけが右にプッシュされます)。このゼロ値の大理石は、その後ヒットします@6デバイスにます。これはポータルであり、大理石を別の対応するポータル、この場合はそのすぐ上に移動します。0マーブルは&0シンクロナイザーに到達し、他の場所で何かをトリガーします。

ビー玉が0でない場合、ビー玉は落下し、\\ヒットによって右に偏向され、1減り、クローンに--落ちます/\。このデバイスは大理石を取り、そのコピーを右に1つ、左に1つ出力します。左側@0は、大理石が再び同じシーケンスを通過するもう一方に上向きになります。左側のものは他の場所で撮影されます。これによりループが作成され、ループごとに1回コマンドライン入力をデクリメントし、すべてのループで0に達するまで何らかの動作をトリガーします。その後、他の動作をトリガーします。

@4各ループに押し込まれた大理石で何が起こるか見てみましょう。

@4 @1 .. @2 @5 @3
II II II II II II
FF &1 FF &2 FF &3
@1 OO @2 OO @3 OO

ここには3つの言語リテラル(FF)があり、すぐにポータルに分類されます。これらのポータルは、3つのIIデバイスにそれらを連れて行きます。ファイルのさらに下で定義IIしたボード:Iを指します。以来:I、2つの異なる入力デバイスを持って、別のボード上のそれの表現は広い2個の細胞でなければなりません。を含む6つのセルがあるためII、この関数の3つのインスタンスがボード上にあることがわかります。

FF(または256または-1あなたがする場合)ビー玉は、入力セルに座って:I十分な入力大理石のSTOである(1以上)の機能を起動するがありますそれまでは待っている機能。それが@4ポータルの出番です。デクリメントされたコマンドライン入力のコピーは、各ループでそこを通過します。これにより、左端の:Iボードがトリガーされます。初期値は256(または-1)で、コマンドライン入力は-1でした。左の大理石はボードの}0デバイスに:I、右の大理石はボードのデバイスに入れられます}1。このボードが何をしたかを思い出せば、これがどんな結果をもたらすかを知ることができます。右側の入力の増分バージョンを左側の出力に出力し(9を10ではなく0に変換します)、右側に1または-9を出力します。

インクリメントされた値はポータルによって右側の入力セルに戻され、右側の値はシンクロナイザーに分類されます。シンクロナイザーが既に大理石を保持している場合、2つの大理石が衝突します。衝突するビー玉は256を法として加算されます。したがって、シンクロナイザーの値は次のようになります。再度1(247が256を法として加算されるため)。

また、入力値が0にループバックすると、大理石が右に出力されることを覚えているかもしれません。:Iボードは隣り合っているため、thsiはボードを右に1回トリガーします。これにより、3つのシンクロナイザーは、コマンドライン入力のshortlex表現になるはずの値よりも1つ高い値で満たされます。これは、ループが0になるまでになります。

また、:O関数が値を値-1を表す数字のASCII値に変換することを覚えているかもしれません。これらのOOセルの出力はボードから落ち、対応するASCII文字がSTDOUTに出力されます。

00 00 00 @5
&0 &0 &0
&3
\/ &2
   \/ &1 !!
      @5

それでは、コマンドライン入力の大理石が0に達し、その&0シンクロナイザーを埋めるとどうなりますか?まあ、いくつかの0の値のビー玉が落ちて、ボードの下部にショートレックス番号の数字(+1)を保持している3つのシンクロナイザーをトリガーします。&3最上位の数字が含まれているため、最初にトリガー&2され、その後にが続き&1ます。その後、この大理石は他の@5デバイスにテレポートされてから!!セルに到達し、ボードが終了します。


4
まるでこれも有効なPerlコードであるかのように見えます
Doorknob

12

CJam、14 11バイト

l40f-Ab)s1>

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

使い方

このアプローチは、edc65の答え明示的な許可を得ている)に大きく基づいています

" Read a line L from STDIN. ";

l

" edc65's answer now forms an integer N by replacing each digit in L by an 8 and computes
  L - ~N = L + N + 1. Instead of adding L and N, we subtract 40 from each char code of L.
  Since the char code of the digit `D` is `D + 48`, this basically adds 8 to each digit.  ";

40f-

" Turn the resulting array into an integer by considering its elements a base 10 number.
  This is implemented as A ↦ A[-1] + 10 * A[-2] + 100 * A[-3] + ⋅⋅⋅, so it won't choke
  on digits greater than the base.                                                        ";

Ab

" Increment the integer on the stack to complete the calculation of L + N + 1.            ";

)

" Push the integers string representation and discard its first character.                ";

s1>

実行例

$ for i in 0 1 10 11 42 100 800 1060 10270 100501
> do echo $i: $(cjam <(echo 'l40f-Ab)s1>') <<< $i)
> done
0:
1: 0
10: 9
11: 00
42: 31
100: 89
800: 689
1060: 949
10270: 9159
100501: 89390

1
これは猥褻である
クラウディウ

3
さらにそれを短縮する方法を見つけるための1
edc65

6

パイソン2(38) (43)

f=lambda n:n*'_'and f(~-n/10)+`~-n%10`

文字置換なし、算術演算のみ。

ゴルフをしていない:

def f(n):
    if n==0: return ''
    else: return f((n-1)//10) + str((n-1)%10)

再帰が機能する正当な理由はありませんが、このパターンを値のリストに適合させるだけです。それぞれを変更した場合n-1nにと、通常の数字表現が得られます。

ゴルフでは、またはより高い優先度で~-n計算するために使用します。これは、空の文字列を生成する場合と、その他の文字列を生成する場合です。は、この目的のための任意の文字列です。n-1/10%10n*'_'n=0'_'


4

ルビー、70 68 66 64 57バイト

f=->n{i=-1;n-=10**i while n>=10**i+=1;i<1?'':"%0#{i}d"%n}

のように呼び出される関数を定義しますf[42]。アルゴリズムの大まかな内訳は次のとおりです。

  • 0別々に扱います。
  • 次の10の累乗が数に収まらなくなるまで、10の累乗を引きます。
  • 数値を、左側にゼロが埋め込まれた文字列に変換します。

フォーマット文字列を使用するというアイデアの功績はFalkoにあります!


または、edc65のアプローチを使用します。

f=->n{"#{n-~n.to_s.tr('^.',?8).to_i}"[1..-1]}

それは45バイトであり、私はそれを含めているだけです。なぜなら、私は彼をating打していないからです。;)


承知しました。とにかく、私の長いPythonコードであなたを捕まえることはできないでしょう。;)
ファルコ14

@Optimizer誰かが20を下回るゴルフ言語の1つでそのアプローチを使用したかどうかは確かです(とはいえ、そのアプローチではRubyで44に到達することはできません...現在45である)
Martinエンダー14

2
@Optimizer私はそれに同意しません。まず第一に、JとAPLはゴルフ言語ではなく、GolfScriptとCJamほど頻繁に勝ちます。しかしさらに、ゴルフは緑のチェックマークではなく、「あなたのリーグで」提出物を破ることです。これらの4つの言語以外のすべてに勝るRubyの提出物を書いた場合、それについて非常に満足することができ、より冗長な言語でゴルフを楽しむためにそれらを禁止する必要はありません。実際、edcのような「通常の」言語での賢いゴルフは、ゴルフ言語での素朴な(ただし短い)実装よりも多くの賛成票を獲得する可能性がはるかに高くなります。
マーティンエンダー14

3

Haskell、67バイト

n('9':x)='0':n x
n(c:x)=succ c:x
n""="0"
f x=reverse$iterate n""!!x

この解決策は基本的に、指定された回数1をショートレックス表記で追加します。

使用法:

>f 9
"8"
>f 100
"89"

3

CJam、16バイト

li_)9*,{`1>}%_&=

オンラインでお試しください。少なくともO(n)時間とメモリが必要なので、100501をオフラインインタプリタに任せてください...

使い方

このアプローチの背後にある基本的な考え方は、自然順序で少なくともN個のshortlex小数を計算し、N番目を除くすべてを破棄することです。非常に効率的ではありませんが、短いです。

li                " Read an integer N from STDIN.                                   ";
  _)9*            " Push M := (N + 1) * 9.                                          ";
      ,           " Push A := [ 0 1 ... M - 1 ].                                    ";
       {   }%     " For each I ∊ A:                                                 ";
       {`1>}%     " Push its string representation and discard the first character. ";
             _&   " Remove duplicates from the resulting array.                     ";
               =  " Retrieve the Nth element.                                       ";

実行例

$ for i in 0 1 10 11 42 100 800 1060 10270 100501
> do echo $i: $(cjam <(echo 'li_)9*,{`1>}%_&=') <<< $i)
> done
0:
1: 0
10: 9
11: 00
42: 31
100: 89
800: 689
1060: 949
10270: 9159
100501: 89390

3

Bash + coreutils、27バイト

@ edc65の巧妙な答えで、デニスの改善@

cut -b2-<<<$[$1-~${1//?/8}]

出力:

$ for n in 0 1 10 11 42 100 110 111 800 1060 1110 1111 10270 100501; do echo "./shortlex.sh $n = \"$(./shortlex.sh $n)\""; done
./shortlex.sh 0 = ""
./shortlex.sh 1 = "0"
./shortlex.sh 10 = "9"
./shortlex.sh 11 = "00"
./shortlex.sh 42 = "31"
./shortlex.sh 100 = "89"
./shortlex.sh 110 = "99"
./shortlex.sh 111 = "000"
./shortlex.sh 800 = "689"
./shortlex.sh 1060 = "949"
./shortlex.sh 1110 = "999"
./shortlex.sh 1111 = "0000"
./shortlex.sh 10270 = "9159"
./shortlex.sh 100501 = "89390"
$ 

前の答え:

Bash + coreutils、71 54バイト

これを行うには少し異なる方法があります:

jot -w%x $1$1|tr 0-9a a0-9|grep -P ^\\d+$|sed $1!d 2>-
  • jot 増加する16進整数を出力します
  • tr これを(0,1、...、8,9、b、... f、0a、00,01、...、99,9b、...、ff、0aa、...、000に変換します、...)
  • grep (0,1、...、8,9,00、...、99,000 ....)を与える数字を含むすべての行を単純にフィルタリングします
  • sed n行目を除くすべてを削除します
  • STDERRは使い捨てファイル「-」にリダイレクトされるため、0が渡されたときに単純に空の文字列が取得されます(sed 1から始まる行番号をカウントするため、0が渡されるとエラーになります)
  • を使用して数値をフィルタリングするため、入力数値よりも/ grepを使用して基数11の整数をより多く生成する必要があります。nの数字を繰り返すだけで十分です。seqdc

shortlex番号が印刷さseqれると$1$1、特に最大入力番号-O(n²)で遅くなるまで、番号の生成が続くことに注意してください。持っていることでスピードアップできますseq7バイトのコストで印刷した直後に終了ます。

jot -w%x $1$1|tr 0-9a a0-9|grep -P ^\\d+$|sed -n $1{p\;q} 2>-

質問には速度の要件はないため、主な回答には短いバージョンを使用します。


@Optimizer nope:try s='jot -w%x $1$1|tr 0-9a a0-9|grep -P ^\\d+$|sed $1!d 2>-'; echo ${#s}。「\\」を1文字として扱う文字列の長さを測定するためにpythonを使用しているのではないかと思います。
デジタル外傷14

2
私の答えは今では変わっていますが、最初のリビジョンで何か賢いことをしたら、それは完全に偶然でした。これは、edc65の答えの直接的な部分です。8はすべて彼のものです...-補助変数$aは不要なようです。cut -b2-<<<$[$1-~${1//?/8}]うまく動作するはずです。
デニス14

1
@デニスそうですね。提案をありがとう!
デジタル外傷14

2

Pythonの2 - 84 70 66

n=input()
i=0
while n>=10**i:n-=10**i;i+=1
print"%%0%dd"%i%n*(i>0)

代替アプローチ(同じ長さ):

n=input()
k=len(`9*(n+1)/10`)
print"%%0%dd"%k%(n-int('1'*k))*(n>0)

書式文字列の使用は賢明です!私もそれを使用してもかまわないことを願っています。:)
マーティンエンダー14

2

Python 3、107文字

これは最終的には勝ちませんでしたが、私はそれが賢いと思いました:

def G():yield'';yield from(r+c for r in G()for c in'0123456789')
S=lambda n:list(zip(range(n+1),G()))[n][1]

シーケンス全体のジェネレーターを64文字で定義します。残念ながら、ジェネレータのn番目の要素を取得するには、いくつかのゆがみを実行する必要がありますS=lambda n:G()[n]


2

パイス、12

@ edc65の回答のも​​う1つの移植版であり、誰が明確な勝者(IMO)ですか:

t`+hQv*l`Q\8

テストパッケージ(@DigitalTrauamaに感謝):

$ for n in 0 1 10 11 42 100 110 111 800 1060 1110 1111 10270 100501; do echo "shortlex.pyth $n = \"$(pyth programs/shortlex.pyth <<< $n)\""; done
shortlex.pyth 0 = ""
shortlex.pyth 1 = "0"
shortlex.pyth 10 = "9"
shortlex.pyth 11 = "00"
shortlex.pyth 42 = "31"
shortlex.pyth 100 = "89"
shortlex.pyth 110 = "99"
shortlex.pyth 111 = "000"
shortlex.pyth 800 = "689"
shortlex.pyth 1060 = "949"
shortlex.pyth 1110 = "999"
shortlex.pyth 1111 = "0000"
shortlex.pyth 10270 = "9159"
shortlex.pyth 100501 = "89390"

説明:

Q = eval(input())             Implicit.
t`                            All but the first digit of
  +hQ                         Q+1 + 
   v                          eval(
    *l`Q                      len(repr(Q)) * 
     \8                       "8"

CJam vs Pyth; 戦いは続きます。:P
デニス14

この挑戦のためにPythを試してみましたが、Listを整数に変換する方法が見つかりませんでした(例:)[8, 8, 9] -> 889。どうやってやるの?
デニス14

@Dennisリストからintに移動するには、基本的に文字列を処理する必要があります。jkリストを文字列にv変換し、それをintに変換します。したがってvjk[8 8 9]、番号889が与えられます。
isaacg

はい、ありがとう。悲しいことに、文字列変換はいくつかのトリックを不可能にします。CJam / GolfScriptベースの変換では、[2 -1] -> 19[1 11] -> 21
デニス14

1
@Dennis Yeah、実際にPythに基本変換を追加したら、それは機能します。しかし、私はまだしていません。
isaacg 14


1

Haskell、57バイト

((g=<<[0..])!!)
g 0=[""]
g n=[c:s|c<-['0'..'9'],s<-g$n-1]

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

答えのために、shortlex番号の無限リストとインデックスを作成します。g n前の世代の各数値の前に次の数字を追加することにより、数値のn番目の「世代」を構築します。




0

ゼリー、5バイト

ḃ⁵ịØD

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

私はゼリーが初めてなので、これを改善できるならコメントしてください!

説明:

ḃ⁵ịØD   Main link.
ḃ       Convert to bijective base ...
 ⁵      10.
  ị     Each number (1 - 10) is converted to the character at its index in the string...
   ØD   “0123456789” (digits)

(上記のresのコメントによれば、問題は数を全単射10に変換することと同等です)

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