计算范围


20

挑战:

计算1范围内所有数字的二进制表示形式中的1的数量。


输入:

两个非十进制正整数


输出:

1两个数字之间范围内的所有s 的总和。


范例:

4 , 7        ---> 8
4  = 100 (adds one)   = 1
5  = 101 (adds two)   = 3
6  = 110 (adds two)   = 5
7  = 111 (adds three) = 8

10 , 20     ---> 27
100 , 200   ---> 419
1 , 3       ---> 4
1 , 2       ---> 2
1000, 2000  ---> 5938

我只是解释了第一个示例,否则,如果我尝试为所有示例进行解释,它将占用大量空间。


注意 :

  • 数字可以相隔超过1000
  • 所有输入均有效。
  • 最小输出为1。
  • 您可以接受数字作为两个元素的数组。
  • 您可以选择数字的订购方式。

获奖标准:

这是因此每种语言的最短代码(以字节为单位)获胜。



1
我们可以将输入作为某种范围类型(IntRange在Kotlin中,Range在Ruby中)吗?
snail_

有趣的事实:情况下1000 - 2000产生5938,但1000降低的情况下,结果也下降了1000: 0-1000 = 4938证明
steenbergh

Answers:


9

JavaScript(ES6),38个字节

以currying语法接受输入(a)(b)

a=>b=>(g=c=>a>b?0:1+g(c^c&-c||++a))(a)

在线尝试!

已评论

a => b => (         // given the input values a and b
  g = c =>          // g = recursive function taking c = current value
    a > b ?         // if a is greater than b:
      0             //   stop recursion and return 0
    :               // else:
      1 +           //   add 1 to the final result
      g(            //   and do a recursive call to g() with:
        c ^ c & -c  //     the current value with the least significant bit thrown away
        || ++a      //     or the next value in the range if the above result is 0
      )             //   end of recursive call
)(a)                // initial call to g() with c = a


5

Java(JDK 10),55字节

a->b->{int c=0;for(;a<=b;)c+=a.bitCount(b--);return c;}

在线尝试!


IntStream.range(a,b+1).map(Integer::bitCount).sum()
saka1029

@ saka1029导入是强制性的。所以实际上a->b->java.util.stream.IntStream.range(a,b+1).map(Integer::bitCount).sum()是整个74字节。即使导入不是强制性的,参数也是必需的,因此我们必须编写a->b->IntStream.range(a,b+1).map(Integer::bitCount).sum(),该计数为57个字节
OlivierGrégoire18年

您可能还需要a->b->IntStream.range(a,b+1).map(Long::bitCount).sum()1字节的改进。边缘的,但​​仍然是一个。
NotBaal

@NotBaal正如Olivier在上面的评论中提到的,导入是强制性的,因此应该是a->b->java.util.stream.IntStream.range(a,b+1).map(Long::bitCount).sum()(71字节)。
凯文·克鲁伊森



4

MATL5 4字节

&:Bz

在线尝试!

感谢Luis Mendo节省了一个字节!

(implicit input a and b, a<b)
&:                              % two-element input range, construct [a..b]
  B                             % convert to Binary as a logical vector (matrix)
   z                            % number of nonzero entries
(implicit output of the result)


4

R41 34字节

function(a,b)sum(intToBits(a:b)>0)

在线尝试!

受到ngm的其他R解决方案的启发。转换为位后,将使用不同的方法。非常感谢Giuseppe暗示了可能的34字节解决方案。


可以使用34个字节!我忘了我在哪里看到了窍门(我知道我没有想到),但是有一个棘手的转换成summable向量-如果您/ ngm找不到它,我会发布。
朱塞佩

@朱塞佩确实!
JayCe

2
我使用一种可能有用的技术将其压缩为37个字节。还发现sdvar强迫他们加倍努力。
ngm

您可以pryr::f用来保存4个字节:tio.run
##K

@pajonk好点!但是我试图坚持使用基本的R软件包,而不是R + pryr。我将在meta上搜索什么可以被视为“纯R”。
JayCe

3

果冻,4字节

rBFS

在线尝试!

说明

rBFS –完整程序。从命令行参数获取两个输入。
r –范围。
 B –对于每个,转换为二进制。
  FS –展平并求和。

O_o,那很快吗?
穆罕默德·萨勒曼

@MuhammadSalman好吧,挑战也是种琐碎的IMO。
Xcoder先生18年

可能是,但发布后一分钟便有答案。
穆罕默德·萨勒曼

1
@MuhammadSalman是的,对于像这样的微不足道的挑战来说并没有那么快;对果冻的了解也随之而来。真正的努力来自于本月的语言QBasic。;-)
暴民埃里克(Erik the Outgolfer)

@EriktheOutgolfer:你能用QBasic / BrainF ** k回答这个问题吗?
穆罕默德·萨尔曼





2

Bash +通用工具,50

jot -w%o - $@|tr 247356 1132|fold -1|paste -sd+|bc

在线尝试!

在bash中,将整数转换为二进制字符串总是有些痛苦。这里的方法略有不同-将整数转换为八进制,然后将每个八进制数字替换为其包含的二进制1的数目。然后我们可以将所有转换后的数字求和


2

APL + WIN,33 26字节

提示输入整数向量:

+/,((↑v)⍴2)⊤(1↓v)+0,⍳-/v←⎕

在线尝试!由Dalog Classic提供

说明:

v←⎕ prompt for input of a vector of two integers max first

(v←1↓v)+0,⍳-/ create a vector of integers from min to max

(↑v)⍴2 set max power of 2 to max 

⊤ convert integers to a matrix of binaries

+/, convert matrix to a vector and sum

2

R44 40 37字节

function(a,b)sum(c(0,intToBits(a:b)))

在线尝试!

先前:

function(a,b)sum(strtoi(intToBits(a:b)))
function(a,b)sum(as.integer(intToBits(a:b)))

2

带通讯工具箱的八度音程,21字节

@(a,b)nnz(de2bi(a:b))

在线尝试!

该代码应该相当明显。范围中每个数字的二进制表示形式中的非零元素数。

这将@(a,b)nnz(dec2bin(a:b)-48)没有通信工具箱。


1

外壳,4个字节

Σṁḋ…

在线尝试!

说明

Σṁḋ…
   …     Get the (inclusive) range.
 ṁḋ      Convert each to binary and concatenate.
Σ        Get the sum.


1

PHP,97字节

(确保可以将其缩短,但要使用这些功能)

在线尝试

<?=substr_count(implode(array_map(function($v){return decbin($v);},
 range($argv[0],$argv[1]))),1);

说明

<?=
 substr_count(   //Implode the array and count every "1"
  implode(
    array_map(function($v){return decbin($v);}, //Transform every decimal to bin
          range($argv[0],$argv[1])   //generate a range between the arguments
     )
),1);   //count "1"'s

看来您可以做到这一点
dzaima

一秒钟我完全忘记了您可以直接将php函数的名称设置为参数:-(
Francisco Hahn

$argv[0]是程序名称或“-”;您应该使用$argv[1]$argv[2]。您可以使用join代替implode,将其缩短为68个字节:<?=substr_count(join(array_map(decbin,range($argv[1],$argv[2]))),1);
Titus

1

PowerShell,72字节

param($x,$y)$x..$y|%{$o+=([convert]::ToString($_,2)-replace0).length};$o

在线尝试!

很久以前,因为转换为二进制[convert]::ToString($_,2)并摆脱了零-replace0。否则,我们只是获取输入数字,确定一个范围,然后将范围内$x..$y的每个数字转换为二进制,删除零,取零.length(即剩余的1的数量),然后将其添加到我们的$o输出中。


尝试使用count,而不是length:)
MAZZY

1
@mazzy count始终是1因为我们要计算的length是字符串,而不是数组。
AdmBorkBork '18年

串!你是对的。谢谢。-replace0很聪明
mazzy


1

,10字节

$+JTB:a\,b

在线尝试!

说明

            a and b are command-line args (implicit)
      a\,b  Inclusive range from a to b
   TB:      Convert to binary (: forces TB's precedence down)
  J         Join into a single string of 1's and 0's
$+          Sum (fold on +)


1

木炭,10字节

IΣ⭆…·NN⍘ι²

在线尝试!链接是详细版本的代码。说明:

     NN     Input numbers
   …·       Inclusive range
  ⭆         Map over range and join
        ι   Current value
         ²  Literal 2
       ⍘    Convert to base as string
 Σ          Sum of digits
I           Cast to string
            Implicitly print

1

Brachylog,8个字节

⟦₂ḃᵐcọht

在线尝试!

说明

⟦₂         Ascending range between the two elements in the input
  ḃᵐ       Map to base 2
    c      Concatenate
     ọ     Occurrences of each element
      h    Head: take the list [1, <number of occurrences of 1>]
       t   Tail: the number of occurrences of 1


1

K(ngn / k)19 13字节

{+//2\x_!1+y}

在线尝试!

{ }是带有参数的函数xy

!1+y 是列表0 1 ... y

x_ 删除前x个元素

2\ 将每个int编码为长度相同的二进制数字列表(特定于ngn / k)

+/

+//求和直到收敛;在这种情况下,所有二进制数字列表的总和


1

Perl 6的32 30个字节

-1个字节,感谢Brad Gillbert

{[…](@_)>>.base(2).comb.sum}

在线尝试!

说明:

[…](@_)    #Range of parameter 1 to parameter 2
       >>    #Map each number to
                      .sum  #The sum of
                 .comb      #The string of
         .base(2)    #The binary form of the number

1
如果你使用,你可以用一个字节减少它[...](@_)代替($^a..$^b)
吉尔伯特b2gills

1

J16,15 14字节

感谢FrownyFrog,节省了1个字节!

+/@,@#:@}.i.,]

在线尝试!

说明:

一个二进位动词,左边的参数是m范围的下限,右边的是-上限n

            ,    append                      
             ]   n to the
          i.     list 0..n-1
         }.      drop m elements from the beginning of that list 
      #:@        and convert each element to binary 
    ,@           and flatten the table
 +/@             and find the sum

你能做到14吗?
FrownyFrog

@FrownyFrog今天晚些时候我会尝试(显然是有可能的,因为您正在询问:))
Galen Ivanov

@FrownyFrog 15目前,我仍在尝试...
Galen Ivanov


@FrownyFrog Aah,太简单了!我在想,}.但总是叉而不是钩。谢谢!
Galen Ivanov

1

QBasic,95 93 83 82字节

@DLosc为我节省了一些很多字节!

使用此技术保存了另一个字节!

INPUT a,b
FOR i=a TO b
k=i
FOR j=i TO 0STEP-1
x=k>=2^j
s=s-x
k=k+x*2^j
NEXT j,i
?s

本月语言FTW!

说明

INPUT a,b           Ask user for lower and upper bound
FOR i=a TO b        Loop through that range
k=i                 we need a copy of i to not break the FOR loop
FOR j=i TO 0STEP-1  We're gonna loop through exponents of 2 from high to low.
                    Setting the first test up for 4 to 2^4 (etc) we know we're overshooting, but that 's OK
x=k>=2^j            Test if the current power of 2 is equal to or smaller than k 
                    (yields 0 for false and -1 for true)
s=s-x               If k is bigger than 2^j, we found a 1, so add 1 to our running total s
                    (or sub -1 from the total s...)
k=k+x*2^j           Lower k by that factor of 2 if the test is true, else by 0
NEXT                Test the next exponent of 2
NEXT                process the next number in range
?s                  print the total

在Dosbox上运行的QBasic 4.5中,最后一个1000到2000的测试用例实际上可以工作: 嗨,嘿!

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.