Programa mais curto para dividir uma seqüência de caracteres sem dígitos, sem RegExps


16

Edição: Se você estiver usando Lisp, eu dei algumas orientações na parte inferior na contagem de bytes.

Objetivo: criar a função mais curta que divide uma sequência em dígitos que não sejam dígitos e retorna uma matriz que consiste apenas em dígitos em cada sequência, sem o uso de expressões regulares. Os zeros à esquerda devem ser incluídos em cada sequência.

Classificação atual (separada em categorias):

  • C / C ++ / C # / Java: 68 (C) ....
  • GolfScript / APL / J: 13 (APL)
  • Todos os outros: 17 (Bash, usos tr), 24 (Ruby)

Regras:

(Peço desculpas pela demora)

  1. O formato deve ser uma função com um argumento de cadeia única. Até dois argumentos adicionais podem ser adicionados, se necessário, para o retorno adequado da matriz (por exemplo, sh / csh / DOS Batch precisa de uma referência variável extra para retornar, etc.).
  2. A declaração da função principal não conta e nem importa outras bibliotecas padrão. `# include`s,` import`s e `using`s não contam. Tudo o resto faz. Isso inclui as funções # # define`s e helper. Desculpe pela confusão. Consulte este manual como um guia útil sobre o que conta / não conta (escrito na sintaxe no estilo C)
    // não conta para o total, pode ser omitido, a menos
    // não óbvio, como metade da biblioteca padrão do Java.
    #include <stdio.h>
    
    import some.builtin.Class // não conta, veja acima
    
    #define printf p // conta para o total
    
    / * Quaisquer outras diretivas de pré-processador, etc. contam. * /
    
    int i = 0; // conta
    
    someFunction (); // conta
    
    char [] [] myMainSplitFunction (char [] [] array) {// não conta
      // Tudo aqui conta
      return returnArray; // Até isso conta.
    } // não conta
    
    / * Tudo aqui conta, incluindo a declaração * /
    char [] [] someHelperFunction (char [] string) {
      // coisa
    } // mesmo isso conta
    
  3. A saída deve ser uma matriz de cadeias ou semelhante (listas de matrizes em Java e similares são aceitáveis). Exemplos de saída aceite: String[], char[][], Array, List, e Array(objecto).
  4. A matriz deve conter apenas primitivas de seqüência de caracteres de comprimento variável ou objetos de seqüência de caracteres. Nenhuma string vazia deve estar presente no retorno, com a exceção abaixo. Nota: as sequências devem conter uma sequência de correspondências consecutivas, como o exemplo de entrada e saída abaixo.
  5. Se não houver correspondências, o corpo da função deve retornar null, uma matriz / lista vazia ou uma matriz / lista contendo uma sequência vazia.
  6. Nenhuma biblioteca externa permitida.
  7. As terminações de linha do DOS contam como um byte, não dois (já abordado na meta, mas precisa ser enfatizado)
  8. E a maior regra aqui: não são permitidas expressões regulares.

Esta é uma questão de , então o menor tamanho vence. Boa sorte!

E aqui estão alguns exemplos de entradas e saídas (com escapamentos no estilo C):

Entrada: "abc123def456"
Saída: ["123", "456"]

Entrada: "aitew034snk582: 3c"
Saída: ["034", "582", "3"]

Entrada: "as5493tax54 \\ 430-52@g9.fc"
Saída: ["5493", "54", "430", "52", "9"]

Entrada: "sasprs] rasgou \" re \\ forz "
Saída: nulo, [], [""] ou similar

Por favor, coloque quantos bytes usados ​​por suas respostas e, como sempre, golfe feliz!


Diretrizes para Lisp

Aqui está o que conta e o que não conta nos dialetos Lisp:

;;; Opção 1

(desafinar extract-strings (ab); Não conta
  (coisa) ;;; Tudo aqui conta
); Não conta

;;; opção 2

(extrair strings de extração (string & aux (início 0) (final 0)); Não conta
  (coisa) ;;; Tudo aqui conta
); Não conta.
Todas as outras lambdas contam totalmente para a contagem de bytes.


Isso não foi perguntado antes?
Ismael Miguel

11
Sim, mas solicitei novamente no Meta e fiz edições substanciais antes de publicá-lo novamente aqui. Por esse motivo, não deve ser classificado como duplicado (o outro relacionado deve ser fechado, se ainda não estiver).
Isiah Meadows

2
O seu "golfe" não deve ser publicado como resposta?
MrWhite

4
Desculpe, mas -1 por desabilitar o GolfScript. Todos os idiomas devem ser permitidos.
Maçaneta

11
@ Doorknob Isso é verdade, mas eu também entendo os sentimentos do OP. As pessoas devem ter a chance de competir, mesmo que não falem GolfScript, J ou APL (e eu sou culpado de ler o último nessas competições.) Você pode dar uma olhada na minha proposta no tópico ao qual ele vinculou?
Tobia 23/02

Respostas:


10

APL, 13 caracteres

(ou 28/30 bytes, leia abaixo)

{⍵⊂⍨⍵∊∊⍕¨⍳10}

Vejo que você baniu o GolfScript da sua pergunta. Entendo sua opinião, mas espero que essa comunidade não bana o APL, porque é uma linguagem de programação verdadeiramente notável, com uma longa história, sem mencionar muita diversão em codificar. Talvez possa ter uma pontuação diferente, se as pessoas sinto que está competindo injustamente. Vou postar meus pensamentos sobre esse assunto no tópico que você vinculou.

Nesse mesmo token, sempre adicionei uma nota de rodapé às minhas postagens de APL, alegando que o APL poderia ser pontuado como 1 char = 1 byte. Minha afirmação se baseia no fato de que algumas implementações de APL (principalmente comerciais) ainda suportam sua própria codificação herdada de byte único, com os símbolos da APL mapeados para os valores superiores de 128 bytes. Mas talvez isso seja um exagero; nesse caso, convém marcar essa entrada como 28 bytes em UTF-16 ou 30 bytes em UTF-8.

Explicação

{        ⍳10}  make an array of naturals from 1 to 10
       ⍕¨      convert each number into a string
      ∊        concatenate the strings into one (it doesn't matter that there are two 1s)
    ⍵∊         test which chars from the argument are contained in the digit string
 ⍵⊂⍨           use it to perform a partitioned enclose, which splits the string as needed

Exemplos

      {⍵⊂⍨⍵∊∊⍕¨⍳10} 'ab5c0x'
 5  0 
      {⍵⊂⍨⍵∊∊⍕¨⍳10}  'z526ks4f.;8]\p'
 526  4  8 

O formato de saída padrão para uma matriz de seqüências de caracteres não deixa claro quantas seqüências existem na matriz, nem quantos espaços em branco. Mas uma manipulação rápida para adicionar aspas deve deixar bem claro:

      {q,⍵,q←'"'}¨ {⍵⊂⍨⍵∊∊⍕¨⍳10} 'ab5c0x'
 "5"  "0" 
      {q,⍵,q←'"'}¨ {⍵⊂⍨⍵∊∊⍕¨⍳10}  'z526ks4f.;8]\p'
 "526"  "4"  "8" 

Em relação ao seu comentário, acho que para outros idiomas competir de maneira justa com os "abreviados", deve-se contar cada símbolo nos outros idiomas como um caractere. Por exemplo, minha solução Mathematica postada aqui deve ser contada como 7 (mais ou menos). Projetar uma linguagem com tokens compactados não é mérito, eu acho.
Dr. belisarius

Você poderia fornecer um despejo hexadecimal do seu golfe? Não consigo ler alguns dos personagens.
Isiah Meadows

@impinball Como o hexdump o ajudaria? Não é como se você visse o que está sendo feito.
Mniip

@impinball, o código APL é {omega delimita o formato omega epsilon epsilon a cada 10 pontos}. Se você precisar dos valores unicode, poderá copiá-lo e colá-lo em qualquer ferramenta online , mesmo que não consiga ver os caracteres (o que é estranho, pois a maioria das fontes Unicode modernas possui os símbolos APL). De qualquer forma, o que você obtém é esse {\ u2375 \ u2282 \ u2368 \ u2375 \ u220a \ u220a \ u2355 \ u00a8 \ u237310} (mente o último "10", que não faz parte da sequência de escape)
Tobia

11
Em vez de ∊⍕¨⍳10, você não poderia simplesmente usar ⎕D? Essa deve ser a constante '0123456789'. O Dyalog APL, no mínimo, o suporta, e o NARS2000 também.
marinus

5

Python 47

Implementação

f=lambda s:"".join([' ',e][e.isdigit()]for e in s).split()

Demo

>>> sample=["abc123def456","aitew034snk582:3c","as5493tax54\\430-52@g9.fc","sasprs]tore\"re\\forz"]
>>> [f(data) for data in sample]
[['123', '456'], ['034', '582', '3'], ['5493', '54', '430', '52', '9'], []]

Algoritmo

Converta cada caractere que não seja dígito em espaço e depois divida a sequência resultante. Uma abordagem simples e clara.

E uma solução divertida com itertools (71 caracteres)

f1=lambda s:[''.join(v)for k,v in __import__("itertools").groupby(s,key=str.isdigit)][::2]

4

Ruby, 70

f=->(s){s.chars.chunk{|c|c.to_i.to_s==c}.select{|e|e[0]}.transpose[1]}

Versão online para teste

Como converter qualquer caractere que não seja um dígito para um int retorna 0 em Ruby (com to_i), a conversão de todos os caracteres em int e de volta em char é a maneira não-regular de verificar um dígito ...


Você também pode criar um membro ('0' .. '9').? para cada caractere, mas o que você fez já é mais curto
fgp 23/02

Você está definitivamente certo - eu deveria ter dito: "a" maneira;)
David Herrmann

4

bash, 26 (conteúdo da função: 22 + sobrecarga de atribuição de matriz 4)

Isso não vai superar a outra bashresposta , mas é interessante porque pode fazer você pensar duas vezes:

f()(echo ${1//+([!0-9])/ })

O uso é:

$ a=(`f "ab5c0x"`); echo ${a[@]}
5 0
$ a=(`f "z526ks4f.;8]\p"`); echo ${a[@]}
526 4 8
$ 

À primeira vista, //+([!0-9])/parece muito com uma substituição de regexp, mas não é. É uma expansão de parâmetro bash , que segue regras de correspondência de padrões , em vez de regras de expressão regular.

Retornar tipos de array bash verdadeiros a partir de funções bash é uma tarefa difícil, então eu escolhi retornar uma lista delimitada por espaço e depois converter para um array em uma atribuição de array fora da chamada de função. Portanto, no interesse da justiça, acho que a (` `)chamada de função ao redor deve ser incluída na minha pontuação.


3

Mathematica 32

StringCases[#,DigitCharacter..]&

Uso

inps ={"abc123def456", "aitew034snk582:3c", "as5493tax54\\430-52@g9.fc", 
        "sasprs]tore\"re\\forz"}  
StringCases[#,DigitCharacter..]&/@inps

{{"123", "456"}, 
 {"034", "582", "3"}, 
 {"5493", "54", "430", "52", "9"}, 
 {}
}

O equivalente a usar expressões regulares é muito mais longo !:

StringCases[#, RegularExpression["[0-9]+"]] &

O Mathematica é péssimo no regex.
CalculatorFeline

3

Bash, 21 bytes 17/21 bytes (aprimorado pelo DigitalTrauma )

Construindo uma lista separada por espaços com tr

function split() {
tr -c 0-9 \ <<E
$1
E
}

substitui qualquer dígito por um espaço

Uso

$ for N in $(split 'abc123def456'); do echo $N; done
123
456

Editar

conforme apontado pelos comentários abaixo, o código pode ser reduzido para 17 bytes:

function split() (tr -c 0-9 \ <<<$1)

e como o resultado não está falando estritamente uma matriz Bash, o uso deve ser

a=(`split "abc123def456"`); echo ${a[@]}

e o extra (``)deve ser contado


11
Gah, você me venceu! Mas por que não usar uma string aqui em vez de um documento aqui? Além disso, você pode salvar uma nova linha no final do conteúdo função que você usar (blah)em vez de {blah;}: split()(tr -c 0-9 \ <<<$1). Dessa forma, seu corpo funcional tem apenas 17 caracteres.
Digital Trauma

11
Sua função retorna uma "lista separada por espaço" em vez de uma matriz. Certamente regressar verdadeiros matrizes de função bash é estranho, mas você poderia pelo menos atribuir o resultado de sua função para um array em seu uso: a=($(split "12 3a bc123")); echo ${a[@]}. Pode-se argumentar que "($ ())" seja contado em sua pontuação
Digital Trauma

Antes de explorar a trabordagem, tentei fazer isso com uma expansão de parâmetros . tré definitivamente a melhor abordagem para fins de golfe.
Digital Trauma

Você já tentou cercar o trcom o operador de expansão? Seria algo como ($(tr...)), e onde a declaração da função não conta, os parênteses externos não contam contra você. Seria apenas a parte de substituição de comando.
Isiah Meadows

Não vejo como isso deve estar funcionando, mas não sou fluente em matrizes Bash. De qualquer forma, a (``)construção é 1 caractere melhor do que a que ($())será preferida.
Coaumdio 25/02

2

Smalltalk (Smalltalk / X), 81

f := [:s|s asCollectionOfSubCollectionsSeparatedByAnyForWhich:[:ch|ch isDigit not]]

valor f: 'abc123def456' -> OrderedCollection ('123' '456')

valor f: 'aitew034snk582: 3c' -> OrderedCollection ('034' '582' '3')

f value: 'as5493tax54 \ 430-52@g9.fc' -> OrderedCollection ('5493' '54' '430' '52' '9')

f valor: 'sasprs] rasgou \ "re \ forz' -> OrderedCollection ()

sigh - O Smalltalk tem uma tendência a usar nomes de funções muito longos ...


2
Esse é um nome de função? o__O
Tobia

@tobia Aparentemente ...
Isiah Meadows

asCollectionOfSubCollectionsSeparatedByAnyForWhichಠ_ಠ Este nome é muito longo
TuxCrafting

1

R, 81

f=function(x){
s=strsplit(x,"",T)[[1]]
i=s%in%0:9
split(s,c(0,cumsum(!!diff(i))))[c(i[1],!i[1])]
}

A função aceita uma string e retorna uma lista de strings.

Exemplos:

> f("abc123def456")
$`1`
[1] "1" "2" "3"

$`3`
[1] "4" "5" "6"

-

> f("aitew034snk582:3c")
$`1`
[1] "0" "3" "4"

$`3`
[1] "5" "8" "2"

$`5`
[1] "3"

-

> f("as5493tax54\\430-52@g9.fc")
$`1`
[1] "5" "4" "9" "3"

$`3`
[1] "5" "4"

$`5`
[1] "4" "3" "0"

$`7`
[1] "5" "2"

$`9`
[1] "9"

-

> f("sasprs]tore\"re\\forz")
$<NA>
NULL

Nota: $xé o nome do elemento da lista.


1

Perl, 53

Editar: em nenhuma correspondência, sub agora retorna a lista com uma string vazia (em vez da lista vazia) conforme necessário.

Também evita a divisão em caracteres de espaço único, pois desencadeia o comportamento de 'divisão em qualquer espaço em branco' , o que provavelmente viola as regras. Eu poderia usar o / /delimitador, que seria dividido em espaço único, mas paradoxalmente pareceria usar o padrão regexp. Eu poderia usar unpacko custo de alguns caracteres extras e assim me livrar da splitcontrovérsia, mas acho que, com o que termino, dividir um caractere literal (que não seja o espaço) é bom.

sub f{shift if(@_=split a,pop=~y/0-9/a/csr)[0]eq''and$#_;@_}

E não, o operador de transliteração do Perl não faz expressões regulares. Eu posso desenrolar o intervalo de 0 a 9 para 0123456789se esse for o problema.


Contanto que não use expressões regulares, é válido.
Isiah Meadows

Meu Perl não é tão forte. Se eu entendo o código, você está substituindo não dígitos por um não dígito específico, dividindo o não dígito escolhido e filtrando as seqüências vazias. Esta é uma leitura correta?
Tim Seguine

11
@ TimSeguine: Não exatamente. Os dígitos que não são dígitos são substituídos e compactados em um único caractere, dividido no qual produz uma string vazia se esse delimitador estiver no início. Em seguida, é deslocada se a lista contiver outras entradas.
user2846289

Lista vazia está bem.
Isiah Meadows

1

C, 68 bytes (apenas o corpo da função)

void split (char *s, char **a) {
int c=1;for(;*s;s++)if(isdigit(*s))c?*a++=s:0,c=0;else*s=0,c=1;*a=0;
}

O primeiro argumento é a sequência de entrada, o segundo é a matriz de saída, que é uma matriz de sequências terminada em NULL. É necessário reservar memória suficiente aantes de chamar a função (no pior caso:sizeof(char*)*((strlen(s)+1)/2) .

A sequência de entrada é modificada pela função (todo caractere que não seja dígito é substituído por '\0' )

Exemplo de uso

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

void split (char *s, char **a) {
int c=1;for(;*s;s++)if(isdigit(*s))c?*a++=s:0,c=0;else*s=0,c=1;*a=0;
}   

void dump(char **t) {
    printf("[ ");for(;*t;t++)printf("%s ", *t);printf("]\n");
}   

int main() {
    char **r = malloc(1024);
    char test1[] = "abc123def456";
    char test2[] = "aitew034snk582:3c";
    char test3[] = "as5493tax54\\430-52@g9.fc";
    char test4[] = "sasprs]tore\"re\\forz";
    split(test1,r); 
    dump(r);
    split(test2,r); 
    dump(r);
    split(test3,r); 
    dump(r);
    split(test4,r); 
    dump(r);
    return 0;
}

Resultado

[ 123 456 ]
[ 034 582 3 ]
[ 5493 54 430 52 9 ]
[ ]

Versão sem golfe:

void split (char *s, char **a) {
    int c=1; // boolean: the latest examined character is not a digit
    for(;*s;s++) {
        if(isdigit(*s)) {
            if(c) *a++ = s; // stores the address of the beginning of a digit sequence
            c=0;
        } else {
            *s=0; // NULL-terminate the digit sequence
            c=1;
        }   
    }   
    *a = 0; // NULL-terminate the result array
} 

1

VBScript, 190 (164 sem declaração de função)

Function f(i)
For x=1 To Len(i)
c=Mid(i,x,1)
If Not IsNumeric(c) Then
Mid(i,x,1)=" "
End If
Next
Do
l=Len(i)
i=Replace(i,"  "," ")
l=l-Len(i)
Loop Until l=0
f=Split(Trim(i)," ")
End Function

Embora não seja nada competitivo, estou surpreso que o VBScript seja tão curto quanto ao fato de ser detalhado (13 bytes apenas para os CRs). Ele percorre a cadeia de caracteres, substituindo caracteres não numéricos por espaços, reduz todo o espaço em branco a espaços únicos e, em seguida, usa um delimitador de espaço para dividi-lo.

Casos de teste

Input: "ab5c0x"
Output: 5,0

Input: "z526ks4f.;8]\p"
Output: 526,4,8

As terminações de linha do DOS contam como um caractere, até onde eu li na meta.
Isiah Meadows

Eu sugeri uma edição para você.
Isiah Meadows

A contagem já assume finais de linha de 1 byte no estilo Linux. Recebo 190 caracteres por minha contagem (apenas verificada novamente).
Comintern

Está bem. Eu devo ter errado.
Isiah Meadows

1

Lisp comum (1 de acordo com a letra; 3173 de acordo com o espírito)

Aqui está uma versão legível. A contagem de bytes é bastante alta devido aos nomes longos em coisas comodigit-char-p e position-ife vector-push-extend.

(defun extract-numeric-substrings (string &aux (start 0) (end 0) (result (make-array 0 :adjustable t :fill-pointer 0)))
  (loop 
     (unless (and end (setq start (position-if #'digit-char-p string :start end)))
       (return result))
     (setq end (position-if (complement #'digit-char-p) string :start (1+ start)))
     (vector-push-extend (subseq string start end) result)))
(extract-numeric-substrings "abc123def456")
#("123" "456")

(extract-numeric-substrings "aitew034snk582:3c")
#("034" "582" "3")

(extract-numeric-substrings "as5493tax54\\430-52@g9.fc")
#("5493" "54" "430" "52" "9")

(extract-numeric-substrings "sasprs]tore\"re\\forz")
#()

O conceito de "declaração de função" é meio vago. Aqui está uma versão que possui apenas um byte (o caractere xno corpo da função); tudo o mais é agrupado nas variáveis ​​auxiliares da lista de lamba da função (parte da declaração da função):

(defun extract-numeric-substrings (string 
                                   &aux (start 0) (end 0) 
                                   (result (make-array 0 :adjustable t :fill-pointer 0))
                                   (x (loop 
                                         (unless (and end (setq start (position-if #'digit-char-p string :start end)))
                                           (return result))
                                         (setq end (position-if (complement #'digit-char-p) string :start (1+ start)))
                                         (vector-push-extend (subseq string start end) result))))
  x)

A contagem real de bytes dependerá de quantas declarações auxiliares precisarão ser movidas para o corpo para que isso seja considerado aceitável. Alguma renomeação de função local também ajudaria (por exemplo, diminua, position-ifpois aparece duas vezes, use variáveis ​​de letra única etc.).

Esta renderização do programa possui 220 caracteres:

(LOOP(UNLESS(AND END(SETQ START(POSITION-IF #'DIGIT-CHAR-P STRING :START END)))(RETURN RESULT))(SETQ END(POSITION-IF(COMPLEMENT #'DIGIT-CHAR-P)STRING :START(1+ START)))(VECTOR-PUSH-EXTEND(SUBSEQ STRING START END)RESULT))

Se nada mais, isso deve promover variáveis ​​auxiliares e comuns do Lisp .

Isso pode ser escrito de forma mais concisa loop, é claro:

(defun extract-numeric-substrings (s &aux (b 0) (e 0) (r (make-array 0 :fill-pointer 0)))
  (loop 
     with d = #'digit-char-p 
     while (and e (setq b (position-if d s :start e)))
     finally (return r)
     do 
       (setq e (position-if-not d s :start (1+ b)))
       (vector-push-extend (subseq s b e) r)))

O loopformulário, com espaço extra removido, possui 173 caracteres:

(LOOP WITH D = #'DIGIT-CHAR-P WHILE(AND E(SETQ B(POSITION-IF D S :START E)))FINALLY(RETURN R)DO(SETQ E(POSITION-IF-NOT D S :START(1+ B)))(VECTOR-PUSH-EXTEND(SUBSEQ S B E)R))

Eu contaria a partir do (resultparêntese final para ser o corpo. A parte que define o nome e os parâmetros é a declaração.
Isiah Meadows

Consulte a regra 2 nas minhas regras alteradas para ver o que realmente estou falando em uma declaração de função (basicamente, declare o nome da função, parâmetros e, se necessário sintaticamente, o que é raro entre os idiomas interpretados, o tipo de retorno).
Isiah Meadows

@impinball Sim, a contagem "1" é uma piada, mas a parte importante aqui é que result é declarada como parâmetro aqui; apenas possui uma forma de inicialização não trivial. É a mesma coisa, em princípio, como um argumento opcional com um valor padrão calculado por alguma expressão complexa. (Em casos mais simples, é fácil imaginar algo como char* substring( char *str, int begin, int end(0) )em alguma linguagem com uma sintaxe do tipo C para especificar que endé opcional e que, se não for fornecido, seu valor será 0. Estou apenas destacando o fato de que alguns desses termos
Joshua Taylor

O @impinball não é muito concreto e o idioma é independente do suficiente para evitar algumas contagens de bytes trollish. :)
Joshua Taylor

A primeira parte que não está especificando parâmetros é onde eu faria a contagem de estatísticas (por exemplo, (defun fn (string &aux (start 0) (end 0) , não contaria, mas tudo o que restaria no lambda contaria).
Isiah Meadows

0

JavaScript, 240 bytes

E para aqueles que estão curiosos, aqui está o meu provavelmente enorme golfe:

function split(a) { // begin function
function f(c){for(var a=-1,d=9;d--;){var e=c.indexOf(d+"");0
>e||e<a&&(a=e)}return 0<a?a:null}var c=f(a);if(null==c)retur
n null;var d=[];for(i=0;;){a=a.substring(c);d[i]||(d[i]="");
c=f(a);if(null==c)break;d[i]+=a.charAt(c);0<c&&i++}return d;
} // end function

Acima em estampa bonita:

function split(a) {
    function f(c) {
        for (var a = -1, d = 9;d--;) {
            var e = c.indexOf(d + "");
            0 > e || e < a && (a = e);
        }
        return 0 < a ? a : null;
    }
    var c = f(a);
    if (null == c) return null;
    var d = [];
    for (i = 0;;) {
        a = a.substring(c);
        d[i] || (d[i] = "");
        c = f(a);
        if (null == c) break;
        d[i] += a.charAt(c);
        0 < c && i++;
    }
    return d;
}

Acima no código descritivo normal

function split(a) {
    function findLoop(string) {
        var lowest = -1;
        var i = 9;
        while (i--) {
            var index = string.indexOf(i + '');
            if (index < 0) continue;
            if (index < lowest) lowest = index;
        }
        return (lowest > 0) ? lowest : null;
    }
    var index = findLoop(a);
    if (index == null) return null;
    var ret = [];
    i = 0;
    for ( ; ; ) {
        a = a.substring(index);
        if (!ret[i]) ret[i] = '';
        index = findLoop(a);
        if (index == null) break;
        ret[i] += a.charAt(index);
        if (index > 0) i++;
    }
    return ret;
}

0

PHP 134

function f($a){
$i=0;while($i<strlen($a)){!is_numeric($a[$i])&&$a[$i]='-';$i++;}return array_filter(explode('-',$a),function($v){return!empty($v);});
}

Você pode reduzi-lo deixando de fora o retorno de chamada em array_filter. Isso removerá automaticamente todas as entradas que forem falseconvertidas para booleanos.
precisa saber é o seguinte

@kelunik que filtrar 0s bem
Einacio

0

C, 158

#define p printf
char s[100],c;int z,i;int main(){while(c=getchar())s[z++]=(c>47&&c<58)*c;p("[");for(;i<z;i++)if(s[i]){p("\"");while(s[i])p("%c",s[i++]);p("\",");}p("]");}

Como C não possui funções de impressão em matriz incorporadas, eu tive que fazer esse trabalho sozinho, então peço desculpas por haver uma vírgula final em cada saída. Essencialmente, o que esse código faz é ler a sequência de caracteres, se não for um dígito, substitui-a por '\ 0' e, em seguida, apenas percorro o código e imprimo todas as cadeias de dígitos. (EOF = 0)

Entrada: ab5c0x
Saída: ["5", "0",]

Entrada: z526ks4f.; 8] \ p
Saída: ["526", "4", "8",]


De acordo com as regras da pergunta (regra 2), você só precisa contar os caracteres no corpo da função. Portanto, sua solução seria realmente menor que 170 bytes. Não tenho certeza se a contagem inclui protótipos variáveis ​​fora do corpo da função.
grovesNL

Vou alterar as regras sobre isso: #defines, declarações de variáveis, etc. contarão, mas a declaração de função não.
Isiah Meadows

Além disso, da última vez que verifiquei, havia um tipo em C anotado como char[][]legal. Se você voltar assim (ou char**), ficará bem.
Isiah Meadows

Não precisa ser saída de texto? Eu pensei que o programa deveria produzir a matriz em um formato de string
ASKASK

0

C #, 98

static string[] SplitAtNonDigits(string s)
{
    return new string(s.Select(c=>47<c&c<58?c:',').ToArray()).Split(new[]{','},(StringSplitOptions)1);
}

Primeiro, isso usa o .Select()método de extensão LINQ para transformar todos os não dígitos em vírgulas. string.Replace()seria preferível, pois retorna um em stringvez de um IEnumerable<char>, mas string.Replace()pode usar apenas um único caractere ou string e não pode usar um predicado comochar.IsDigit() or 47<c&c<58.

Como mencionado, .Select()aplicado a uma string retorna um IEnumerable<char>, então precisamos transformá-la novamente em uma string, transformando-a em uma matriz e passando a matriz para ostring construtor.

Finalmente, dividimos a string em vírgulas usando string.Split().(StringSplitOptions)1é uma maneira mais curta de dizer StringSplitOptions.RemoveEmptyEntries, que cuida automaticamente de várias vírgulas e vírgulas consecutivas no início / fim da sequência.


11
Em vez de char.IsDigit(c), você pode usar'/'<c&&c<':'
grovesNL

11
Bom ponto ... ou melhor ainda 47<c&&c<58. (Francamente, estou surpreso que funcione com números, mas aparentemente funciona).
BenM 24/02

11
E posso salvar um caractere extra valioso usando um único '&' em vez de um duplo '&&'. Em C #, isso ainda é AND lógico quando os dois operandos são booleanos - ele apenas executa AND bit a bit quando são inteiros.
BenM 24/02

Agradável. Eu não sabia que era capaz de fazer isso.
grovesNL

Uma variante ligeiramente mais curto é dividir espaço em branco em vez de ,, em seguida, remover manualmente os itens vaziosreturn new string(s.Select(c=>47<c&c<58?c:' ').ToArray()).Split().Where(a=>a!="").ToArray();
VisualMelon

0

JS / Nó: 168 162 147 138 caracteres

function n(s){
var r=[];s.split('').reduce(function(p,c){if(!isNaN(parseInt(c))){if(p)r.push([]);r[r.length-1].push(c);return 0;}return 1;},1);return r;
}

Versão embelezada:

function n(s) {
  var r = [];
  s.split('').reduce(function (p, c) {
    if (!isNaN(parseInt(c))) {
      if (p) {
        r.push([]);
      }
      r[r.length - 1].push(c);
      return 0;
    }
    return 1;
  }, 1);
  return r;
}

Esta questão só quer a matriz retornada, então você pode remover console.log(r)e algumas outras coisas
Não que Charles

A declaração função não contam para a pontuação (razão é a de ajudar a nivelar o campo de jogo)
Isiah Meadows

Está bem. Ajustou a pontuação de acordo com o comentário de @ impinball. (Na verdade, existem duas funções declarou aqui contagem Char inclui a função anônima.)
palanik

Deveria. Atualizei as regras para ajudar a explicar melhor.
Isiah Meadows

Enquanto isso, veio com algo melhor ...
palanik

0

Ruby, 24

f=->s{s.tr("
-/:-~",' ').split}

Define dígitos usando espaço negativo dentro do intervalo ascii imprimível.


A declaração de função não conta.
Isiah Meadows

0

php , 204

function s($x){$a=str_split($x);$c=-1;$o=array();
for($i= 0;$i<count($a);$i++){if(ord($a[$i])>=48&&ord($a[$i])<=57)
{$c++;$o[$c]=array();}while(ord($a[$i])>=48&&ord($a[$i])<=57)
{array_push($o[$c],$a[$i]);$i++;}}return $o;}

Código descritivo:

function splitdigits($input){

    $arr = str_split($input);
    $count = -1;
    $output = array();
    for($i = 0; $i < count($arr); $i++){


    if(ord($arr[$i]) >= 48 && ord($arr[$i]) <= 57){
        $count++;
        $output[$count] = array();
    }

    while(ord($arr[$i]) >= 48 && ord($arr[$i]) <= 57){
        array_push($output[$count], $arr[$i]);
        $i++;
    } 

}

return $output;
}

Este é um código bastante longo e tenho certeza de que haverá uma versão php muito mais curta para esse código de golfe. Isso é o que eu poderia criar no php.


existem algumas melhorias: você pode substituir array()por [], array_push($output[$count], $arr[$i]);por $output[$count][]=$arr[$i];e as ord()verificações por is_numeric(). e você nem precisa dividir a string para iterar sobre seus caracteres. Além disso, apenas o código interno da função conta, portanto, como você é, a contagem de caracteres é 204.
Einacio

A declaração da função não conta. Consulte a regra 2 como um guia sobre o que conta e o que não conta.
Isiah Meadows

0

Pitão

def find_digits(_input_):
    a,b = [], ""
    for i in list(_input_):
        if i.isdigit(): b += i
        else:
            if b != "": a.append(b)
            b = ""
    if b != "": a.append(b)
    return a

0

Python 104 83

def f(s, o=[], c=""):
    for i in s:
        try:int(i);c+=i
        except:o+=[c];c=""
    return [i for i in o+[c] if i]

Resposta @Abhijit é muito inteligente, esta é apenas uma versão "minificada" do que eu tinha em mente.

assert f("abc123def456") == ["123", "456"]
assert f("aitew034snk582:3c") == ["034", "582", "3"]
assert f("as5493tax54\\430-52@g9.fc") == ["5493", "54", "430", "52", "9"]
assert f("sasprs]tore\"re\\forz") == []

Como não gera saída, o código está funcionando, se executado um a um, pois algumas variáveis ​​são definidas na declaração.


Você não precisa contar a declaração da função, se o fez. Assim como um heads-up
Isiah Meadows

0

PHP 98 89

Como na resposta bash do DigitalTrauma, isso não usa um regex.

function f($x) {
// Only the following line counts:
for($h=$i=0;sscanf(substr("a$x",$h+=$i),"%[^0-9]%[0-9]%n",$j,$s,$i)>1;)$a[]=$s;return@$a;
}

Casos de teste:

php > echo json_encode(f("abc123def456")), "\n";
["123","456"]
php > echo json_encode(f("aitew034snk582:3c")), "\n";
["034","582","3"]
php > echo json_encode(f("as5493tax54\\430-52@g9.fc")), "\n";
["5493","54","430","52","9"]
php > echo json_encode(f("sasprs]tore\"re\\forz")), "\n";
null

0

Haskell 31

{-# LANGUAGE OverloadedStrings #-}
import Data.Char (isDigit)
import Data.Text (split)

f=filter(/="").split(not.isDigit)

Divide a cadeia em todos os caracteres não numéricos e remove as cadeias vazias geradas por delimitadores consecutivos.


0

VBA 210, 181 sem declaração de função

Function t(s)
Dim o()
For Each c In Split(StrConv(s,64),Chr(0))
d=IsNumeric(c)
If b And d Then
n=n&c
ElseIf d Then:ReDim Preserve o(l):b=1:n=c
ElseIf b Then:b=0:o(l)=n:l=l+1:End If:Next:t=o
End Function

0

Rebol (66 caracteres)

remove-each n s: split s complement charset"0123456789"[empty? n]s

Ungolfed e wrapped na declaração de função:

f: func [s] [
    remove-each n s: split s complement charset "0123456789" [empty? n]
    s
]

Exemplo de código no console Rebol:

>> f "abc123def456"
== ["123" "456"]

>> f "aitew035snk582:3c"
== ["035" "582" "3"]

>> f "as5493tax54\\430-52@g9.fc"
== ["5493" "54" "430" "52" "9"]

>> f {sasprs]torer"re\\forz}
== []

0

JavaScript, 104 97 89

Golfe:

Edit: Quando os loops saem do final da matriz, céundefined , o que é falso e finaliza o loop.

27/2: Usar ?:salva o wordiness de if/else.

function nums(s) {
s+=l='length';r=[''];for(k=i=0;c=s[i];i++)r[k]+=+c+1?c:r[k+=!!r[k][l]]='';
r[l]--;return r
}

O retorno de carro no corpo é para facilitar a leitura e não faz parte da solução.

Ungolfed:

A idéia é anexar cada caractere à última entrada da matriz, se for um dígito, e garantir que a última entrada da matriz seja uma sequência.

function nums(s) {
    var i, e, r, c, k;
    k = 0;
    s+='x'; // ensure the input does not end with a digit
    r=[''];
    for (i=0;i<s.length;i++) {
        c=s[i];
        if (+c+1) { // if the current character is a digit, append it to the last entry
            r[k] += c;
        }
        else { // otherwise, add a new entry if the last entry is not blank
            k+=!!r[k].length;
            r[k] = '';
        }
    }
    r.length--; // strip the last entry, known to be blank
    return r;
}

0

Javascript, 72

function f(a){
 a+=".",b="",c=[];for(i in a)b=+a[i]+1?b+a[i]:b?(c.push(b),""):b;return c
}

Ungolfed

a+=".",b="",c=[];        //add '.' to input so we dont have to check if it ends in a digit
for(i in a)
    b=+a[i]+1?           //check if digit, add to string if it is
        b+a[i]:         
    b?                   //if it wasnt a digit and b contains digits push it
        (c.push(b),""):  //into the array c and clear b
    b;                   //else give me b back
return c

Entrada / saída de amostra

console.log(f("abc123def456"));
console.log(f("aitew034snk582:3c"));
console.log(f("as5493tax54\\430-52@g9.fc"));
console.log(f("sasprs]tore\"re\\forz"));

["123", "456"]
["034", "582", "3"]
["5493", "54", "430", "52", "9"]
[] 

JSFiddle


11
Eu gosto disso! Muito mais simples que o meu. Você pode eliminar outros 8 caracteres substituindo if(+a[i]+1)b+=a[i];else if(b)c.push(b),b=""por b=+a[i]+1?b+a[i]:b?(c.push(b),""):b.
DocMax 27/02

@ DocMax thx, editei para incluir sua sugestão :). Isso (c.push(b),"")parecia inteligente, nunca vi isso.
Danny

Eu tinha esquecido disso até que o vi usado extensivamente hoje mais cedo em codegolf.stackexchange.com/questions/22268#22279
DocMax 27/02/14

Isso não é válido '', é confundido com 0 e é um truque de javascript difícil de gerenciar. Tente '12 34 56 '
edc65 21/10

0

R 52

Esta função divide seqüências de caracteres por classe de caractere (isto não é regex! :)) classe é N - caracteres numéricos e P {N} significa negação dessa classe. o = T significa omitir substrings vazios.

x
## [1] "wNEKbS0q7hAXRVCF6I4S" "DpqW50YfaDMURB8micYd" "gwSuYstMGi8H7gDAoHJu"
require(stringi)
stri_split_charclass(x,"\\P{N}",o=T)
## [[1]]
## [1] "0" "7" "6" "4"

## [[2]]
## [1] "50" "8" 

## [[3]]
## [1] "8" "7"

0

PHP 99

<?php

$a = function($s) {
foreach(str_split($s)as$c)$b[]=is_numeric($c)?$c:".";return array_filter(explode('.',implode($b)));
};

var_dump($a("abc123def456"));
var_dump($a("aitew034snk582:3c"));
var_dump($a("as5493tax54\\430-52@g9.fc"));
var_dump($a("sasprs]tore\"re\\forz"));


Resultado

array(2) {
  [3]=>
  string(3) "123"
  [6]=>
  string(3) "456"
}
array(3) {
  [5]=>
  string(3) "034"
  [8]=>
  string(3) "582"
  [9]=>
  string(1) "3"
}
array(5) {
  [2]=>
  string(4) "5493"
  [5]=>
  string(2) "54"
  [6]=>
  string(3) "430"
  [7]=>
  string(2) "52"
  [9]=>
  string(1) "9"
}
array(0) {
}

0

JavaScript 88

88 caracteres quando não está contando a função n (x) {}

function n(x){
y=[],i=0,z=t=''
while(z=x[i++])t=!isNaN(z)?t+z:t&&y.push(t)?'':t
if(t)y.push(t)
return y
}
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.