Chương trình ngắn nhất để phân tách một chuỗi ở dạng không có chữ số mà không có RegExps


16

EDIT: Nếu bạn đang sử dụng Lisp, tôi đã đưa ra một số hướng dẫn ở phía dưới trong việc đếm byte.

Mục tiêu: Tạo hàm ngắn nhất phân tách một chuỗi ở dạng không có chữ số và trả về một mảng chỉ gồm các chữ số trong mỗi chuỗi, không sử dụng bất kỳ biểu thức chính quy nào. Các số 0 đứng đầu sẽ được bao gồm trong mỗi chuỗi.

Bảng xếp hạng hiện tại (được phân loại trong danh mục):

  • C / C ++ / C # / Java: 68 (C) ....
  • GolfScript / APL / J: 13 (APL)
  • Tất cả những người khác: 17 (Bash, sử dụng tr), 24 (Ruby)

Quy tắc:

(Tôi xin lỗi vì sự dài dòng)

  1. Định dạng phải là một hàm với một đối số chuỗi đơn. Có thể thêm tối đa hai đối số bổ sung nếu cần thiết cho sự trở lại đúng của mảng (ví dụ: sh / csh / DOS Batch cần một tham chiếu biến phụ để trả về, v.v.).
  2. Khai báo hàm chính không tính và cũng không nhập các thư viện chuẩn khác. `# bao gồm`, `import` và` using` không được tính. Mọi thứ khác làm. Điều này không bao gồm các hàm `# định nghĩa và hàm trợ giúp. Xin lỗi vì sự nhầm lẫn. Hãy xem đây là một hướng dẫn hữu ích về những gì không / không tính (được viết bằng cú pháp kiểu C)
    // không được tính vào tổng số, có thể được bỏ qua trừ khi
    // không rõ ràng, giống như một nửa thư viện chuẩn của Java.
    #inc loại <stdio.h>
    
    nhập một số.builtin.Class // không được tính, xem ở trên
    
    #define printf p // tính vào tổng số
    
    / * Bất kỳ chỉ thị tiền xử lý nào khác, v.v. * /
    
    int i = 0; // đếm
    
    một số chức năng (); // đếm
    
    char [] [] myMainSplitFunction (char [] [] mảng) {// không được tính
      // Mọi thứ ở đây đều có giá trị
      return returnArray; // Ngay cả điều này cũng được tính.
    } // không tính
    
    / * Mọi thứ ở đây đều được tính, bao gồm cả khai báo * /
    char [] [] someHelperFunction (char [] chuỗi) {
      // đồ đạc
    } // thậm chí số này còn được tính
    
  3. Đầu ra phải là một chuỗi chuỗi hoặc tương tự (Danh sách mảng trong Java và tương tự đều được chấp nhận). Ví dụ về sản lượng được chấp nhận: String[], char[][], Array, List, và Array(object).
  4. Mảng phải chỉ chứa các nguyên hàm chuỗi có độ dài thay đổi hoặc các đối tượng chuỗi. Không có chuỗi trống nào có mặt trong phần trả về, với ngoại lệ bên dưới. Lưu ý: các chuỗi phải chứa một chuỗi các kết quả khớp liên tiếp, chẳng hạn như đầu vào và đầu ra ví dụ bên dưới.
  5. Nếu không có kết quả khớp, thì thân hàm sẽ trả về null, một mảng / danh sách trống hoặc một mảng / danh sách chứa một chuỗi rỗng.
  6. Không cho phép thư viện bên ngoài.
  7. Kết thúc dòng DOS được tính là một byte, không phải hai (đã được bao phủ trong meta, nhưng cần nhấn mạnh)
  8. Và quy tắc lớn nhất ở đây: không cho phép biểu thức chính quy.

Đây là một câu hỏi , vì vậy kích thước nhỏ nhất sẽ thắng. Chúc may mắn!

Và đây là một số ví dụ đầu vào và đầu ra (với lối thoát kiểu C):

Đầu vào: "abc123def456"
Đầu ra: ["123", "456"]

Đầu vào: "aitew034snk582: 3c"
Đầu ra: ["034", "582", "3"]

Đầu vào: "as5493tax54 \\ 430-52@g9.fc"
Đầu ra: ["5493", "54", "430", "52", "9"]

Đầu vào: "sasprs] xé \" re \\ forz "
Đầu ra: null, [], [""] hoặc tương tự

Vui lòng đặt bao nhiêu byte được sử dụng bởi câu trả lời của bạn và như mọi khi, chơi golf vui vẻ!


Hướng dẫn cho Lisp

Đây là những gì không và không được tính trong phương ngữ Lisp:

;;; lựa chọn 1

(defun trích xuất chuỗi (ab); Không tính
  (đồ đạc) ;;; Mọi thứ ở đây đều có giá trị
); Không tính

;;; Lựa chọn 2

(defun trích xuất chuỗi (chuỗi & phụ (bắt đầu 0) (kết thúc 0)); Không tính
  (đồ đạc) ;;; Mọi thứ ở đây đều có giá trị
); Không được tính.
Tất cả các lambdas khác hoàn toàn được tính vào số byte.


Điều này không được hỏi trước sao?
Ismael Miguel

1
Có, nhưng tôi đã hỏi lại nó trên Meta và chỉnh sửa đáng kể trước khi đăng lại ở đây. Bởi vì điều này, nó không nên được phân loại là một bản sao (cái khác có liên quan nên được đóng lại nếu chưa có).
Isiah Meadows

2
Không nên "chơi gôn" của bạn như là một câu trả lời?
MrWhite

4
Xin lỗi, nhưng -1 vì đã không cho phép GolfScript. Tất cả các ngôn ngữ nên được cho phép.
Doorknob

1
@Doorknob Điều đó đúng, nhưng tôi cũng hiểu cảm giác của OP. Mọi người nên có cơ hội cạnh tranh ngay cả khi họ không nói GolfScript, J hoặc APL (và tôi có lỗi khi hiểu ý sau trong các cuộc thi này.) Bạn có thể xem đề xuất của tôi trong chủ đề mà anh ấy liên kết không?
Tobia

Câu trả lời:


10

APL, 13 ký tự

(hoặc 28/30 byte, đọc bên dưới)

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

Tôi thấy bạn đã cấm GolfScript từ câu hỏi của bạn. Tôi hiểu tình cảm của bạn, nhưng tôi hy vọng cộng đồng này cuối cùng sẽ cấm APL, bởi vì đó là ngôn ngữ lập trình thực sự đáng chú ý với lịch sử lâu dài, chưa kể rất nhiều điều thú vị để viết mã. Có lẽ nó có thể được ghi điểm khác, nếu mọi người cảm thấy nó cạnh tranh không lành mạnh Tôi sẽ đăng suy nghĩ của tôi về vấn đề này đến chủ đề mà bạn đã liên kết.

Trên cùng một mã thông báo đó, tôi đã luôn thêm chú thích vào các bài đăng APL của mình, tuyên bố rằng APL có thể được ghi là 1 char = 1 byte. Khiếu nại của tôi dựa trên thực tế là một số triển khai APL (chủ yếu là thương mại) vẫn hỗ trợ mã hóa byte đơn kế thừa của riêng họ, với các ký hiệu APL được ánh xạ tới các giá trị 128 byte trên. Nhưng có lẽ điều này là quá nhiều, trong trường hợp đó bạn có thể muốn ghi điểm này là 28 byte trong UTF-16 hoặc 30 byte trong UTF-8.

Giải trình

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

Ví dụ

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

Định dạng đầu ra mặc định cho một mảng các chuỗi không làm rõ có bao nhiêu chuỗi trong mảng đó, cũng không có bao nhiêu khoảng trống. Nhưng một thao tác nhanh chóng để thêm dấu ngoặc kép sẽ làm cho nó đủ rõ ràng:

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

Về nhận xét của bạn, tôi nghĩ rằng đối với các ngôn ngữ khác cạnh tranh công bằng với các ngôn ngữ "tốc ký", người ta nên tính mỗi ký hiệu trong các ngôn ngữ khác là một ký tự. Ví dụ: giải pháp Mathicala của tôi được đăng ở đây nên được tính là 7 (nhiều hơn hoặc ít hơn). Thiết kế một ngôn ngữ với mã thông báo nén hoàn toàn không có giá trị, tôi nghĩ vậy.
Tiến sĩ belisarius

Bạn có thể cung cấp một bãi chứa hex của golf của bạn? Tôi không thể đọc một số nhân vật.
Isiah Meadows

@impinball Làm thế nào hexdump sẽ giúp bạn? Nó không giống như bạn sẽ thấy những gì đang được thực hiện.
mniip

@impinball mã APL là {omega kèm theo định dạng omega epsilon epsilon mỗi iota 10}. Nếu bạn cần các giá trị unicode, bạn chỉ có thể sao chép và dán nó vào bất kỳ công cụ trực tuyến nào , ngay cả khi bạn không thể nhìn thấy các ký tự (điều này thật lạ, vì hầu hết các phông chữ Unicode hiện đại đều có ký hiệu APL) Trong mọi trường hợp bạn nhận được là {\ u2375 \ u2282 \ u2368 \ u2375 \ u220a \ u220a \ u2355 \ u00a8 \ u237310} (lưu ý "10" cuối cùng không phải là một phần của chuỗi thoát)
Tobia

1
Thay vì ∊⍕¨⍳10, bạn không thể sử dụng ⎕D? Đó phải là hằng số '0123456789'. Dyalog APL ít nhất hỗ trợ nó, và NARS2000 cũng vậy.
bến tàu

5

Con trăn 47

Thực hiện

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

Bản giới thiệu

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

Thuật toán

Chuyển đổi từng ký tự không có chữ số thành khoảng trắng và sau đó phân tách chuỗi kết quả. Một cách tiếp cận đơn giản và rõ ràng.

Và một giải pháp thú vị với itertools (71 ký tự)

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

4

Ruby, 70

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

Phiên bản trực tuyến để thử nghiệm

Vì việc chuyển đổi bất kỳ ký tự không có chữ số nào thành int trả về 0 trong Ruby (với to_i), chuyển đổi mọi char thành int và quay lại char là cách không phải regex để kiểm tra chữ số ...


Bạn cũng có thể làm một ('0' .. '9'). Thành viên? cho mỗi char, nhưng những gì bạn đã làm đã ngắn hơn
fgp

Bạn chắc chắn đúng - Tôi nên nói: "một" cách;)
David Herrmann

4

bash, 26 (nội dung chức năng: 22 + phí gán mảng 4)

Điều này sẽ không đánh bại câu trả lời khácbash , nhưng nó thú vị bởi vì nó có thể khiến bạn phải thực hiện gấp đôi:

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

Cách sử dụng là:

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

Thoạt nhìn, //+([!0-9])/trông rất giống một sự thay thế regrec, nhưng không phải vậy. Nó là một mở rộng tham số bash , tuân theo các quy tắc khớp mẫu , thay vì các quy tắc biểu thức thông thường.

Trả về các kiểu mảng bash thực sự từ các hàm bash là một nỗi đau, vì vậy tôi đã chọn trả về một danh sách được phân tách bằng dấu cách, sau đó chuyển đổi thành một mảng trong một phép gán mảng bên ngoài lệnh gọi hàm. Vì vậy, vì lợi ích của sự công bằng, tôi cảm thấy (` `)cuộc gọi chức năng nên được đưa vào điểm số của tôi.


3

Toán học 32

StringCases[#,DigitCharacter..]&

Sử dụng

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

Việc sử dụng regexes tương đương dài hơn nhiều!:

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

Mathicala hút tại regex.
Máy

3

Bash, 21 byte 17/21 byte (được cải thiện bởi DigitalTrauma )

Xây dựng một danh sách ngăn cách với tr

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

thay thế bất kỳ chữ số nào bằng một khoảng trắng

Sử dụng

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

Biên tập

như được chỉ ra bởi các ý kiến ​​dưới đây, mã có thể được rút xuống còn 17 byte:

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

và kết quả là không nói một cách nghiêm túc một mảng Bash, nên sử dụng

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

(``)cần tính thêm


1
Gah bạn đánh tôi với nó! Nhưng tại sao không sử dụng một chuỗi ở đây thay vì một tài liệu ở đây? Ngoài ra, bạn có thể lưu một dòng mới ở cuối nội dung chức năng bạn sử dụng (blah)thay vì {blah;}: split()(tr -c 0-9 \ <<<$1). Bằng cách đó, cơ thể chức năng của bạn chỉ có 17 ký tự.
Chấn thương kỹ thuật số

1
Hàm của bạn trả về một "danh sách được phân tách bằng dấu cách" thay vì một mảng. Chắc chắn trả về các mảng thực sự từ hàm bash rất khó xử, nhưng ít nhất bạn có thể gán kết quả của hàm cho một mảng trong cách sử dụng của bạn : a=($(split "12 3a bc123")); echo ${a[@]}. Có thể lập luận rằng "($ ())" được tính vào điểm số của bạn
Chấn thương kỹ thuật số

Trước khi khám phá trphương pháp, tôi đã thử làm điều này với việc mở rộng tham số . trchắc chắn là cách tiếp cận tốt hơn cho mục đích chơi golf.
Chấn thương kỹ thuật số

Bạn đã thử xung quanh trvới các toán tử mở rộng? Nó sẽ được đưa ra một cái gì đó giống như ($(tr...)), và khi khai báo hàm không được tính, các dấu ngoặc đơn bên ngoài sẽ không được tính vào bạn. Nó sẽ chỉ là phần thay thế lệnh.
Isiah Meadows

Tôi không thấy cách này sẽ hoạt động, nhưng tôi không rành về mảng Bash. Dù sao, (``)cấu trúc là 1-char tốt hơn so với ($())cái và sẽ được ưa thích hơn.
Coaumdio

2

Smalltalk (Smalltalk / X), 81

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

giá trị f: 'abc123def456' -> OrderedCollection ('123' '456')

giá trị f: 'aitew034snk582: 3c' -> OrderedCollection ('034' '582' '3')

giá trị f: 'as5493tax54 \ 430-52@g9.fc' -> OrderedCollection ('5493' '54' '430' '52' '9')

giá trị f: 'sasprs] xé \ "re \ forz' -> OrderedCollection ()

thở dài - Smalltalk có xu hướng sử dụng tên hàm dài veeeery ...


2
Đó có phải là một tên chức năng? o__O
Tobia

@tobia Rõ ràng ...
Isiah Meadows

asCollectionOfSubCollectionsSeparatedByAnyForWhich_ Tên này quá dài
Thiền vào

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

Hàm chấp nhận một chuỗi và trả về một danh sách các chuỗi.

Ví dụ:

> 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

Lưu ý: $xlà tên của thành phần danh sách.


1

Perl, 53

Chỉnh sửa: không có kết quả trùng khớp, phụ bây giờ trả về danh sách với chuỗi trống (thay vì danh sách trống) theo yêu cầu.

Nó cũng tránh phân tách trên một ký tự không gian đơn, vì nó kích hoạt 'phân chia trên bất kỳ hành vi không gian trắng' nào , có thể vi phạm các quy tắc. Tôi có thể sử dụng / /dấu phân cách, sẽ phân tách trên một không gian duy nhất, nhưng nghịch lý là nó sẽ trông giống như sử dụng mô hình regrec. Tôi có thể sử dụng unpackvới chi phí của một số nhân vật phụ và do đó loại bỏ splithoàn toàn tranh cãi, nhưng tôi nghĩ rằng, những gì tôi kết thúc bằng, chia tách một nhân vật theo nghĩa đen (trừ không gian) là ổn.

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

Và, không, toán tử chuyển ngữ của Perl không thực hiện các biểu thức chính quy. Tôi có thể hủy đăng ký phạm vi 0-9 0123456789nếu đó là vấn đề.


Miễn là nó không sử dụng các biểu thức thông thường, nó hợp lệ.
Isiah Meadows

Perl của tôi không quá mạnh. Nếu tôi hiểu mã, bạn đang thay thế các chữ số không bằng một chữ số cụ thể, sau đó tách trên chữ số không được chọn đó, sau đó lọc ra các chuỗi trống. Đây có phải là một cách đọc đúng?
Tim Seguine

1
@TimSeguine: Không chính xác. Các chữ số không được thay thế và được nén thành một ký tự đơn, tách trên đó tạo ra chuỗi rỗng nếu dấu phân cách đó xảy ra ở đầu. Sau đó nó được chuyển đi nếu danh sách chứa các mục khác.
dùng2846289

Danh sách Enpty là được.
Isiah Meadows

1

C, 68 byte (chỉ cơ thể của hàm)

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

Đối số đầu tiên là chuỗi đầu vào, đối số thứ hai là mảng đầu ra, là mảng chuỗi kết thúc NULL. Phải có đủ bộ nhớ atrước khi gọi hàm (trường hợp xấu nhất:sizeof(char*)*((strlen(s)+1)/2) :).

Chuỗi đầu vào được sửa đổi bởi hàm (mỗi ký tự không có chữ số được thay thế bởi '\0')

Ví dụ sử dụng

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

Đầu ra

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

Phiên bản chưa chơi gôn:

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 không có khai báo hàm)

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

Mặc dù không cạnh tranh chút nào, tôi ngạc nhiên khi VBScript xuất hiện ngắn gọn về điều này với mức độ dài dòng (chỉ 13 byte cho CR). Nó lặp qua chuỗi, thay thế bất kỳ ký tự không phải số nào bằng khoảng trắng, sau đó giảm tất cả khoảng trắng thành các khoảng trắng đơn, sau đó sử dụng dấu phân cách khoảng trắng để phân chia nó.

Các trường hợp thử nghiệm

Input: "ab5c0x"
Output: 5,0

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

Kết thúc dòng DOS được tính là một ký tự theo như tôi đã đọc trên meta.
Isiah Meadows

Tôi đề nghị chỉnh sửa cho bạn.
Isiah Meadows

Số lượng đã giả định kết thúc dòng 1 byte kiểu Linux. Tôi nhận được 190 ký tự theo số lượng của tôi (chỉ cần xác minh lại).
Comitern

Đồng ý. Tôi đã phải linh tinh.
Isiah Meadows

1

Lisp thông thường (1 theo chữ cái; ≈173 theo tinh thần)

Đây là phiên bản dễ đọc. Số đếm byte là khá cao vì những cái tên dài trong những thứ như digit-char-pposition-ifvector-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")
#()

Khái niệm "khai báo hàm" là loại mơ hồ. Đây là phiên bản chỉ có một byte (ký tự xtrong thân hàm); mọi thứ khác được gói vào các biến phụ của danh sách lamba của hàm (một phần của khai báo của hàm):

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

Số lượng byte thực tế sẽ phụ thuộc vào số lượng khai báo phụ sẽ phải được chuyển vào phần thân để điều này được coi là chấp nhận được. Một số đổi tên chức năng cục bộ cũng sẽ giúp (ví dụ, rút ​​ngắnposition-if vì nó xuất hiện hai lần, sử dụng các biến chữ cái đơn, v.v.).

Kết xuất chương trình này có 220 ký tự:

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

Nếu không có gì khác, điều này sẽ thúc đẩy các biến & aux chung của Lisp .

Điều này có thể được viết chính xác hơn với loop , tất nhiên:

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

Biểu loopmẫu, với không gian thừa được loại bỏ, có 173 ký tự:

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

Tôi sẽ tính bắt đầu từ (resulttrên đến dấu ngoặc đơn cuối cùng để trở thành cơ thể. Phần xác định tên và tham số là khai báo.
Isiah Meadows

Vui lòng tham khảo quy tắc 2 về các quy tắc đã sửa đổi của tôi để xem những gì tôi thực sự nói về khai báo hàm (về cơ bản, khai báo tên hàm, tham số và nếu được yêu cầu về mặt cú pháp, rất hiếm trong số các ngôn ngữ được giải thích, loại trả về).
Isiah Meadows

@impinball Vâng, số "1" là một trò đùa, nhưng phần quan trọng ở đây là result được khai báo như một tham số ở đây; nó chỉ có một hình thức khởi tạo không tầm thường. Về nguyên tắc, đó là điều tương tự, như là một đối số tùy chọn với giá trị mặc định được tính bằng một số biểu thức phức tạp. (Trong các trường hợp đơn giản hơn, thật dễ dàng để tưởng tượng một cái gì đó giống như char* substring( char *str, int begin, int end(0) )trong một ngôn ngữ với cú pháp giống như C để chỉ định đó endlà tùy chọn và nếu nó không được cung cấp, thì giá trị của nó là 0. Tôi chỉ nhấn mạnh thực tế là một số thuật ngữ này
Joshua Taylor

@impinball không đủ cụ thể và ngôn ngữ không đủ khả năng để ngăn chặn một số lượng byte trollish. :)
Joshua Taylor

Phần đầu tiên không chỉ định tham số là nơi tôi sẽ đếm (ví dụ: (defun fn (string &aux (start 0) (end 0)sẽ không tính, nhưng mọi thứ còn lại trong lambda sẽ).
Isiah Meadows

0

JavaScript, 240 byte

Và đối với những người tò mò, đây là sân golf khổng lồ của tôi:

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

Trên in đẹp:

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

Ở trên trong mã mô tả bình thường

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

Bạn có thể rút ngắn nó bằng cách bỏ qua cuộc gọi lại tại array_filter. Điều này sẽ tự động xóa tất cả các mục nhập falsekhi chúng được chuyển sang booleans.
kelunik

@kelunik cũng sẽ lọc ra 0s
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("]");}

Vì C không có chức năng in mảng tích hợp nên tôi phải tự mình thực hiện công việc đó nên tôi xin lỗi rằng có một dấu phẩy cuối cùng trong mỗi đầu ra. Về cơ bản những gì mã đó làm là nó đọc chuỗi nếu nó không phải là một chữ số, nó sẽ thay thế nó bằng '\ 0' và sau đó tôi chỉ lặp qua mã và in ra tất cả các chuỗi chữ số. (EOF = 0)

Đầu vào: ab5c0x
Đầu ra: ["5", "0",]

Đầu vào: z526ks4f .; 8] \ p
Đầu ra: ["526", "4", "8",]


Theo quy tắc của câu hỏi (quy tắc 2), bạn chỉ phải đếm các ký tự trong thân hàm. Vì vậy, giải pháp của bạn thực sự sẽ có ít hơn 170 byte. Tôi không chắc chắn nếu số lượng bao gồm các nguyên mẫu thay đổi bên ngoài cơ thể chức năng, mặc dù.
GrovesNL

Tôi sẽ sửa đổi các quy tắc về điều này: #defines, khai báo biến, v.v. sẽ được tính, nhưng khai báo hàm sẽ không.
Isiah Meadows

Ngoài ra, lần trước tôi đã kiểm tra, có một loại chữ C char[][]được ký hiệu là hợp pháp. Nếu bạn trở lại như vậy (hoặc char**), bạn sẽ ổn thôi.
Isiah Meadows

Nó không phải là đầu ra văn bản? Tôi mặc dù chương trình được cho là xuất mảng theo định dạng chuỗ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);
}

Đầu tiên, điều này sử dụng .Select()phương thức mở rộng LINQ để biến tất cả các chữ số không thành dấu phẩy. string.Replace()sẽ là tốt hơn, vì nó trả về một stringthay vì mộtIEnumerable<char> , nhưng string.Replace()chỉ có thể lấy một char hoặc chuỗi đơn và không thể sử dụng một vị từ như char.IsDigit()hoặc47<c&c<58 .

Như đã đề cập, .Select() áp dụng cho một chuỗi trả về một IEnumerable<char>, vì vậy chúng ta cần biến nó trở lại thành một chuỗi bằng cách biến nó thành một mảng và chuyển mảng vàostring tạo.

Cuối cùng, chúng tôi chia chuỗi tại dấu phẩy bằng cách sử dụng string.Split(). (StringSplitOptions)1là một cách nói ngắn hơn StringSplitOptions.RemoveEmptyEntries, nó sẽ tự động chăm sóc nhiều dấu phẩy và dấu phẩy liên tiếp ở đầu / cuối chuỗi.


1
Thay vì char.IsDigit(c), bạn có thể sử dụng'/'<c&&c<':'
grovesNL

1
Điểm tốt ... hoặc thậm chí tốt hơn , 47<c&&c<58. (Thành thật mà nói, tôi ngạc nhiên khi nó hoạt động với các con số, nhưng rõ ràng là có).
BenM

1
Và tôi có thể lưu một ký tự có giá trị thêm bằng cách sử dụng một '&' thay vì một dấu '&&'. Trong C #, điều này vẫn logic VÀ khi cả hai toán hạng đều là booleans - nó chỉ thực hiện một chút VÀ khi chúng là số nguyên.
BenM

Đẹp một. Tôi không biết nó đã có thể làm điều đó.
GrovesNL

Một biến thể ngắn hơn một chút là phân chia trên khoảng trắng thay vì ,và sau đó xóa thủ công các mục trốngreturn new string(s.Select(c=>47<c&c<58?c:' ').ToArray()).Split().Where(a=>a!="").ToArray();
VisualMelon

0

Mã / nút: 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;
}

Phiên bản làm đẹp:

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

Câu hỏi này chỉ muốn mảng được trả về, vì vậy bạn có thể xóa console.log(r)và một số thứ khác
Không phải Charles

Tuyên bố chức năng không được tính vào điểm số (lý do là để giúp san bằng sân chơi)
Isiah Meadows

Đồng ý. Điều chỉnh điểm theo nhận xét của @ impinball. (Trên thực tế có hai hàm được khai báo ở đây. Số Char bao gồm hàm ẩn danh)
palanik

Nó nên. Tôi cập nhật các quy tắc để giúp giải thích nó tốt hơn.
Isiah Meadows

Trong khi đó, đã đưa ra một cái gì đó tốt hơn ...
palanik

0

Ruby, 24

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

Xác định các chữ số sử dụng không gian âm trong phạm vi ascii có thể in.


Khai báo hàm không tính.
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;}

Mã mô tả:

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

Đây là mã khá dài và tôi chắc chắn sẽ có một phiên bản php ngắn hơn nhiều cho mã golf này. Đây là những gì tôi có thể đến với php.


có một số cải tiến: bạn có thể thay thế array()bằng [], array_push($output[$count], $arr[$i]);bằng $output[$count][]=$arr[$i];ord()kiểm tra bằng is_numeric(). và bạn thậm chí không cần phải phân tách chuỗi để lặp lại các ký tự của nó. Ngoài ra, chỉ có mã bên trong của hàm được tính, vì vậy số lượng char của bạn là 204.
Einacio

Khai báo hàm không tính. Tham khảo quy tắc 2 như một hướng dẫn về những gì được tính và những gì không.
Isiah Meadows

0

Con trăn

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

Con trăn 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]

Câu trả lời @Abhijit rất thông minh, đây chỉ là một phiên bản "rút gọn" của những gì tôi đã nghĩ trong đầu.

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

Điều này mang lại không có đầu ra, vì vậy mã đang hoạt động, nếu được chạy từng cái một, vì một số biến được định nghĩa tại khai báo.


Bạn không phải đếm khai báo hàm, nếu bạn đã làm. Chỉ cần ngẩng cao đầu
Isiah Meadows

0

PHP 98 89

Như trong câu trả lời bash của DigitalTrauma, điều này không sử dụng biểu thức chính quy.

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

Các trường hợp thử nghiệm:

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)

Nó phân tách chuỗi trên tất cả các ký tự không phải là số và loại bỏ các chuỗi trống được tạo bởi các dấu phân cách liên tiếp.


0

VBA 210, 181 không có khai báo hàm

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 ký tự)

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

Ungolfed và bọc trong khai báo chức năng:

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

Mã ví dụ trong bảng điều khiển 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

Chơi gôn

Chỉnh sửa: Khi các vòng đi ra khỏi cuối của mảng, cundefined, mà là falsy và kết thúc vòng lặp.

27/2: Sử dụng ?:tiết kiệm sự minh mẫn của 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
}

Sự trở lại vận chuyển trong cơ thể là để dễ đọc và không phải là một phần của giải pháp.

Ung dung:

Ý tưởng là nối từng ký tự vào mục cuối cùng trong mảng nếu nó là một chữ số và để đảm bảo mục nhập mảng cuối cùng là một chuỗi khác.

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
}

Bị đánh cắp

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

Đầu vào / đầu ra mẫu

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

Câu đố


1
Tôi thích nó! Đơn giản hơn nhiều so với của tôi. Bạn có thể thả thêm 8 ký tự bằng cách thay thế if(+a[i]+1)b+=a[i];else if(b)c.push(b),b=""bằng b=+a[i]+1?b+a[i]:b?(c.push(b),""):b.
DocMax

@DocMax thx, tôi đã chỉnh sửa để bao gồm đề xuất của bạn :). Điều đó (c.push(b),"")có vẻ thông minh, không bao giờ nhìn thấy điều đó.
Daniel

Tôi đã quên nó cho đến khi tôi thấy nó được sử dụng rộng rãi vào ngày hôm nay trong codegolf.stackexchange.com/questions/22268#22279
DocMax

Điều đó không hợp lệ, '' bị nhầm thành 0 và đó là một cách giải quyết javascript khó quản lý. Hãy thử '12 34 56 '
edc65

0

R 52

Hàm này phân tách các chuỗi theo lớp ký tự (đây không phải là lớp regex! :)) là N - ký tự số và P {N} có nghĩa là phủ định của lớp này. o = T có nghĩa là bỏ qua các chuỗi con trống.

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


Đầu ra

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 ký tự khi không đếm hàm 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
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.