xkcd样式页面编号


65

Randall Munroe的书“ xkcd,第0卷”对页码使用了一个相当奇数的系统。前几个页码是

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

这看起来有点像三元,但是请注意,他从跳过20100,从1202002001000。定义此序列的一种方法是说,它枚举了最多包含一个21之后不包含的所有三进制数2。您可以在OEIS的条目A169683中找到它。这个数字系统被称为偏斜二进制

您的任务是找到N此数字系统中给定正整数的表示形式。

您可以编写程序或函数,通过STDIN(或最接近的替代方案),命令行参数或函数自变量获取输入,并通过STDOUT(或最接近的替代方案),函数返回值或函数(out)参数输出结果。

输出可能是字符串,带有十进制表示形式的数字(等于偏斜二进制表示形式)或数字列表(整数或字符/字符串)。您不得返回前导零。

这是代码高尔夫球,因此最短的答案(以字节为单位)获胜。

有趣的事实:这个数字系统实际上有一些优点。当增加一个数字时,您将始终最多更改两个相邻的数字-您将不必在整个数字中进行更改。使用正确的表示形式,可以递增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

我会悬赏于最短的答案,它可以在不到一秒钟的时间内解决最后一个测试用例(以及任何其他类似大小的输入,因此不要考虑对其进行硬编码)。

排行榜

这是一个堆栈片段,用于按语言生成常规排行榜和获胜者概述。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# 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
自从第一本书问世以来,我就一直拥有这本书,却从未注意到页面编号。
Alex

2
@AlexA。我将其放在Kindle上,在这里您无法进行任何有趣的页面编号。
LegionMammal978

21
@ LegionMammal978:悲惨的。
Alex A.

1
@ SuperJedi224 共识似乎不是,所以很抱歉(如果您的语言可以处理的唯一输入是这种情况,我会从共识中例外,但事实并非如此)。
马丁·恩德

4
这使我想起了我3岁时的计算方式。我推断:“没有五十,所以一百零九之后必须是二百。” 见状之间差异我才意识到我的错误59->60,并109->110与额外的0
Cyoce

Answers:


12

Pyth,17个字节

Ljb3ye.f!-P-yZ01Q

这有点荒谬地缓慢- O(output^log_2(3))。它是输入长度的指数,但不是双指数,就像页面上的某些答案一样。从@Dennis的答案中获取一些想法,请点击此处

示范。

它利用.f,Pyth的“循环,直到找到n个匹配项”功能。


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%

感谢@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 Ĵ + K + 1)是小于2 K + 1 -1,的值一个ķ一个0可以通过连续模块划分由回收的2 K + 1 -12 k -1等。

首先,我们必须先找到2 k + 1 -1的值。由于n最多为2(2 k + 1 -1),因此整数n +1必须严格小于2 k + 2

因此,取n + 1的二进制对数的整数部分将得出k + 1

最后,我们观察到整数n +1以2底的log 2(n +1)个数字。

这个怎么运作

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#

在最后两个迭代中,我们执行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)。返回等于歪斜二进制数的十进制表示形式。

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)。返回数字列表。


2and在3 中编译?我在2中并2and2抛出语法错误
TankorSmash 2015年

3
@TankorSmash 2and2是行不通的,因为它会得到解析为2 and2-尝试2and 2,它应该工作,如果你的Python版本够新(在Python 2.7.10测试)
SP3000

哦,很好,你是对的。即使在2.7.3上也可以。
TankorSmash 2015年

12

CJam,22 21 20字节

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

这是一种O(e n n)方法,其中n是输入。它列出所述第一⌊e Ñ在基座3的非负整数,消除那些具有2秒或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()))中运行,在最后一个测试用例中不到一秒钟。基于运行直到错误循环。没有尾随换行符。

示范。

说明:

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初始化为大于输入的最小歪斜二进制数字位置的值。然后,每次循环时,我们都会执行以下操作:

  • 除去的值的每个数位JQ=%QJ。例如,如果Q=10J=7Q成为3,其对应于二进制偏斜改变从11010。这在第一次迭代中没有影响。
  • 用更改J为下一个较小的偏斜二进制基值=/J2。这是由2难倒分工,改变J=7J=3,例如。因为这是在输出第一个数字之前发生的,所以将其J设置为比所需位置高一个数字的位置。
  • 使用/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=
Martin Ender 2015年

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 2015年

@nderscore非常酷:D
罗盘

1
如果使用ES7,则为-7个字节:替换Math.pow(3,s.length+c)3**(s.length+c)
古斯塔沃·罗德里格斯

3
@GustavoRodrigues我什至还没有学习完ES6!@ _ @
罗盘2015年

7

视网膜,55字节

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

一元输入。

每一行都应转到其自己的文件,但是您可以将代码作为带有-s标志的一个文件来运行。例如:

> echo 11111|retina -s skew
12

方法:从string开始,对输入的字符串执行递增的次数0

我们使用以下递增规则:

  • 如果包含2^2 -> ^12; 02 -> 12;12 -> 20
  • 如果不包含20$ -> 1$;1$ -> 2$

2字符串中最多可以有一个;^$在规则中标记字符串的开头和结尾。)

有关视网膜的更多信息。


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并以字符串形式返回结果的方法

使用a 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
您可以通过使其成为函数而不是完整程序(并以输入作为参数而不是来自Scanner)来将其缩短很多。
Geobits,2015年

2
您不需要if(j == 0) 语句中的花括号(四个字节)。您无需声明k; 您可以j再次使用(多四个)。您可以在列表声明(new ArrayList<>();)(另一个4)中使用通用类型推断(在Java 7中)
durron597 2015年

4

哈斯克尔,73 72

感谢@nimi 1个字节!

该解决方案不会赢得任何奖励,最后几次测试需要花费大量时间才能运行,但是我认为我打得不错。

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

该解决方案是一种非常幼稚的方法,它n通过递增0 n次来计算偏斜二进制数。


4

CJam,24个字节

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

这是一种O(n log n)方法,其中n是输入。它以偏斜二进制表示形式0开头,并递增相应的整数n次。

CJam解释器中在线尝试。

背景

可以通过以下两个简单步骤来增加偏斜二进制数中的数字:

  1. 最终将2替换为0

  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,然后再倒退2并向前跳10,否则它只是以1计数。

由于VBA坚持以科学计数形式提供输出,因此该代码在65534处停止工作,但是对于更大的数字,逻辑应该可以正常工作

期待高尔夫方面的建议,VBA并不是非常友好的高尔夫,但是它并不经常出现,我认为它可以在Java方面胜过所有人。

Edit1:感谢Manu帮助削减了62个字节

Edit2:交换debug.printmsgbox输出。保存了5个字节


1
您可以从中删除括号Debug.Print (q)。另外,您可以删除大多数空白(编辑器会将它们放回去,但不是必须的)。您无需声明k as Long,只需编写即可k。这将是Variant类型的变量,并且代码仍将起作用。使用这些技巧,您应该可以减少到165个字节。
CommonGuy 2015年

还有一些想法:您可以忽略的第一个和最后一个参数InStr,它们是可选的。Trim()不需要,因为您没有空格。正确应用后,我得到147个字节
CommonGuy 2015年

1
感谢您的帮助手册,一个简单的问题,输出应该是标准输出。我不确定VBA中会是什么。debug.print q将是标准输出?msgbox q较短,但再次看起来好像不是标准输出。 Sheet1.cells(1,1)看起来像“ 典型”输出,但假定其在excel中运行。我只是不太确定代码高尔夫球对这类事情的严格程度。
JimmyJazzx 2015年

恭喜,您打败了Java答案;)我也不知道...只要使用MsgBox,如果有人抱怨,您仍然可以将其改回。
CommonGuy 2015年

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"

有趣的事实:这个数字系统实际上有一些优点。当增加一个数字时,您将始终最多更改两个相邻的数字-您将不必在整个数字中进行更改。使用正确的表示形式,可以递增O(1)。

谢谢您的事实-这是我解决方案的基础:)


如何在正则表达式中留下不必要的括号?o_O
Qwertiy

3

八度,107101字节

如果我想知道这个权利应该是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将所有内容都视为浮点数,而我没有足够的精度来计算最后一个。我通过花费宝贵的字节来强制所有内容都是无符号整数来解决这个问题。最后一个的结果太大而不能视为数字,因此结果是一个字符串。

输出(我包括在内,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是最好的高尔夫语言。这是一个可以计算最后一个测试用例的版本。在我对其进行测试的机器上,它运行了不到一秒钟,我很想知道它如何在其他所有人中运行。

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

如果仅使用整数,则可能会短一些,为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功能。
Michael B

@MichaelB哦,我以为我曾经用过@,愚蠢的我。该CHAR(8000)建议非常好,我会尝试的。我似乎总是忘记了STR()要感谢的存在。
PenutReaper 2015年

实际上没有帮助。但是,您可以将CTE之后的部分重写为:: select @t=concat(@t,@/i)应该更小。需要sql2012。
Michael B

@MichaelB啊。CONCAT,我在2008年。因此,如果不立即使用SQL提琴,就无法对其进行测试。好电话。
PenutReaper 2015年

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因为(.*)in $1应当贪婪并首先获得该角色。但是,如果将其删除,则代码将不再产生正确的结果!顺便说一句,您不需要final ;
CJ Dennis

@CJDennis感谢您保存该字节。无论如何,。?除非数字中没有数字(例如20),否则将使数字紧靠两位。在例如120或10020的情况下,正则表达式组如下:()(1)2(0)和(10)(0)2(0)。然后,简单地忽略第一组,增加第二组(如果可能,总是为一位,否则为空白),然后忽略第三组(始终由零组成)并添加零。我只是将OEIS条目用作此正则表达式的指南。
frederick 2015年

我将您的代码缩减为53个字节:$c=<>;s/(.*)2(.*)/$1+1 .$2.0/e||$_++while($c--);print。我是对的,(.?)从未捕获任何东西。
CJ Dennis

可以优化为$_=1;$c=<>;s/(.?)2/1+$1.0/e||$_++while(--$c);print,即50个字节。.*如果只是将其替换为原始文本,则可以优化开头或结尾的内容。同样也没有理由在末尾加0,因为原始总是只有零$3
Thraidh

2

Pyth,19个字节

m/=%Qtydtd^L2_SslhQ

对数复杂度。在必要的时间内轻松完成。以数字列表形式输出。

示范


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我们在座位边上等待
罗伯特·格兰特

@RobertGrant他从两件事变成一件事!
CJ Dennis

两件事:1.代替使用$ ARGV [0],使用<>作为输入。除非有任何文件作为参数,否则它将从stdin接收输入。2.对于像这样的奇数计数方案,请使用正则表达式。代替执行奇数数学运算,您可以像替换字符串一样替换数字中的数字。最好的部分是,如果它是完全由数字组成的字符串,则可以同时对其使用数学运算(如增量)。查看正则表达式运算符的文档,因为它们在很多情况下都非常有用。
frederick 2015年

抱歉,我按Enter键并保存后再完成评论。
frederick 2015年

@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错误消息(为此它在我的计算机上以0.03秒为单位计算结果)

取消MaxExtraPrecision限制后,它将在一秒钟内处理高达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数组缓冲区转换为可打印的数字字符串。输入的运行时少于一毫秒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一点优势...
Toby Speight 2015年


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 2015年

@Qwertiy我已为您的答案提供了归属,如果没有正则表达式中的括号,我将无法给出相同的结果
rink.attendant.6 2015年

整个事件被替换。您为什么需要它加入小组?JS版本可在不带括号的Firefox中使用。
Qwertiy 2015年

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

Stax,16 个字节

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

运行并调试

我不确定确切的形式复杂度类是什么,但是它的速度足以在十分之一秒的时间内完成这台计算机上的所有测试用例。

拆开包装,松开包装并进行评论,看起来像这样。在此程序中,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

运行这个

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.