计算整数的出现次数


13

根据这个问题,数字2中有多少<1,000,000个正整数?。我正在寻找最有创意的解决方案,以将所有Integer从计数XY包含Integer ZZ可以是0到Y

即使整数Z出现频率更高,每个找到的Integer只会计数一次。例如:

Z = 2
123 counts 1
22222 also counts 1

我将从一个用Java编写的非常简单的算法开始(因为每个人都喜欢它):

public class Count {
    public static void main(String[] args) {
        int count = 0;
        for (int i = Integer.parseInt(args[0]); i <= Integer.parseInt(args[1]); i++) {
            if (Integer.toString(i).contains(args[2])) {
                count++;
            }
        }
        System.out.println(count);
    }
}

如果你用

java -jar Count.jar 0 1000000 2

结果如下:

468559

因为这个问题并不难解决,所以只是一场。2月28日之前发布的最受好评的答案将获胜!


从您的帖子中还不清楚,但是我想Z可以在0到inf之间?还是介于0到9之间?
mmumboss 2014年

Z可以是0之间和Y这没有任何意义的是Z可以比Y.更大
OBL Tobl

@OblTobl您真的要显式排除Z> Y情况吗?在这种情况下,为什么不仅仅期望输出为0?
Cruncher 2014年

@Cruncher我不介意!但我认为这没什么用;-)
Obl Tobl 2014年

这是否N可以123并且只有在子字符串123存在的情况下才匹配?
Populus 2014年

Answers:


26

重击(20)

seq $1 $2|grep -c $3

用法

$ bash count.sh 0 1000000 2
468559

10
如果调用的时间比程序本身长,这很有趣;-)
Obl Tobl 2014年

11

功能

与往常一样,由于StackExchange添加的行高会破坏行,请考虑$('pre').css('line-height',1)在浏览器控制台中运行以解决此问题。

与我的其他Funciton答案不同,该答案不使用任何函数声明。这只是一个程序。但是,它使用了lambda表达式-我在12月向Funciton添加的功能:)

期望输入为三个空格分隔的十进制整数(可以为负)(即x y z)。实际上,z可以是任何字符串;例如,对区间中的负数进行计数可能只是减号(,U + 2212):

           ┌───╖
     ┌───┬─┤ ♯ ╟──────────┐
     │   │ ╘═══╝ ╔════╗ ┌─┴─╖             ┌────╖ ╔═══╗
   ┌─┴─╖ └────┐  ║ 21 ║ │ × ╟─────────────┤ >> ╟─╢   ║
 ┌─┤ ʃ ╟───┐  │  ╚══╤═╝ ╘═╤═╝             ╘═╤══╝ ╚═══╝
 │ ╘═╤═╝   │  └──┐  └─────┘   ┌───────────┐ │
 │ ╔═╧═╗ ┌─┴─╖ ┌─┴─╖ ╔════╗ ┌─┴─╖   ┌───╖ ├─┴────────┐
 │ ║   ╟─┤ · ╟─┤ ʘ ╟─╢ 32 ╟─┤ · ╟───┤ ʘ ╟─┘          │
 │ ╚═══╝ ╘═╤═╝ ╘═══╝ ╚════╝ ╘═╤═╝   ╘═╤═╝ ┌─────┐    │
 │         └───────┐  ╔═══╗ ┌─┴─╖     │ ┌─┴─╖   │    │
 │ ┌───────────┐   └──╢ 0 ╟─┤ ʃ ╟─┐   │ │ ♯ ║   │    │
 │ │   ┌───╖ ┌─┴─╖    ╚═══╝ ╘═╤═╝ │   │ ╘═╤═╝ ┌─┴─╖  │
 │ │ ┌─┤ ♯ ╟─┤   ╟─┬─┐ ╔════╗ │ ┌─┴─╖ │   │ ┌─┤ × ║  │
 │ │ │ ╘═══╝ └─┬─╜ └─┘ ║ −1 ║ └─┤ · ╟─┴───┘ │ ╘═╤═╝  │
 │ │ │    ┌────┴────┐  ╚══╤═╝   ╘═╤═╝       │ ╔═╧══╗ │
 │ │ │    │ ┌───╖ ┌─┴─╖ ┌─┴─╖ ┌───┴─────╖   │ ║ 21 ║ │
 │ │ │    └─┤ ♯ ╟─┤ ? ╟─┤ = ║ │ str→int ║   │ ╚════╝ │
 │ │ │      ╘═══╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═══════╝   │ ┌────╖ │
 │ │ │      ╔═══╗ ┌─┴─╖   └─┐ ┌─┴─╖         └─┤ >> ╟─┘
 │ │ │      ║ 0 ╟─┤ ? ╟─┐   └─┤ · ╟───┐       ╘═╤══╝
 │ │ │      ╚═══╝ ╘═╤═╝ └─┐   ╘═╤═╝   └───┐   ┌─┴─╖
 │ │ │            ┌─┴─╖   └─┐ ┌─┴─╖       └───┤ ʘ ║
 │ │ └────────────┤ · ╟─┐   └─┤ ≤ ║           ╘═╤═╝
 │ │              ╘═╤═╝ │     ╘═╤═╝ ┌─────────╖ │
 │ │        ╔═══╗ ╔═╧═╕ │       └─┬─┤ int→str ╟─┘
 │ │        ║ 0 ╟─╢   ├─┤         │ ╘═════════╝
 │ │        ╚═══╝ ╚═╤═╛ └─────────┘
 │ └────────────────┴─┐              │
 │    ┌─────────╖   ┌─┴─╖ ┌─┐   ┌────┴────╖
 └────┤ str→int ╟───┤   ╟─┴─┘   │ int→str ║
      ╘═════════╝   └─┬─╜       ╘════╤════╝
                      └──────────────┘

1
太酷了!使用您自己
创造

2
@pcnThird:我认为Timwi将所有时间都花在打高尔夫球或创造打高尔夫的语言上(另请参阅Sclipting)!
加布2014年

10

C#

public class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine(Enumerable.Range(Convert.ToInt32(args[0]), (Convert.ToInt32(args[1]) + 1) - Convert.ToInt32(args[0])).Count(x => x.ToString().Contains(args[2])));
    }
}

count.exe 0 1000000 2
468559

聪明的解决方案!我喜欢你做到了没有循环。
Obl Tobl 2014年

@OblTobl没有可见的循环。
贾斯汀

当然,还是很不错
Obl Tobl 2014年

1
它有一个错误,.Range接受(int start, int count),没有(start, end)。我总是自己陷入陷阱:)
Grozz 2014年

为我提供帮助,可以在记事本中快速完成此操作...我已经调整了代码,现在它是正确的!
Mo D

5

APL(29)

{+/∨/¨(⍕⍺)∘⍷¨⍕¨⊃{⍺+0,⍳⍵-⍺}/⍵}

这是一个函数,将其Z作为左参数,将间隔[X,Y]作为右参数:

      2 {+/∨/¨(⍕⍺)∘⍷¨⍕¨⊃{⍺+0,⍳⍵-⍺}/⍵} 0 1e6
468559
      0 {+/∨/¨(⍕⍺)∘⍷¨⍕¨⊃{⍺+0,⍳⍵-⍺}/⍵} 0 1e6
402131
      42 {+/∨/¨(⍕⍺)∘⍷¨⍕¨⊃{⍺+0,⍳⍵-⍺}/⍵} 0 1e6
49401

不太清楚...但是真的很酷!
Obl Tobl 2014年

4

Python 2.7

极品飞车

说明

在此处输入图片说明

实作

def Count(lo,hi,key):
    if hi == 0: return 0
    # Count(lo,hi,key) = Count(0,hi,key) - Count(0,lo - 1,key)
    if lo != 0: return Count(0, hi, key) - Count(0, lo - 1, key)
    # Calculate no of digits in the number to search
    # LOG10(hi) may be a descent trick but because of float approximation
    # this would not be reliable
    n = len(str(hi)) - 1
    # find the most significant digit
    a_n = hi/10**n
    if a_n < key:
        count = a_n*(10**n - 9**n)
    elif a_n > key:
        count = (a_n - 1)*(10**n - 9**n) + 10**n
    else:
        count = a_n*(10**n - 9**n) + 1
    if hi % 10**n != 0:
        if a_n != key:
            return count + Count(0, hi%10**n, key)
        else:
            return count + hi%10**n
    else:
        return count

演示版

In [2]: %timeit Count(0,123456789987654321,2)
100000 loops, best of 3: 13.2 us per loop

比较方式

@丹尼斯

$ \time -f%e bash count.sh 0 1234567 2
585029
11.45

@arshajii

In [6]: %timeit count(0,1234567,2)
1 loops, best of 3: 550 ms per loop

当然,这要快得多,但不能满足问题的要求。key可以是和之间的任何整数,而不是数字。lohi
丹尼斯

仍然有一个数学解决方案,尽管要更长一些……
Red Alert

3

Python 2.7

使用正则表达式的解决方案:

>>> from re import findall as f
>>> count=lambda x,y,z:len(f('\d*%d\d*'%z,str(range(x,y+1))))
>>>
>>> count(0,1000000,2)
468559

您可以re.findall通过这样做来使用__import__('re').findall('\d...
单线

3

重击- 32 31 17 14个字符+ X,Y和Z的长度

感谢devnull的建议seq

seq [X] [Y]|grep -c [Z]

例如X = 100,Y = 200,Z = 20

$ seq 100 200|grep -c 20
2

例如X = 100,Y = 200,Z = 10

$ seq 100 200|grep -c 10
11

例如X = 0,Y = 1000000,Z = 2

$ seq 0 1000000|grep -c 2
468559

好清楚的一个!
Obl Tobl 2014年

echo如果可以使用seq并减少4个字符的长度,为什么要使用?(1表示命令长度,2表示省略花括号,1表示替换..单个空格)
devnull 2014年

@devnull-谢谢您,它也可以删除xargswc-并且它的运行速度也快得多!

3

的PHP

没什么了,只是在这里庆祝我的第一篇文章。

<?php

    $x = $argv[1];
    $y = $argv[2];
    $z = $argv[3];
    $count = 0;

    do
    {
        if (!(strpos($x, $z) === false))
            $count++;
        $x++;
    } while ($x <= $y);

    echo $count;

?>

输入值

php script.php 0 1000000 2

输出量

468559

3

Scala:

args(0).toInt to args(1).toInt count (_.toString contains args(2))


2

红宝石

这是使用reduce的好例子!

puts (ARGV[0]..ARGV[1]).reduce(0) { |c, n| n.to_s.include?(ARGV[2].to_s) ? c + 1 : c }

输入:

ruby script.rb 0 1000000 2

输出:

468559

2

蟒蛇高尔夫-61

f=lambda x,y,z:len([i for i in range(x,y)if str(z)in str(i)])

Python非高尔夫

def f(x, y, z):
    c = 0
    for i in range(x, y):
        c += str(z) in str(i)
    return c

2

Java8的

如果您忽略了强制性的Java Framework内容,那么使用新的IntStream内容,这实际上就成了一个衬里:

import java.util.stream.IntStream;
public class A{
  public static void main(String[] args){
    System.out.println(IntStream.rangeClosed(Integer.parseInt(args[0], Integer.parseInt(args[1])).filter(x -> ((Integer)x).toString().contains(args[2])).count());
  }
}

它可以在这里运行,尽管我必须对值进行硬编码。


真正有趣的Java解决方案
Obl Tobl 2014年

2

F#

此解决方案用于IndexOf搜索字符串,然后使用一点点数字摆弄以将结果转换为1(如果找到),将其转换为0(如果未找到),然后将结果求和:

let count x y (z : string) = 
    [ x .. y ] |> Seq.sumBy(fun n -> min 1 (n.ToString().IndexOf z + 1))

可以这样称呼它:

count 0 1000000 "2" // 468559

2

正则表达式

跟随将计数1的数字直至49。

#!/bin/bash

echo "12313451231241241111111111111111111111111111111111111"  |\  
sed "s/[^1]//g;s/11111/5/g;s/1111/4/g;s/111/3/g;s/11/2/g;s/555555555/45/g;s/55555555/40/g;s/5555555/35/g;s/555555/30/g;s/55555/25/g;s/5555/20/g;s/555/15/g;s/55/10/g;s/54/9/g;s/53/8/g;s/52/7/g;s/51/6/g;s/50/5
/g;s/40/4/g;s/30/3/g;s/20/2/g;s/10/1/g"

2

R 23 25 27字符

只是获得适合该工作的工具。在R中简单使用grep,没有什么幻想。

这就是它的作用:向量中的grep所有实例直到为止,并使用计数结果的数量。2010e6length

length(grep(2,0:100000,value=TRUE))

length(grep(2,0:10e6))

结果: [1] 468559


当然,您可以编写一个将数字作为输入的函数,如示例中所示。

count = function(x=0, y=1000000, z=2){
  length(grep(z,x:y))
}

现在,您可以count使用x,y和z 进行调用,如果未设置(默认情况下),则x,y和z的值分别为0、1000000和2。一些例子:

count()
[1] 468559

要么

count(20, 222, 2)
[1] 59

要么

count(0, 100, 10)
[1] 2

这里有些人认为时间很重要,在R中使用此功能大约需要1秒钟。

system.time(count())
user  system elapsed 
0.979   0.003   0.981

也许太短了;-)
Obl Tobl 2014年

好吧,无论如何这都不是代码问题:)我想知道:如果程序必须将数字作为输入(而不是对它们进行硬编码),它将是什么样?
Timwi'2

为难以想象的创造了一个功能;)
CousinCocaine

1

JavaScript(ES6),63

f=(i,j,n)=>{for(c=0;i<=j;!~(''+i++).indexOf(n)?0:c++);return c}

用法:

f(0, 1e6, 2)
> 468559

未打高尔夫球:

f = (i,j,n) => {
  for(
    // Initialize the counter.
    c=0;
    // Iterate through all integers.
    i<=j;
    // Convert current number into string then increment it.
    // Check if the digit appears into the current number.
    !~(''+i++).indexOf(n)
      // Occurence not found.
      ? 0
      // Occurence found.
      // Add 1 to the counter.
      : c++
  );
  return c
}

1

红宝石

基本上,我采用了Pablo的答案并将其半高尔夫球(如果您删除不必要的空格,则为38个字符),变成一个不太好的使用示例select

它选择(x .. y)包含的范围内的每个索引z。不幸的是,该中间结果存储在数组中,然后返回其大小。

x,y,z = $*
p (x..y).select{ |i| i[z] }.size

从语法和语义i[z]上看,它看起来都很整洁,尽管该部分似乎没有任何意义。

之所以有效xy是因为它实际上是字符串,而不是数字!因此,每个i也是一个字符串,并且i[z]当然会检查该字符串z是否包含在中i

$ ruby count-digits.rb 100 200 20
2
$ ruby count-digits.rb 0 1000000 2
468559

1

Python 2.7、70个标志

f = lambda x,y,z: sum(map(lambda x: str(z) in str(x), range(0, y+1)))

>>> f(0, 1000000, 2)
468559

较短,65个标志

g = lambda x, y, z: sum(str(z) in str(i) for i in range(0, y+1))
>>> g(0, 1000000, 2)
468559

我不认为你需要range(0,y+1),如果range(y+1)做同样的事情。此外,如果您打高尔夫球,也可以删除大部分空间...
SimonT 2014年

1

使用Ruby的Enumerable#grep

start, stop, target = $*
p (start..stop).grep(Regexp.new target).size

1

T-SQL

如果我可以假设变量@X@Y以及@Z可供选择:

使用(任意大;)现有数字表-65

select count(*)from n where n>=@X and n<=@Y and n like '%'+@Z+'%'

递归CTE-127

with n(n)as(select @X union all select n+1 from n where n<@Y)select count(*)from n where n like'%'+@Z+'%'option(MAXRECURSION 0)

如果需要显式定义变量:

两个答案均加58-数字表:123,递归CTE:185

declare @X int=0;declare @Y int=100;declare @Z varchar(30)='2';

我不知道递归CTE可以使用多少内存,但是肯定不会赢得任何速度竞赛。在0到1000000中搜索2的示例在我的系统上花费8秒钟。

这是一个SQL Fiddle,如果有人想玩的话。1000000查询需要30秒钟以上才能运行。


不快但是很有创造力!
Obl Tobl 2014年

1

Rebol

; version 1 (simple loop counting)

count: func [x [integer!] y [integer!] z [integer!] /local total] [
    total: 0
    for n x y 1 [if found? find to-string n z [++ total]]
    total
]


; version 2 (build series/list and get length)

count: func [x [integer!] y [integer!] z [integer!]] [
    length? collect [for n x y 1 [if find to-string n z [keep true]]]
]

Rebol控制台(REPL)中的用法示例:

>> count 0 1000000 2
== 468559

1

电源外壳

两种解决方案,均为40 37个字符。

对于所有版本的PowerShell:

$a,$b,$c=$args;($a..$b-match$c).count

PowerShell V3及更高版本具有的sls别名Select-String@如果只有一个值通过管道,则需要强制数组。

$a,$b,$c=$args;@($a..$b|sls $c).count

1

批量

@setLocal enableDelayedExpansion&@set a=0&@for /L %%a in (%1,1,%2) do @set b=%%a&@if "!b:%3=!" NEQ "!b!" @set/aa+=1
@echo !a!

H:\uprof>count 0 1000000 2
468559

H:\uprof>count 1 2 3
0

更具可读性-

@setLocal enableDelayedExpansion
@set a=0
@for /L %%a in (%1,1,%2) do (
    @set b=%%a
    @if "!b:%3=!" NEQ "!b!" @set/aa+=1
)
@echo !a!

漂亮又简单。使用字符串操作来检查变量!b!是否与没有第三个用户输入%3!b:%3=!)的变量相同。


1

Mathematica

第一种方式:字符串

x, y, z转换为字符串。如果string-integer不是free z,则将其计数。

f[{x_,y_},z_] :=Length[Select[ToString/@Range[Max[x, z], y], !StringFreeQ[#, ToString@z] &]]

例子

f[{22, 1000}, 23]
f[{0, 10^6}, 2]

20
468559


第二种方式:数字列表

g[{x_,y_},z_]:=(t=Sequence@@ IntegerDigits@z;Length@Cases[IntegerDigits@Range[190], 
{s___,t,e___}])

例子

g[{22, 1000}, 23]
g[{0, 10^6}, 2]

20
468559


即使对于简单的问题,Mathematica也总是令人着迷
Obl Tobl 2014年

1

高尔夫脚本

我一直在努力提高我的GolfScript技能,所以我想尝试一下这个问题。这是我想出的:

`@@0\{.3$>}{.`4$?-1>@+\(}while@;;\;

可以这样分解:

0 1000000 2    # parameters

`@@            # convert Z to string and put at bottom of stack
0\             # init counter and swap
{.3$>}         # loop condition: Y > X
{              # loop body
  .`           # convert to string
  4$?          # search for substring
  -1>@+        # if found add to counter
  \(           # decrement Y
}              # end loop body
while          # perform loop
@;;\;          # cleanup

即使是GolfScript,从目标上讲,它更多的是尝试使它相对有效而不是紧凑,因此,我敢肯定,有人可以指出各种可以改进的方式。

演示:请注意,我已在演示中减小了Y,以便可以在不到5秒的时间内完成。


1

PHP-112

没有可见的循环,但内存很大!

<?=count(array_filter(range($argv[1],$argv[2]),function($i)use($argv){return strpos($i,$argv[3].'')!==false;}));

用法 php script.php 0 1000000 2


1

ECMAScript 3至6

(JavaScript,JScript等)

使用正则表达式:

function f(x,y,z,r){for(r=0,z=RegExp(z);x<y;r+=+z.test(''+x++));return r}

分解:

function f(x,y,z,r){        // note argument `r`, eliminating the need for `var `
  for( r=0, z=RegExp(z)     // omitting `new` since ES will add it if omitted
     ; x<y                  // 
     ; r+=+z.test(''+x++)   // `x++` == post increment
                            // `''+Number` == convert Number to string
                            // `test` gives true | false
                            // `+Boolean` converts boolean to 1 | 0
                            // `r+=Number` incrementing r (were Number is always 1 or 0)
     );                     // no body thus semicolon is mandatory!
  return r;                 // returning r
}

使用indexOf:

function f(x,y,z,r){for(r=0;x<y;r+=+!!~(''+x++).indexOf(z));return r}

分解:

function f(x,y,z,r){                // note argument `r`, eliminating the need for `var `
  for( r=0                          // omitting `new` since ES will add it if omitted
     ; x<y                          // 
     ; r+=+!!~(''+x++).indexOf(z)   // `x++` == post increment
                                    // `''+Number` == convert Number to string
                                    // `indexOf` returns index or `-1` when not found
                                    // `!!~ indexOf` converts sentinel value to boolean
                                    // `+Boolean` converts boolean to 1 | 0
                                    // `r+=Number` incrementing r (were Number is 1 or 0)
     );                             // no body thus semicolon is mandatory!
  return r;                         // returning r
}

这个函数体比弗洛伦的函数体少一个字符,因此使用ES6 =>函数表示法时,总数为62个字符

调用f(0,1e6,2)
示例:用法示例:alert( f(0,1e6,2) );

JSFiddle在这里

PS:以上两个函数均返回其局部变量r
因此,当将结果变量泄漏r到全局范围中时,可以再次保存10个字符:

function f(x,y,z){for(r=0;i<=j;r+=+!!~(''+i++).indexOf(z));}

使用示例: alert( f(0,1e6,2)||r );


1

德尔福-120

我的品位有点高,要看看我能不能下车。

var x,y,z,i,c:int16;begin readLn(x,y,z);for i:=x to y do if inttostr(i).contains(inttostr(z))then inc(c);writeln(c);end.

不介意长度,我喜欢看到一个delphi解决方案;-)
Obl Tobl 2014年

@OblTobl太好了,但是尝试使其简短起来很有趣:P
Teun Pronk 2014年

1

Python 2.7-50个字符

在现有的Python答案上有所节省。

lambda x,y,z:sum(1for n in range(y-x)if`z+x`in`n`)

使用以下技巧:

  • Sum可以应用于生成器,与len不同,因此请使用sum(1 ...)而不是len([n ...])
  • 使用``代替str(),这也允许...
  • 杀死所有空格-参见“ 1for”和“ if z+xin n
  • 通过从0开始并测试偏移量来删除第一个range()arg(实际上...什么都没给我节省,但我更喜欢它的外观:))

实际上:

In [694]: (lambda x,y,z:sum(1for n in range(y-x)if`z+x`in`n`))(0,1000000,2)
Out[694]: 468559

1

k [28个字符]

{+/($x+!y)like"*",$:[z],"*"}

用法

{+/($x+!y)like"*",$:[z],"*"}[0;1000000;2]
468559

1
您可以将替换$:[z]为来保存字符($z)
mollmerx 2014年

但是,您的解决方案的上限不正确。它从x枚举到x + y-1,而不是从x枚举到y。
mollmerx 2014年
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.