xkcdスタイルのページ番号


65

Randall Munroeの本「xkcd、volume 0」では、ページ番号にやや奇数のシステムを使用しています。最初のいくつかのページ番号は

1, 2, 10, 11, 12, 20, 100, 101, 102, 110, 111, 112, 120, 200, 1000, 1001, ...

これは、3進法に少し似ていますが、彼が20まっすぐに100、から120200そしてにスキップすることに注意し200てください1000。このシーケンスを定義する1つの方法は、それがせいぜい1を含むすべての3進数を列挙して21その後でないと言うこと2です。これはOEISのエントリA169683にあります。この番号体系は、スキューバイナリと呼ばれます。

あなたの仕事はN、この番号体系で与えられた正の整数の表現を見つけることです。

プログラムまたは関数を作成し、STDIN(または最も近い代替)、コマンドライン引数または関数引数を介して入力を取得し、STDOUT(または最も近い代替)、関数の戻り値または関数(out)パラメーターを介して結果を出力できます。

出力は、文字列、スキューバイナリ表現に等しい10進表現の数値、または(整数または文字/文字列としての)数字のリストです。先行ゼロを返してはなりません。

これはコードゴルフなので、最短の回答(バイト単位)が勝ちです。

おもしろい事実:この番号体系には、実際にはいくつかのメリットがあります。数字をインクリメントするとき、常に最大で2つの隣接する数字を変更します-数字全体に変更を伝える必要はありません。O(1)の増分を許可する正しい表現を使用します。

テストケース

1 => 1
2 => 2
3 => 10
6 => 20
7 => 100
50 => 11011
100 => 110020
200 => 1100110
1000 => 111110120
10000 => 1001110001012
100000 => 1100001101010020
1000000 => 1111010000100100100
1048576 => 10000000000000000001

1000000000000000000 => 11011110000010110110101100111010011101100100000000000001102

最後のテストケース(および同様の大きさの他の入力なので、ハードコーディングについては考えないでください)を1秒未満で解決できる最短回答に報奨金を与えます。

リーダーボード

これは、通常のリーダーボードと言語ごとの勝者の概要の両方を生成するスタックスニペットです。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、見出しから回答を開始してください。

# Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

# Ruby, <s>104</s> <s>101</s> 96 bytes

<script>site = 'meta.codegolf'; postID = 5314; isAnswer = true; QUESTION_ID = 51517</script><script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>jQuery(function(){var u='https://api.stackexchange.com/2.2/';if(isAnswer)u+='answers/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJeRCD';else u+='questions/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJO6t)';jQuery.get(u,function(b){function d(s){return jQuery('<textarea>').html(s).text()};function r(l){return new RegExp('<pre class="snippet-code-'+l+'\\b[^>]*><code>([\\s\\S]*?)</code></pre>')};b=b.items[0].body;var j=r('js').exec(b),c=r('css').exec(b),h=r('html').exec(b);if(c!==null)jQuery('head').append(jQuery('<style>').text(d(c[1])));if (h!==null)jQuery('body').append(d(h[1]));if(j!==null)jQuery('body').append(jQuery('<script>').text(d(j[1])))})})</script>


32
私はその本が最初に出てきて以来、その本を持っていて、ページ番号に気づいていませんでした。
アレックスA.

2
@AlexA。面白いページ番号付けができないKindleにあります。
LegionMammal978

21
@ LegionMammal978:悲劇的。
アレックスA.

1
@ SuperJedi224 コンセンサスはnoのようですので、申し訳ありません(コンセンサスがあなたの言語で処理できる唯一の入力であればコンセンサスから例外を作りますが、そうではないようです)。
マーティンエンダー

4
これは、私が3歳のときにどのように数えていたかを思い出させます。私は「50はないので、百から九は二百でなければならない」と推論しました。私は唯一の違いを見て時に私のミスを実現59->60し、109->110余分な0で、
Cyoce

回答:


12

Pyth、17バイト

Ljb3ye.f!-P-yZ01Q

これはやや途方もなく遅いです- O(output^log_2(3))。入力の長さは指数関数的ですが、ページ上のいくつかの回答のように、二重指数関数的ではありません。@Dennisの回答から取ったいくつかのアイデアはこちら

デモンストレーション。

これは、使用可能.f機能を「n個の一致が発見されるまでループ」Pythのを、。


32

CJam、24 23 22 21 19バイト

ri_)2b,,W%{2\#(md}/

これはO(log n)アプローチです。nは入力で、最後のテストケースを即座に完了します。数字1の値によるモジュラー除算を使用して、nをスキューバイナリに直接変換します。

このコードは、JavaインタープリターでSTDERRに送られるエラーで終了します。これはMetaコンセンサスに従って許可されています。

CJamインタープリターでこのコードを試しても、出力の最終行以外はすべて無視してください。

を先頭に追加2>することにより、2バイトのコストでエラーを排除できますW%

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

バックグラウンド

スキューバイナリ表現a k ... a 0は、整数n =(2 k + 1 -1)a k + ... +(2 1 -1)a 0に対応します。

以来、両方の(2 K -1)+ ... +(2 1 -1)= 2 のk + 1 - (K + 2)及び(2 K -1)+ ... + 2(2 J -1)= 2 k + 1-(2 j + 1-2 j + k + 1)2 k + 1 -1未満であり、a kからa 0の値は2 k + 1 -1による連続的なモジュラー除算によって回復できます。、2 k -1など

最初に、2 k + 1 -1の値を見つける必要があります。以来、nが最大である2(2 K + 1 -1)、整数N + 1は、より厳密に小さくなければならない2 K + 2

したがって、n + 1の 2進対数の整数部分を取得すると、k + 1が生成されます。

最後に、我々は整数ことを観察N + 1⌊log 2 ⌋(N + 1)をベース2の桁。

使い方

ri    e# Read an integer N from STDIN.
2b,   e# Push the number of binary digits of N + 1, i.e, K + 2 = log(N + 1) + 1.
,W%   e# Push the range [K+1 ... 0].
{     e# For each J in the range:
  2\# e#   J -> 2**J
  (   e#     -> 2**J - 1
  md  e#   Perform modular division of the integer on the stack (initially N)
      e#   by 2**J - 1: N, 2**J - 1 -> N/(2**J - 1), N%(2**J - 1)
}/    e#

最後の2回の反復では、10によるモジュラー除算を実行します。最初は、スタックに不要な0をプッシュします。スタックから0 0 md不要な0をポップする最後の実行試行は、何かをプッシュする代わりにすぐに終了し、スタックをSTDOUTにダンプします。


28

Python 2、67バイト

def f(n):x=len(bin(n+1))-3;y=2**x-1;return n and n/y*10**~-x+f(n%y)

与えられたテストケースで動作するようです。これが正しければ、これは約O(place values set in output)になりますので、最後のケースを簡単に実行できます。

のように呼び出しf(100)ます。スキューバイナリに等しい10進表現を返します。

Python 3、65バイト

def g(n,x=1):*a,b=n>x*2and g(n,x-~x)or[n];return a+[b//x,b%x][:x]

効率はやや劣りますが、それでも対数なので、最後のケースはほぼ瞬時です。

のように呼び出しg(100)ます。数字のリストを返します。


2and3でコンパイル?私は2 2and2
歳で

3
@TankorSmashは、2and2それは次のように解析され得ると思いますので、動作しません2 and2してみてください- 2and 2あなたのPythonのバージョンは、(Pythonの2.7.10でテスト)十分に新しい場合は動くはずです、
SP3000

いいね、あなたは正しい。2.7.3でも動作します。
TankorSmash

12

CJam、22 21 20バイト

ri_me,3fb{0-W<1-!},=

これはO(e n n)アプローチで、nは入力です。これは、最初の一覧表示⌊e N、ベース3の非負整数を有するもの排除2つの S又は1つの最初の後にSを2(もしあれば)とを選択するN + 1 番目

CJamインタープリターでオンラインで試してください。

使い方

ri    e# Read an integer N from STDIN.
_me,  e# Push [0 ... floor(exp(N))-1].
3fb   e# Replace each integer in the range by the array of its digits in base 3.
{     e# Filter; for each array A:
  0-  e#   Remove all 0's.
  W<  e#   Remove the last element.
  1-  e#   Remove all 1's.
  !   e#   Logical NOT. Pushes 1 iff the array is empty.
},    e#   If ! pushed 1, keep the array.
=     e# Select the (N+1)th element of the filtered array.

9

Pyth、20バイト

Jt^2hslhQ#p/=%QJ=/J2

O(log(input()))で実行されます。最終テストケースでは1秒未満です。run until errorループに基づいています。末尾の改行はありません。

デモンストレーション。

説明:

Jt^2hslhQ#p/=%QJ=/J2
                        Implicit: Q is the input.
      lhQ                          log(Q+1,2)
     slhQ                    floor(log(Q+1,2))
    hslhQ                    floor(log(Q+1,2))+1
  ^2hslhQ                 2^(floor(log(Q+1,2))+1)
 t^2hslhQ                 2^(floor(log(Q+1,2))+1)-1
Jt^2hslhQ               J=2^(floor(log(Q+1,2))+1)-1
         #              until an error is thrown:
            =%QJ        Q=Q%J
                =/J2    J=J/2
           /            The value Q/J, with the new values of Q and J.
          p             print that charcter, with no trailing newline.

Jは、入力よりも大きい最小のスキュー2進数位置の値に初期化されます。次に、ループを通過するたびに、次のことを行います。

  • Jから値の各桁を削除Q=%QJます。例えば、もしQ=10J=7Qとなる3からスキューバイナリ変化に対応する11010。これは最初の反復では効果がありません。
  • を使用Jして、次に小さいスキューバイナリベース値に変更し=/J2ます。これは、2によるフロア分割で、たとえばに変更J=7J=3れます。これは最初の数字が出力される前に発生するためJ、必要以上に1桁高い位置に初期化されます。
  • /QJ(効果的に)実際の数字の値を見つけます。
  • p末尾の改行を避けるために、Pythのデフォルトの印刷ではなく、でその値を印刷します。

このループはJゼロになるまで繰り返され、ゼロになるとゼロ除算エラーがスローされ、ループは終了します。


8

ES6、105バイト

f=n=>{for(o=0;n--;c?o+=Math.pow(3,s.length-c):o++)s=t(o),c=s.search(2)+1;return t(o);},t=a=>a.toString(3)

使用法: f(1048576)=> `" 10000000000000000001 "

自分の責任で最後の引数をテストしてください。5秒後にあきらめました。

そして、コメント付きできれいに印刷してください!

f=n=>{ //define function f with input of n (iteration)
    for(o=0; //define o (output value in decimal)
        n--; //decrement n (goes towards falsy 0) each loop until 0
        c?o+=Math.pow(3,s.length-c):o++) //if search finds a 2, increment output by 3^place (basically moves the 2 to the left and sets the place to 0), else ++
        s=t(o), //convert output to base 3      
        c=s.search(2)+1; //find the location of 2, +1, so a not-found becomes falsy 0.
    return t(o); //return the output in base 3
},

t=a=>a.toString(3);  //convert input a to base 3

5
ところで、名前のない関数は完全に受け入れられるので、必要はありませんf=
マーティンエンダー

2
-16バイト:f=n=>{for(o=0;~n--;o+=c?Math.pow(3,s.length+c):1)s=o.toString(3),c=~s.search(2);return s}
nderscore

@nderscoreかなりクール:D-
コンパス

1
-7バイトは、あなたはES7を使用している場合:交換してくださいMath.pow(3,s.length+c)3**(s.length+c)
グスタボロドリゲス

3
@GustavoRodrigues ES6の学習さえ終わっていません!@ _ @
コンパス

7

網膜、55バイト

^
0a
(+`12(.*a)1
20$1
0?2(.*a)1
10$1
0a1
1a
)`1a1
2a
a
<empty line>

単項で入力を取ります。

各行は独自のファイルに移動する必要がありますが、-sフラグを使用してコードを1つのファイルとして実行できます。例えば:

> echo 11111|retina -s skew
12

メソッド:stringから開始して、入力された文字列でnumber回インクリメントを実行する0

次の増分ルールを使用します。

  • 含まれている場合2^2 -> ^12; 02 -> 12;12 -> 20
  • が含まれていない場合20$ -> 1$;1$ -> 2$

(そこでは、ほとんどのいずれかになります。2文字列に、^そして$ルール内の文字列の開始と終了をマークします。)

Retinaの詳細。


7

Java、154 148

n->{String s="0";for(;n-->0;)s=s.contains("2")?s.replaceAll("(^|0)2","10").replace("12","20"):s.replaceAll("1$","2").replaceAll("0$","1");return s;}

この回答は、整数の引数を取り、回答を文字列として返す単一の匿名関数の形式を取ります。以下は、このソリューションをテストするための完全なクラスです。

import java.util.function.Function;
public class Skew {
    public static void main(String[] args){
        Function<Integer,String> skew = n->{String s="0";for(;n-->0;)s=s.contains("2")?s.replaceAll("(^|0)2","10").replace("12","20"):s.replaceAll("1$","2").replaceAll("0$","1");return s;};

        for(String s:args){
            System.out.println(skew.apply(Integer.parseInt(s)));
        }
    }
}

5

Bash + coreutils、52

dc -e3o0[r1+prdx]dx|grep -v 2.\*[12]|sed -n $1{p\;q}

これはブルートフォーサーであるため、数値が大きいほど遅くなります。

出力:

$ ./xkcdnum.sh 1000
111110120
$ 

5

Java、337 335 253 246 244バイト

インデックスをaとして受け取りlong、結果を文字列として返すメソッド

使用するlongインデックスのためにそうすることができ、理論的に最後のテストケースを扱うが、私は本当にそれを示唆しています。

String f(long i){List<Long>l=new ArrayList<>();l.add(0L);for(;i-->0;){int j=l.indexOf(2);if(j!=-1){l.set(j,0L);if(j==0){l.add(0,1L);}else{l.set(j-1,l.get(j-1)+1);}}else{j=l.size()-1;l.set(j,l.get(j)+1);}}String s="";for(long q:l)s+=q;return s;}

4
これを完全なプログラムではなく関数にすることで(およびスキャナーからではなく引数として入力を取得することで)これをかなり短くすることができます。
ジオビット

2
if(j == 0) 文の中括弧は必要ありません(4バイト)。宣言する必要はありませんkjもう一度使用できます(さらに4つ)。あなたは(あなたのリスト宣言で(Javaの7の)ジェネリック型の推論を使用することができますnew ArrayList<>();)(別の4)
durron597

4

ハスケル、73 72

1バイトの@nimiに感謝します!

このソリューションは賞金を獲得することはできません。最後の数回のテストは実行に膨大な時間を要しますが、私はそれをかなりうまくやったと思います。

i(2:b)=1:0:b
i[b]=[b+1]
i(b:2:c)=b+1:0:c
i(b:c)=b:i c
s=(iterate i[0]!!)

このソリューションは、n0 n回インクリメントすることでスキューバイナリ数を計算するかなり単純なアプローチです。


4

CJam、24バイト

Q{0\+2a/())+a\+0a*}ri*si

これはO(n log n)アプローチです。ここで、nは入力です。0のスキューバイナリ表現から始まり、対応する整数をn回インクリメントします。

CJamインタープリターでオンラインで試してください。

バックグラウンド

スキューバイナリでの数値のインクリメントは、次の2つの簡単な手順で実行できます。

  1. 最終的な20に置き換えます

  2. 場合は2が交換されている、その左に数字をインクリメントします。

    それ以外の場合は、最後の桁を増やします。

使い方

Q     e# Push an empty array.
{     e# Define an anonymous function:
  0\+ e#   Prepend a 0 to the array.
  2a/ e#   Split the array at 2's.
  (   e#   Shift out the first chunk of this array.
  )   e#   Pop the last digit.
  )+  e#   Increment it and append it to the array.
  a\+ e#   Prepend the chunk to the array of chunks.
  0a* e#   Join the chunks, using [0] as separator.
      e#   If there was a 2, it will get replaced with a 0. Otherewise, there's
      e#   only one chunk and joining the array dumps the chunk on the stack.
}     e#
ri*   e# Call the function int(input()) times.
si    e# Cast to string, then to integer. This eliminates leading 0's.

4

VBA、209 147 142バイト

Sub p(k)
For i=1To k
a=StrReverse(q)
If Left(Replace(a,"0",""),1)=2Then:q=q-2*10^(InStr(a,2)-1)+10^InStr(a,2):Else:q=q+1
Next
msgbox q
End Sub

私の数学は非効率的であり、私のゴルフは仕事を使うことができます。しかし、これはPoGでの最初の試みであり、これを試してみたいと思いました。しかし、ブルートフォースの方法の並べ替え。

最後の桁が2でない限り、1だけカウントし、2ずつ戻り、10にジャンプします。さらに、末尾の0を加算します。

これは、VBAが科学表記法で出力することを要求するため、65534で動作を停止しますが、ロジックはさらに大きい数値でも正常に動作するはずです

ゴルフの提案を楽しみにしていますが、VBAはゴルフにあまり適していませんが、表されることはあまりなく、Javaに勝つことができると思います。

Edit1:62バイトを削るのを手伝ってくれてありがとうManu

Edit2:出力として交換さdebug.printmsgboxました。5バイト保存


1
からブラケットを削除できますDebug.Print (q)。また、空白のほとんどを削除することができます(エディターはそれらを元に戻しますが、必要ではありません)。宣言する必要はなくk as Long、単に書くだけkです。Variant型の変数になり、コードは引き続き機能します。これらのヒントを使用すると、最大で165バイトになります。
CommonGuy

さらなる考え:の最初と最後の引数InStrは省略できますが、それらはオプションです。Trim()空白がないため、必要ありません。正しく適用すると、147バイトになります
CommonGuy

1
ヘルプマヌのおかげで、簡単な質問が1つあります。出力は標準出力でなければなりません。それがVBAでどうなるかはわかりません。debug.print q標準出力になりますか?msgbox q短いですが、やはり標準出力ではないようです。 Typical出力のSheet1.cells(1,1)ように見えますが、Excelで実行されていることを前提としています。私は、この種のことに関して、コードゴルフがどれほど厳格であるかについてはよくわかりません。
-JimmyJazzx

おめでとう、あなたはjavaの答えを破りました;)私も知りません... MsgBox誰かが文句を言ったら、それを元に戻すことができます。
CommonGuy

4

JavascriptをES6、99 86 78 76 72文字

f=n=>{for(s="1";--n;s=s.replace(/.?2|.$/,m=>[1,2,10][+m]||20));return s}

// Old version, 76 chars:
f=n=>{for(s="1";--n;s=s.replace(/02|12|2|.$/,m=>[1,2,10][+m]||20));return s}

// Old version, 86 chars:
f=n=>{for(s="1";--n;s=s.replace(/(02|12|2|.$)/,m=>[1,2,10,,,,,,,,,,20][+m]));return s}

// Old version, 99 chars:
f=n=>{for(s="1";--n;s=s.replace(/(^2|02|12|20|.$)/,m=>({0:1,1:2,2:10,12:20,20:100}[+m])));return s}

テスト:

;[1,2,3,6,7,50,100,200,1000,10000,100000,1000000,1048576].map(f) == "1,2,10,20,100,11011,110020,1100110,111110120,1001110001012,1100001101010020,1111010000100100100,10000000000000000001"

おもしろい事実:この番号体系には、実際にはいくつかのメリットがあります。数字をインクリメントするとき、常に最大で2つの隣接する数字を変更します-数字全体に変更を伝える必要はありません。O(1)の増分を許可する正しい表現を使用します。

事実をありがとう-それは私のソリューションのベースです:)


正規表現に不要なブレースを残すにはどうすればよいですか?o_O
Qwertiy

3

オクターブ、107 101バイト

この権利を考えている場合、O(log n)である必要があります ...

function r=s(n)r="";for(a=2.^(uint64(fix(log2(n+1))):-1:1)-1)x=idivide(n,a);r=[r x+48];n-=x*a;end;end

プリティプリント:

function r=s(n)
  r="";
  for(a=2.^(uint64(fix(log2(n+1))):-1:1)-1)
    x=idivide(n,a);
    r=[r x+48];
    n-=x*a;
  end
end

Octaveはデフォルトですべてを浮動小数点数として扱い、最後の1つを計算するのに必要な精度を持っていなかったため、私は最後の課題に対処するのに多少苦労しました。私は貴重なバイトを費やしてすべてを符号なし整数にすることでそれを回避しました。最後の結果は数値として扱うには大きすぎたため、結果は文字列です。

出力(これ1e18 - 1を正確に行えることを示すために含めています。最後の出力セットは、その値を計算するのにかかる時間を示しています):

octave:83> s(uint64(1e18))
ans = 11011110000010110110101100111010011101100100000000000001102

octave:84> s(uint64(1e18)-1)
ans = 11011110000010110110101100111010011101100100000000000001101

octave:85> tic();s(uint64(1e18)-1);toc()
Elapsed time is 0.0270021 seconds.

3

T-SQL、221 189 177バイト

編集:このコードの元のバージョンは、いくつかの数値に対して誤った出力を生成しますが、これは修正されています。

ここでのすべてのクエリでは、計算する数値を最初のコンマの前に追加するだけです。

T-SQLが最高のゴルフ言語であることは誰もが知っています。これは、最後のテストケースでさえ計算するバージョンです。私がテストしたマシンでは、1秒未満で実行されました。他のすべてのユーザーに対してどのように実行されるかを知りたいと思います。

DECLARE @ BIGINT=,@T VARCHAR(MAX)='';WITH M AS(SELECT CAST(2AS BIGINT)I UNION ALL SELECT I*2FROM M WHERE I<@)SELECT @T += STR(@/(I-1),1),@%=(I-1)FROM M ORDER BY I DESC SELECT @T

そして、ここでも再びですが、読みやすいです:

DECLARE 
    @ BIGINT=,
    @T VARCHAR(MAX)='';

WITH M AS
(
    SELECT
        CAST(2 AS BIGINT) I

    UNION ALL

    SELECT I * 2
    FROM M
    WHERE I < @
)

SELECT 
    @T+=STR(@/(I-1),1),
    @%=(I-1)
FROM M 
ORDER BY I DESC

SELECT @T

intのみを使用する場合、これは少し短くなり、157バイトになります。

DECLARE @ INT=,@T VARCHAR(MAX)='';WITH M AS(SELECT 2I UNION ALL SELECT I*2FROM M WHERE I<@)SELECT @T+=STR(@/(I-1),1),@%=(I-1)FROM M ORDER BY I DESC SELECT @T

そしてもう一度、より読みやすく:

DECLARE 
    @ INT=,
    @T VARCHAR(MAX)='';

WITH M AS
(
    SELECT
        2I

    UNION ALL

    SELECT 
        I * 2
    FROM M
    WHERE I < @
)

SELECT 
    @T+=STR(@/(I-1),1),
    @%=(I-1)
FROM M 
ORDER BY I DESC

SELECT @T

@SQLの有効な識別子であることを忘れないでくださいChar(8000) 。nvarchar(max)よりも安価である可能性が高いでしょう。のchar代わりにvarcharに変換するか、str関数を使用することもできます。
マイケルB

@MichaelBああ、私@は愚かな私を使用していたと思った。CHAR(8000)アドバイスはかなり良いですが、私はそれを試してみましょう。いつもSTR()感謝の気持ちを忘れているようです。
PenutReaper

実際には役に立たない。ただし、CTEの後の部分を次のように書き換えることができますselect @t=concat(@t,@/i)。ただし、sql2012が必要です。
マイケルB

@MichaelBああ。CONCAT、私は2008年です。だから、今のところSQLフィドルを使わずにテストすることはできません。でもいいね。
PenutReaper

3

チューリング機械コード、333 293バイト

ここで使用されているエンコーディングを使用しています

このマシンは9つの状態と11色を使用します。

バイナリ入力が許容される場合、これはわずか4色に減らすことができ、プロセスで数十バイトを節約できます。

0 _ _ l 1
0 * * r 0
1 9 8 l 2 
1 8 7 l 2
1 7 6 l 2
1 6 5 l 2
1 5 4 l 2
1 4 3 l 2
1 3 2 l 2
1 2 1 l 2
1 1 0 l 2
1 0 9 l 1
1 _ _ r 8
2 _ _ l 3
2 * * l 2
3 _ 1 r 4
3 * * l 5
4 _ _ r 0
4 * * r 4
5 * * l 5
5 _ _ r 6
6 _ _ l 7
6 2 0 l 7
6 * * r 6
7 _ 1 r 4
7 0 1 r 4
7 1 2 r 4
8 _ _ * halt
8 * _ r 8

上記のリンクが機能しない場合(場合によっては機能しますが、ページの読み込みが拒否される場合もあります)、このJava実装を使用しテストすることもできます


2

Perl、66バイト

番号はSTDINを介して入力されます。

$_=1;$c=<>;s/(.*)(.?)2(.*)/$1.$2+1 .$3.0/e||$_++while(--$c);print;

ソリューションの仕組みを説明していただけますか?欲張りで最初にそのキャラクターを取得する必要(.?)がある$2ので(.*)、私はあなたがどのように必要なのかわかりません$1。しかし、それが削除されると、コードは正しい結果を生成しなくなります!ところで、finalは必要ありません;
CJデニス

@CJDennisそのバイトを保存してくれてありがとう。とにかく、。?数字がない場合(20など)を除き、2の直前に数字が来ます。120または10020などの場合、正規表現グループは()(1)2(0)および(10)(0)2(0)のようになります。次に、最初のグループは単に無視され、2番目のグループ(可能な場合は常に1桁または空白)が増分され、3番目のグループ(常にゼロで構成される)は無視され、ゼロが追加されます。この正規表現のガイドとして、OEISエントリを使用しました。
フレデリック

コードを53バイトに減らしました:$c=<>;s/(.*)2(.*)/$1+1 .$2.0/e||$_++while($c--);print。私は正しかった、(.?)何も捕獲しなかった。
CJデニス

$_=1;$c=<>;s/(.?)2/1+$1.0/e||$_++while(--$c);print50バイトであるに最適化できます。.*元のテキストに置き換えるだけで、先頭または末尾の最適化を解除できます。また、元のには常にゼロしかないため、最後に0を追加する理由はありません$3
スレイド


2

Perl、84 70 67バイト

$n=<>;$d*=2while($d++<$n);$_.=int($n/$d)while($n%=$d--,$d/=2);print

それほどゴルフではありません良くなっていますが、すぐに動作します!

デニスの提案により、51(50バイト+ -pスイッチ)になりました。

$d*=2while$d++<$_;$\.=$_/$d|0while$_%=$d--,$d/=2}{

それはしなければならないようにと呼ばれるperl -p skew_binary.pl num_list.txt場所num_list.txt、それにエンコードするための番号を持つ単一の行が含まれています。


@frederick我々は2を待っている私たちの席の端にしている
ロバート・グラント

@RobertGrant彼は、2つのことから1つのことへのコメントをゴルフしました!
CJデニス

2つのこと:1. $ ARGV [0]を使用する代わりに、入力として<>を使用します。引数としてファイルがない限り、stdinからの入力を受け取ります。2.このような奇数のカウントスキームでは、正規表現を使用します。奇妙な数学演算を行う代わりに、数字の数字を文字列であるかのように置き換えることができます。最良の部分は、それが完全に数字で構成される文字列であるという条件で、数学演算(増分など)を同時に使用できることです。正規表現演算子は多くの場合に非常に役立つため、ドキュメントを確認してください。
フレデリック

申し訳ありませんが、Enterキーを押してコメントを終了する前に保存しました。
フレデリック

@frederickはそれほど控えめではありません。何が起こったか知っています!
ロバートグラント

1

Mathematica、65

これを行う前に他の提出物をのぞき見したことを認めなければなりませんが、十分に速いはずです。

f = (n = #;
     l = 0; 
     While[n > 0,
      m = Floor[Log2[1 + n]];
      l += 10^(m - 1);
      n -= 2^m - 1
     ]; l)&

使用法:

f[1000000000000000000]

出力:

11011110000010110110101100111010011101100100000000000001102

10 ^ 228のどこかでMaxExtraPrecisionエラーメッセージを表示し始めます(私のマシンでは.03秒で結果を計算します)。

MaxExtraPrecisionの制限を削除すると、1秒で最大10 ^ 8000までの数値を処理できます。

入力:

Timing[Block[{$MaxExtraPrecision = Infinity}, f[10^8000]];]

出力:

{1.060807, Null}

1

C、95バイト

void f(unsigned long i,int*b){for(unsigned long a=~0,m=0;a;a/=2,b+=!!m)m|=*b=i/a,i-=a**b;*b=3;}

これは、整数と、数字を返すバッファーを受け入れます。結果はに格納されb、値で終了します3(出力では発生しません)。0(質問では正の整数のみが指定されているため)の入力を処理する必要がないため、空の出力を避けるための特別なケースはありません。

拡張コード

void f(unsigned long i,int*b)
{
    for (unsigned long a=~0, m=0;  a;  a/=2, b+=(m!=0)) {
        *b = i/a;               /* rounds down */
        i -= *b * a;
        m = m | *b;             /* m != 0 after leading zeros */
    }
    *b=3;                       /* add terminator */
}

最上位の桁から順番に減算を行います。唯一の問題は、変数を使用してm先行ゼロの出力を回避することです。unsigned long long必要に応じて、10バイトのコストで自然に拡張できます。

テストプログラム

変換する数値をコマンド引数として渡します。int配列バッファを印刷可能な数字文字列に変換します。入力の実行時間は1ミリ秒未満です1000000000000000000

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char**argv)
{
    while (*++argv) {
        unsigned long i = strtoul(*argv, NULL, 10);
        int result[1024];
        f(i,result);

        /* convert to string */
        char s[1024];
        {char*d=s;int*p=result;while(*p!=3)*d++=*p+++'0';*d=0;}
        printf("%lu = %s\n", i, s);
    }

    return EXIT_SUCCESS;
}

試験結果

$ ./51517 $(seq 20)
1 = 1
2 = 2
3 = 10
4 = 11
5 = 12
6 = 20
7 = 100
8 = 101
9 = 102
10 = 110
11 = 111
12 = 112
13 = 120
14 = 200
15 = 1000
16 = 1001
17 = 1002
18 = 1010
19 = 1011
20 = 1012

私はC ++バージョンは似ていますが、使うことができますねauto a=~0ullわずかな利点のために...
トビースパイツ


0

CoffeeScript、92 69バイト

Qwertiyの回答と更新に基づく:

f=(n)->s='1';(s=s.replace /(.?2|.$)/,(m)->[1,2,10][+m]||20)while--n;s

# older version, 92 bytes
f=(n)->s='1';(s=s.replace /(^2|02|12|20|.$)/,(m)->{0:1,1:2,2:10,12:20,20:100}[+m])while--n;s

2
正規表現内の不要なブレースを削除して、簡単な最適化さえ行わずに他の言語に変換することは、私にとってはクールではないようです
...-Qwertiy

@Qwertiy私はあなたの答えへの帰属を提供しました、そして両方の答えで正規表現の括弧なしで同じ結果を出すことはできません
-rink.attendant.6

オカレンス全体が置き換えられます。なぜあなたはそれがグループの中にある必要があるのですか?JSバージョンは、括弧なしでFirefoxで動作します。
Qwertiy

0

Japt、31バイト

_r/?2|.$/g_÷C ç20 ª°Zs3}}gU['0]

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

このJSソリューションのほぼ直接の移植。より良い方法があるかどうかはわかりません。

開梱と仕組み

X{Xr/?2|.$/gZ{Z÷C ç20 ||++Zs3}}gU['0]

X{     Declare a function...
Xr       Accept a string, replace the regex...
/?2|.$/g   /.?2|.$/   (g is needed to match *only once*, opposite of JS)
Z{       ...with the function... (matched string will be 0,1,2,02 or 12)
Z÷C        Implicitly cast the matched string into number, divide by 12
ç20        Repeat "20" that many times (discard fractions)
||         If the above results in "", use the next one instead
++Z        Increment the value
s3         Convert to base-3 string (so 0,1,2 becomes 1,2,10)
}}
gU['0] Repeatedly apply the function on "0", U (input) times

0

スタックス、16 バイト

üxëàè£öΦGΩ│Je5█ò

実行してデバッグする

正式な複雑度クラスが何であるかは正確にはわかりませんが、このマシンで10分の1秒ですべてのテストケースを実行するのに十分高速です。

開梱されていない、コメントされていない、これはこのように見えます。このプログラムでは、xレジスタには元々入力が含まれています。

z       push []
{       start block for while loop
 |X:2N  -log2(++x)
 {^}&   increment array at index (pad with 0s if necessary)
 xc:G-X unset high bit of x; write back to x register
w       while; loop until x is falsy (0)
$       convert to string

これを実行する

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