Самая короткая программа для разбиения строки без цифр без RegExps


16

РЕДАКТИРОВАТЬ: Если вы используете Lisp, я дал некоторые рекомендации в подсчет байтов.

Цель: создать самую короткую функцию, которая разбивает строку на нецифровые символы и возвращает массив, состоящий только из цифр в каждой строке, без использования каких-либо регулярных выражений. Ведущие нули должны быть включены в каждую строку.

Текущие результаты (разделены на категории):

  • C / C ++ / C # / Java: 68 (C) ....
  • GolfScript / APL / J: 13 (APL)
  • Все остальные: 17 (Bash, использует tr), 24 (Ruby)

Правила:

(Прошу прощения за длительность)

  1. Формат должен быть как функция с одним строковым аргументом. При необходимости для правильного возврата массива может быть добавлено до двух дополнительных аргументов (например, для sh / csh / DOS Batch требуется дополнительная ссылка на переменную для возврата и т. Д.).
  2. Объявление первичной функции не учитывается, равно как и импорт других стандартных библиотек. `# include`s,` import`s и `using`s не учитываются. Все остальное делает. Это включает в себя `# define`s и вспомогательные функции. Извините за путаницу. Обратитесь к этому как к полезному руководству относительно того, что учитывается / не учитывается (написано в синтаксисе в стиле C)
    // к общему количеству не относится, может быть опущено, если
    // неочевидно, как половина стандартной библиотеки Java.
    #include <stdio.h>
    
    import some.builtin.Class // не в счет, см. выше
    
    #define printf p // рассчитывает на общее количество
    
    / * Подсчитать любые другие директивы препроцессора и т. Д. * /
    
    int i = 0; // считает
    
    SomeFunction (); // считает
    
    char [] [] myMainSplitFunction (массив char [] []) {// не считается
      // Здесь все имеет значение
      return returnArray; // Даже это считается.
    } // не считается
    
    / * Здесь учитывается все, включая объявление * /
    char [] [] someHelperFunction (char [] string) {
      // материал
    } // даже это считается
    
  3. Выходные данные должны быть строковым массивом или аналогичным (допустимы списки массивов в Java и аналогичные). Примеры принятого выхода: String[], char[][], Array, List, и Array(объект).
  4. Массив должен содержать только строковые примитивы переменной длины или строковые объекты. В возвращении не должно быть пустых строк, за исключением ниже. Примечание: строки должны содержать строку последовательных совпадений, например, пример ввода и вывода ниже.
  5. Если совпадений нет, тело функции должно вернуть nullпустой массив / список или массив / список, содержащий пустую строку.
  6. Внешние библиотеки не допускаются.
  7. Окончания строки DOS считаются одним байтом, а не двумя (уже включены в мета, но необходимо подчеркнуть)
  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, [], [""] или аналогичный

Пожалуйста, укажите, сколько байтов используется в ваших ответах, и, как всегда, счастливого гольфа!


Руководство для Лисп

Вот что учитывается и не учитывается на диалектах Лисп:

;;; Опция 1

(defun extract-strings (ab); не считается
  (вещи) ;;; Все здесь имеет значение
); Не считается

;;; Вариант 2

(defun extract-strings (string & aux (начало 0) (конец 0)); Не считается
  (вещи) ;;; Все здесь имеет значение
); Не считается
Все остальные лямбды полностью учитываются в счет байтов.


Разве это не спрашивалось раньше?
Исмаэль Мигель

1
Да, но я повторно спросил его в Meta и внес в него существенные изменения, прежде чем опубликовать его здесь. Из-за этого он не должен классифицироваться как дубликат (другой связанный должен быть закрыт, если это еще не сделано).
Isiah Meadows

2
Разве ваш "гольф" не должен быть опубликован в качестве ответа?
MrWhite

4
Извините, но -1 за запрещение GolfScript. Все языки должны быть разрешены.
Дверная ручка

1
@ Doorknob Это правда, но я также понимаю чувства ОП. У людей должен быть шанс участвовать в соревнованиях, даже если они не говорят на GolfScript, J или APL (и я виновен в том, что просматривал последние на этих соревнованиях). Можете ли вы взглянуть на мое предложение в теме, с которой он связан?
Tobia

Ответы:


10

APL, 13 символов

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

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

Я вижу, вы запретили GolfScript с вашего вопроса. Я понимаю ваше мнение, но я надеюсь, что это сообщество в конечном итоге не запретит APL, потому что это действительно замечательный язык программирования с длинной историей, не говоря уже о том, что писать код интересно, может быть, он может быть оценен иначе, если люди чувствую, что это несправедливо конкурирует. Я опубликую свои мысли по этому вопросу в той теме, которую вы связали.

На этом же токене я всегда добавлял сноску к своим сообщениям APL, утверждая, что APL может быть оценен как 1 символ = 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? Это не так, как вы бы видели, что делается.
Мниип

@impinball код APL: {omega вложите коммутируемый формат omega epsilon epsilon в каждую йоту 10}. Если вам нужны значения Unicode, вы можете просто скопировать и вставить их в любой онлайн-инструмент , даже если вы не видите символов (что странно, поскольку большинство современных шрифтов Unicode имеют символы APL). В любом случае вы получаете следующее {\ u2375 \ u2368 \ u275a \ u220a \ u2355 \ u00a8 \ u237310} (помните последние "10", которые не являются частью escape-последовательности)
Тобия

1
Вместо того ∊⍕¨⍳10, чтобы вы не могли просто использовать ⎕D? Это должно быть постоянным '0123456789'. Dyalog APL, по крайней мере, поддерживает его, как и NARS2000.
Маринус

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

Онлайн версия для тестирования

Так как преобразование любого нецифрового символа в int возвращает 0 в Ruby (с to_i), преобразование каждого символа в int и обратно в тип char является не-регулярным способом проверки на наличие цифры ...


Вы также можете сделать ('0' .. '9'). Member? для каждого символа, но то, что вы сделали, уже короче
фгп

Вы определенно правы - я должен был сказать: "путь";)
Дэвид Херрманн

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 символов.
Цифровая травма

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

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

Вы пытались окружить trоператор расширения? Было бы что-то вроде этого ($(tr...)), и если объявление функции не учитывается, внешние скобки не будут учитываться против вас. Это будет только часть подстановки команд.
Исия Медоус

Я не понимаю, как это должно работать, но я не свободно владею массивами Bash. В любом случае, (``)конструкция на 1 символ лучше, чем та, ($())которая должна быть предпочтительной.
Коаумдио

2

Smalltalk (Smalltalk / X), 81

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

Значение f: 'abc123def456' -> OrderedCollection ('123' '456')

Значение f: 'aitew034snk582: 3c' -> OrderedCollection ('034' '582' '3')

Значение f: 'as5493tax54 \ 430-52@g9.fc' -> OrderedCollection ('5493' '54' '430' '52' '9')

Значение f: 'sasprs] tore \ "re \ forz' -> OrderedCollection ()

sigh - Smalltalk имеет тенденцию использовать очень длинные имена функций ...


2
Это имя функции? o__O
Тобия

@tobia Видимо ...
Isiah Meadows

asCollectionOfSubCollectionsSeparatedByAnyForWhichಠ_ಠ Это имя слишком длинное
TuxCrafting

1

Р, 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 не выполняет регулярные выражения. Я могу развернуть диапазон 0-9, 0123456789если это проблема.


Пока он не использует регулярные выражения, он действителен.
Исия Медоуз

Мой Perl не такой сильный. Если я понимаю код, вы заменяете нецифровые символы на определенные нецифровые, затем разделяетесь на выбранные нецифровые, а затем отфильтровываете пустые строки. Это правильное чтение?
Тим Сегин

1
@TimSeguine: не совсем. Нецифровые символы заменяются и сводятся к одному символу, разбиение на которое приводит к появлению пустой строки, если этот разделитель оказывается в начале. Затем он удаляется, если список содержит другие записи.
user2846289

Список Enpty в порядке.
Исия Медоуз

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

Первый аргумент - это входная строка, второй - выходной массив, который является массивом строк с нулевым символом в конце. Достаточная память должна быть зарезервирована для 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 символов (только что подтверждено).
Коминтерн

Ok. Должно быть, я ошибся.
Исия Медоус

1

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

Если ничего другого, это должно продвигать переменные Common Aup's & 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последней скобки, чтобы быть телом. Часть, которая определяет имя и параметры, является декларацией.
Исия Медоус

Пожалуйста, обратитесь к правилу 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, который также отфильтровывает 0s
Einacio

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

Кроме того, в прошлый раз, когда я проверял, в Си был указан тип, char[][]который является допустимым. Если вы вернетесь как (или char**), все будет в порядке.
Isiah Meadows

Это не должен быть текстовый вывод? Я думал, что программа должна была выводить массив в строковом формате
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скорее, чем a IEnumerable<char>, но string.Replace()может принимать только один символ или строку и не может использовать предикат типа char.IsDigit()or 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. (Честно говоря, я удивлен, что это работает с числами, но, очевидно, это работает).
BenM

1
И я могу сохранить дополнительный ценный символ, используя один '&' вместо двойного '&&'. В C # это все еще логическое И, когда оба операнда являются логическими значениями - это делает только побитовое И когда они целые.
BenM

Хороший. Я не знал, что смог это сделать.
grovesNL

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

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)и некоторые другие вещи
не то, что Чарльз

Объявление функции не учитывается при подсчете очков (причина в том, чтобы помочь выровнять игровое поле)
Isiah Meadows

Ok. Скорректирована оценка в соответствии с комментарием @ impinball. (На самом деле здесь объявлены две функции. Число
символов

Должно. Я обновил правила, чтобы помочь объяснить это лучше.
Isiah Meadows

Между тем, придумал что-то лучше ...
Паланик

0

Руби, 24

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

Определяет цифры, используя отрицательное пространство в диапазоне для печати ascii.


Объявление функции не считается.
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;}

Описательный код:

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(). и вам даже не нужно разбивать строку, чтобы перебрать ее символы. кроме того, учитывается только внутренний код функции, так что это ваш счетчик символов 204.
Einacio

Объявление функции не считается. Обратитесь к правилу 2 в качестве руководства о том, что имеет значение, а что нет.
Исия Медоус


0

питон 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") == []

Это не приводит к выводу, поэтому код работает, если выполняется один за другим, так как некоторые переменные определены в объявлении.


Вам не нужно считать объявление функции, если вы это сделали. Так же, как головы
Исия Медоус

0

PHP 98 89

Как и в ответе bash от DigitalTrauma, здесь не используется регулярное выражение.

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

Haskell 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

Реболь (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

Golfed:

Редактировать: когда циклы выходят из конца массива, cэтоundefined , что falsy и завершает цикл.

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
}

Возврат каретки в корпусе предназначен для удобства чтения и не является частью решения.

Ungolfed:

Идея состоит в добавлении каждого символа в последнюю запись в массиве, если это цифра, и в противном случае, чтобы последняя запись в массиве была строкой.

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

Пример ввода / вывода

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
Мне это нравится! Гораздо проще, чем мой собственный. Вы можете сбросить еще 8 символов, заменив if(+a[i]+1)b+=a[i];else if(b)c.push(b),b=""на b=+a[i]+1?b+a[i]:b?(c.push(b),""):b.
DocMax

@DocMax спасибо, я отредактировал, чтобы включить ваше предложение :). Это (c.push(b),"")казалось умным, никогда не видел этого.
Дэнни

Я забыл об этом, пока не увидел, что он широко использовался ранее сегодня в 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

88 символов, если не считать функцию 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.