Kürzestes Programm zum Aufteilen eines Strings bei Nicht-Ziffern ohne RegExps

16

BEARBEITEN: Wenn Sie Lisp verwenden, habe ich unten einige Richtlinien zum Zählen von Bytes angegeben.

Ziel: Erstellen Sie die kürzeste Funktion, die eine Zeichenfolge in nicht-Ziffern aufteilt und ein Array zurückgibt, das nur aus Ziffern in jeder Zeichenfolge besteht, ohne reguläre Ausdrücke zu verwenden. Führende Nullen sind in jede Zeichenfolge aufzunehmen.

Aktueller Stand (unterteilt in Kategorien):

  • C / C ++ / C # / Java: 68 (C) ....
  • GolfScript / APL / J: 13 (APL)
  • Alle anderen: 17 (Bash, benutzttr ), 24 (Ruby)

Regeln:

(Ich entschuldige mich für die Langeweile)

  1. Das Format muss eine Funktion mit einem einzelnen Zeichenfolgenargument sein. Bei Bedarf können bis zu zwei zusätzliche Argumente für die ordnungsgemäße Rückgabe des Arrays hinzugefügt werden (z. B. benötigt sh / csh / DOS Batch eine zusätzliche Variablenreferenz für die Rückgabe usw.).
  2. Die Deklaration der primären Funktion zählt nicht und andere Standardbibliotheken werden auch nicht importiert. `# include`s,` import`s und `using`s zählen nicht. Alles andere macht. Dies beinhaltet `# define`s und Hilfsfunktionen. Entschuldigung für die Verwirrung. Hier finden Sie eine hilfreiche Anleitung, was zählt / nicht zählt (in C-Syntax geschrieben).
    // zählt nicht zur Gesamtsumme, kann weggelassen werden, es sei denn
    // nicht offensichtlich, wie die Hälfte von Javas Standardbibliothek.
    #include <stdio.h>
    
    import some.builtin.Class // zählt nicht, siehe oben
    
    #define printf p // zählt zur Gesamtsumme
    
    / * Alle anderen Präprozessoranweisungen usw. zählen. * /
    
    int i = 0; // zählt
    
    someFunction (); // zählt
    
    char [] [] myMainSplitFunction (char [] [] Array) {// zählt nicht
      // Hier zählt alles
      return returnArray; // Auch das zählt.
    } // zählt nicht
    
    / * Alles hier zählt, einschließlich der Erklärung * /
    char [] [] someHelperFunction (char [] string) {
      // Zeug
    } // auch das zählt
    
  3. Die Ausgabe muss ein String-Array oder ähnliches sein (Array-Listen in Java und ähnlich sind akzeptabel). Beispiele für akzeptierten Ausgang: String[], char[][], Array, List, und Array(Objekt).
  4. Das Array darf nur String-Primitive oder String-Objekte variabler Länge enthalten. In der Rückgabe sollten keine leeren Zeichenfolgen vorhanden sein, mit Ausnahme der folgenden. Hinweis: Die Zeichenfolgen müssen eine Folge aufeinanderfolgender Übereinstimmungen enthalten, z. B. die folgende Beispieleingabe und -ausgabe.
  5. Wenn es keine Übereinstimmungen gibt, sollte der Funktionskörper nullein leeres Array / eine leere Liste oder ein Array / eine Liste mit einer leeren Zeichenfolge zurückgeben.
  6. Keine externen Bibliotheken erlaubt.
  7. DOS-Zeilenenden zählen als ein Byte, nicht als zwei (bereits in Meta behandelt, muss aber hervorgehoben werden)
  8. Und die größte Regel hier: keine regulären Ausdrücke erlaubt.

Dies ist eine Frage, also gewinnt die kleinste Größe. Viel Glück!

Und hier sind einige Beispiele für Ein- und Ausgänge (mit C-Stil-Escapezeichen):

Eingabe: "abc123def456"
Ausgabe: ["123", "456"]

Eingabe: "aitew034snk582: 3c"
Ausgabe: [034, 582, 3]

Eingabe: "as5493tax54 \\ [email protected]"
Ausgabe: [5493, 54, 430, 52, 9]

Eingabe: "sasprs] riss \" re \\ forz "
Ausgabe: null, [], [""] oder ähnlich

Bitte geben Sie an, wie viele Bytes Ihre Antworten benötigen und wie immer viel Spaß beim Golfen!


Richtlinien für Lisp

In Lisp-Dialekten zählt Folgendes:

;;; Option 1

(defun extract-strings (ab); Zählt nicht
  (Zeug) ;;; Hier zählt alles
); Zählt nicht

;;; Option 2

(defun extract-strings (string & aux (start 0) (end 0)); Zählt nicht
  (Zeug) ;;; Hier zählt alles
); Zählt nicht.
Alle anderen Lambdas zählen vollständig zur Byteanzahl.

Isiah Meadows
quelle
Wurde das nicht schon einmal gefragt?
Ismael Miguel
1
Ja, aber ich habe es erneut bei Meta angefragt und umfangreiche Änderungen vorgenommen, bevor ich es erneut hier poste. Aus diesem Grund sollte es nicht als Duplikat klassifiziert werden (das andere verwandte sollte geschlossen werden, falls nicht bereits geschehen).
Isiah Meadows
2
Sollte Ihr "Golf" nicht als Antwort gepostet werden?
MrWhite
4
Entschuldigung, aber -1 für das Nichtzulassen von GolfScript. Alle Sprachen sollten erlaubt sein.
Türklinke
1
@Doorknob Das stimmt, aber ich verstehe auch die Gefühle des OP. Die Leute sollten die Chance haben, sich zu messen, auch wenn sie kein GolfScript, J oder APL sprechen (und ich bin schuld daran, das letztere in diesen Wettbewerben zu lesen.) Können Sie sich meinen Vorschlag in dem von ihm verlinkten Thread ansehen ?
Tobia

Antworten:

10

APL, 13 Zeichen

(oder 28/30 Bytes, lesen Sie unten)

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

Ich sehe, Sie haben GolfScript von Ihrer Frage ausgeschlossen. Ich verstehe Ihr Gefühl, aber ich hoffe, dass diese Community APL nicht verbannen wird, denn es ist eine wirklich bemerkenswerte Programmiersprache mit einer langen Geschichte, ganz zu schweigen von viel Spaß beim Programmieren. Vielleicht könnte es einfach anders bewertet werden, wenn die Leute fühle es ist unfair im Wettbewerb. Ich werde meine Gedanken zu diesem Thema in dem von Ihnen verlinkten Thread veröffentlichen.

Aus dem gleichen Grund habe ich meinen APL-Posts immer eine Fußnote hinzugefügt, in der behauptet wird, dass APL mit 1 Zeichen = 1 Byte bewertet werden könnte. Meine Behauptung beruht auf der Tatsache, dass einige (meist kommerzielle) APL-Implementierungen immer noch ihre eigene ältere Einzelbyte-Codierung unterstützen, wobei die APL-Symbole den oberen 128-Byte-Werten zugeordnet sind. Aber vielleicht ist das zu viel. In diesem Fall möchten Sie diesen Eintrag mit 28 Bytes in UTF-16 oder 30 Bytes in UTF-8 bewerten.

Erläuterung

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

Beispiele

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

Das Standardausgabeformat für ein Array von Zeichenfolgen macht weder deutlich, wie viele Zeichenfolgen sich im Array befinden, noch wie viele Leerzeichen. Eine schnelle Manipulation zum Hinzufügen von Anführungszeichen sollte jedoch klar genug sein:

      {q,⍵,q←'"'}¨ {⍵⊂⍨⍵∊∊⍕¨⍳10} 'ab5c0x'
 "5"  "0" 
      {q,⍵,q←'"'}¨ {⍵⊂⍨⍵∊∊⍕¨⍳10}  'z526ks4f.;8]\p'
 "526"  "4"  "8" 
Tobia
quelle
In Bezug auf Ihren Kommentar denke ich, dass für andere Sprachen, die in einem fairen Wettbewerb mit "Kurzschreibern" stehen, jedes Symbol in den anderen Sprachen als ein Zeichen gezählt werden sollte. Beispielsweise sollte meine hier veröffentlichte Mathematica-Lösung mit 7 (mehr oder weniger) gezählt werden. Das Entwerfen einer Sprache mit komprimierten Token ist meiner Meinung nach überhaupt nicht sinnvoll.
Dr. Belisarius
Könnten Sie einen Hex-Dump Ihres Golfs zur Verfügung stellen? Ich kann einige der Zeichen nicht lesen.
Isiah Meadows
@impinball Wie würde dir der Hexdump helfen? Es ist nicht so, dass du sehen würdest, was getan wird.
24.
@impinball Der APL-Code lautet {omega include commute omega epsilon epsilon format each iota 10}. Wenn Sie die Unicode-Werte benötigen, können Sie sie einfach kopieren und in ein beliebiges Online-Tool einfügen , auch wenn Sie die Zeichen nicht sehen können (was seltsam ist, da die meisten modernen Unicode-Schriftarten die APL-Symbole haben) {2375 \ 2282 \ 2375 \ 220a \ 220a \ 2355 \ 00a8 \ 237310} (beachten Sie die letzten "10", die nicht Teil der Escape-Sequenz ist)
Tobia
1
Könnten ∊⍕¨⍳10Sie nicht einfach verwenden ⎕D? Das sollte die Konstante sein '0123456789'. Zumindest Dyalog APL und NARS2000 unterstützen dies.
Marinus
5

Python 47

Implementierung

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

Demo

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

Algorithmus

Konvertieren Sie jedes nicht-stellige Zeichen in ein Leerzeichen und teilen Sie die resultierende Zeichenfolge. Ein einfacher und klarer Ansatz.

Und eine unterhaltsame Lösung mit itertools (71 Zeichen)

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

Rubin, 70

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

Online Version zum Testen

Da die Konvertierung eines nicht-stelligen Zeichens in ein int in Ruby (mit to_i) 0 ergibt, ist die Konvertierung jedes Zeichens in int und zurück in char die nicht-reguläre Methode, um nach einer Ziffer zu suchen ...

David Herrmann
quelle
Sie können auch ein ('0' .. '9'). Mitglied machen? für jeden char, aber was du getan hast, ist schon kürzer
fgp
Sie haben definitiv Recht - ich hätte sagen sollen: "ein" Weg;)
David Herrmann
4

Bash, 26 (Funktionsinhalt: 22 + Arrayzuweisungs-Overhead 4)

Dies wird die andere bashAntwort nicht schlagen , aber es ist interessant, weil es Sie dazu bringen könnte, doppelt zu nehmen:

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

Verwendung ist:

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

//+([!0-9])/Sieht auf den ersten Blick wie eine reguläre Ersetzung aus, ist es aber nicht. Es handelt sich um eine Bash-Parameter-Erweiterung , die Mustervergleichsregeln anstelle von Regeln für reguläre Ausdrücke folgt .

Die Rückgabe echter Bash-Array-Typen aus Bash-Funktionen ist mühsam. Daher habe ich mich dafür entschieden, stattdessen eine durch Leerzeichen getrennte Liste zurückzugeben und dann in ein Array in einer Array-Zuweisung außerhalb des Funktionsaufrufs zu konvertieren. Aus Gründen der Fairness (` `)sollte der Funktionsaufruf in meiner Punktzahl enthalten sein.

Digitales Trauma
quelle
3

Mathematica 32

StringCases[#,DigitCharacter..]&

Verwendung

inps ={"abc123def456", "aitew034snk582:3c", "as5493tax54\\[email protected]", 
        "sasprs]tore\"re\\forz"}  
StringCases[#,DigitCharacter..]&/@inps

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

Das Äquivalent mit regulären Ausdrücken ist viel länger !:

StringCases[#, RegularExpression["[0-9]+"]] &
Dr. belisarius
quelle
Mathematica saugt an Regex.
CalculatorFeline
3

Bash, 21 Bytes 17/21 Bytes (verbessert durch DigitalTrauma )

Erstellen einer durch Leerzeichen getrennten Liste mit tr

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

Ersetzt eine beliebige Ziffer durch ein Leerzeichen

Verwendung

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

Bearbeiten

Wie in den Kommentaren unten gezeigt, kann der Code auf 17 Byte reduziert werden:

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

und da das Ergebnis nicht unbedingt ein Bash-Array ist, sollte die Verwendung so sein

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

und das extra (``)sollte gezählt werden

Coaumdio
quelle
1
Gah du hast mich geschlagen! Aber warum nicht einen Here-String anstelle eines Here-Dokuments verwenden? Sie können auch eine neue Zeile am Ende der Funktion Inhalte speichern Sie verwenden (blah)statt {blah;}: split()(tr -c 0-9 \ <<<$1). Auf diese Weise beträgt Ihr Funktionskörper nur 17 Zeichen.
Digital Trauma
1
Ihre Funktion gibt eine "durch Leerzeichen getrennte Liste" anstelle eines Arrays zurück. Sicherlich gibt true zurück , Arrays von bash Funktion umständlich ist, aber man könnte zumindest weisen Sie das Ergebnis Ihrer Funktion auf ein Array in der Nutzung: a=($(split "12 3a bc123")); echo ${a[@]}. Es könnte argumentiert werden, dass "($ ())" in Ihrer Punktzahl gezählt wird
Digital Trauma
Bevor ich den trAnsatz untersuchte, versuchte ich dies mit einer Parametererweiterung . trist definitiv der bessere Ansatz zum Golfen.
Digital Trauma
Haben Sie versucht, die Umgebung tr mit dem Expansionsoperator zu umgehen? Es würde zu etwas kommen ($(tr...)), und wo die Funktionsdeklaration nicht zählt, würden die äußeren Klammern nicht gegen Sie zählen. Es wäre nur der Befehlsersetzungsteil.
Isiah Meadows
Ich verstehe nicht, wie das funktionieren soll, aber ich spreche keine Bash-Arrays. Auf jeden Fall ist das (``)Konstrukt 1-Zeichen besser als das ($())eine und wird bevorzugt.
Coaumdio
2

Smalltalk (Smalltalk / X), 81

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

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

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

f-Wert: 'as5493tax54 \ [email protected]' -> OrderedCollection ('5493' '54' '430' '52' '9')

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

seufz - Smalltalk neigt dazu, sehr lange Funktionsnamen zu verwenden ...

blabla999
quelle
2
Ist das ein Funktionsname? o__O
Tobia
@ Tobia Anscheinend ...
Isiah Meadows
asCollectionOfSubCollectionsSeparatedByAnyForWhichಠ_ಠ Dieser Name ist zu lang
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])]
}

Die Funktion akzeptiert eine Zeichenfolge und gibt eine Liste von Zeichenfolgen zurück.

Beispiele:

> 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\\[email protected]")
$`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

Hinweis: $xist der Name des Listenelements.

Sven Hohenstein
quelle
1

Perl, 53

Bearbeiten: keine Übereinstimmungen gefunden wurden, gibt sub nun eine Liste mit einer leeren Zeichenfolge (anstelle einer leeren Liste) nach Bedarf zurück.

Es vermeidet auch Splitting auf einzelnes Leerzeichen, als es löst ‚Split auf jeden white-space‘ Verhalten, das wahrscheinlich die Regeln verstößt. Ich könnte ein / /Trennzeichen verwenden, das sich auf ein einzelnes Leerzeichen aufteilt , aber paradoxerweise sieht es so aus, als würde man ein reguläres Ausdrucksmuster verwenden. Ich könnte unpackauf Kosten einiger zusätzlicher Zeichen die splitKontroversen beseitigen, aber ich denke, dass es in Ordnung ist, ein wörtliches Zeichen (außer Leerzeichen) aufzuteilen.

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

Und nein, Perls Transliterationsoperator führt keine regulären Ausdrücke aus. Ich kann den Bereich von 0 bis 9 abrollen0123456789 wenn das das Problem ist.

user2846289
quelle
Solange es keine regulären Ausdrücke verwendet, ist es gültig.
Isiah Meadows
Mein Perl ist nicht so stark. Wenn ich den Code verstehe, ersetzen Sie Nicht-Ziffern durch eine bestimmte Nicht-Ziffer, teilen die ausgewählte Nicht-Ziffer auf und filtern dann leere Zeichenfolgen heraus. Ist das eine richtige Lesart?
Tim Seguine
1
@ TimSeguine: Nicht genau. Nicht-Ziffern werden ersetzt und zu einem einzelnen Zeichen zusammengefasst, wodurch eine leere Zeichenfolge entsteht, wenn sich das Trennzeichen zufällig am Anfang befindet. Es wird dann weggeschoben, wenn die Liste andere Einträge enthält.
user2846289
Leere Liste ist in Ordnung.
Isiah Meadows
1

C, 68 Bytes (nur der Körper der Funktion)

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

Das erste Argument ist die Eingabezeichenfolge, das zweite ist das Ausgabearray, bei dem es sich um ein NULL-terminiertes Zeichenfolgenarray handelt. aVor dem Aufruf der Funktion muss ausreichend Speicherplatz reserviert werden (worst case:) sizeof(char*)*((strlen(s)+1)/2).

Die Eingabezeichenfolge wird von der Funktion geändert (jedes nicht-stellige Zeichen wird durch ersetzt '\0').

Anwendungsbeispiel

#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\\[email protected]";
    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;
}

Ausgabe

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

Ungolf-Version:

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
} 
Coaumdio
quelle
1

VBScript, 190 (164 ohne Funktionsdeklaration)

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

Ich bin zwar überhaupt nicht wettbewerbsfähig, aber ich bin überrascht, dass VBScript diesbezüglich so kurz herauskommt, da es so ausführlich ist (13 Byte für die CRs allein). Es durchläuft die Zeichenfolge, ersetzt alle nicht numerischen Zeichen durch Leerzeichen, reduziert dann das gesamte Leerzeichen auf einzelne Leerzeichen und teilt es dann mit einem Leerzeichenbegrenzer auf.

Testfälle

Input: "ab5c0x"
Output: 5,0

Input: "z526ks4f.;8]\p"
Output: 526,4,8
Komintern
quelle
DOS-Zeilenenden zählen als ein Zeichen, soweit ich Meta gelesen habe.
Isiah Meadows
Ich habe eine Bearbeitung für Sie vorgeschlagen.
Isiah Meadows
Die Anzahl setzt bereits 1-Byte-Zeilenenden im Linux-Stil voraus. Ich bekomme 190 Zeichen durch meine Zählung (gerade noch einmal überprüft).
Comintern
In Ordnung. Ich muss falsch gezählt haben.
Isiah Meadows
1

Common Lisp (1 nach dem Buchstaben; ≈173 nach dem Geist)

Hier ist eine lesbare Version. Die Byte - Zählung ist ziemlich hoch , weil der langen Namen in Dingen wie digit-char-pund position-ifund 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\\[email protected]")
#("5493" "54" "430" "52" "9")

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

Das Konzept der "Funktionsdeklaration" ist irgendwie vage. Hier ist eine Version, die nur ein Byte (das Zeichen) enthältx im Funktionskörper). alles andere ist in den Hilfsvariablen der Lamba-Liste der Funktion (Teil der Funktionsdeklaration) gebündelt:

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

Die tatsächliche Anzahl der Bytes hängt davon ab, wie viele Hilfsdeklarationen in den Body verschoben werden müssten, damit dies als akzeptabel angesehen wird. Einige lokale Umbenennungen von Funktionen würden ebenfalls helfen (z. B. Verkürzenposition-if da sie zweimal vorkommen, Verwenden von Variablen mit einem Buchstaben usw.).

Dieses Rendering des Programms hat 220 Zeichen:

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

Wenn nichts anderes, sollte dies Common Lisps & aux-Variablen fördern .

Dies lässt sich loopnatürlich prägnanter formulieren mit :

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

Das loopFormular, in dem zusätzlicher Speicherplatz entfernt wurde, enthält 173 Zeichen:

(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))
Joshua Taylor
quelle
Ich würde von der ersten (resultbis zur letzten Klammer zählen, um der Körper zu sein. Der Teil, der den Namen und die Parameter definiert, ist die Deklaration.
Isiah Meadows
Beziehen Sie sich auf Regel 2 in meinen geänderten Regeln, um zu sehen, worüber ich in einer Funktionsdeklaration wirklich spreche (deklarieren Sie im Grunde den Funktionsnamen, die Parameter und, falls syntaktisch erforderlich, den Rückgabetyp, der in interpretierten Sprachen selten vorkommt).
Isiah Meadows
@impinball Ja, die „1“ count ist eine Art von Witz, aber der wichtige Teil ist hier, dass result wird als Parameter hier erklärt; Es hat nur eine sehr nicht triviale Initialisierungsform. Dies ist im Prinzip dasselbe wie ein optionales Argument mit einem Standardwert, der durch einen komplexen Ausdruck berechnet wird. (In einfacheren Fällen ist es leicht vorstellbar, dass char* substring( char *str, int begin, int end(0) )in einer Sprache mit einer C-ähnlichen Syntax angegeben wird, dass dies endoptional ist 0. Wenn dies nicht angegeben wird, lautet der Wert . Ich möchte nur die Tatsache hervorheben, dass einige dieser Begriffe
Joshua Taylor
@impinball ist nicht ganz konkret und sprachunabhängig genug, um einige trollische Byte-Zählungen zu verhindern. :)
Joshua Taylor
Der erste Teil, der keine Parameter spezifiziert, ist, wo ich stat zählen würde (z. B. (defun fn (string &aux (start 0) (end 0)würde nicht zählen, aber alles, was im Lambda verbleibt, würde zählen).
Isiah Meadows
0

JavaScript, 240 Byte

Und für diejenigen von euch, die neugierig sind, hier ist mein wahrscheinlich riesiges 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

Oben in hübscher Schrift:

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

Oben im normalen beschreibenden Code

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;
}
Isiah Meadows
quelle
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);});
}
Einacio
quelle
Sie können es verkürzen, indem Sie den Rückruf unter weglassen array_filter. Dadurch werden automatisch alle Einträge entfernt, die falsebei der Umwandlung in boolesche Werte vorhanden sind.
Kelunik
@kelunik das würde auch 0s herausfiltern
herausfiltern
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("]");}

Da in C keine Array-Druckfunktionen integriert sind, musste ich diese Arbeit selbst erledigen, daher entschuldige ich mich, dass in jeder Ausgabe ein Endkomma steht. Im Wesentlichen liest dieser Code die Zeichenfolge, wenn es sich nicht um eine Ziffer handelt, die durch '\ 0' ersetzt wird, und dann durchlaufe ich den Code und drucke alle Ziffernketten aus. (EOF = 0)

Eingabe: ab5c0x
Ausgabe: ["5", "0",]

Eingabe: z526ks4f.; 8] \ p
Ausgabe: ["526", "4", "8",]

ASKASK
quelle
Gemäß den Regeln der Frage (Regel 2) müssen Sie nur die Zeichen im Funktionskörper zählen. Ihre Lösung wäre also weniger als 170 Bytes. Ich bin mir jedoch nicht sicher, ob die Anzahl der variablen Prototypen außerhalb des Funktionskörpers liegt.
HainenNL
Ich werde die Regeln dazu ändern: #defines, Variablendeklarationen usw. zählen, die Funktionsdeklaration jedoch nicht.
Isiah Meadows
Als ich das letzte Mal nachgesehen habe, gab es einen Typ in C, der als char[][]legal notiert ist. Wenn Sie als das (oder char**) zurückkehren, wird es Ihnen gut gehen.
Isiah Meadows
Es muss keine Textausgabe sein? Ich
dachte,
0

C # 98

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

Zunächst wird die LINQ- .Select()Erweiterungsmethode verwendet, um alle Nicht-Ziffern in Kommas umzuwandeln. string.Replace()wäre vorzuziehen, da es stringeher ein als ein IEnumerable<char>, aber zurückgibtstring.Replace() nur ein einzelnes Zeichen oder eine Zeichenfolge annehmen und kein Prädikat wie verwenden kannchar.IsDigit() oder verwenden kann47<c&c<58 .

Wie bereits erwähnt, gibt die .Select()Anwendung auf eine Zeichenfolge ein zurückIEnumerable<char> Wir müssen sie also wieder in eine Zeichenfolge umwandeln, indem wir sie in ein Array umwandeln und das Array an die übergebenstring Konstruktor übergeben.

Zuletzt teilen wir die Zeichenkette mit Kommas auf string.Split(). (StringSplitOptions)1Dies ist eine kürzere Art zu sagen StringSplitOptions.RemoveEmptyEntries, die automatisch mehrere aufeinanderfolgende Kommas und Kommas am Anfang / Ende der Zeichenfolge berücksichtigt.

BenM
quelle
1
Stattdessen char.IsDigit(c)können Sie'/'<c&&c<':'
grovesNL
1
Guter Punkt ... oder noch besser 47<c&&c<58. (Ehrlich gesagt bin ich überrascht, dass es mit Zahlen funktioniert, aber anscheinend schon).
BenM
1
Und ich kann ein zusätzliches wertvolles Zeichen speichern, indem ich ein einfaches "&" anstelle eines doppelten "&" verwende. In C # ist dies immer noch ein logisches UND, wenn beide Operanden boolesche Werte sind. Es wird nur ein bitweises UND ausgeführt, wenn es sich um Ganzzahlen handelt.
BenM
Schön. Ich wusste nicht, dass es dazu in der Lage ist.
HainenNL
Eine etwas kürzere Variante besteht darin ,, den Leerraum zu return new string(s.Select(c=>47<c&c<58?c:' ').ToArray()).Split().Where(a=>a!="").ToArray();
teilen
0

JS / Node: 168 162 147 138 Zeichen

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

Verschönerte Version:

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;
}
palanik
quelle
Diese Frage möchte nur, dass das Array zurückgegeben wird, damit Sie console.log(r)einige andere Dinge entfernen können
nicht, dass Charles
Die Funktionsdeklaration zählt nicht für die Punktzahl (der Grund ist, das Spielfeld auszugleichen)
Isiah Meadows
In Ordnung. Die Punktzahl wurde gemäß dem Kommentar von @ impinball angepasst. (Tatsächlich sind hier zwei Funktionen deklariert. Die
Zeichenanzahl
Es sollte. Ich habe die Regeln aktualisiert, um sie besser zu erklären.
Isiah Meadows
In der Zwischenzeit habe
ich mir
0

Rubin, 24

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

Definiert Ziffern mit negativen Leerzeichen innerhalb des druckbaren ASCII-Bereichs.

Histokrat
quelle
Funktionsdeklaration zählt nicht.
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;}

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

Dies ist ein ziemlich langer Code und ich bin sicher, dass es eine viel kürzere PHP-Version für diesen Code Golf geben wird. Das könnte ich mir in PHP einfallen lassen.

palerdot
quelle
Es gibt einige Verbesserungen: Sie können array()mit [], array_push($output[$count], $arr[$i]);mit $output[$count][]=$arr[$i];und die ord()Schecks mit ersetzen is_numeric(). und Sie müssen nicht einmal die Zeichenfolge teilen, um über die Zeichen zu iterieren. Außerdem zählt nur der innere Code der Funktion, so dass Sie die
Zeichenanzahl
Die Funktionsdeklaration zählt nicht. In Regel 2 finden Sie eine Anleitung, was zählt und was nicht.
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
Ich habe StackExchange verlassen
quelle
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 Antwort ist weit schlau, dies ist nur eine "verkleinerte" Version von dem, was ich im Sinn hatte.

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

Dies liefert keine Ausgabe, daher funktioniert der Code, wenn er einzeln ausgeführt wird, da einige Variablen in der Deklaration definiert sind.

gcq
quelle
Sie müssen die Funktionsdeklaration nicht mitzählen, wenn Sie dies getan haben. Nur als Heads-Up
Isiah Meadows
0

PHP 98 89

Wie in der bash-Antwort von DigitalTrauma wird hier kein regulärer Ausdruck verwendet.

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

Testfälle:

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\\[email protected]")), "\n";
["5493","54","430","52","9"]
php > echo json_encode(f("sasprs]tore\"re\\forz")), "\n";
null
PleaseStand
quelle
0

Haskell 31

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

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

Die Zeichenfolge wird auf alle nicht numerischen Zeichen aufgeteilt, und die leeren Zeichenfolgen, die durch aufeinanderfolgende Trennzeichen generiert werden, werden entfernt.

lortabac
quelle
0

VBA 210, 181 ohne Funktionsdeklaration

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
Gaffi
quelle
0

Rebol (66 Zeichen)

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

Ungolfed und eingewickelt in Funktionserklärung:

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

Beispielcode in der Rebol-Konsole:

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

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

>> f "as5493tax54\\[email protected]"
== ["5493" "54" "430" "52" "9"]

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

JavaScript, 104 97 89

Golf gespielt:

Bearbeiten: Wenn die Schleifen das Ende des Arrays verlassen, cistundefined das falsch und beendet die Schleife.

27.02 .: Mit wird ?:die Wortgewandtheit von gespeichert 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
}

Der Wagenrücklauf im Gehäuse dient der Lesbarkeit und ist nicht Teil der Lösung.

Ungolfed:

Die Idee ist, jedes Zeichen an den letzten Eintrag im Array anzuhängen, wenn es eine Ziffer ist, und sicherzustellen, dass der letzte Array-Eintrag andernfalls eine Zeichenfolge ist.

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;
}
DocMax
quelle
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\\[email protected]"));
console.log(f("sasprs]tore\"re\\forz"));

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

JSFiddle

Danny
quelle
1
Ich mag das! Viel einfacher als meine. Sie können durch das Ersetzen weitere 8 Zeichen fallen if(+a[i]+1)b+=a[i];else if(b)c.push(b),b=""mit b=+a[i]+1?b+a[i]:b?(c.push(b),""):b.
DocMax
@ DocMax thx, ich bearbeitet, um Ihren Vorschlag aufzunehmen :). Das (c.push(b),"")schien klug, das habe ich nie gesehen.
Danny
Ich hatte es vergessen, bis ich sah, dass es heute in codegolf.stackexchange.com/questions/22268#22279
DocMax
Das ist nicht gültig, '' wird mit 0 verwechselt und es ist eine Javascript-Eigenheit, die schwer zu handhaben ist. Versuchen Sie '12 34 56 '
edc65
0

R 52

Diese Funktion teilt Strings nach Zeichenklassen auf (dies ist kein regulärer Ausdruck! :)). Die Klasse besteht aus N - numerischen Zeichen und P {N} bedeutet die Negation dieser Klasse. o = T bedeutet, dass leere Teilzeichenfolgen weggelassen werden.

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"
bartektartanus
quelle
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\\[email protected]"));
var_dump($a("sasprs]tore\"re\\forz"));


Ausgabe

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) {
}
Kelunik
quelle
0

JavaScript 88

88 Zeichen ohne Zählfunktion 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
}
Wolfhammer
quelle