Вибух перегляду струни


39

Чи не любите ви ті діаграми, що розриваються, в яких машина або предмет розбиваються на найдрібніші шматочки?

введіть тут опис зображення

Давайте зробимо це до рядка!

Змагання

Напишіть програму або функцію, яка

  1. вводить рядок, що містить лише символи для друку ASCII ;
  2. розчленовує рядок на групи непробільних рівних символів ("шматки" рядка);
  3. виводить ці групи в будь-якому зручному форматі, з деяким роздільником між групами .

Наприклад, подано рядок

Ah, abracadabra!

Вихідні дані будуть наступними групами:

!
,
А
ааааа
bb
c
г
год
rr

Кожна група у висновку містить рівні символи з пробілами. Нова лінія використовується як роздільник між групами. Більше про дозволені формати нижче.

Правила

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

Можна припустити, що вхід містить щонайменше один непробільний символ .

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

Якщо висновок здійснюється через функцію return, це також може бути масив або рядки, або масив масивів символів, або схожа структура. У цьому випадку структура забезпечує необхідне розділення.

Роздільник між символами кожної групи необов’язковий . Якщо він існує, застосовується те саме правило: воно не може бути символом, який не є пробілом, і може з’являтися на вході. Крім того, це не може бути той самий роздільник, який використовується між групами.

Крім цього, формат є гнучким. Ось кілька прикладів:

  • Групи можуть бути рядками, розділеними новими рядками, як показано вище.

  • Групи можуть бути розділені будь-яким символом, що не належить до ASCII, наприклад ¬. Виведенням для вищевказаного входу буде рядок:

    !¬,¬A¬aaaaa¬bb¬c¬d¬h¬rr
    
  • Групи можуть бути розділені n > 1 пробілами (навіть якщо n є змінним) з символами між кожною групою, розділеними одним пробілом:

    !  ,    A   a a a a a    b b  c       d   h  r r
    
  • Вихідним може бути також масив або список рядків, повернутих функцією:

    ['!', 'A', 'aaaaa', 'bb', 'c', 'd', 'h', 'rr']
    
  • Або масив масивів char:

    [['!'], ['A'], ['a', 'a', 'a', 'a', 'a'], ['b', 'b'], ['c'], ['d'], ['h'], ['r', 'r']]
    

Приклади форматів, які не дозволені, відповідно до правил:

  • Кома не може бути використана як роздільник ( !,,,A,a,a,a,a,a,b,b,c,d,h,r,r), оскільки вхід може містити коми.
  • Не прийнято пропускати роздільник між групами ( !,Aaaaaabbcdhrr) або використовувати один і той же роздільник між групами та всередині груп ( ! , A a a a a a b b c d h r r).

Групи можуть з’являтися у будь-якому порядку у висновку. Наприклад: алфавітний порядок (як у прикладах вище), порядок першої появи в рядку, ... Порядок не повинен бути послідовним або навіть детермінованим.

Зауважте, що вхідні дані не можуть містити символи нового рядка Aта aє різними символами (групування залежить від регістру ).

Виграє найкоротший код у байтах.

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

У кожному тестовому випадку перший рядок вводиться, а решта - це вихід, причому кожна група в іншому рядку.

  • Тест 1:

    Ах, абракадабра!
    !
    ,
    А
    ааааа
    bb
    c
    г
    год
    rr
    
  • Тест 2:

    \ o / \ o / \ o /
    ///
    \\\
    ооо
    
  • Тест 3:

    Чоловік, план, канал: Панама!
    !
    ,,
    :
    А
    П
    аааааааа
    c
    буду
    мм
    nnnn
    p
    
  • Тестовий випадок 4:

    "Покажіть мені, як ви робите цей трюк, той, який змушує мене кричати", - сказала вона
    ""
    ,
    S
    ааааа
    куб
    дд
    еееееее
    hhhhhh
    ii
    кк
    мммм
    н
    ooooo
    rr
    ssss
    tttttt
    у
    ww
    у
    

1
Якщо ми використовуємо символи, що не належать до ASCII, як "¬", як роздільник, чи можна це рахувати як 1 байт?
Leaky Nun

5
@LeakyNun Ні, вона буде зарахована так, як відповідає залежно від кодування, використовуваного для вихідного коду, як зазвичай
Луїс Мендо

Чи прийнятний останній рядок після останньої групи?
JustinM

Чи прийнятний провідний новий рядок продукції?
DJMcMayhem

1
@RohanJhunjhunwala Молодці! :-) Так, декілька нових рядків як розділювачів добре
Луїс Мендо

Відповіді:



23

Python 3.5+, 77 46 44 41 байт

lambda s:[a*s.count(a)for a in{*s}-{' '}]

Досить просто. Переходить через унікальні символи в рядку, перетворюючи його на набір (використовуючи розширене розпакування програми Python 3.5), потім використовує розуміння списку для побудови розірваних діаграм, підраховуючи кількість разів, в яких кожен символ відбувається в рядку str.count. Ми фільтруємо пробіли, видаляючи їх із набору.

Порядок виводу може змінюватися від запуску до запуску; множини є не упорядкованими, тому порядок, в якому обробляються їх елементи, і, таким чином, ця відповідь виводиться, не можна гарантувати.

Це лямбда-вираз; використовувати його, префікс lambdaс f=.

Спробуйте це на Ideone! Ideone використовує Python 3.4, що недостатньо.

Приклад використання:

>>> f=lambda s:[a*s.count(a)for a in{*s}-{' '}]
>>> f('Ah, abracadabra!')
[',', 'A', 'aaaaa', 'd', '!', 'bb', 'h', 'c', 'rr']

Збережено 3 байти завдяки @shooqie!


3
Поздравляємо на 1 к!
Луїс Мендо

2
В Python> 3,5 ви можете зробити {*s}для set(s).
shooqie

11

Сітківка, 13 байт

O`.
!`(\S)\1*

Сортування дуже просте (це вбудований), це розділення літер, що займає 9 байт. Спробуйте в Інтернеті!

Перший рядок s Orts всі збіги регулярного вираження. (який є кожним символом), що дає нам !,Aaaaaabbcdhrr.

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


Що робить! Робити?
Пуховик


8

Perl 6 , 28 байт

*.comb(/\S/).Bag.kv.map(*x*)

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

Пояснення:

# Whatever lambda 「*」


# grab the characters
*.comb(
  # that aren't white-space characters
  /\S/
)
# ("A","h",",","a","b","r","a","c","a","d","a","b","r","a","!")


# Turn into a Bag ( weighted Set )
.Bag
# {"!"=>1,","=>1,"A"=>1,"a"=>5,"b"=>2,"c"=>1,"d"=>1,"h"=>1,"r"=>2}


# turn into a list of characters and counts
.kv
# ("!",1,",",1,"A",1,"a",5,"b",2,"c",1,"d",1,"h",1,"r",2)


# map over them 2 at a time
.map(
  # string repeat the character by the count
  * x *
)
# ("!",",","A","aaaaa","bb","c","d","h","rr")

7

Vim, 50 , 46 байт

i <esc>:s/./&\r/g
:sor
qq:%s/\v(.)\n\1/\1\1
@qq@qD

Пояснення / gif надійдуть пізніше.


1
Одного разу рішення Emacs & vim виглядають однаково.
YSC

7

Піта, 6

.gk-zd

Спробуйте тут або запустіть тестовий набір .

Досить просто, -zdвидаляє пробіли з вхідних даних і .gkгрупує кожен залишився елемент за його значенням. На жаль, я не знайшов способу використання змінних автозаповнення. Зауважте, що висновок відображається у вигляді рядків Python, тому певні символи (читати: зворотні косої риси) уникають. Якщо ви хочете, щоб він був більш читабельним, додайте jдо початку коду.


7

Haskell, 38 байт

f s=[filter(==c)s|c<-['!'..],elem c s]

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



6

JavaScript (ES6), 41 байт

s=>[...s].sort().join``.match(/(\S)\1*/g)

Чи не спричинить це також запис " "у поверненому масиві? Не впевнений, чи дозволено це
Ink Ink

@ValueInk Ба, я думав про це, коли почав, але негайно забув. Виправлено зараз.
Ніл

Гм, як join()викликається з тими подвійними задніми палками?
Техас Кале

1
@TejasKale Це рядок шаблону ES6. Коли ви префіксуєте метод до рядка шаблону, він передає шаблон як масив методу, тому в цьому випадку він закінчується викликом .join(['']). joinпотім перетворює це в (порожній) рядок і використовує його для приєднання елементів масиву. Не всі методи перетворюють їх параметр у рядок, але ця методика зручна для тих, що роблять.
Ніл


5

Haskell, 40 байт

f x=[v:w|d<-['!'..],v:w<-[filter(==d)x]]

Приклад використання: f "Ah, abracadabra!"-> ["!",",","A","aaaaa","bb","c","d","h","rr"].

Шаблон v:wвідповідає лише списку щонайменше з одним елементом, тому всі символи, які не є у вводі, ігноруються.

Також 40 байт:

import Data.List
group.sort.filter(>' ')

@ThreeFx: Але groupвід Data.Listтеж. У будь-якому випадку, я думаю, що цей синтаксис є ghciлише і потребує відповіді, тому мова є власною . Я хочу дотримуватися стандартного Haskell.
німі

4

Ruby, 41 + 1 = 42 байти

+1 байт для -nпрапора.

gsub(/(\S)(?!.*\1)/){puts$1*$_.count($1)}

Здійснює введення інформації про stdin, наприклад:

$ echo 'Ah, abracadabra!' | ruby -ne 'gsub(/(\S)(?!.*\1)/){puts$1*$_.count($1)}'
A
h
,
c
d
bb
rr
aaaaa
!

4

C # 125 98 байт

using System.Linq;s=>s.GroupBy(c=>c).Where(g=>g.Key!=' ').Select(g=>new string(g.Key,g.Count())));

Пояснення

//Using anonymous function to remove the need for a full signature 
//And also allow the implicit return of an IEnumerable
s =>

    //Create the groupings
    s.GroupBy(c => c)

    //Remove spaces
    .Where(g=> g.Key!=' ')

    //Generate a new string using the grouping key (the character) and repeating it the correct number of times
    .Select(g => new string(g.Key, g.Count()));
  • Завдяки @TheLethalCoder, який запропонував використовувати анонімну функцію, яка також дозволила мені видалити ToArrayвиклик і просто неявно повернути IEnumerable, що разом економить 27 байт

Ви можете зберегти 18 байт (якщо я правильно порахував), компілювавши його в Func<string, string[]>ies=>s.GroupBy....
TheLethalCoder

@TheLethalCoder Ви впевнені, що це є прийнятним замість функції, я завжди насторожено ставився до цього, тому що він додає ще трохи зайвої котлової панелі, щоб мати змогу виконати її, і аргумент щодо необхідності використання Linq просто здається ... ну неправильно.
JustinM

Ось недавній приклад, коли я це роблю ... codegolf.stackexchange.com/a/91075/38550 він видалить усі ваші шаблони, доки дозволені функції
TheLethalCoder

@TheLethalCoder Добре, що для мене досить добре. :) Це також дозволило мені зняти дзвінок ToArray
JustinM - Поновити Моніку

4

R, 198 189 96 95 байт

for(i in unique(a<-strsplit(gsub(" ","",readline()),"")[[1]]))cat(rep(i,sum(a==i)),"\n",sep="")

Безголівки:

a<-strsplit(gsub(" ","",readline()),"")[[1]] #Takes the input from the console

for(i in unique(a)) #loop over unique characters found in variable a

cat(rep(i,sum(a==i)),"\n",sep="") # print that character n times, where n was the number of times it appeared

Наразі це рішення не працює повністю, коли \вони задіяні.
Тепер це!

Спасибі набагато вам @JDL для гри в гольф з 102 байт!


@JDL: Просимо запропонувати зміни в коментарях. Ваші зміни дійсно цікаві, але начебто брутально змінювати чужий код таким чином.
Фредерік

1
вибачте за це, але в мене тоді не було 50 репутації і я не міг коментувати. Зробимо в майбутньому, хоча!
JDL

@JDL: Досить справедливо!
Фредерік

Спробуйте призначити змінну всередині функції: for(i in unique(a=strsplit(gsub(" ","",readline()),"")[[1]]))cat(rep(i,sum(a==i)),"\n",sep="")- зберігає 2 байти.
Андрей Костирка

@ AndreïKostyrka: У цій формі він не зберігає байти, тому що ви повинні помістити цілу частину a = strsplit (...) між дужками: в основному це різниця -2 + 2. Однак, використовуючи, <-ви заощадите 1 байт!
Фредерік

4

Свіфт, 105 91 байт

Дякуємо @NobodyNada за 14 байт :)

Так, я досить новачка у Свіфта ...

func f(a:[Character]){for c in Set(a){for d in a{if c==d && c != " "{print(c)}}
print("")}}

Символи в межах групи розділені одним новим рядком. Групи розділені двома новими рядками.


Ви можете зберегти 13 байт, взявши введення [Character]замість а String, оскільки правила говорять "Вхід повинен бути рядком або масивом символів". Також print("")можна замінити просто print().
NobodyNada

@NobodyNada printбез аргументів чомусь не спрацював, але [Character]пропозиція була твердою. Спасибі!
jrich

3

Октава , 61 байт

@(x)mat2cell(y=strtrim(sort(x)),1,diff(find([1 diff(+y) 1])))

Це анонімна функція, яка приймає рядок як вхідний і виводить масив рядків комірок.

Спробуйте в Ideone .

Як це працює

  • sortсортує вхідний рядок. Зокрема, пробіли будуть на початку.
  • strtrim видаляє провідні пробіли.
  • diff(+y) обчислює послідовні відмінності між символами (для виявлення групових меж) ...
  • ... так diff(find([1 diff(+y) 1])дає вектор групових розмірів.
  • mat2cell потім розбиває відсортовану рядок на шматки з тими розмірами.

3

Математика, 36 байт

Тут вбудовані функції Gatherта Charactersвиконують більшу частину роботи.

Gather@Select[Characters@#,#!=" "&]&

3

> <> , 49 байт

i:0(?v
84}0~/&{!*
v!?: <}/?=&:&:<
>&1+&}aol1-?!;^

Дуже просто марно витрачається на виході, але я припускаю, що все-таки дозволено з огляду на поблажливість правил

Пояснення:

i:0(?v           Collects text from input
84}0~/&{!*       adds 32 (first ascii starting at space) to register and 0 to stack
v!?: <}/?=&:&:<  checks all characters to the current register, if equal:
       o         prints the character and continues looping
>&1+&}aol1-?!;^  when all characters are checked, adds 1 to register, prints a newline,
                 checks the stack length to halt the program if 0, and starts looping again

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

В основному це ставить кожен символ ASCII на свій новий рядок, і якщо жоден із цих символів не існує, рядок буде порожнім

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

Редагувати: я помилявся, у коді сталася помилка, що призвело до того, що він ніколи не завершиться, якщо у введенні буде пробіл


3

Pyth, 5 байт

.gksc

Спробуйте тут!

Приймає дані як рядок Python (тобто загортається в лапки, уникнуті лапки та косої риси).

Пояснення:

    c    Split (implied) input on whitespace
   s     Sum together
.gk      Group by value

Якщо ви гарантуєте хоча б один простір на вході, є 4-байтове рішення:

t.gk

Спробуйте тут!

Пояснення:

 .gk (Q)  groups the characters in the string by their value
           this sorts them by their value, which guarantees that spaces are first
t         Remove the first element (the spaces)

3

PowerShell v2 +, 44 байти

[char[]]$args[0]-ne32|group|%{-join$_.Group}

Вводить введення $args[0]як лінійний рядок аргументу командного рядка. Визначає це як- charмасив і використовує оператор -not ekval для виведення пробілів (ASCII)32 ). Це працює тому, що кастинг має перевагу більш високого порядку, і коли масив використовується як лівий оператор зі скаляром як правий, він діє як фільтр.

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

Тепер у нас є власні об’єкти (и), які мають назви груп, рахунки тощо. Якщо ми просто надрукуємо, у нас з'явиться безліч сторонніх даних. Таким чином, ми повинні труби ті в петлю , |%{...}і кожна ітерація -joinв.Group разом в один рядок. Ці результуючі рядки залишаються на конвеєрі, а висновок неявний після завершення програми.

Приклад

PS C:\Tools\Scripts\golfing> .\exploded-view-of-substrings.ps1 'Programming Puzzles and Code Golf'
PP
rr
ooo
gg
aa
mm
i
nn
u
zz
ll
ee
s
dd
C
G
f


2

Обробка, 109 байт

void s(char[] x){x=sort(x);char l=0;for(char c:x){if(c!=l)println();if(c!=' '&&c!='\n'&&c!='\t')print(c);l=c;}}

Її груба сила підходить, сортуйте масив, а потім проведіть крізь нього. Якщо він не відповідає останньому друкованому символу, спочатку надрукуйте новий рядок. Якщо це пробіл, пропустіть крок друку.


2

Javascript (за допомогою зовнішньої бібліотеки - безліч) ( 78 67 байт)

 n=>_.From(n).Where(y=>y!=' ').GroupBy(x=>x).WriteLine(y=>y.Write())

Посилання на lib: https://github.com/mvegh1/Eumerable

Пояснення коду: Це було зроблено численними! Завантажте рядок у бібліотеку, яка перетворить його на масив char. Відфільтруйте записи пробілів. Групуйте за ознакою. Запишіть кожну групу до рядка за вказаним присудком. Цей предикат говорить про об'єднання всіх елементів поточної групи в рядок, без роздільника.

введіть тут опис зображення



2

Перл6, 48 47 45

slurp.comb.Bag.kv.map:{$^a.trim&&say $a x$^b}

Завдяки манетарній роботі за покращення.


1
Не велике поліпшення, але, $a.trimздається, це робиться для стану.
манантська робота

Здається, логічним операторам все ще не потрібні пробіли навколо них, тому $^a.trim&&say $a x$^bпрацює. (Вибачте за додавання підказок байтом, але це моя перша спроба на Perl6.)
манатура

Маленький друкарський помилок, ви випадково видалили отвір {.
манастирські роботи

1

Рубін, 46 байт

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

->s{(s.chars-[' ']).uniq.map{|c|c*s.count(c)}}

Моя оригінальна повна версія програми, 48 байт після додавання nпрапора:

p gsub(/\s/){}.chars.uniq.map{|c|c*$_.count(c)}

Ви можете замінити .count(c)з .count c?
Кіос

@Cyoce немає, оскільки *оператор присутній поруч, і аналізатор скаржиться.
Значення чорнила

s.chars- [''] | [] всередині дужок уникне uniq
GB

@GB Це було б, але якщо ми прив'язуємо його до нього, mapтоді йому потрібні додаткові паролі і ((s.chars-[' '])|[]).mapмає таку ж кількість символів, що і (s.chars-[' ']).uniq.map. А інший, коротший спосіб перевірити унікальні символи (за допомогою regex), вже розглядає @Jordan в іншій відповіді
Value Ink

Це працює всередині дужок, вам не потрібні додаткові дужки, оскільки пріоритет '-' вище.
ГБ

1

Пітона, 107

Можливо скоротити лямбда, але пізніше

x=sorted(input())
i=0
while i<len(x):x[i:]=['  '*(x[i]!=x[i-1])]+x[i:];i-=~(x[i]!=x[i-1])
print("".join(x))

1

CJam, 10 байт

{S-$e`::*}

Неназваний блок, який очікує рядок у верхній частині стека і замінює його списком рядків.

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

Пояснення

S-  Remove spaces.
$   Sort.
e`  Run-length encode, gives pairs [R C], where R is the run-length and
    C is the character.
::* Repeat the C in each pair R times.

1

Загальний Лісп, 123

(lambda(s &aux(w(string-trim" "(sort s'char<))))(princ(elt w 0))(reduce(lambda(x y)(unless(char= x y)(terpri))(princ y))w))

Безголовки:

(lambda (s &aux (w (string-trim " " (sort s 'char<))))
  (princ (elt w 0))
  (reduce
    (lambda (x y) 
      (unless (char= x y) (terpri))
      (princ y))
  w))

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


1

Emacs, 36 натискань клавіш

C-SPACE C-EM-xsort-rTABRETURN.RETURN.RETURNC-AC-M-S-%\(\(.\)\2*\)RETURN\1C-QC-JRETURN!

Результат

A man, a plan, a canal: Panama! ->

!
,,
:
A
P
aaaaaaaaa
c
ll
mm
nnnn
p

Пояснення

  1. C-SPACE C-E
  2. M-x sort-rTAB RETURN .RETURN .RETURN
  3. C-A
  4. C-M-S-% \(\(.\)\2*\)RETURN\1 C-Q C-JRETURN !

  1. Виберіть рядок введення;
  2. Дзвінок sort-regexp-fieldsз аргументами .і .;
    • Аргумент №1: Regexp уточнюючі записи для сортування
    • Аргумент №2: ключ повторного визначення Regexp у записах
  3. Повернення на початку лінії;
  4. Застосовувати заміну regexp \(\(.\)\2*\)-> \1\nна всіх матчах.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.