RegExpsなしで数字以外で文字列を分割する最短プログラム


16

編集:あなたがLispを使用している場合、バイト数をカウントする際の下部にいくつかのガイドラインを示しました。

目的:正規表現を使用せずに、文字列を数字以外で分割し、各文字列の数字のみで構成される配列を返す最短の関数を作成します。先行ゼロは各文字列に含まれます。

現在の順位(カテゴリで区切られた):

  • C / C ++ / C#/ Java: 68(C)....
  • GolfScript / APL / J: 13(APL)
  • その他すべて: 17(Bash、使用tr)、24(Ruby)

ルール:

(長さをおaびします)

  1. 形式は、単一の文字列引数を持つ関数でなければなりません。配列を適切に返すために必要な場合は、最大2つの引数を追加できます(たとえば、sh / csh / DOS Batchは返すために追加の変数参照を必要とします)。
  2. 主要な関数宣言はカウントされず、他の標準ライブラリのインポートもカウントされません。「#include」、「import」、および「using」はカウントされません。他のすべてが行います。これには、 `#define`sとヘルパー関数が含まれます。混乱させて申し訳ありません。カウント/カウントしないもの(Cスタイルの構文で記述されている)についての有用なガイドとしてこれを参照してください。
    //合計にはカウントされません。ただし、
    // Javaの標準ライブラリの半分のように、非自明。
    #include <stdio.h>
    
    import some.builtin.Class //カウントされません、上記を参照
    
    #define printf p //合計にカウント
    
    / *その他のプリプロセッサディレクティブなどがカウントされます。* /
    
    int i = 0; //カウント
    
    someFunction(); //カウント
    
    char [] [] myMainSplitFunction(char [] [] array){//カウントしません
      //ここにあるすべてがカウントされます
      return returnArray; //これも重要です。
    } //カウントしない
    
    / *宣言を含むここのすべてがカウントされます* /
    char [] [] someHelperFunction(char [] string){
      //もの
    } //これもカウント
    
  3. 出力は、文字列配列または類似のものである必要があります(Javaなどの配列リストも使用できます)。受け入れられた出力の例:String[]char[][]ArrayList、およびArray(オブジェクト)。
  4. 配列には、可変長の文字列プリミティブまたは文字列オブジェクトのみが含まれている必要があります。以下の例外を除き、戻り値に空の文字列が存在しないようにする必要があります。注:文字列には、以下の入力および出力の例のように、連続した一致の文字列が含まれます。
  5. 一致するものがない場合、関数本体はnull、空の配列/リスト、または空の文字列を含む配列/リストを返します。
  6. 外部ライブラリは許可されていません。
  7. DOS行末は2バイトではなく1バイトとしてカウントされます(すでにメタでカバーされていますが、強調する必要があります)
  8. そしてここでの最大のルール:正規表現は許可されていません。

これは問題なので、最小サイズが優先されます。幸運を!

次に、入力と出力の例をいくつか示します(Cスタイルのエスケープ付き)。

入力: "abc123def456"
出力:["123"、 "456"]

入力: "aitew034snk582:3c"
出力:["034"、 "582"、 "3"]

入力:「as5493tax54 \\ 430-52@g9.fc」
出力:["5493"、 "54"、 "430"、 "52"、 "9"]

入力: "sasprs] tore \" re \\ forz "
出力:null、[]、[""]、または同様

回答で使用されたバイト数を入力してください。いつものように、楽しいゴルフを!


Lispのガイドライン

Lispの方言で考慮すべきこととしないことは次のとおりです。

;;; オプション1

(defun extract-strings(ab);カウントしません
  (もの);;; ここにあるすべてが重要です
); 数えません

;;; オプション2

(defun extract-strings(string&aux(start 0)(end 0));カウントしません
  (もの);;; ここにあるすべてが重要です
); 数えません。
他のすべてのラムダは、バイトカウントに完全にカウントされます。


これは以前に尋ねられなかったのですか?
イスマエルミゲル14

1
はい。ただし、ここで再度投稿する前に、Metaで再確認し、大幅に編集しました。このため、重複として分類されるべきではありません(他の関連するものはまだ閉じられていなければなりません)。
イサイアメドウズ14

2
あなたの「ゴルフ」を答えとして掲載すべきではありませんか?
MrWhite 14

4
申し訳ありませんが、GolfScriptを許可しない場合は-1です。すべての言語を許可する必要があります。
ドアノブ

1
@Doorknobそれは本当ですが、私もOPの気持ちを理解しています。GolfScript、J、またはAPLを話さなくても、人々は競争するチャンスがあります(これらのコンテストで後者を熟読することは罪です)。彼がリンクしたスレッドで私の提案を見てください。
トビア14

回答:


10

APL、13文字

(または28/30バイト、以下をお読みください)

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

あなたはあなたの質問からGolfScriptを禁止したようです。私はあなたの感情を理解していますが、このコミュニティが最終的にAPLを禁止しないことを願っています。なぜなら、それは長い歴史を持つ本当に驚くべきプログラミング言語であり、コードを書くのが非常に楽しいことは言うまでもありません。不当に競合していると感じます。この問題に関する私の考えを、あなたがリンクしたスレッドに投稿します。

同じトークンで、私は常にAPL投稿に脚注を追加し、APLは1文字= 1バイトとして記録できると主張しました。私の主張は、APLシンボルが上位128バイトの値にマッピングされた、いくつかの(ほとんどの商用)APL実装が依然として独自のレガシーシングルバイトエンコーディングをサポートしているという事実に基づいています。しかし、これは長すぎるかもしれません。その場合、このエントリをUTF-16で28バイト、UTF-8で30バイトとしてスコアリングすることができます。

説明

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

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

文字列の配列のデフォルトの出力形式では、配列内の文字列の数や空白の数が明確になりません。しかし、引用符を追加するための簡単な操作は、十分に明確にする必要があります。

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

あなたのコメントに関しては、他の言語では「速記」言語とかなり競合するため、他の言語の各記号を1つの文字として数える必要があると思います。例えば、ここに投稿された私のMathematicaソリューションは7(多かれ少なかれ)としてカウントされるべきです。圧縮されたトークンを使用して言語を設計することは、まったくメリットがないと思います。
ベリサリウス博士14

ゴルフの16進ダンプを提供できますか?一部の文字が読めません。
イサイアメドウズ14

@impinball hexdumpはどのように役立ちますか?何が行われているのかがわかるわけではありません。
mniip 14

@impinball APLコードは{omega囲み通勤オメガイプシロンイプシロンフォーマット各iota 10}です。ユニコード値が必要な場合は、文字が見えなくてもコピーして任意のオンラインツールに貼り付けることができます(最新のUnicodeフォントにはAPLシンボルが含まれているため、奇妙なことです) {\ u2375 \ u2282 \ u2368 \ u2375 \ u220a \ u220a \ u2355 \ u00a8 \ u237310}(エスケープシーケンスの一部ではない最後の「10」に注意)
トビア14

1
代わりに∊⍕¨⍳10、あなただけを使用できません⎕Dか?それは定数でなければなりません'0123456789'。Dyalog APLは少なくともそれをサポートしており、NARS2000もサポートしています。
マリヌ14

5

Python 47

実装

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

デモ

>>> 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'], []]

アルゴリズム

各非数字文字をスペースに変換してから、結果の文字列を分割します。シンプルで明確なアプローチ。

itertools(71文字)を使用した楽しいソリューション

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

4

ルビー、70

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

テスト用のオンラインバージョン

Rubyで数字以外の文字をintに変換すると(to_iを使用して)0が返されるため、すべての文字をintに変換してからcharに戻すことは、数字をチェックする非正規表現の方法です...


( '0' .. '9')。memberを実行することもできますか?すべての文字のために、しかし、あなたがやったことは、すでに短い
FGP

あなたは間違いなく正しいです-私は言った必要があります:「方法」
デビッド・ハーマン14

4

bash、26(関数の内容:22 +配列割り当てオーバーヘッド4)

これは他のbash答えに勝るものではありませんが、それはあなたがダブルテイクするかもしれないので興味深いです:

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

使用法は次のとおりです。

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

一見すると//+([!0-9])/、正規表現の置換によく似ていますが、そうではありません。これは、正規表現ルールではなく、パターンマッチングルールに従うbashパラメーター拡張です。

bash関数から真のbash配列型を返すのは苦痛なので、代わりにスペース区切りのリストを返し、関数呼び出し以外の配列割り当てで配列に変換することにしました。そのため、公平性のため(` `)に、関数呼び出しの前後をスコアに含める必要があると感じています。


3

Mathematica 32

StringCases[#,DigitCharacter..]&

使用法

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

正規表現を使用した同等のものはもっと長くなります!:

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

Mathematicaは正規表現を嫌います。
CalculatorFeline

3

Bash、21バイト17/21バイト(DigitalTraumaにより改善

で区切られたリストを作成する tr

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

スペース以外の数字を置き換えます

使用法

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

編集

以下のコメントで指摘されているように、コードは17バイトに削減できます。

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

結果は厳密に言えばBash配列ではないため、使用法は次のようになります。

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

そして余分(``)は数えられるべきです


1
ああ、私に打ち負かされた!しかし、ヒアドキュメントの代わりにヒアストリングを使用してみませんか?また、次の(blah)代わりに使用する関数コンテンツの終わりに改行を保存できます{blah;}split()(tr -c 0-9 \ <<<$1)。そうすれば、関数の本体はわずか17文字です。
デジタル外傷14

1
関数は、配列ではなく「スペース区切りリスト」を返します。確かにbash関数から真の配列を返すのは厄介ですが、少なくとも使用法では関数の結果を配列に割り当てることができます a=($(split "12 3a bc123")); echo ${a[@]}。「($())」があなたのスコアにカウントされると主張することができます
デジタル外傷14

trアプローチを検討する前に、パラメーター拡張を使用してこれを試しましたtrゴルフの目的には間違いなくより良いアプローチです。
デジタル外傷14

tr展開演算子で囲みましたか?のようなもの($(tr...))になり、関数宣言がカウントされない場合、外側の括弧はカウントされません。コマンド置換部分のみです。
イサイアメドウズ14

これがどのように機能するかはわかりませんが、Bash配列には堪能ではありません。とにかく、(``)コンストラクトは1文字よりも1文字優れており、($())優先されます。
コアムディオ14

2

Smalltalk(Smalltalk / X)、81

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

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

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

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

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

ため息-Smalltalkはveeeeryの長い関数名を使用する傾向があります...


2
それは関数名ですか?o__O
トビア

@tobiaどうやら
メドウズ14

asCollectionOfSubCollectionsSeparatedByAnyForWhichname_ಠこの名前は長すぎます
-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])]
}

この関数は文字列を受け入れ、文字列のリストを返します。

例:

> 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

注:$xは、リスト要素の名前です。


1

Perl、53

編集:一致しない場合、subは必要に応じて(空のリストの代わりに)空の文字列を含むリストを返すようになりました。

また、おそらく「ルールに違反する」「空白で分割」動作をトリガーするため、単一スペース文字での分割も回避します。/ /区切り文字を使用することもできますが、これは単一のスペースで分割されますが、逆説的には正規表現パターンを使用するように見えます。私unpackはいくつかの余分な文字を犠牲にして使用することができたので、split論争を完全に取り除くことができましたが、私は最後に、リテラル文字(スペース以外)で分割することは問題ないと思います。

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

そして、いいえ、Perlの音訳演算子は正規表現を行いません。それが0123456789問題であれば、0-9の範囲を展開できます。


正規表現を使用しない限り、有効です。
イサイアメドウズ14

私のPerlはそれほど強くありません。私がコードを理解していれば、数字以外を特定の数字以外で置き換え、選択した数字以外で分割し、空の文字列を除外します。これは正しい読みですか?
ティムセギーン14

1
@TimSeguine:正確ではありません。数字以外は置換され、単一の文字に押しつぶされます。その区切り文字が先頭にある場合、その文字で分割すると空の文字列が生成されます。リストに他のエントリが含まれている場合は、シフトされます。
user2846289 14

空のリストは大丈夫です。
イサイアメドウズ

1

C、68バイト(関数の本体のみ)

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

最初の引数は入力文字列で、2番目の引数は出力配列で、NULLで終了する文字列配列です。a関数を呼び出す前に十分なメモリを確保する必要があります(最悪の場合:)sizeof(char*)*((strlen(s)+1)/2)

入力文字列は関数によって変更されます(数字以外の文字はすべてに置き換えられます'\0'

使用例

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

出力

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

非ゴルフバージョン:

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)

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

まったく競争力はありませんが、VBScriptがどれほど冗長であるか(CRだけで13バイト)を考えると、この点でVBScriptがこれほど短いことに驚かされます。文字列をループし、非数値文字をスペースで置き換え、すべての空白を単一のスペースに減らし、スペース区切り文字を使用してそれを分割します。

テストケース

Input: "ab5c0x"
Output: 5,0

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

メタ行で読んだ限り、DOS行末は1文字としてカウントされます。
イサイアメドウズ14

編集を提案しました。
イサイアメドウズ14

カウントは、Linuxスタイルの1バイトの行末をすでに想定しています。カウントで190文字を取得しました(再度確認しました)。
コミンテルン14

OK。誤算したに違いない。
イサイアメドウズ14

1

Common Lisp(手紙によると1、精神によると173)

これが読みやすいバージョンです。digit-char-pposition-ifなどの長い名前のため、バイト数はかなり多くなり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")
#()

「関数宣言」の概念は、ちょっとあいまいです。これは、1バイト(x関数本体の文字)のみを持つバージョンです。他のすべては、関数のランバリストの補助変数(関数の宣言の一部)にバンドルされています。

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

実際のバイトカウントは、これを許容できると見なすために、本体に移動する必要がある補助宣言の数に依存します。いくつかのローカル関数の名前変更も役立ちます(たとえば、position-if2回表示されるため短くなる、1文字の変数を使用する、など)。

このプログラムのレンダリングには220文字が含まれています。

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

他に何もなければ、これはCommon Lispの&aux変数を昇格させるはずです

loopもちろん、これはもっと簡潔に書くことができます:

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

loopフォーム、余分なスペースを削除しては、173の文字があります。

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

私は(result、本文から最後の括弧までを数えます。名前とパラメーターを定義する部分が宣言です。
イサイアメドウズ14

修正されたルールのルール2を参照して、関数宣言で実際に何を話しているのかを確認してください(基本的には、関数名、パラメーター、および構文的に必要な場合、インタープリター言語ではまれです、戻り値の型を宣言します)
イサイアメドウズ14

うん@impinball、「1」カウントは一種のジョークであるが、ここで重要な部分は、あるresult され、ここでパラメータとして宣言します。それは非常に重要な初期化フォームを持っています。原則として、何らかの複雑な式で計算されるデフォルト値を持つオプションの引数と同じです。(単純なケースでは、それはのようなものを想像するのは簡単ですchar* substring( char *str, int begin, int end(0) )それを指定するには、Cに似た構文を持ついくつかの言語でのendオプションであり、それが提供されていない場合、その値があることを0私はこれらの用語のいくつかの事実を強調しています。
ジョシュアテイラー14

@impinballは非常に具体的ではなく、言語にとらわれないため、トロリーのバイトカウントを防止できます。:)
ジョシュアテイラー14

パラメーターを指定していない最初の部分は、カウントを統計する場所です(たとえば(defun fn (string &aux (start 0) (end 0)、カウントしませんが、ラムダに残っているものはすべてカウントします)。
イサイアメドウズ14

0

JavaScript、240バイト

好奇心you盛な方のために、ここに私の巨大なゴルフがあります:

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

上記のきれいな印刷物:

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

上記の通常の記述コード

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

でコールバックを省略することで短縮できますarray_filter。これによりfalse、ブール値にキャストされたすべてのエントリが自動的に削除されます。
ケルニック14


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

Cには配列印刷関数が組み込まれていないので、私は自分でそれを行わなければならなかったので、すべての出力に最後のコンマがあることをおiveびします。基本的にそのコードが行うことは、文字列が数字でない場合に文字列を読み取り、それを「\ 0」に置き換えてから、コードをループしてすべての数字チェーンを印刷することです(EOF = 0)

入力:ab5c0x
出力:["5"、 "0"、]

入力:z526ks4f。; 8] \ p
出力:["526"、 "4"、 "8"、]


質問の規則(規則2)に従って、関数本体の文字を数えるだけです。したがって、実際のソリューションは170バイト未満になります。ただし、カウントに関数本体以外の変数プロトタイプが含まれているかどうかはわかりません。
grovesNL 14

これに関するルールを修正します。s #define、変数宣言などはカウントされますが、関数宣言はカウントされません。
イサイアメドウズ14

また、最後にチェックしたときに、Cにchar[][]正当なものとして表記されたタイプがありました。あなたがそのように(またはchar**)戻ってきた場合、あなたは大丈夫です。
イサイアメドウズ14

テキスト出力する必要はありませんか?Iプログラムが出力する文字列形式の配列はずだったのに
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);
}

まず、これはLINQ .Select()拡張メソッドを使用して、すべての非数字をコンマに変換します。string.Replace()それを返すために、好ましいと考えられるstringのではなくをIEnumerable<char>、しかしstring.Replace()、単一の文字または文字列のみを取ることができ、LIKE述部を使用することはできませんchar.IsDigit()47<c&c<58

前述のよう.Select()に、文字列に適用するとが返されるIEnumerable<char>ため、配列に変換してstringコンストラクタに渡すことで、文字列に戻す必要があります。

最後に、を使用して文字列をカンマで分割しますstring.Split()(StringSplitOptions)1StringSplitOptions.RemoveEmptyEntries、文字列の先頭/末尾にある複数の連続したコンマとコンマを自動的に処理するという、より短い言い方です。


1
代わりにchar.IsDigit(c)、あなたが使用することができます'/'<c&&c<':'
grovesNL

1
良い点...またはさらに良い、47<c&&c<58。(率直に言って、私はそれが数字で動作することに驚いていますが、明らかに動作します)。
BenM 14

1
そして、二重の「&&」の代わりに単一の「&」を使用することにより、余分な貴重なキャラクターを保存できます。C#では、これは、両方のオペランドがブール値の場合でも論理ANDです。整数の場合、ビット単位のANDのみを実行します。
BenM 14

良いですね。それができるとは知りませんでした。
grovesNL 14

少し短い変形では、の代わりに空白で分割し,、空のアイテムを手動で削除しますreturn new string(s.Select(c=>47<c&c<58?c:' ').ToArray()).Split().Where(a=>a!="").ToArray();
VisualMelon 14年

0

JS / Node:168 162 147 138文字

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

美化バージョン:

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

あなたが削除することができますので、この質問は、配列が返さ望んでいるconsole.log(r)といくつかの他のもの
未チャールズその

関数の宣言は、(理由は、ヘルプレベルに活躍の場である)スコアにカウントされません
アイザイアメドウズ

OK。@impinballのコメントに従ってスコアを調整しました。(実際には、2つの関数がここで宣言されています
。Char

そうすべき。説明をよくするためにルールを更新しました。
イサイアメドウズ14

一方、より良い何か...を思い付いた
palanik

0

ルビー、24

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

印刷可能なアスキー範囲内の負のスペースを使用して数字を定義します。


関数宣言はカウントされません。
イサイアメドウズ14

0

php204

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

記述コード:

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

これは非常に長いコードであり、このコードゴルフ用のはるかに短いphpバージョンがあると確信しています。これは私がPHPで思い付くことができるものです。


あなたは置き換えることができますいくつかの改善があるarray()[]array_push($output[$count], $arr[$i]);$output[$count][]=$arr[$i];、とord()とのチェックがis_numeric()。また、文字列を分割してその文字を繰り返す必要もありません。また、それはあなたが数えるCHARであるように機能数の唯一の内側のコードは、204です
Einacio

関数宣言はカウントされません。何が重要で何が重要でないかのガイドとしてルール2を参照してください。
イサイアメドウズ14

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の答えははるかに賢明です、これは私が念頭に置いていたものの単なる「縮小」バージョンです。

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

これにより出力が生成されないため、いくつかの変数が宣言で定義されているため、コードが1つずつ実行されると機能します。


関数宣言をカウントする必要はありません。ヘッドアップとして
イザヤメドウズ14

0

PHP 98 89

DigitalTraumaのbashの回答のように、これは正規表現を使用しません。

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

テストケース:

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

ハスケル31

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

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

文字列をすべての非数値文字で分割し、連続する区切り文字によって生成された空の文字列を削除します。


0

VBA 210、181、関数宣言なし

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文字)

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

ゴルフなしで関数宣言にラップ:

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

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

ゴルフ:

編集:ループが配列の終わりを歩く場合、cありますundefined、それは偽であり、ループを終了します。

2/27:を使用すると?:、の冗長性が節約され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
}

本体の復帰は読みやすくするためのものであり、ソリューションの一部ではありません。

ゴルフをしていない:

アイデアは、配列の最後のエントリが数字の場合は各エントリに文字を追加し、それ以外の場合は最後の配列のエントリが文字列であることを確認することです。

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
}

非ゴルフ

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

サンプル入出力

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
私はそれが好きです!私よりもずっと簡単です。に置き換えることでif(+a[i]+1)b+=a[i];else if(b)c.push(b),b=""、さらに8文字を削除できますb=+a[i]+1?b+a[i]:b?(c.push(b),""):b
DocMax 14

@DocMax thx、私はあなたの提案を含めるように編集しました:)。それ(c.push(b),"")は賢いように見えた、それを見たことがない。
ダニー14

私はそれが今日以前に広く使用されましたまで、私はそれについて忘れていたcodegolf.stackexchange.com/questions/22268#22279
DocMax

それは有効ではありません。「」は0と間違えられ、管理が難しいJavaScriptの癖です。'12 34 56 'を試してください
edc65

0

R 52

この関数は、文字クラス(これは正規表現ではありません!:))で文字列を分割します。クラスはN-数字であり、P {N}はこのクラスの否定を意味します。o = Tは、空のサブストリングを省略することを意味します。

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


出力

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

関数n(x){}をカウントしない場合は88文字

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
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.