计算给定范围内的幸运彩票


18

在俄罗斯,我们有一种类似的传统:我们喜欢寻找幸运票。

普通票的外观如下:

车票

如您所见,该票证有一个六位数的号码。

如果前三位数字的总和等于后三位数字的总和,则认为六位数数字是幸运的。

照片上的数字不是很幸运:

038937
038 937
0 + 3 + 8 = 11
9 + 3 + 7 = 19
11 != 19

挑战

给定范围的限制(包括),返回其中包含的幸运彩票号码的数量。

参量

  • 输入:2个整数:范围中的第一个和最后一个整数
  • 输入范围为0至999999(含)之间
  • 输出:1个整数:该范围内有多少个幸运数字
  • 您可以接受输入并以任何可接受的格式返回输出
  • 假设数字小于100000的前导零。

例子

0, 1 => 1
100000, 200000 => 5280
123456, 654321 => 31607
0, 999999 => 55252

这是因此每种语言中以字节为单位的最短答案都可以胜出。

更新:这是幸运的 幸运儿


Answers:


10

05AB1E8(或10?) 11(或13?)个字节

Ÿʒ₄n+¦S3ôOË

在线尝试验证更多测试用例

注意:在05AB1E中,字符串和整数是可互换的,因此输出数字不包含前导零。但是,这可以通过增加1个字节(12个字节)来解决:

Ÿ₄n+€¦ʒS3ôOË

在线尝试验证更多测试用例

+3个字节以3个以下的错误修正数字(范围[000000, 000999])。

说明:

Ÿ          # Create an inclusive (on both sides) range from the two inputs
           #  i.e. 038920 and 038910 → 
           #   [38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920]
 ʒ         # Filter this list by:
  n+      #  Add 1,000,000 to the number
     |     #  And remove the leading 1
           #   i.e. 38910 → 1038910 → '038910'
  S        #  Transform it to a list of digits
           #   i.e. '038910' → ['0','3','8','9','1','0']
   3ô      #  Split it into chunks of length 3
           #   i.e. ['0','3','8','9','1','0'] → [['0','3','8'],['9','1','0']]
     O     #  Sum the digits in both parts
           #   i.e. [['0','3','8'],['9','1','0']] → [11,10]
      Ë    #  Check if they are equal (if they are, they remain in the filtered list)
           #   i.e. [11,10] → 0

编辑:似乎我(和大多数其他答案)略微误解了挑战,并要求输入数量而不是范围内的数字本身。在这种情况下,}g可以添加尾随(关闭过滤器;并获取过滤后的列表中剩余的数字量),因此改为10个 13 字节

Ÿʒ₄nS3ôOË}g

在线尝试验证更多测试用例


对于小于1000的范围(例如[0; 1000]),您的结果似乎有点不正确(找到了1000个幸运数字)。
frosqh

1
如果我正确理解了挑战,则向每个数字添加1.000.000并删除第一个字符将解决此问题。也将摆脱使用R
阿德南'18

@Adnan谢谢,这确实是一种很好的处理方式。
凯文·克鲁伊森

这是需要的数量(和输出不需要前导零),所以13
乔纳森·艾伦

9

C#(.NET Core),93 + 18 = 111字节

a=>b=>Enumerable.Range(a,b-a+1).Select(e=>$"{e:D6}").Count(e=>e[0]+e[1]+e[2]==e[3]+e[4]+e[5])

在线尝试!

的18个字节using System.Linq;。我以为输入和输出格式可以灵活。因此,我将两个整数用作输入(范围(包括端值在内))。

一些测试结果:

a=1000
b=1100

Lucky numbers = 3 [001001, 001010, 001100]

a=2000
b=2100

Lucky numbers = 3 [002002, 002011, 002020]

a=222000
b=222100

Lucky numbers = 7 [222006, 222015, 222024, 222033, 222042, 222051, 222060]

a=0
b=999999

Lucky numbers = 55252 (that's 5.5% of the total numbers)

8

JavaScript(ES6),66个字节

以currying语法接受输入(m)(n),其中m排他性包含上限,n是包含性下限。

m=>g=n=>n<=m&&![...n+=''].reduce((t,d,i)=>t-=n[i+3]?d:-d,0)+g(-~n)

在线尝试!

怎么样?

我们通过遍历数字d i并更新总t来测试每个数字ndit

  • 如果此后至少还有3个剩余数字ttdi
  • 否则tt+di

如果在处理结束时,则n是一个幸运数字。t=0n


JavaScript(ES6),67个字节

相同的输入格式。

m=>g=n=>n<=m&&!eval([...n/1e3+''].join`+`.split`+.`.join`^`)+g(n+1)

在线尝试!

怎么样?

对于每个数字n

  • 除以:例如100038937 --> 38.937
  • 强制转换为字符串并拆分: ['3','8','.','9','3','7']
  • 加入+"3+8+.+9+3+7"
  • 替换+.^"3+8^+9+3+7"
  • 评估为JS代码并测试结果是否为:(11 XOR 190241119

如果,则不生成小数点,并且除非 n = 0(真),否则所计算的表达式只是正和(伪)。这是两种情况下的预期结果。n0(mod1000)n=0


它已被包含在内。
乔纳森·艾伦

7

红宝石56 54字节

->a,b{(a..b).count{|i|j=i.digits;j[0,3].sum*2==j.sum}}

在线尝试!

方法:

  1. 为每个数字创建一个数字数组(结果相反)
  2. 比较数组中前3位数字的总和(数字中的后3位)乘以2与整个数组的总和
  3. 计算两个和相等的数字

6

Japt38个 15字节

õV Ëì ò3n)mx r¥

-23感谢Shaggy!

我第一次提交Japt;感谢Shaggy的所有帮助!

在线尝试!


欢迎来到Japt!:)
Shaggy

@粗野的谢谢!这是一种非常简洁的语言!
血液学

为了帮助您入门。随意ping通我聊天,如果您有任何问题。
毛茸茸的

@Shaggy太神奇了。我从中学到了很多东西。您打算将其发布为自己的答案吗?你应该!
血液学

不,您可以拥有它:)就像我说的那样,可以帮助您入门。
粗野的

6

Python 3中,117个 113 106 135字节

这是我有史以来的第一个答案,因此我相信还有改进的余地。

def x(a,b):
    n=0
    for i in range(a,b+1):
        if sum(map(int,str(i//1000)))==sum(map(int,str(i%1000))):n+=1
    print(n)
  • -4字节归功于WW
  • -7字节归功于Asone Tuhid
  • +29字节创建函数

通过整数除法获得前三位数字,并通过取模获得后三位数字。范围中的前整数和后整数分别作为函数的参数xas a和输入b。输出为n,已打印。

取消高尔夫:

def x(a, b):
    n = 0
    for i in range(a, b + 1):
        if sum(map(int, str(i // 1000))) == sum(map(int, str(i % 1000))):
            n += 1
    print(n)

1
if btw之后不需要缩进。同样,在转换前三位数或最后三位数之前,转换为字符串可能会更便宜。
小麦巫师

2
欢迎来到PPCG!查阅Python中打高尔夫球的技巧以获取技巧和窍门,如果您感兴趣的话,大多数语言都有类似的主题。同样,包括TIO链接作为演示也是一个好习惯。
Asone Tuhid

我建议更换n=n+1n+=1和移动它的if语句之后(if...:n+=1
ASONE Tuhid

您不能将ab作为预先声明的变量。您要么必须具有某种功能,要么就需要通过输入来获取这些功能
Jo King

1
如果要保留它的功能,可以将n=0零件移至页眉中,例如def x(a,b,n=0)
Jo King

6

R93 86字节

@ Giuseppe /末尾的简短逻辑

function(a,b){for(i in sprintf("%06d",a:b)){x=utf8ToInt(i);F=F+!sum(x[1:3]-x[4:6])}
F}

在线尝试!

整数输入。用他们垫0。转换为六个ASCII码点。滥用F内置函数。


我从该函数返回一个不适用。
罗伯特S。18年

我已经撤消了修改。由于该scipen问题,新版本在0处失败。那好吧。
ngm



6

外壳,12个字节

#ȯ§¤=Σ↓↑3↔d…

在线尝试!

说明

#(§¤=Σ↓↑3↔d)…  -- example input: 100000 101000
            …  -- inclusive range: [100000,100001..100999,101000]
#(         )   -- count elements where (example with 100010)
          d    -- | digits: [1,0,0,0,1,0]
         ↔     -- | reversed: [0,1,0,0,0,1]
  §     3      -- | fork elements (3 and [0,1,0,0,0,1])
       ↑       -- | | take: [0,1,0]
      ↓        -- | | drop: [0,0,1]
   ¤=          -- | > compare the results by equality of their
     Σ         -- | | sums 1 == 1
               -- | : 1
               -- : 3

看来您的解决方案具有与初始版本相同的缺陷:[000000, 001001]应该导致2000000001001),但是导致结果1001。(我为此添加1,000,000并删除了尾随1作为修复,但是不确定在Husk中有多么容易/字节效率。)
Kevin Cruijssen

1
@KevinCruijssen:我想我可以记得最初面临的挑战尚不清楚,我没有时间研究它,所以我只是回过头来,似乎是正确的。
ბიმო

5

木炭,15字节

ILΦ…·NN⁼Σι⊗Σ÷ιφ

在线尝试!链接是详细版本的代码。编辑:我本来以为是必需的幸运数字列表。这可以用14个字节(通过删除占用列表长度的)来完成,或者如果您想要一些不错的格式,则可以用20个字节来完成:

EΦ…·NN⁼Σι⊗Σ÷ιφ﹪%06dι

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

    NN                  Input the range endpoints
  …·                    Inclusive range
 Φ                      Filter
        ι               Current value
       Σ                Sum of digits
            ι           Current value
             φ          Predefined variable 1000
           ÷            Integer divide
          Σ             Sum of digits
         ⊗              Doubled
      ⁼                 Equals
E                       Map over results
                   ι    Current value
               %06d     Literal string
              ﹪         Format value
                        Implicitly print each result on its own line


3

Python 3 89 86个字节

-2感谢Xcoder先生。

-3来自Asone Tuhid答案的启发。

lambda a,b:sum(sum(map(int,str(i)))==2*sum(map(int,str(i)[-3:]))for i in range(a,b+1))

测试结果:

Example 1 : 
a = 0
b = 1
Lucky numbers : 1 

Example 2 : 
a = 100000
b = 200000
Lucky numbers : 5280 

Example 3 : 
a = 123456
b = 654321
Lucky numbers : 31607 

Example 3 : 
a = 0
b = 999999
Lucky numbers : 55252 

在线尝试!


1
在计数版本中,sum可以制造任何发电机,因此[...] 不需要括号
Xcoder先生18年

range(a,b+1)spec现在声明为“ inclusive”(如果不是,则可以用*r它代替a,b-请参见我的Python 2答案)。另请注意,规范现在确认确实应该是输出的计数。
乔纳森·艾伦,

3

MATL,24字节

&:1e3&\,!'%03d'&V2&sw]=s

在线尝试!

(-2个字节,感谢Luis Mendo。)

&: -在两个给定数字之间形成一个包含范围

1e3&\ -'divrem'-除以1000,得到两个数组中的提醒和底商。

, -做两次

!'03d'&V -转置每个值并将其转换为零填充的三宽度字符串

&s -对每一行的值求和

w -切换以弹出提醒数组,然后再次执行该操作

] -结束循环

= -检查是否相等(在数组相等的地方返回1)

s -求和以得到计数(隐式输出)


3

科特林152个 119字节

{a:Int,b:Int->(a..b).map{String.format("%06d",it)}.filter{it[0].toInt()+it[1].toInt()+it[2].toInt()==it[3].toInt()+it[4].toInt()+it[5].toInt()}.count()}

在线尝试!

取两个整数,然后将其转换为六个符号字符串并计数。

由于mazzy及其对119个字节的解决方案,因此对其进行了优化。

{a:Int,b:Int->(a..b).count{val d="%06d".format(it);(d[0]-'0')+(d[1]-'0')+(d[2]-'0')==(d[3]-'0')+(d[4]-'0')+(d[5]-'0')}}

在线尝试!


1
您可以将其压缩到133个字节{a:Int,b:Int->(a..b).map{"%06d".format(it)}.filter{(it[0]-'0')+(it[1]-'0')+(it[2]-'0')==(it[3]-'0')+(it[4]-'0')+(it[5]-'0')}.count()}
mazzy '18

3

dc,44字节

sb[d]sD[dA00~[rA~rA~++rx]dx=D1+dlb!<L]dsLxkz

从原本为空的堆栈中获取两个参数,然后输出到堆栈顶部。

在线尝试!

此处的巧妙之处在于使用了未命名(即未存储)的宏,该宏在执行前已被复制,以便在其他三位数部分上运行其自身的副本。

说明

内部宏[rA~rA~++rx]的作用是“计算堆栈上倒数第二个三位数的数字总和,然后将堆栈的原始顶部作为宏执行”。

主程序:

sb             Saves the upper bound as b so we'll know when to quit
[d]sD          Defines the macro D, which contextually is "increment stack depth"
[              Start the main loop - the next number to test is on top 
  d              Make a copy to increment later for loop purposes
  A00            The literal "1000"
  ~              Quotient and remainder, so "123456" is now "123 456"
  [rA~rA~++rx]d  Stack is now "123 456 M M", where M is the anonymous macro
  x              Run M on the stack "123 456 M", which (see definition 
                 above) ends up running M on the stack "123 15", which
                 leaves "15 6" (and executes the 6, which is a no-op)
  =D             If the two sums were equal, increment the stack depth
  1+             Increment the current test number
  dlb!<L         Loop unless the test number is now larger than b
]dsLx          Name and start the loop
kz             Current depth is 1+answer, so throw away top and return

3

Pascal(FPC)163153字节

var a,b:Int32;begin read(a,b);for a:=a to b do if a div$186A0+a div$2710mod$A+a div$3E8mod$A=a div$64mod$A+a div$Amod$A+a mod$Athen b:=b+1;write(b-a)end.

在线尝试!

说明

这是一些看起来正常的代码:

var a,b,i,s,c,d:Int32;
begin
  read(a,b);
  s:=0;
  for i:=a to b do begin
    c:=i div 1000;
    d:=i mod 1000;
    if c div 100+(c div 10) mod 10+c mod 10=d div 100+(d div 10) mod 10+d mod 10 then begin s:=s+1; {writeln(i)} end;
  end;
  write('There are ',s,' numbers');
end.

在线尝试!

然后我滥用了for循环的行为:

  • 循环值是预先设置的(从ab),因此a可以用作循环变量dropping i
  • 在for循环的末尾,循环变量保留在最终值(b循环前的值)处。我用b了一个容器,当找到一个幸运数字并且在循环的末尾b与它的旧值相差了幸运数字的数量时,就对它进行了递增,因此b-a给出了正确的结果。这下降了s

d直接替换操作可以a缩短循环。c直接用操作代替并a不能缩短循环,但是在删除之后d,循环beginend是不必要的,最后我仅使用了2个变量:)

$在高尔夫球代码中开始十六进制常量。尽管它们不保存字节,但它们消除了十进制常量之前所需的空格。


3

Java(OpenJDK 8),162字节

...借鉴了上面的Kotlin示例。

import java.util.stream.IntStream;

(a,b)->IntStream.range(a,b+1).mapToObj(i->String.format("%06d",i).getBytes()).filter(c->c[0]+c[1]+c[2]==c[3]+c[4]+c[5]).count();

在线尝试!

比较字符串字节的总和与将实际数字求和一样好。


2
您可以通过使用(a->b->)来保存一个字节,但是IntStream由于它不在中,因此您需要完全符合条件java.lang
雅各布

欢迎来到PPCG!如@Jakob所述,导入是字节数的一部分,因此您必须java.util.stream.IntStream代码和字节数前添加。雅各布(Jakob)也提到,您可以使用来保存一个字节a->b->,也可以通过更改String.format为来保存一些其他字节"".format在线尝试:139个字节。不错的第一答案。向我+1。入住愉快!
凯文·克鲁伊森

2

PHP,131字节

<?$f='array_sum(str_split(str_split(sprintf("%06d",$i),3)[';for($i=$argv[1]-1;$i++<$argv[2];)eval("\$a+=$f 0]))==$f 1]));");echo$a;

要运行它:

php -n <filename> <from> <to>

例:

php -n lucky_tickets.php 100 100000

在线尝试!


2

Perl 6的51个 49字节

{+grep {[==] .flip.comb[^3,3..*]>>.sum},$^a..$^b}

在线尝试!

带有两个数字并返回幸运数字的匿名代码块。超时以获取更大的输入


2

果冻 9  8 字节

-1感谢丹尼斯(rµ...E)S-> r...E€S因为一切都矢量化。)

rdȷD§E€S

双向链接接受范围的两个端点(任意方向),这将产生幸运彩票的计数。

在线尝试!还是看一个测试套件

怎么样?

请注意,对于任何小于 1000000ñ,我们可以得到两个数字,这些数字的总和等于所需的值,以使用整数除法检查 1000
(说, X=ñ1000
及其其余部分
(例如ÿ=ñ1000
...即ñ=1000×X+ÿ

现在我们要比较的数字的总和 Xÿ 每个 ñ 在一个范围内并计算相等的那些。

rdȷD§E€S - Link: integer a; integer b
r        - inclusive range [a,b] (either [a,a+1,a+2,...,b] or [a,a-1,a-2,...,b])
         -                              e.g.: 0       or 78        or 7241
  ȷ      - literal 1000
 d       - divmod (vectorises)                [0,0]      [0,78]       [7,241]
   D     - to decimal lists (vectorises)      [[0],[0]]  [[0],[7,8]]  [[7],[2,4,1]]
    §    - sum each (vectorises)              [0,0]      [0,15]       [7,7]
     E€  - for €ach: all equal?               1          0            1
       S - sum (counts the 1s in the resulting list)

E€S保存µ
丹尼斯

@Dennis啊,是的,我正在使用另一种解决方案,该解决方案并未对所有内容进行矢量化处理!
乔纳森·艾伦,

2

Powershell,85个字节

($args[0]..$args[1]|%{'{0:D6}'-f$_}|?{+$_[0]+$_[1]+$_[2]-eq+$_[3]+$_[4]+$_[5]}).count

测试脚本:

$f = {

($args[0]..$args[1]|%{'{0:D6}'-f$_}|?{+$_[0]+$_[1]+$_[2]-eq+$_[3]+$_[4]+$_[5]}).count

}

@(
    ,((0,1), 1)
    ,((1000,2000), 3)
    ,((2000,3000), 6)
    ,((10000, 20000), 282)
    ,((101000, 102000), 6)
    ,((201000, 202000), 10)
    ,((901000, 902000), 63)
    ,((100000, 200000), 5280)
    ,((123456, 654321), 31607)
    #,((0, 999999), 55252)
) | % {
    $c, $e = $_
    "      $c"
    $r = &$f $c[0] $c[1]
    "$($e-eq$r): actual=$r expected=$e"
}

输出:

      0 1
True: actual=1 expected=1
      1000 2000
True: actual=3 expected=3
      2000 3000
True: actual=6 expected=6
      10000 20000
True: actual=282 expected=282
      101000 102000
True: actual=6 expected=6
      201000 202000
True: actual=10 expected=10
      901000 902000
True: actual=63 expected=63
      100000 200000
True: actual=5280 expected=5280
      123456 654321
True: actual=31607 expected=31607

电源外壳?我真的没有看到一个未来:d
ДмитрийАрхипенко

2

Kotlin,95个字节

{a:Int,b:Int->(a..b).count{val d="%06d".format(it);d.chars().sum()==2*d.take(3).chars().sum()}}

.kt 测试:

var  f = {a:Int,b:Int->(a..b).count{val d="%06d".format(it);d.chars().sum()==2*d.take(3).chars().sum()}}

fun main(args: Array<String>) {
    println(f(0,1))             // 1
    println(f(1000,2000))       // 3
    println(f(2000,3000))       // 6
    println(f(101000, 102000))  // 6
    println(f(201000, 202000))  // 10
    println(f(901000, 902000))  // 63
    println(f(10000, 20000))    // 282
    println(f(100000, 200000))  // 5280
    println(f(123456, 654321))  // 31607
    println(f(0, 999999))       // 55252
}

说明

从范围内计数所有数字位数的总和等于前3位数字的两倍之和。



1

Python 2中 83  80个字节

-3通过使用Asone Tuhid的观察- 功劳!

lambda a,b:sum(sum(map(int,`v/1000`))*2==sum(map(int,`v`))for v in range(a,b+1))

在线尝试!

很像我的果冻答案(但输入必须在此处排序,即a<=b


75个字节的输入a, b+1(即,范围不包括右边界):

lambda*r:sum(sum(map(int,`v/1000`))*2==sum(map(int,`v`))for v in range(*r))

试试这个


1

Clojure,102字节

#(count(for[i(range %(inc %2)):when(=(let[d(map int(format"%06d"i))](apply +(map -(drop 3 d)d)))0)]i))

混合字符串和数学不太有趣。



1

C(gcc),90 88字节

l=10;u(c,k,y){for(y=0;c<=k;)c++%l+c/l%l+c/100%l-c/1000%l-c/10000%l-c/100000%l?:++y;c=y;}

我的Java 回答的端口。在这里在线尝试。多亏了ceilingcat打高尔夫球两个字节。

取消高尔夫:

l=10; // constant, we will be using the number 10 rather a lot
u(c, k, // function returning an integer and taking two integer arguments: lower and upper bound
  y) { // abusing the argument list to declare a variable of type integer: the number of lucky tickets found in the range
    for(y = 0; c <= k; ) // set count to 0 and loop through the range
        c++ %l + c/l %l + c/100 %l // if the digit sum of the second half of the ticket number ...
        - c/1000 %l - c/10000 %l - c/100000 %l // ... is the same as the digit sum of the first half ...
        ?: ++y; // ... it's a lucky ticket: increment the count
    c = y; // return the count
}

建议L'✐'而不是10000并分配10给变量。
ceilingcat '18

@ceilingcat我喜欢它为我提供了一个额外的变量名,但是我不能通过分配10来保存任何字节:bit.ly/2O5ND2Y至于L'…'技巧,那太整齐了;但这会节省字节吗?在我看来这是一个多字节字符,因此在保存字符时,它无法保存字节……还是可以吗?
OOBalance

@ceilingcat我的错误,可以通过将10分配给变量来保存两个字节。谢谢。
OOBalance

1

Java 8,101 99字节

u->l->{int n=0,d=10;for(;l<=u;)if(l++%d+l/d%d+l/100%d==l/1000%d+l/10000%d+l/100000%d)++n;return n;}

与其他Java答案不同的方法。代替使用流和字符串,它使用循环并直接计算数字。在这里在线尝试。

谢谢 ceilingcat打高尔夫球两个字节。

取消高尔夫:

u -> l -> { // lambda taking two integer arguments in currying syntax and returning an integer
    int n = 0, // the counter
        d = 10; // auxiliary constant, we will be using the number 10 rather a lot
    for(; l <=u ; ) // loop over all ticket numbers in the range
        if(l++ %d + l/d %d + l/100 %d // if the digit sum of the second half of the number ...
           == l/1000 %d + l/10000 %d + l/100000 %d) // ... is the same as the digit sum of the first half ...
            ++n; // ... it's a lucky ticket, add 1 to the counter
    return n; // return the count
}

1

VBA(Excel),159个字节

使用立即窗口和单元格[A1] [A2]作为输入。

c=[A1]-[A2]:d=IIf(c<0,[A1],[A2]):For x=d To d+Abs(c):e=String(6-Len(x),"0")&x:For y=1To 3:i=i+Mid(e,y,1):j=j+Mid(e,7-y,1):Next:z=IIf(i=j,z+1,z):i=0:j=0:Next:?z

1

F#,110个字节

let t=string>>Seq.sumBy(int>>(-)48)
let r s e=Seq.where(fun n->t(n/1000)=t(n-(n/1000)*1000)){s..e}|>Seq.length

在线尝试!

t将字符串转换为数字并将其求和。r接受从s到的数字范围e,并过滤掉不幸的数字。前三个数字由收集n/1000。后三位数字由计算n-(n/1000)*1000

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.