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


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
Приклад, що містить "і 'здається гарною ідеєю.
Емінья

Буде чи ""[""]бути прийнятним?
Арнольд

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

Спробуйте
(введення - це список символів, а вихід - список списків символів)

Розширено:

*                   # 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

Вихід з classify-

{ # 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'],
]

Чому ключі ніколи не вийшли з ладу? Чи не відслідковується порядок вставки, як 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

Але, але ... О мій.
Адам

Я підозрював, що ви могли опублікувати цей виклик через нового примітиву (⊆). Очевидно, що не :)
квітня 1818

Схоже, збентежений Кірбі тримає дитячу пляшечку.
Чарівний восьминіг Урна

для всіх, кому потрібно шукати "Кірбі", як я - це антропоморфний рожевий куля з японської відеоігри
п.

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 днів, тоді я просто опублікував це b / c без відповіді haha: P.
Чарівний восьминога Урна

Дивно, не бачили жодного повідомлення про це. Хоча
інакше

@Emigna добре, я маю на увазі, я його видалив ха-ха.
Magic Octopus Urn

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

5

Хаскелл , 39 байт

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

Спробуйте в Інтернеті!

Вставляє символ нового рядка перед кожним символом, який з’являється вперше, в результаті чого рядок, відокремлений новим рядком, із ведучим новим рядком. Заздалегідь складіть lines.список.


Хаскелл , 55 байт

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

Спробуйте в Інтернеті!

Неодноразово приймає префікс перший символ плюс не унікальні символи, які слідують за ним.


@WheatWizard На жаль, так lines.
xnor

Можливо, я хочу зробити, tail.linesщоб видалити зайвий порожній рядок зараз, коли я думаю про це.
Пшеничний майстер

4

APL (Dyalog) , 9 байт

Дякуємо, Ерік Аутгольфер за економію 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

⊢⊂⍨: Розбийте вхідний рядок з новими розділами, починаючи з 1s у векторі вище


9 байт (монадійні fgта монадійські f∘gповодяться так само)
Ерік Переможник

Чому замість =?
Адам

На момент написання я не вважав, що показники будуть у правильних позиціях. Хоча зрозуміло, що вони є
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
Тут у Japt виникає криза ідентичності, вона чомусь називає себе Рубі. 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'
Пд

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

@JonathanAllan також не правда
стрижень

Ах, досить чесно, моя віра була помилковою!
Джонатан Аллан


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

Спробуйте в Інтернеті!

Повертає (можливо, порожній) список підрядків.

Дякую Майклу М за збереження 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?
планнапус

@MichaelM Дуже приємно! Я все ще повинен додати if(n)туди, оскільки substringвидає помилку для порожнього введення рядка.
Джузеппе

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

@Giuseppe: Відміняючи "if (n)" в R 3.4.3 відображає порожній рядок введення "" в порожній рядок виходу "", що має бути нормальним (?)
Michael M

2

Стакс , 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 байт завдяки Еміньї

i:::a$1g?!o1po

Спробуйте в Інтернеті!

Друкує провідний та нижчий новий рядок.

Він відслідковує, які літери вже з’явилися, pвиписавши копію символу на відповідному місці у другому рядку та надрукувавши новий рядок, якщо значення, отримане з цієї позиції, не було 1. Закінчується помилкою при спробі друку-1


Велике використання g/p! 16 байт
Емінья


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! Я відредагував вашу публікацію до нашого стандартного формату та додав посилання на Спробуйте в Інтернеті, щоб інші люди могли перевірити ваш код. Метою Code Golf є написання найкоротшого можливого коду, і я бачу кілька способів зробити це скороченим, як, наприклад, використання коротших назв змінних та залишення частини пробілу. Ви можете ознайомитись із загальними порадами та сторінками PHP-підказок, щоб отримати ще кілька ідей.
Не дерево

1

Червоний , 79 байт

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

Спробуйте в Інтернеті!

Безголівки:

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

SNOBOL4 (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(для SPLIT) насправді не розбивається, але замість цього витягує перший символ Nі зберігає його ( .) в Y. У Fневдачі вона стрибає на END. Збіг повинен провалюватися лише тоді, коли Nє порожній рядок. Таким чином, коли вхід порожній, він перескакує безпосередньо ENDі нічого не видає.

S = S Yконкатенати Yна S.

SPAN(S)жадібністю відповідає біг персонажів S, і посилає його ( .) , щоб OUTPUT, настройки ( .) Nдо REMAining символів 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 замість власного рядка. Дякуємо, Value Ink !

-1 байт: Використовуйте c=s[i]... cзамість s[i]... s[i]. Дякуємо, Value Ink !

-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

@raznagul Не впевнений, як я це пропустив, але ти маєш повне право! ..>.>
Кевін Кройсейсен

Ви встановлюєте i=0двічі. Ви можете зберегти 3 байти, скинувши другий:for(;i<l;i++)
OOBalance

@OOBalance Не знаю, як це сталося ..: S Але дякую, що помітили! :)
Кевін Круїссен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.