Разделить строку при первом появлении каждого символа


45

Связанный.

Получив печатную строку ASCII, разбейте ее на список непустых строк с новой подстрокой, начинающейся каждый раз, когда встречается символ, который ранее не встречался в том же случае.

Примеры

"mississippi" → ["m","i","ssissi","ppi"]

"P P & C G" → ["P"," P ","& ","C ","G"]

"AAA" → ["AAA"]

"Adam" → ["A","d","a","m"]

"" → []


Анекдот : результат будет иметь от 0 до 95 элементов. 95- я подстрока будет обязательно продолжаться до конца, потому что в этот момент все печатные символы ASCII начали подстроку, поэтому каждый дополнительный символ будет встречаться раньше и, следовательно, не может вызвать начало новой подстроки.


1
Пример, содержащий "и, 'кажется, хорошая идея.
Emigna

Будет ли ""[""]приемлемым?
Арно

5
@Emigna Это просто портит пример выходного формата без дополнительной ясности.
Адам

1
Если выводится как строка, разделенная символом новой строки, может ли быть начальный / конечный символ новой строки?
wastl

2
@wastl Э-э, я разрешу это в этом случае, потому что он не может указывать пустые сегменты, хотя это противоречит моему предыдущему решению о [""]недействительности. Вздох.
Адам

Ответы:


22

Желе , 4 байта

QƤĠị

Попробуйте онлайн!

объяснение

QƤĠị  Input is a string, say s = "adam"
 Ƥ    For each prefix of s: ["a","ad","ada","adam"]
Q     remove duplicates: ["a","ad","ad","adm"]
  Ġ   Group indices by equal values: [[1],[2,3],[4]]
   ị  Index into s: ["a","da","m"]

Внутреннее представление строк, которое отображает ссылка TIO, немного отличается.



6

05AB1E , 11 байт

ÙSk¥sg¸«£õK

Попробуйте онлайн!

объяснение

Ù             # remove duplicates in input
 S            # split to a list of characters
  k           # get the (first) index of each character in the input
   ¥          # calculate delta's
    sg¸«      # append the length of the input
        £     # split the list into pieces of these sizes
         õK   # remove empty string (for the special case "" -> [])

1
Для тех, кто сталкивается с этим ответом, ¸«может быть ªв новой версии 05AB1E.
Кевин Круйссен

6

C  75   65  63 байта

Спасибо @Digital Trauma за сохранение 10 байтов и спасибо @gastropner и @ l4m2 за сохранение байта каждый!

f(char*s){for(int l[128]={};*s;putchar(*s++))l[*s]++||puts(l);}

Печатает ведущий перевод строки.

Попробуйте онлайн!

Без перевода строки (71 байт):

f(char*s){int l[128]={};for(l[*s]=1;*s;putchar(*s++))l[*s]++||puts(l);}

Попробуйте онлайн!



@gastropner Умный трюк; Спасибо!
Steadybox

{0}=> {}?
l4m2

@ l4m2 Да, спасибо!
Steadybox

5

Perl 6 ,  58 52  40 байт

{$/={};.comb.classify({$+=!$/{$_}++}).sort».value».join}

Попробуй

*.comb.classify({$+=!(%){$_}++}).sort».value».join

Попробуй

*.classify({$+=!(%){$_}++}).sort».value

Попробуйте
(вход - это список символов, а вывод - список списков символов).

Expanded:

*                   # parameter for WhateverCode lambda

  .classify(        # classify that list
    {
        $           # anonymous scalar state variable (accumulator)

      +=            # increment it if:

        !           # Bool invert the following
          (
            %       # anonymous hash state variable
          ){ $_ }++ # look to see if the character was seen already
    }
  ).sort\           # sort the Pairs by key (makes the order correct)
  ».value           # get the value from each Pair

Выход из classifyIS

{ # Hash
  1 => ['m'],
  2 => ['i'],
  3 => ['s','s','i','s','s','i'],
  4 => ['p','p','i'],
}

И .sortпросто превращает это в:

[
  1 => ['m'],
  2 => ['i'],
  3 => ['s','s','i','s','s','i'],
  4 => ['p','p','i'],
]

».value удаляет ключи

[
  ['m'],
  ['i'],
  ['s','s','i','s','s','i'],
  ['p','p','i'],
]

Почему ключи когда-нибудь вышли из строя? Разве порядок вставки не отслеживается как a HashMapпротив a LinkedHashMapв Java, где порядок основан на памяти против порядка вставки?
Волшебная урна осьминога

1
@MagicOctopusUrn Ни одна версия Perl не заказывала хэши. Фактически, Perl 5 версии 18 сделал Хэши более рандомизированными, что помогает сделать определенный тип атаки типа «отказ в обслуживании» менее вероятным, а также заставил ошибочный пользовательский код чаще выявлять его ошибочное поведение. Теперь кто-то может (и, вероятно, имеет) реализовать класс, который отслеживает, но для загрузки и использования потребуется более 5 символов.
Брэд Гилберт b2gills

5

J 7 байт

~:<;.1]

Попробуйте онлайн!

объяснение

Нуб-сито шанс сиять!

~: <;.1 ]
        ]  Input
~:         Nub sieve (1 if the character is the first instance in string)
    ;.1    Split input on 1s in nub sieve
   <       And box each

2
Я собирался опубликовать точно такой же (не удивительно) ответ, это хорошо, что я посмотрел ваше представление до этого :)
Гален Иванов

2
@GalenIvanov Я - и я думаю, что большинство других игроков в гольф J тоже - наслаждаюсь возможностью использовать сито или классифицировать себя.
Коул

5

APL (Dyalog Unicode) , 8 байтов SBCS

(≢¨∪\)⊆⊢

Попробуйте онлайн!


Но, но ... О боже.
Адам

Я подозревал, что вы могли опубликовать этот вызов из-за нового примитива (⊆). Очевидно, нет :)
НГН

Похоже, смущенный Кирби держит детскую бутылочку.
Волшебная урна осьминога

для всех, кому нужно посмотреть «Кирби», как я, - это антропоморфный розовый шар из японской видеоигры
августа

5

05AB1E , 8 байтов

Ùvyy¶ì.;

Попробуйте онлайн!


Всегда будет выводить 1 предшествующий символ новой строки, который является константой и не указывает на разделение. 10-байтовая альтернатива, которая не выводит предыдущий символ новой строки Ùvyy¶ì.;}¦, вы можете попробовать здесь . Согласно Адаму, предшествующий или завершающий перевод строки является приемлемым.


Input      = mississippi                               | Stack
-----------#-------------------------------------------+----------------------------------
Ù          # Push unique letters of first input.       | ['misp']
 v         # Iterate through each unique letter.       | []
  yy       # Push 2 copies of the letter (or yD)       | ['m','m']
    ¶      # Push a newline char.                      | ['m','m','\n']
     ì     # Prepended to the letter.                  | ['m','\nm']
      .;   # Replace first instance with '\n + letter' | ['\nmississippi']

После каждой итерации мы получаем:

['\nmississippi'] > ['\nm\nississippi'] > ['\nm\ni\nssissippi'] > ['\nm\ni\nssissi\nppi']

Который:

m
i
ssissi
ppi

Приятно! Обыграй меня с
большим

@Emigna это сидел как комментарий к твоему ответу в течение 2 дней, тогда я только отправил это без ответа, ха-ха: P.
Волшебная Урна Осьминога

Странно, не видел никакого уведомления об этом.
Впрочем,

@ Emigna, я имею в виду, я удалил это, ха-ха.
Волшебная Урна Осьминога

Пропуск цикла спасает байт ÙSD¶ì.;. Не уверен, почему мы не думали об этом раньше: P
Emigna

5

Haskell , 39 байт

foldl(\s c->s++['\n'|all(/=c)s]++[c])""

Попробуйте онлайн!

Вставляет символ новой строки перед каждым символом, который появляется впервые, в результате получается строка, разделенная новой строкой, с ведущей новой строкой. Приготовьтесь lines.составить список.


Haskell , 55 байтов

(""%)
_%[]=[]
p%s|(a,b)<-span(`elem`s!!0:p)s=a:(a++p)%b

Попробуйте онлайн!

Неоднократно принимает префикс первого символа плюс неуникальные символы, следующие за ним.


@WheatWizard Упс, да lines.
xnor

Возможно, мне захочется tail.linesудалить лишнюю пустую строку, когда я думаю об этом.
Пшеничный волшебник

4

APL (Дьялог) , 9 байт

Спасибо, Эрик Outgolfer за сохранение 1 байта!

⊢⊂⍨⍳∘≢∊⍳⍨

Попробуйте онлайн!

Объяснение:

⍳⍨: Для каждого символа получить индекс его первого появления. напримерmississippi -> 1 2 3 3 2 3 3 2 9 9 2

⍳∘≢: Диапазон от 1 до длины ввода.

: Членство. например1 2 3 4 5 6 7 8 9 10 11∊1 2 3 3 2 3 3 2 9 9 2 -> 1 1 1 0 0 0 0 0 1 0 0

⊢⊂⍨: Разделить входную строку новыми разделами, начинающимися 1с s в векторе выше


9 байтов (монадическое fgи монадическое f∘gведут себя одинаково)
Эрик Outgolfer

Почему вместо =?
Адам

На момент написания статьи я не думал, что индексы будут в правильном положении. Хотя понятно, что они
H.PWiz

4

Japt , 11 байт

‰ r@=iRUbY

Проверьте это онлайн!

объяснение

Это был вдохновлен Волшебное Octopus Урна «s решение 05AB1E .

‰ r@=iRUbY    Implicit: U = input string
‰             Split U into chars, and keep only the first occurrence of each.
   r@          Reduce; for each char Y in this string...
        UbY      Find the first index of Y in U.
      iR         Insert a newline at this index in U.
     =           Set U to the result.
               As reduce returns the result of the last function call, this gives the
               value of U after the final replacement, which is implicitly printed.

1
У Джапта кризис идентичности, по какой-то причине он называет себя Руби. iRUbY!
Волшебная Урна Осьминога

3

JavaScript (ES6), 37 байт

Сохранено 7 байт: начальный перевод строки был явно разрешен (Спасибо @Shaggy!)

Принимает ввод как массив символов. Вывод строки, разделенной новой строкой.

s=>s.map(c=>s[c]=s[c]?c:`
`+c).join``

Контрольные примеры


Разрешены ведущие символы новой строки, поэтому вы можете уменьшить их до 37 байт
Shaggy

3

брейкфук, 66 байт

,[>+[<[>+<<-<+>>-]>[>]<<[[+]++++++++++.>>>]<]<[>+<-]>>>[>>]<<-.>,]

отформатирован:

,
[
  >+
  [
    <[>+< <-<+>>-]
    >[>]
    <<[[+]++++++++++.>>>]
    <
  ]
  <[>+<-]
  >>>[>>]
  <<-.>,
]

Попробуйте онлайн

Новую строку в выводе (которая выводится только в том случае, если ввод не пуст) можно удалить за счет 5 байтов, заменив тело xосновного (самого внешнего) цикла на .>,[x].



2

К4 , 19 байт

Решение:

$[#x;(*:'.=x)_;,]x:

Примеры:

q)k)$[#x;(*:'.=x)_;,]x:"mississippi"
,"m"
,"i"
"ssissi"
"ppi"
q)k)$[#x;(*:'.=x)_;,]x:"P P & C G"
,"P"
" P "
"& "
"C "
,"G"
q)k)$[#x;(*:'.=x)_;,]x:"AAA"
"AAA"
q)k)$[#x;(*:'.=x)_;,]x:"Adam"
,"A"
,"d"
,"a"
,"m"
q)k)$[#x;(*:'.=x)_;,]x:""
,[""]

Объяснение:

8 байт просто для обработки ""...

$[#x;(*:'.=x)_;,]x: / the solution
                 x: / save input as variable x
$[  ;         ; ]   / $[condition;true;false]
  #x                / length of x ("" has length 0, i.e. false)
             _      / cut right at left indices
     (      )       / do together
          =x        / group x into key/value (char!indices)
         .          / return value (get indices)
      *:'           / first (*:) each
               ,    / enlist, "" => [""]

2

Python 2 , 81 74 байта

def f(s):d=sorted(map(s.find,set(s)));print map(lambda a,b:s[a:b],d,d[1:])

Попробуйте онлайн!



@JonathanAllan это вводящий в заблуждение побочный эффект, setне следите за порядком, контр-доказательства ->s='c'*6+'a'*100+'b'
Род

Я знаю, что мы не можем полагаться на это в будущих реализациях, но я полагаю, что при заданных упорядоченных целых числах мы сохраняем порядок в наборе из-за того, что хеш целого числа является целым числом (как вы показали, что это не так для других объектов - можете ли вы найти слово, которое не работает с моей альтернативой?).
Джонатан Аллан


Ах, честно, моя вера была ложной!
Джонатан Аллан


2

Perl, 30 байт

Включает +1в себя дляp

Дайте ввод без завершающей новой строки на STDIN. Вывод также без завершающей строки:

echo -n adam | perl -pE 's%.%$v{$&}+++!pos?$&:$/.$&%eg'; echo

Если вы не заботитесь о ведущей и ведомой новой строки это 25( +3для -pпотому что код содержит ') также работает:

#!/usr/bin/perl -p
s%%$/x!$v{$'&~v0}++%eg

Отличное решение как всегда! Исходя из предоставленных тестовых примеров, вам не нужно называть свой хэш, вы можете это сделать ${$&}++. Это не так надежно, но может быть достаточно для этого вызова? Кроме того, был достигнут консенсус в отношении мета, perl -pкоторый не требует дополнительного байта, вам просто нужен заголовок, а Perl with `-p` не просто Perl. Я пытаюсь не забыть сделать это сам ...
Дом Гастингс

@DomHastings Анекдот о не более чем 95 возможных строках довольно убедительно подразумевает, что 1это действительно так, и в этом случае vнеобходимо. Что касается подсчета, я в основном следую codegolf.meta.stackexchange.com/a/7539/51507, который для меня является наиболее последовательным мета-постом о подсчете perl.
Тон Хоспел

Всегда приятно учиться у мастера. Именно в этом случае &~v0для захвата первого персонажа. Спасибо, что присоединились к этому сайту и поделились своим долгим опытом.
msh210

Вы можете использовать Strawberry Perl, который использует "вместо 'с -e, а затем вы можете считать -epкак +1, а не +3. (Проверено.)
msh210

2

JavaScript, 61 54 52 байта

Принимает ввод как массив символов.

s=>s.map(x=>a[x]?a[y]+=x:a[x]=a[++y]=x,a=[],y=-1)&&a

Попробуй

o.innerText=JSON.stringify((f=
s=>s.map(x=>a[x]?a[y]+=x:a[x]=a[++y]=x,a=[],y=-1)&&a
)([...i.value=""]));oninput=_=>o.innerText=JSON.stringify(f([...i.value]))
<input id=i><pre id=o></pre>


2

R , 94 87 байт

function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))

Попробуйте онлайн!

Возвращает (возможно, пустой) список подстрок.

Спасибо Michael M за сохранение 7 байтов!


3
function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))будет короче - и, конечно, немного уродливее ...
Майкл М

Почему substringвместо substr?
plannapus

@MichaelM Очень мило! Я все еще должен добавить if(n)туда, потому что substringвыдает ошибку для ввода пустой строки.
Джузеппе

1
@plannapus substrвозвращает вектор длины, равный его первому входу, а substringвозвращает длину, равную наибольшему из его входов.
Джузеппе

@Giuseppe: удаление «if (n)» в R 3.4.3 отображает пустую входную строку «« в пустую выходную строку »», что должно быть хорошо (?)
Майкл М

2

Stax , 8 байт

ç↓‼►▐NVh

Запуск и отладка онлайн

Представление ascii той же программы таково.

c{[Ii=}(m

Для каждого символа он разделяется, когда индекс текущего символа является текущей позицией.

c            copy the input
 {    }(     split the string when the result of the enclosed block is truthy
  [          duplicate the input string under the top of the stack
   I         get the character index of the current character
    i=       is it equal to the iteration index?
        m    print each substring

2

> <> , 22 17 14 байтов

-1 байт благодаря Emigna

i:::a$1g?!o1po

Попробуйте онлайн!

Печатает начальный и конечный перевод строки.

Он отслеживает, какие буквы уже появились, pвыдавая копию символа в соответствующем месте во второй строке и печатая новую строку, если значение, выбранное из этой позиции не было 1. Завершается ошибкой при попытке печати-1


Отличное использование g/p! 16 байт
Emigna


1

JavaScript (ES6), 68 байт

s=>s.map(c=>o[c]?t+=c:(t&&m.push(t),t=o[c]=c),t='',o=m=[])&&[...m,t]

Вводит в виде списка символов.

Тестовые случаи:


У меня было похожее решение, и я спросил, [""]приемлемо ли это для последнего контрольного примера. Но это не так . :-(
Арнаулд

Ну, в любом случае, вы получили гораздо лучшее решение:)
Рик Хичкок,

1

PHP, 317 байт

function SplitOnFirstUnique($s){
    $len = strlen($s); 
    $output = [];
    $newstring = '';
    for ($i=0; $i < $len ; $i++) { 
        $newstring = $newstring.$s[$i];
        if(!in_array($s[$i] , $output  )){
            $output[] = $newstring;
            $newstring = '';
        }
    }
    return $output;
}

Попробуйте онлайн!


2
Здравствуйте и добро пожаловать в PPCG! Я отредактировал ваше сообщение в нашем стандартном формате и добавил ссылку на Try It Online, чтобы другие люди могли проверить ваш код. Цель Code Golf - написать максимально короткий код, и я вижу несколько способов сделать это короче, например, использовать более короткие имена переменных и исключить некоторые из пробелов. Вы можете ознакомиться с общими советами и страницами с советами по PHP, чтобы узнать больше идей.
Не дерево

1

Красный , 79 байт

func[s][foreach c next unique/case append s"^@"[print copy/part s s: find s c]]

Попробуйте онлайн!

Ungolfed:

f: func [s] [
    b: next unique/case append s "^@"  ; append `null` to the end of the string, than
                                       ; find the unique characters and 
                                       ; store all except the first to b  
    foreach c b [                      ; for each character in b
        print copy/part s s: find s c  ; print the part of the string to
                                       ; where the character is found and
                                       ; set the beginning of the string to that position
    ]
] 

1

СНОБОЛ4 (CSNOBOL4) , 115 91 77 байт

	N =INPUT
S	N LEN(1) . Y	:F(END)
	S =S Y
	N SPAN(S) . OUTPUT REM . N	:(S)
END

Попробуйте онлайн!

Печатает подстроки, разделенные символами новой строки.

Объяснение:

строка S(for SPLIT) фактически не разделяется, а извлекает первый символ Nи сохраняет его ( .) в Y. На Failure он прыгает на END. Совпадение должно завершиться неудачно только тогда, когда Nпустая строка. Таким образом, когда вход пуст, он сразу переходит ENDи ничего не выводит.

S = S Yсоединяется Yна S.

SPAN(S)жадно сопоставляет набор символов в Sи отправляет его ( .) в OUTPUTsetting ( .) Nдля REMследующих символов N(если они есть). Затем он возвращается к S.



1

Рубин , 65 62 58 байт

->s,*a{s.size.times{|i|(i==s.index(c=s[i])?a:a[-1])<<c}
a}

Попробуйте онлайн!

Лямбда, принимающая строку и возвращающая массив строк.

Подход: для каждого индекса либо добавьте символ с этим индексом в sмассив результатов, либо в последнюю строку в массиве результатов. String#indexвозвращает индекс первого экземпляра аргумента.

-2 байта: Инициализировать aкак аргумент splat вместо отдельной строки. Спасибо, стоимость чернил !

-1 байт: Используйте c=s[i]... cвместо s[i]... s[i]. Спасибо, стоимость чернил !

-4 байта: использовать .timesвместо.map



1

Java 8, 193 169 155 151 байт

s->{for(int l=s.length(),i=0,j;i<l;i++)if(s.indexOf(s.charAt(i))==i){for(j=i;++j<l&&s.indexOf(s.charAt(j))!=j;);System.out.println(s.substring(i,j));}}

-14 байтов благодаря @raznagul (за что-то очевидное, я почему-то упустил себя ..)
-3 байта благодаря @OOBalance (снова за что-то очевидное, я как-то пропустил себя ..: S)

Объяснение:

Попробуйте онлайн.

s->{                    // Method with String parameter and no return-type
  for(int l=s.length(), //  The length of the input-String
          i=0,j;        //  Index integers
      i<l;i++)          //  Loop `i` from 0 to `l` (exclusive)
    if(s.indexOf(s.charAt(i))==i){
                        //   If the character at index `i` hasn't occurred yet:
      for(j=i;++j<l     //    Inner loop `j` from `i` to `l` (exclusive),
          &&s.indexOf(s.charAt(j))!=j;);
                        //     as long as the character at index `j` has already occurred
      System.out.println(//    Print:
        s.substring(i,j));}}
                        //     The substring of the input from index `i` to `j` (exclusive)

1
Я не думаю, что вам нужно if(l<1). Если lэто 0цикл не должен выполняться в любом случае, как 0<0есть false.
Разнагул

@raznagul Не знаю, как я это пропустил, но вы правы! ..>.>
Кевин Круйссен

Вы сидите i=0дважды. Вы можете сэкономить 3 байта, опустив второй:for(;i<l;i++)
OOBalance

@OOBalance Не уверен, как это произошло ..: S Но спасибо, что заметили! :)
Кевин Круйссен
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.