Contar ocorrências de um número inteiro [fechado]


13

Com base na pergunta Quantos números inteiros positivos <1.000.000 contêm o dígito 2? . Estou procurando a solução mais criativa para contar todos os números inteiros de Xpara Yconter o número inteiro Z. Zpode ser de 0 a Y.

Todo número inteiro encontrado conta apenas uma vez, mesmo que o número inteiro Zapareça com mais frequência. Por exemplo:

Z = 2
123 counts 1
22222 also counts 1

Começarei com um algoritmo realmente simples escrito em Java (porque é amado por todos):

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);
    }
}

se você executar isso com

java -jar Count.jar 0 1000000 2

você obtém isso como resultado:

468559

Como esse problema não é difícil de resolver, é apenas um . A resposta mais votada até 28 de fevereiro vence!


Não está totalmente claro em sua postagem, mas acho que Z pode estar entre 0 e inf? Ou apenas entre 0 e 9?
mmumboss

Z pode estar entre 0 e não Y. Não faz sentido que Z pode ser maior do que Y.
Obl Tobl

@OblTobl Deseja realmente excluir explicitamente o caso Z> Y? Por que não apenas o resultado esperado nesse caso ser 0?
Cruncher

@ Cruncher eu não me importo! mas é um pouco inútil eu acho ;-)
Obl Tobl

Isso significa que Npode ser 123e só corresponderia se a substring 123 existir?
Populus

Respostas:


26

bash (20)

seq $1 $2|grep -c $3

Uso

$ bash count.sh 0 1000000 2
468559

10
é engraçado se a chamada for mais longa que o programa em si ;-) #
224 Obl Tobl

11

Funciton

Como de costume, como a altura da linha adicionada pelo StackExchange divide as linhas, considere a execução $('pre').css('line-height',1)no console do navegador para corrigir isso.

Ao contrário das minhas outras respostas do Funciton, este não usa nenhuma declaração de função. É apenas um programa. Porém, ele usa uma expressão lambda - um recurso que eu adicionei ao Funciton em dezembro :)

Espera a entrada como três números inteiros decimais (pode ser negativo) separados por espaços (ou seja x y z). De fato, zpode ser qualquer string; por exemplo, poderia ser apenas o sinal de menos ( , U + 2212) para contar o número de números negativos no intervalo :)

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

1
Isso é bem legal! Usando um idioma que você criou
pcnThird

2
@pcnThird: Eu acho que Timwi passa o tempo todo jogando golfe ou criando idiomas para jogar golfe (veja também Sclipting)!
Gabe

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])));
    }
}

Exemplo

count.exe 0 1000000 2
468559

solução inteligente! Eu gosto que você fez isso sem loop.
Obl Tobl

@OblTobl sem um loop visível .
1174 Justin justin

é claro, bom de qualquer maneira
Obl Tobl

1
Tem um bug, .Rangeaceita (int start, int count), não (start, end). Eu sempre cair nessa armadilha eu mesmo :)
Grozz

Serve-me bem por rapidamente digitar isso no Bloco de Notas ... Alterei o código para que agora esteja correto!
Mo D

5

APL (29)

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

Esta é uma função que assume Zcomo argumento à esquerda e o intervalo [X,Y]como argumento à direita:

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

não muito claro ... mas muito legal!
Obl Tobl

4

Python 2.7

Necessito de velocidade

Explicação

insira a descrição da imagem aqui

Implementação

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

Demo

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

Comparação

@Dennis

$ \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

É claro que isso é muito mais rápido, mas não atende aos requisitos da pergunta. keypode ser qualquer número inteiro , não dígito, entre loe hi.
1111 Dennis

ainda há uma solução matemática, apesar de que seria ainda mais ...
Red Alert

3

Python 2.7

Uma solução usando expressões regulares:

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

Você pode usar re.findallem um one-liner fazendo__import__('re').findall('\d...
SimonT

3

bash - 32. 31 17 14 caracteres + comprimento de X, Y e Z

Obrigado devnull por sugerir seq!

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

por exemplo, X = 100, Y = 200, Z = 20

$ seq 100 200|grep -c 20
2

por exemplo, X = 100, Y = 200, Z = 10

$ seq 100 200|grep -c 10
11

por exemplo, X = 0, Y = 1000000, Z = 2

$ seq 0 1000000|grep -c 2
468559

agradável e claro!
Obl Tobl

Por que usar echoquando você pode usar seqe reduzir o comprimento em 4 caracteres? (1 para o comprimento de comando, 2 para ser capaz de omitir chaves e um para a substituição ..com um único espaço)
devnull

@ devnull - obrigado, e também pode se livrar de xargse wc- e também corre muito mais rápido!

3

PHP

Nada original, apenas comemorando meu primeiro post aqui.

<?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;

?>

Entrada

php script.php 0 1000000 2

Resultado

468559

3

Scala:

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


2

Rubi

Este é um ótimo exemplo para usar reduzir!

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

Entrada:

ruby script.rb 0 1000000 2

Resultado:

468559

2

Golfe em Python - 61

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

Python não-golfe

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

2

Java8

Usando o novo material do IntStream, isso se torna essencialmente um liner, se você ignorar o material obrigatório do Java Framework:

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());
  }
}

Pode ser executado aqui , embora eu tenha que codificar os valores.


Solução Java realmente interessante
Obl Tobl

2

F #

Esta solução usa IndexOfpara pesquisar a string e, em seguida, um pouco de manipulação de números para converter o resultado em 1, se encontrado, e 0, se não encontrado, e soma o resultado:

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

E pode ser chamado assim:

count 0 1000000 "2" // 468559

2

Expressão regular

A seguir, os dígitos de 1 até 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 27caracteres

Basta obter a ferramenta certa para o trabalho. Uso simples de grep em R, nada extravagante.

Isto é o que ele faz: greptodas as instâncias do 2vetor 0até 10e6e contam o número de resultados usando length.

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

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

Resultado: [1] 468559


Fora do curso, você pode escrever uma função que aceita os números como entrada, exatamente como é mostrado no exemplo.

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

Agora você pode chamar countcom x, ye z, se não estiver definido (por padrão), os valores de x, ye z serão 0, 1000000 e 2, respectivamente. Alguns exemplos:

count()
[1] 468559

ou

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

ou

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

Alguns aqui acham que o tempo é importante, usando esta função em R leva cerca de 1 segundo.

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

talvez seja muito curto ;-) #
224 Obl Tobl '16:

Bem, isso não é o código-golfe de qualquer maneira :) Eu me pergunto: como seria o programa se tivesse que tomar os números como entrada (em vez de codificá-los)?
Timwi

Criado uma função para a imaginação;)
CousinCocaine

1

JavaScript (ES6), 63

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

Uso:

f(0, 1e6, 2)
> 468559

Sem golfe:

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

Rubi

Basicamente eu tirei a resposta de Pablo e joguei semi-golfe (38 caracteres se você deixar espaço em branco desnecessário) em um exemplo não tão bom de uso select.

Ele seleciona todos os índices no intervalo (x .. y)que contémz . Infelizmente, este resultado intermediário é armazenado em uma matriz, cujo tamanho é retornado.

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

Parece bem organizado, tanto sintática quanto semanticamente, embora a i[z]parte não pareça realmente fazer sentido.

Funciona porque xe yrealmente são strings, não números! Assim, cada ium também é uma string e, é i[z]claro, verifica se a string zestá contida i.

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

1

Python 2.7, 70 sinais

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

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

Mais curto, 65 sinais

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

Eu não acho que você precisa range(0,y+1)se range(y+1)faz a mesma coisa. Além disso, você pode remover a maioria desses espaços se você está golfe ...
SimonT

1

Usando Ruby Enumerable#grep:

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

1

T-SQL

Se eu posso assumir variáveis @X, @Ye @Zestão disponíveis:

Com uma tabela de números existente (arbitrariamente grande;) - 65

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

Com um CTE recursivo - 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)

Se as variáveis ​​precisarem ser definidas explicitamente:

Adicione 58 a ambas as respostas - tabela de números: 123, CTE recursiva: 185

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

Não tenho idéia de quanta memória o CTE recursivo pode usar, mas certamente não vai ganhar nenhum concurso de velocidade. O exemplo de pesquisa de 2 em 0 a 1000000 leva 8 segundos no meu sistema.

Aqui está um SQL Fiddle se alguém quiser brincar com ele. A consulta 1000000 leva mais de 30 segundos para ser executada.


não é rápido, mas muito criativo!
Obl Tobl

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

Exemplo de uso no console Rebol (REPL):

>> count 0 1000000 2
== 468559

1

PowerShell

Duas soluções, ambas 40 37 caracteres.

Para todas as versões do PowerShell:

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

O PowerShell V3 e superior têm o slsalias para Select-String. Isso exige @forçar uma matriz se apenas um valor passar pelo pipeline.

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

1

Lote

@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

Um pouco mais legível -

@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!

Agradável e simples. Utiliza manipulação de string para verificar se a variável !b!é igual a si mesma sem a terceira entrada do usuário, %3( !b:%3=!).


1

Mathematica

Primeira maneira: strings

x, y, zsão convertidos em strings. Se um número inteiro de string não estiver livre z, ele será contado.

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

Exemplos

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

20
468559


Segunda maneira: listas de dígitos

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

Exemplos

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

20
468559


Mathematica é sempre fascinante, mesmo para problemas simples
Obl Tobl

1

GolfScript

Eu tenho tentado melhorar minhas habilidades no GolfScript, então pensei em tentar com esta pergunta. Aqui está o que eu vim com:

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

Isso pode ser dividido assim:

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

Embora seja o GolfScript, o objetivo era tentar torná-lo relativamente mais eficiente do que compacto, por isso tenho certeza de que alguém pode apontar várias maneiras de melhorar isso.

Demonstração : observe que reduzi Y na demonstração para que ela seja concluída em <5 segundos.


1

PHP - 112

Sem loops visíveis, mas um pouco pesado na memória!

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

Uso php script.php 0 1000000 2


1

ECMAScript 3 a 6

(javascript, JScript, etc.)

usando regex:

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

demolir:

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
}

usando indexOf:

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

demolir:

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
}

esse corpo da função é um caractere a menos do que o de florent; portanto, ao usar a =>notação de função ES6 , o total seria de 62 caracteres

Chamada de exemplo: f(0,1e6,2)
Exemplo de uso:alert( f(0,1e6,2) );

JSFiddle aqui

PS: as duas funções acima retornam sua variável localr .
Portanto, ao colocar a variável de resultado rno escopo global, é possível salvar novamente 10 caracteres:

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

Exemplo de uso: alert( f(0,1e6,2)||r );


1

Delphi - 120

Um pouco demais para o meu gosto, vou ver se consigo tirar algum proveito.

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.

não se importa para o comprimento, eu adoraria ver uma solução delphi ;-)
Obl Tobl

@OblTobl Ótimo, mas é muito divertido tentar torná-lo curto: P
Teun Pronk

1

Python 2.7 - 50 caracteres

Um pouco de economia nas respostas existentes do Python.

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

Usando os seguintes truques:

  • A soma pode ser aplicada a um gerador, diferentemente do len, então use sum (1 ...) em vez de len ([n ...])
  • Use `` em vez de str (), que também permite ...
  • Mate todos os espaços - veja '1for' e 'if z+xinn '
  • Remova o primeiro argumento range () começando em 0 e testando o deslocamento (na verdade ... não me poupa nada, mas eu gosto mais da aparência :))

Em ação:

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 caracteres]

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

Uso

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

1
Você pode salvar um personagem substituindo $:[z]por ($z).
Mollmerx

No entanto, o limite superior da sua solução está incorreto. Enumera de x a x + y-1, não de x a y.
Mollmerx
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.