Найкоротша програма для розділення рядка на нецифрові без RegExps


16

EDIT: Якщо ви використовуєте Lisp, я дав кілька підказок внизу підрахунку байтів.

Мета: Зробіть найкоротшу функцію, яка розбиває рядок на нецифрові цифри і повертає масив, що складається з лише цифр у кожній рядку, без використання регулярних виразів. Провідні нулі повинні бути включені в кожен рядок.

Поточна таблиця (розділена на категорії):

  • C / C ++ / C # / Java: 68 (C) ....
  • GolfScript / APL / J: 13 (APL)
  • Усі інші: 17 (Bash, використовує tr), 24 (Ruby)

Правила:

(Прошу вибачення за тривалість)

  1. Формат повинен бути функцією з аргументом єдиного рядка. До необхідності для належного повернення масиву можуть бути додані до двох додаткових аргументів (наприклад, sh / csh / DOS Batch потребує додаткової посилання на змінну для повернення тощо).
  2. Декларація первинної функції не враховує та не імпортує інші стандартні бібліотеки. `# включити`, `імпорт` і `використання` s не враховуються. Все інше робить. Сюди входять функції `# define` і помічники. Вибачте за непорозуміння. Перегляньте це як корисний посібник щодо того, що не враховується (написано в синтаксисі стилю C)
    // не зараховується до загальної кількості, може бути опущено, якщо тільки
    // не очевидний, як половина стандартної бібліотеки Java.
    #include <stdio.h>
    
    import some.builtin.Class // не рахується, див. вище
    
    #define printf p // зараховується до загального
    
    / * Будь-які інші директиви препроцесора тощо. * /
    
    int i = 0; // рахує
    
    деякийFunction (); // рахує
    
    char [] [] myMainSplitFunction (масив char [] []) {// не враховується
      // Тут все враховується
      return returnArray; // Навіть це рахується.
    } // не рахується
    
    / * Тут все враховується, включаючи декларацію * /
    char [] [] someHelperFunction (char [] рядок) {
      // начинка
    } // навіть це враховується
    
  3. Вихід повинен бути рядковим масивом або подібним (списки масивів на Java і подібні є прийнятними). Приклади прийнятого виходу: String[], char[][], Array, List, і Array(об'єкт).
  4. Масив повинен містити лише містити рядкові примітиви змінної довжини або рядкові об'єкти. У звороті не повинно бути жодних порожніх рядків, за винятком нижче. Примітка: рядки повинні містити рядок послідовних збігів, таких як приклад введення та виводу нижче.
  5. Якщо збігів немає, то тіло функції має повернутися null, порожній масив / список або масив / список, що містить порожній рядок.
  6. Заборонено використання зовнішніх бібліотек.
  7. Закінчення рядків DOS вважаються одним байтом, а не двома (вже охоплені мета, але потрібно підкреслити)
  8. І найголовніше правило тут: заборонено регулярні вирази.

Це питання з , тому виграє найменший розмір. Удачі!

Ось кілька прикладів входів та виходів (із втечами у стилі С):

Вхід: "abc123def456"
Вихід: ["123", "456"]

Вхід: "aitew034snk582: 3c"
Вихід: ["034", "582", "3"]

Вхідні дані: "as5493tax54 \\ 430-52@g9.fc"
Вихід: ["5493", "54", "430", "52", "9"]

Вхід: "sasprs] рвав \" re \\ forz "
Вихід: null, [], [""] або подібні

Будь ласка, покладіть, скільки байтів використали ваші відповіді, і як завжди, щасливого гольфу!


Керівні принципи для Lisp

Ось що робить і що не враховує в діалектах Lisp:

;;; Варіант 1

(розмикання екстрактів-рядків (ab); не враховується
  (речі) ;;; Тут все враховується
); Не рахується

;;; Варіант 2

(розмикання витяжних рядків (string & aux (початок 0) (кінець 0)); не враховується
  (речі) ;;; Тут все враховується
); Не рахується.
Усі інші лямбда в повному обсязі відносяться до кількості байтів.


Хіба цього не питали раніше?
Ісмаїл Мігель

1
Так, але я повторно запитав його на Meta і вніс істотні зміни до неї, перш ніж публікувати її тут Через це його не слід класифікувати як дублікат (інший пов'язаний з ним повинен бути закритим, якщо ще не є).
Ісія Медоуз

2
Чи не повинен ваш "гольф" розміщуватися як відповідь?
MrWhite

4
Вибачте, але -1 за заборону GolfScript. Усі мови повинні бути дозволені.
Дверна ручка

1
@Doorknob Це правда, але я також розумію почуття ОП. Люди повинні мати шанс змагатись, навіть якщо вони не розмовляють із GolfScript, J або APL (і я винен, що переглядаю останніх у цих змаганнях.) Чи можете ви поглянути на мою пропозицію в темі, з якою він пов’язаний?
Тобія

Відповіді:


10

APL, 13 символів

(або 28/30 байт, читайте нижче)

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

Я бачу, що ви заборонили GolfScript від свого запитання. Я розумію ваші настрої, але я сподіваюся, що ця громада в кінцевому підсумку не заборонить APL, оскільки це справді чудова мова програмування з довгою історією, не кажучи вже про багато цікавого для кодування. Можливо, її просто можна оцінити інакше, якщо люди відчуваю, що вона конкурує несправедливо. Я викладу свої думки з цього приводу на ту нитку, яку ви пов’язали.

На цьому ж маркуванні я завжди додавав виноску до своїх публікацій APL, стверджуючи, що APL може бути оцінено як 1 char = 1 байт. Моя претензія спирається на той факт, що кілька (переважно комерційні) реалізацій APL все ще підтримують власну застарілу однобайтову кодування із символами APL, відображеними на верхні 128 значень байтів. Але, можливо, це занадто велика розтяжність, і в цьому випадку ви можете оцінити цей запис як 28 байт у UTF-16 або 30 байт в UTF-8.

Пояснення

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

Щодо Вашого коментаря, я думаю, що для інших мов справедливо конкурують з "скороченими", кожен символ в інших мовах слід вважати одним знаком. Наприклад, моє рішення Mathematica, розміщене тут, повинно рахуватися як 7 (більше чи менше). Дизайн мови зі стислими лексемами зовсім не заслуга, я думаю.
Доктор Белісарій,

Не могли б ви надати шестигранний відвал свого гольфу? Я не можу прочитати деяких персонажів.
Isiah Meadows

@impinball Як би допомогти вам hexdump? Це не так, як ти б бачив, що робиться.
mniip

@impinball APL-код є {omega enclose commute omega epsilon epsilon формат кожного йота 10}. Якщо вам потрібні значення unicode, ви можете просто скопіювати і вставити їх на будь-який інтернет-інструмент , навіть якщо ви не бачите символів (що дивно, оскільки у більшості сучасних шрифтів Unicode є символи APL). {\ u2375 \ u2282 \ u2368 \ u2375 \ u220a \ u220a \ u2355 \ u00a8 \ u237310} (майте на увазі останнє "10", яке не входить до послідовності втечі)
Tobia

1
Замість цього ∊⍕¨⍳10, ви не могли просто використовувати⎕D ? Це має бути постійним '0123456789'. Dyalog APL принаймні підтримує його, як і NARS2000.
marinus

5

Пітон 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]}

Інтернет-версія для тестування

Оскільки перетворення будь-якого нецифрового символу в int повертає 0 в Ruby (з to_i), перетворення кожного char в int і назад в char - це нерегексивний спосіб перевірити цифру ...


Ви також можете зробити ("0" .. "9") члена? на кожен шар, але те, що ви зробили, вже коротше
fgp

Ви, безумовно, праві - я мав би сказати: "a" шлях;)
David Herrmann

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])/це дуже схоже на заміну regexp, але це не так. Це розширення параметрів bash , яке відповідає правилам відповідності шаблону , а не правилам регулярного вираження.

Повернення справжніх типів масиву bash з функцій bash - це біль, тому я вирішив замість цього повернути обмежений простір список, а потім перетворити на масив у призначенні масиву поза викликом функції. Отже, з метою справедливості, я вважаю, що (` `)навколо моменту оцінки повинен бути включений виклик функції.


3

Математика 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]+"]] &

Математика висмоктує регекс.
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 знаків.
Цифрова травма

1
Ваша функція повертає "розділений пробілом список" замість масиву. Звичайно повернення справжніх масивів з Баш функції незручно, але ви могли б по крайней мере , привласнити результат вашої функції в масив в вашому використанні: a=($(split "12 3a bc123")); echo ${a[@]}. Можна стверджувати, що "($ ())" враховується у вашому рахунку
Digital Trauma

Перш ніж вивчити trпідхід, я спробував це зробити з розширенням параметра . trце, безумовно, кращий підхід для цілей гольфу.
Цифрова травма

Ви намагалися оточити trоператор розширення? Вийшло б щось на зразок ($(tr...)), і де декларація функції не враховується, зовнішні дужки не будуть зараховані проти вас. Це була б лише частина підстановки команд.
Isiah Meadows

Я не бачу, як це має працювати, але я не вільно володію масивами Баша. У будь-якому випадку, (``)конструкція на 1 бал краща, ніж конструкція, ($())і їй слід віддати перевагу.
Coaumdio

2

Smalltalk (Smalltalk / X), 81

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

значення f: 'abc123def456' -> OrdersCollection ('123' '456')

значення f: 'aitew034snk582: 3c' -> OrdersCollection ('034' '582' '3')

значення f: 'as5493tax54 \ 430-52@g9.fc' -> OrriedCollection ('5493' '54' '430' '52' '9')

f значення: 'sasprs] tore \ "re \ forz' -> OrdersCollection ()

зітхання - Smalltalk має тенденцію використовувати найменування довгих функцій veeeery ...


2
Це ім'я функції? o__O
Tobia

@tobia Мабуть ...
Isiah Meadows

asCollectionOfSubCollectionsSeparatedByAnyForWhichಠ_ಠ Це ім'я занадто довго
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

Перл, 53

Редагувати: немає відповідностей, sub тепер повертає список із порожнім рядком (замість порожнього списку), як потрібно.

Він також уникає поділу на один простір символів, оскільки він викликає "розкол на будь-яку поведінку білого простору" , що, ймовірно, порушує правила. Я міг би використовувати / /роздільник, який би розділявся на один простір, але парадоксально це виглядатиме, як використовувати шаблон регулярного виразів. Я міг би використати unpackціною деяких зайвих персонажів і так splitвзагалі позбутися суперечок, але я вважаю, що те, чим я закінчую, розбиваюсь на буквальний символ (крім простору), це нормально.

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

І, ні, оператор транслітерації Perl не робить регулярних виразів. Я можу скасувати діапазон 0-9, 0123456789якщо в цьому проблема.


Поки він не використовує регулярні вирази, він дійсний.
Isiah Meadows

Мій Perl не такий сильний. Якщо я розумію код, ви заміняєте нецифрові знаки на певну нецифрову, потім розділяєте на вибраний нецифровий, а потім фільтруєте порожні рядки. Це правильне читання?
Тім Сегуїн

1
@TimSeguine: Не зовсім так. Нецифрові цифри замінюються та стискаються до одного символу, розщеплення за яким утворює порожній рядок, якщо цей роздільник є на початку. Потім він зміщується, якщо список містить інші записи.
користувач2846289

Порожній список добре.
Isiah Meadows

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

Перший аргумент - це вхідний рядок, другий - це вихідний масив, який являє собою масив рядків, що закінчується 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 виходить таким коротким щодо цього, враховуючи, наскільки це багатослівний (13 байт лише для CR). Він проходить цикл через рядок, замінюючи будь-які нечислові символи пробілами, потім зменшує пробіл до одиничних пробілів, а потім використовує роздільник пробілу для поділу.

Тестові справи

Input: "ab5c0x"
Output: 5,0

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

Закінчення рядків DOS вважаються одним символом, наскільки я читав на мета.
Іся Медоуз

Я запропонував вам редагувати.
Isiah Meadows

Підрахунок вже передбачає закінчення рядка 1 байт стилю Linux. За моїм рахунком я отримую 190 символів (просто перевірено ще раз).
Комінтерн

Добре. Я, мабуть, зробив облік.
Isiah Meadows

1

Лис звичайний (1 відповідно до букви; ≈173 відповідно до духу)

Ось читабельна версія. Кількість байтів досить велика через довгі імена в таких речах, як digit-char-pі position-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")
#()

Поняття "декларація функції" є щось неясне. Ось версія, що має лише один байт (символ xу тілі функції); все інше вкладається в допоміжні змінні списку "lamba" функції (частина декларації функції):

(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-ifоскільки воно з’являється двічі, використовувати змінні однієї літери тощо).

Ця програма має 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))

Якщо нічого іншого, це повинно сприяти змінним загальним 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остаточної дужки, це буде тіло. Частина, що визначає назву та параметри, - це декларація.
Isiah Meadows

Будь ласка, зверніться до правила 2 моїх змінених правил, щоб побачити, про що я дійсно говорю в декларації функції (в основному, оголосити ім'я функції, параметри та, якщо потрібно синтаксично, що рідко серед інтерпретованих мов, тип повернення).
Ісія Медоуз

@impinball Так, «1» відлік свого роду жарт, але важлива частина тут є те , що result буде оголошений в якості параметра тут; він просто має дуже нетривіальну форму ініціалізації. У принципі це те саме, що і необов'язковий аргумент зі значенням за замовчуванням, яке обчислюється деяким складним виразом. (У більш простих випадках легко уявити щось на зразок char* substring( char *str, int begin, int end(0) )якоїсь мови з C-подібним синтаксисом, щоб вказати, що endце необов'язково, а якщо він не надається, то його значення є 0. Я просто підкреслюю той факт, що деякі з цих термінів
Джошуа Тейлор

@impinball не є достатньо конкретним та агностичним мовою, щоб запобігти підрахунку байтових тролеїв. :)
Джошуа Тейлор

Перша частина, яка не вказує параметри, - це те, де я би підрахував статистику (наприклад (defun fn (string &aux (start 0) (end 0), не рахував би, але все, що залишилося в лямбда).
Isiah Meadows

0

JavaScript, 240 байт

А для тих, хто цікавий, ось мій, мабуть, величезний гольф:

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коли їх передають на булеви.
kelunik

@kelunik, який також відфільтрує 0,
Ейнасіо,

0

С, 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 немає вбудованих функцій друку масиву, мені довелося робити цю роботу самостійно, тому я вибачаюся, що у кожному виході є остаточна кома. По суті, те, що робить цей код, це те, що він читає рядок, якщо він не є цифрою, він замінює його на '\ 0', а потім я просто перебираю код і роздруковую всі ланцюги цифр. (EOF = 0)

Вхід: ab5c0x
Вихід: ["5", "0",]

Вхід: z526ks4f.; 8] \ p
Вихід: ["526", "4", "8",]


Відповідно до правил запитання (правило 2), вам потрібно лише порахувати символи в тілі функції. Таким чином, ваше рішення фактично буде менше 170 байт. Я не впевнений, чи включає в себе число змінних прототипів поза тілом функції.
grovesNL

Я буду змінювати правила щодо цього: #defines, змінні декларації тощо будуть рахуватися, але оголошення функції не буде.
Isiah Meadows

Крім того, востаннє я перевіряв, чи був такий тип в C, char[][]який є легальним. Якщо ви повернетесь таким (або char**), вам буде добре.
Іся Медоуз

Це не повинно бути виведенням тексту? Я хоч програма повинна була вивести масив у строковому форматі
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);
}

По-перше, для цього використовується .Select()метод розширення LINQ для перетворення всіх нецифрових знаків у коми. string.Replace()було б кращим, оскільки він повертає stringскоріше, ніж а IEnumerable<char>, але string.Replace()може приймати лише одну таблицю чи рядок і не може використовувати присудок, як char.IsDigit()або 47<c&c<58.

Як було сказано, .Select()застосований до рядка повертає an IEnumerable<char>, тому нам потрібно повернути його в рядок, перетворивши його в масив і передавши масив в stringконструктор.

Нарешті, ми розділили рядок за допомогою коми string.Split(). (StringSplitOptions)1це коротший спосіб вимови StringSplitOptions.RemoveEmptyEntries, який автоматично бере на себе кілька послідовних коми і коми на початку / кінці рядка.


1
Замість цього char.IsDigit(c)ви можете використовувати'/'<c&&c<':'
grovesNL

1
Хороше запитання ... або навіть краще, 47<c&&c<58. (Чесно кажучи, я здивований, що це працює з номерами, але, мабуть, так і є).
БенМ

1
І я можу зберегти додатковий цінний персонаж, використовуючи сингл "&" замість подвійного "&&". У C # це все-таки логічно І, коли обидва операнди булеві - це робить лише побітові І, коли вони цілі.
БенМ

Хороший. Я не знав, що зможе це зробити.
grovesNL

Трохи коротший варіант - розділити на пробіл замість ,, а потім видалити порожні елементи вручнуreturn new string(s.Select(c=>47<c&c<58?c:' ').ToArray()).Split().Where(a=>a!="").ToArray();
VisualMelon

0

JS / Вузол: 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)і деякі інші речі
Не те, щоб Чарльз

Декларація функції не зараховується до рахунку (причина полягає в тому, щоб допомогти вирівняти ігрове поле)
Isiah Meadows,

Добре. Коригується оцінка відповідно до коментаря @ impinball. (Насправді тут задекларовано дві функції. Підрахунок
знаків

Це повинно. Я оновив правила, щоб допомогти пояснити це краще.
Isiah Meadows

Тим часом придумав щось краще ...
паланік

0

Рубі, 24

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

Визначає цифри, використовуючи негативний пробіл у діапазоні ascii для друку.


Декларація функції не враховується.
Ісія Медоуз

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

Описовий код:

function splitdigits($input){

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


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

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

}

return $output;
}

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


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

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

0

Python

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

0

Python 104 83

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

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

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

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


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

0

PHP 98 89

As in DigitalTrauma's bash answer, this doesn't use a regex.

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

Test cases:

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

0

Haskell 31

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

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

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


0

VBA 210, 181 without function declaration

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

0

Rebol (66 chars)

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

Ungolfed and wrapped in function declaration:

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

Example code in Rebol console:

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

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

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

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

0

JavaScript, 104 97 89

Golfed:

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

2/27: Using ?: saves the wordiness of if/else.

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

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

Ungolfed:

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

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

0

Javascript, 72

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

Ungolfed

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

Sample input/output

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

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

JSFiddle


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

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

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

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

0

R 52

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

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

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

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

0

PHP 99

<?php

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

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


Output

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

0

JavaScript 88

88 chars when not counting function n(x){}

function n(x){
y=[],i=0,z=t=''
while(z=x[i++])t=!isNaN(z)?t+z:t&&y.push(t)?'':t
if(t)y.push(t)
return y
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.