Programma più breve per dividere una stringa a cifre non senza RegExps


16

EDIT: Se stai usando Lisp, ho dato alcune linee guida in fondo nel conteggio dei byte.

Obiettivo: creare la funzione più breve che divide una stringa in non cifre e restituisce un array composto da sole cifre in ciascuna stringa, senza l'uso di espressioni regolari. Gli zeri iniziali devono essere inclusi in ogni stringa.

Classifiche attuali (separate in categorie):

  • C / C ++ / C # / Java: 68 (C) ....
  • GolfScript / APL / J: 13 (APL)
  • Tutti gli altri: 17 (Bash, usi tr), 24 (Ruby)

Regole:

(Mi scuso per la lunghezza)

  1. Il formato deve essere una funzione con un singolo argomento stringa. È possibile aggiungere fino a due argomenti aggiuntivi, se necessario, per il corretto ritorno dell'array (es. Sh / csh / DOS Batch ha bisogno di un riferimento variabile aggiuntivo per restituire, ecc.).
  2. La dichiarazione della funzione primaria non conta, né importa altre librerie standard. `# include`s,` import`s e `using`s non contano. Tutto il resto lo fa. Ciò include `# define`s e funzioni di supporto. Dispiace per la confusione. Fare riferimento a questo come una guida utile per ciò che non conta / non conta (scritto nella sintassi in stile C)
    // non conta per il totale, può essere omesso a meno che
    // non ovvio, come metà della libreria standard di Java.
    #include <stdio.h>
    
    import some.builtin.Class // non conta, vedi sopra
    
    #define printf p // conta per il totale
    
    / * Ogni altra direttiva sul preprocessore, ecc. Conta. * /
    
    int i = 0; // conta
    
    someFunction (); // conta
    
    char [] [] myMainSplitFunction (char [] [] array) {// non conta
      // Tutto qui conta
      return returnArray; // Anche questo conta.
    } // non conta
    
    / * Tutto qui conta, inclusa la dichiarazione * /
    char [] [] someHelperFunction (char [] string) {
      // cose
    } // anche questo conta
    
  3. L'output deve essere un array di stringhe o simile (gli elenchi di array in Java e simili sono accettabili). Esempi di uscita accettato: String[], char[][], Array, List, e Array(oggetto).
  4. L'array deve contenere solo primitive di stringa a lunghezza variabile o oggetti stringa. Nel ritorno non devono essere presenti stringhe vuote, con l'eccezione di seguito. Nota: le stringhe devono contenere una stringa di corrispondenze consecutive, come ad esempio l'input e l'output di seguito.
  5. Se non ci sono corrispondenze, il corpo della funzione dovrebbe restituire nulluna matrice / lista vuota o una matrice / lista contenente una stringa vuota.
  6. Non sono consentite librerie esterne.
  7. Le terminazioni di riga DOS contano come un byte, non due (già trattate in meta, ma devono essere enfatizzate)
  8. E la regola più grande qui: non sono consentite espressioni regolari.

Questa è una domanda di , quindi vince la dimensione più piccola. In bocca al lupo!

E qui ci sono alcuni esempi di input e output (con escape in stile C):

Input: "abc123def456"
Uscita: ["123", "456"]

Input: "aitew034snk582: 3c"
Uscita: ["034", "582", "3"]

Input: "as5493tax54 \\ 430-52@g9.fc"
Uscita: ["5493", "54", "430", "52", "9"]

Input: "sasprs] tore \" re \\ forz "
Output: null, [], [""] o simile

Inserisci quanti byte sono utilizzati dalle tue risposte e, come sempre, buon golf!


Linee guida per Lisp

Ecco cosa conta e non conta nei dialetti Lisp:

;;; opzione 1

(defun extract-string (ab); non conta
  (cose) ;;; Tutto qui conta
); Non conta

;;; opzione 2

(defun extract-string (string & aux (inizio 0) (fine 0)); non conta
  (cose) ;;; Tutto qui conta
); Non conta.
Tutti gli altri lambda vengono conteggiati per il conteggio dei byte.


Non è stato chiesto prima?
Ismael Miguel,

1
Sì, ma l'ho chiesto nuovamente su Meta e gli ho apportato modifiche sostanziali prima di pubblicarlo di nuovo qui. Per questo motivo, non dovrebbe essere classificato come duplicato (l'altro correlato dovrebbe essere chiuso se non già).
Isiah Meadows,

2
Il tuo "golf" non dovrebbe essere pubblicato come risposta?
MrWhite,

4
Siamo spiacenti, ma -1 per non consentire GolfScript. Tutte le lingue dovrebbero essere consentite.
Maniglia della porta

1
@Doorknob È vero, ma capisco anche i sentimenti dell'OP. Le persone dovrebbero avere la possibilità di competere anche se non parlano GolfScript, J o APL (e sono colpevole di esaminare quest'ultima in queste competizioni.) Puoi dare un'occhiata alla mia proposta nel thread che ha collegato?
Tobia,

Risposte:


10

APL, 13 caratteri

(o 28/30 byte, leggi sotto)

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

Vedo che hai escluso GolfScript dalla tua domanda. Capisco il tuo sentimento, ma spero che questa comunità alla fine non bandirà APL, perché è un linguaggio di programmazione davvero notevole con una lunga storia, per non parlare del divertimento nel codificare. Forse potrebbe essere assegnato un punteggio diverso, se le persone sento che fa concorrenza ingiustamente. Pubblicherò i miei pensieri su questo argomento nel thread che hai collegato.

Per lo stesso motivo, ho sempre aggiunto una nota a piè di pagina ai miei post APL, sostenendo che APL poteva essere valutato come 1 carattere = 1 byte. La mia affermazione si basa sul fatto che alcune implementazioni (principalmente commerciali) di APL supportano ancora la loro codifica a byte singolo legacy, con i simboli APL associati ai valori superiori di 128 byte. Ma forse questo è troppo lungo, nel qual caso potresti voler segnare questa voce come 28 byte in UTF-16 o 30 byte in UTF-8.

Spiegazione

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

Esempi

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

Il formato di output predefinito per una matrice di stringhe non chiarisce quante stringhe ci siano nella matrice, né quanti spazi vuoti. Ma una rapida manipolazione per aggiungere le virgolette dovrebbe chiarire abbastanza:

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

Per quanto riguarda il tuo commento, penso che per altre lingue competere equamente con quelle "stenografiche" si dovrebbe considerare ogni simbolo nelle altre lingue come un carattere. Ad esempio, la mia soluzione Mathematica pubblicata qui dovrebbe essere conteggiata come 7 (più o meno). Progettare una lingua con token compressi non è affatto merito, credo.
Dr. belisarius,

Potresti fornire una discarica esadecimale del tuo golf? Non riesco a leggere alcuni dei personaggi.
Isiah Meadows,

@impinball Come ti aiuterebbe hexdump? Non è che vedresti cosa si sta facendo.
mniip,

@impinball il codice APL è {omega racchiudi il formato omega epsilon epsilon ogni iota 10}. Se hai bisogno dei valori unicode puoi semplicemente copiarli e incollarli su qualsiasi strumento online , anche se non riesci a vedere i caratteri (il che è strano, poiché la maggior parte dei moderni caratteri Unicode hanno i simboli APL) In ogni caso quello che ottieni è questo {\ u2375 \ u2282 \ u2368 \ u2375 \ u220a \ u220a \ u2355 \ u00a8 \ u237310} (attenzione agli ultimi "10" che non fanno parte della sequenza di escape)
Tobia,

1
Invece di ∊⍕¨⍳10, non potresti semplicemente usare ⎕D? Questa dovrebbe essere la costante '0123456789'. Dyalog APL lo supporta almeno, così come NARS2000.
Marin l'

5

Python 47

Implementazione

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

dimostrazione

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

Converti ogni carattere non cifra nello spazio e quindi dividi la stringa risultante. Un approccio semplice e chiaro.

E una soluzione divertente con itertools (71 caratteri)

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

4

Ruby, 70 anni

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

Versione online per il test

Dal momento che la conversione di qualsiasi carattere non numerico in un int restituisce 0 in Ruby (con to_i), la conversione di ogni carattere in int e di nuovo in carattere è il modo non regex di verificare una cifra ...


Puoi anche fare un membro ('0' .. '9'). per ogni personaggio, ma quello che hai fatto è già più breve
fgp

Hai assolutamente ragione - avrei dovuto dire: "un" modo;)
David Herrmann,

4

bash, 26 (contenuto della funzione: 22 + overhead di assegnazione di array 4)

Questo non batterà l'altra bashrisposta , ma è interessante perché potrebbe farti prendere due volte:

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

L'uso è:

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

A prima vista, //+([!0-9])/assomiglia molto a una sostituzione regexp, ma non lo è. È un'espansione dei parametri bash , che segue le regole di corrispondenza dei modelli , anziché le regole delle espressioni regolari.

Restituire veri tipi di array bash dalle funzioni bash è una seccatura, quindi ho scelto di restituire un elenco delimitato da spazi, quindi di convertirli in un array in un'assegnazione di array al di fuori della chiamata di funzione. Quindi, nell'interesse dell'equità, ritengo che la (` `)chiamata in funzione dovrebbe essere inclusa nel mio punteggio.


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"}, 
 {}
}

L'equivalente con regex è molto più lungo !:

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

Mathematica fa schifo a regex.
CalculatorFeline

3

Bash, 21 byte 17/21 byte (migliorato da DigitalTrauma )

Costruire un elenco separato da spazi con tr

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

sostituisce qualsiasi non cifra con uno spazio

uso

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

modificare

come indicato dai commenti seguenti, il codice può essere ridotto a 17 byte:

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

e poiché il risultato non sta parlando rigorosamente di un array Bash, l'uso dovrebbe essere

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

e l'extra (``)dovrebbe essere contato


1
Gah mi hai battuto! Ma perché non usare una stringa qui invece di un documento qui? Inoltre è possibile salvare una nuova riga alla fine del contenuto funzione si usa (blah)al posto di {blah;}: split()(tr -c 0-9 \ <<<$1). In questo modo il corpo della tua funzione ha solo 17 caratteri.
Trauma digitale

1
La funzione restituisce un "elenco separato da spazi" anziché un array. Certamente restituendo vero array dalla funzione di bash è imbarazzante, ma si potrebbe almeno assegnare il risultato della funzione ad un array in vostro uso: a=($(split "12 3a bc123")); echo ${a[@]}. Si potrebbe sostenere che "($ ())" sia conteggiato nel tuo punteggio
Trauma digitale

Prima di esplorare l' trapproccio, ho provato a farlo con un'espansione dei parametri . trè sicuramente l'approccio migliore ai fini del golf.
Trauma digitale

Hai provato a circondare l' troperatore di espansione? Verrebbe fuori qualcosa del genere ($(tr...)), e dove la dichiarazione di funzione non conta, le parentesi esterne non contano contro di te. Sarebbe solo la parte di sostituzione del comando.
Isiah Meadows,

Non vedo come dovrebbe funzionare, ma non sono fluente negli array Bash. Comunque, il (``)costrutto è 1 carattere migliore del($()) quello e deve essere preferito.
Coaumdio,

2

Smalltalk (Smalltalk / X), 81

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

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

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

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

valore f: 'sasprs] tore \ "re \ forz' -> OrderedCollection ()

sigh - Smalltalk ha la tendenza a usare nomi lunghi di funzioni veeeery ...


2
È un nome di funzione? o__O
Tobia,

@tobia Apparentemente ...
Isiah Meadows il

asCollectionOfSubCollectionsSeparatedByAnyForWhichಠ_ಠ Questo nome è troppo lungo
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])]
}

La funzione accetta una stringa e restituisce un elenco di stringhe.

Esempi:

> 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è il nome dell'elemento elenco.


1

Perl, 53

Modificare: in assenza di corrispondenze, il sub ora restituisce l'elenco con stringa vuota (anziché elenco vuoto) come richiesto.

Evita anche la divisione su un singolo carattere di spazio, in quanto attiva il comportamento di "divisione su qualsiasi spazio vuoto " , che probabilmente viola le regole. Potrei usare / /delimitatore, che si dividerebbe su un singolo spazio, ma paradossalmente sembrerebbe usare il modello regexp. Potrei usarlo unpackal costo di alcuni personaggi extra e quindi liberarmi del splittutto dalle polemiche, ma penso che, con ciò che finisco, dividere un personaggio letterale (diverso dallo spazio) sia OK.

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

E, no, l'operatore di traslitterazione di Perl non fa espressioni regolari. Posso srotolare l'intervallo 0-9 a 0123456789se questo è il problema.


Finché non usa espressioni regolari, è valido.
Isiah Meadows,

Il mio Perl non è così forte. Se capisco il codice, stai sostituendo le non-cifre con una specifica non-cifra, quindi suddividendole sulla non-cifra scelta, quindi filtrando le stringhe vuote. È una lettura corretta?
Tim Seguine,

1
@TimSeguine: non esattamente. Le non cifre vengono sostituite e schiacciate in un singolo carattere, dividendosi sulla quale si produce una stringa vuota se il delimitatore si trova all'inizio. Viene quindi spostato se l'elenco contiene altre voci.
user2846289

L'elenco Enpty va bene.
Isiah Meadows,

1

C, 68 byte (solo il corpo della funzione)

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

Il primo argomento è la stringa di input, il secondo è l'array di output, che è un array di stringhe con terminazione NULL. aPrima di chiamare la funzione è necessario riservare memoria sufficiente (caso peggiore:) sizeof(char*)*((strlen(s)+1)/2).

La stringa di input viene modificata dalla funzione (ogni carattere non cifra viene sostituito da '\0')

Esempio di utilizzo

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

Produzione

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

Versione senza golf:

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 senza dichiarazione di funzione)

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

Sebbene non sia affatto competitivo, sono sorpreso che VBScript esca così breve su questo dato quanto sia prolisso (13 byte per i soli CR). Passa attraverso la stringa, sostituendo eventuali caratteri non numerici con spazi, quindi riduce tutto lo spazio bianco a spazi singoli e quindi utilizza un delimitatore di spazio per dividerlo.

Casi test

Input: "ab5c0x"
Output: 5,0

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

Le terminazioni di riga DOS contano come un carattere per quanto ho letto su meta.
Isiah Meadows,

Ti ho suggerito una modifica.
Isiah Meadows,

Il conteggio presuppone già la fine di una riga di byte in stile Linux. Ricevo 190 caratteri dal mio conteggio (appena verificato di nuovo).
Comintern,

Ok. Devo aver contato male.
Isiah Meadows,

1

Lisp comune (1 secondo la lettera; ≈173 secondo lo spirito)

Ecco una versione leggibile. Il conteggio dei byte è abbastanza alto a causa dei nomi lunghi in cose come digit-char-pe 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")
#()

Il concetto di "dichiarazione di funzione" è piuttosto vago. Ecco una versione che ha solo un byte (il carattere xnel corpo della funzione); tutto il resto è raggruppato nelle variabili ausiliarie dell'elenco lamba della funzione (parte della dichiarazione della funzione):

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

Il conteggio effettivo dei byte dipenderà dal numero di dichiarazioni ausiliarie che dovrebbero essere spostate nel corpo affinché questo sia ritenuto accettabile. Anche qualche ridenominazione di funzioni locali sarebbe di aiuto (ad es. Abbreviareposition-if poiché appare due volte, utilizzare variabili a lettera singola, ecc.).

Questo rendering del programma ha 220 caratteri:

(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 non altro, questo dovrebbe promuovere le variabili aux e Common Lisp .

Questo può essere scritto in modo più conciso loop, ovviamente:

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

Il loopmodulo, con spazio aggiuntivo rimosso, ha 173 caratteri:

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

Conterrei da inizio (resultalla parentesi finale per essere il corpo. La parte che definisce il nome e i parametri è la dichiarazione.
Isiah Meadows,

Si prega di fare riferimento alla regola 2 sulle mie regole modificate per vedere di cosa sto davvero parlando in una dichiarazione di funzione (fondamentalmente, dichiarare il nome della funzione, i parametri e, se sintatticamente richiesto, che è raro tra le lingue interpretate, il tipo restituito).
Isiah Meadows,

@impinball Sì, il conteggio "1" è una specie di scherzo, ma la parte importante qui è che qui result viene dichiarato un parametro; ha solo una forma di inizializzazione molto banale. È la stessa cosa, in linea di principio, di un argomento facoltativo con un valore predefinito calcolato da un'espressione complessa. (In casi più semplici, è facile immaginare qualcosa di simile char* substring( char *str, int begin, int end(0) )in qualche linguaggio con una sintassi di tipo C per specificare che endè facoltativo e che se non viene fornito, quindi il suo valore lo è 0. Sto solo mettendo in evidenza il fatto che alcuni di questi termini
Joshua Taylor,

@impinball non sono abbastanza concreti e il linguaggio è abbastanza agnostico da impedire alcuni conteggi di trollish byte. :)
Joshua Taylor,

La prima parte che non specifica i parametri è dove vorrei contare le statistiche (ad es. (defun fn (string &aux (start 0) (end 0)Non conterei, ma tutto ciò che rimane nella lambda lo farebbe).
Isiah Meadows,

0

JavaScript, 240 byte

E per quelli di voi che sono curiosi, ecco il mio probabilmente enorme golf:

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

Sopra in bella stampa:

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

Sopra nel normale codice descrittivo

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

Puoi accorciarlo tralasciando il callback a array_filter. Ciò rimuoverà automaticamente tutte le voci che si verificano falsequando vengono espresse in booleane.
Kelunik,

@kelunik che filtrerebbe anche gli 0
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("]");}

Dato che C non ha funzioni di stampa di array integrate, ho dovuto fare quel lavoro da solo, quindi mi scuso che ci sia una virgola finale in ogni output. Essenzialmente, quel codice fa leggere la stringa se non è una cifra, la sostituisce con '\ 0' e quindi eseguo semplicemente il ciclo attraverso il codice e stampo tutte le catene di cifre. (EOF = 0)

Ingresso: ab5c0x
Uscita: ["5", "0",]

Ingresso: z526ks4f.; 8] \ p
Uscita: ["526", "4", "8",]


Secondo le regole della domanda (regola 2), devi solo contare i caratteri nel corpo della funzione. Quindi la tua soluzione sarebbe effettivamente inferiore a 170 byte. Tuttavia, non sono sicuro che il conteggio includa prototipi variabili al di fuori del corpo della funzione.
GroveNL

Modificherò le regole su questo: #defines, le dichiarazioni variabili, ecc. Conteranno, ma la dichiarazione di funzione no.
Isiah Meadows,

Inoltre, l'ultima volta che ho controllato, c'era un tipo in C notata come char[][]legale. Se ritorni come quello (o char**), starai bene.
Isiah Meadows,

Non deve essere un output di testo? Pensavo che il programma avrebbe dovuto produrre l'array in un formato stringa
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);
}

Innanzitutto, utilizza il .Select()metodo di estensione LINQ per trasformare tutte le non cifre in virgole. string.Replace()sarebbe preferibile, poiché restituisce un stringanziché un IEnumerable<char>, ma string.Replace()può prendere solo un singolo carattere o stringa e non può fare uso di un predicato come char.IsDigit()o47<c&c<58 .

Come accennato, .Select()applicato a una stringa restituisce un IEnumerable<char>, quindi è necessario trasformarlo nuovamente in una stringa trasformandolo in un array e passando l'array nelstring costruttore.

Infine, abbiamo diviso la stringa tra virgole usando string.Split(). (StringSplitOptions)1è un modo più breve di dire StringSplitOptions.RemoveEmptyEntries, che si occuperà automaticamente di più virgole e virgole consecutive all'inizio / alla fine della stringa.


1
Invece di char.IsDigit(c), puoi usare'/'<c&&c<':'
grovesNL

1
Buon punto ... o, meglio ancora, 47<c&&c<58. (Francamente, sono sorpreso che funzioni con i numeri, ma a quanto pare funziona).
BenM,

1
E posso salvare un personaggio extra prezioso usando un singolo '&' invece di un doppio '&&'. In C #, questo è ancora logico AND quando entrambi gli operandi sono booleani - fa solo un bit bit AND quando sono numeri interi.
BenM,

Ben fatto. Non sapevo che fosse in grado di farlo.
GroveNL

Una variante leggermente più corta è quella di dividere lo spazio bianco anziché ,, quindi rimuovere manualmente gli oggetti vuotireturn new string(s.Select(c=>47<c&c<58?c:' ').ToArray()).Split().Where(a=>a!="").ToArray();
VisualMelon

0

JS / Nodo: 168 162 147 138 Chars

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

Versione abbellita:

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

This question only wants the array returned, so you can remove console.log(r) and some other things
Not that Charles

The function declaration doesn't count toward the score (reason is to help level the playing field)
Isiah Meadows

Ok. Adjusted the score as per @impinball's comment. (Actually there are two functions declared here. Char count includes the anonymous function)
palanik

It should. I updated the rules to help explain it better.
Isiah Meadows

Meanwhile, came up with something better...
palanik

0

Ruby, 24

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

Defines digits using negative space within the printable ascii range.


Function declaration doesn't count.
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;}

Descriptive Code:

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

This is pretty long code and I'm sure there will be a much shorter php version for this code golf. This is what I could come up with in php.


there are some improvements: you can replace array() with [], array_push($output[$count], $arr[$i]); with $output[$count][]=$arr[$i];, and the ord() checks with is_numeric(). and you don't even need to split the string to iterate over its characters. also, only the inner code of the function counts, so as it is you char count is 204.
Einacio

The function declaration doesn't count. Refer to rule 2 as a guide on what counts and what doesn't.
Isiah Meadows

0

Python

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]

@Abhijit answer is far clever, this is just a "minified" version of what i had in mind.

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") == []

This yields no output, so the code is working, if ran one by one, as some variables are defined at the declaration.


You don't have to count the function declaration, if you did. Just as a heads up
Isiah Meadows

0

PHP 98 89

As in DigitalTrauma's bash answer, this doesn't use a 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;
}

Test cases:

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)

It splits the string on all non-numeric characters and removes the empty strings generated by consecutive delimiters.


0

VBA 210, 181 without function declaration

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

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

Ungolfed and wrapped in function declaration:

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

Example code in Rebol console:

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

Golfed:

Edit: When the loops walks off the end of the array, c is undefined, which is falsy and terminates the loop.

2/27: Using ?: saves the wordiness of 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
}

The carriage return in the body is for readability and is not part of the solution.

Ungolfed:

The idea is to append each character to the last entry in the array if it is a digit and to ensure the last array entry is a string otherwise.

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

Sample input/output

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


1
I like it! Much simpler than my own. You can drop another 8 characters by replacing if(+a[i]+1)b+=a[i];else if(b)c.push(b),b="" with b=+a[i]+1?b+a[i]:b?(c.push(b),""):b.
DocMax

@DocMax thx, I edited to include your suggestion :). That (c.push(b),"") seemed clever, never seen that.
Danny

I had forgotten about it until I saw it used extensively earlier today in codegolf.stackexchange.com/questions/22268#22279
DocMax

That's not valid, ' ' is mistaken for 0 and it's a javascript quirk difficult to manage. Try '12 34 56'
edc65

0

R 52

This function splits strings by character class (this is not regex! :)) class is N - numeric characters and P{N} means negation of this class. o=T means omit empty substrings.

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


Output

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 chars when not counting function 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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.