Exploded view of a string

38

5

Don't you love those exploded-view diagrams in which a machine or object is taken apart into its smallest pieces?

enter image description here

Let's do that to a string!

The challenge

Write a program or function that

  1. inputs a string containing only printable ASCII characters;
  2. dissects the string into groups of non-space equal characters (the "pieces" of the string);
  3. outputs those groups in any convenient format, with some separator between groups.

For example, given the string

Ah, abracadabra!

the output would be the following groups:

!
,
A
aaaaa
bb
c
d
h
rr

Each group in the output contains equal characters, with spaces removed. A newline has been used as separator between groups. More about allowed formats below.

Rules

The input should be a string or an array of chars. It will only contain printable ASCII chars (the inclusive range from space to tilde). If your language does not support that, you can take the input in the form of numbers representing ASCII codes.

You can assume that the input contains at least one non-space character.

The output should consist of characters (even if the input is by means of ASCII codes). There has to be an unambiguous separator between groups, different than any non-space character that may appear in the input.

If the output is via function return, it may also be an array or strings, or an array of arrays of chars, or similar structure. In that case the structure provides the necessary separation.

A separator between characters of each group is optional. If there is one, the same rule applies: it can't be a non-space character that may appear in the input. Also, it can't be the same separator as used between groups.

Other than that, the format is flexible. Here are some examples:

  • The groups may be strings separated by newlines, as shown above.

  • The groups may be separated by any non-ASCII character, such as ¬. The output for the above input would be the string:

    !¬,¬A¬aaaaa¬bb¬c¬d¬h¬rr
    
  • The groups may be separated by n>1 spaces (even if n is variable), with chars between each group separated by a single space:

    !  ,    A   a a a a a    b b  c       d   h  r r
    
  • The output may also be an array or list of strings returned by a function:

    ['!', 'A', 'aaaaa', 'bb', 'c', 'd', 'h', 'rr']
    
  • Or an array of char arrays:

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

Examples of formats that are not allowed, according to the rules:

  • A comma can't be used as separator (!,,,A,a,a,a,a,a,b,b,c,d,h,r,r), because the input may contain commas.
  • It's not accepted to drop the separator between groups (!,Aaaaaabbcdhrr) or to use the same separator between groups and within groups (! , A a a a a a b b c d h r r).

The groups may appear in any order in the output. For example: alphabetical order (as in the examples above), order of first appearance in the string, ... The order need not be consistent or even deterministic.

Note that the input cannot contain newline characters, and A and a are different characters (grouping is case-sentitive).

Shortest code in bytes wins.

Test cases

In each test case, first line is input, and the remaining lines are the output, with each group in a different line.

  • Test case 1:

    Ah, abracadabra!
    !
    ,
    A
    aaaaa
    bb
    c
    d
    h
    rr
    
  • Test case 2:

    \o/\o/\o/
    ///
    \\\
    ooo
    
  • Test case 3:

    A man, a plan, a canal: Panama!
    !
    ,,
    :
    A
    P
    aaaaaaaaa
    c
    ll
    mm
    nnnn
    p
    
  • Test case 4:

    "Show me how you do that trick, the one that makes me scream" she said
    ""
    ,
    S
    aaaaa
    cc
    dd
    eeeeeee
    hhhhhh
    ii
    kk
    mmmm
    n
    ooooo
    rr
    ssss
    tttttt
    u
    ww
    y
    

Luis Mendo

Posted 2016-08-24T22:37:12.873

Reputation: 87 464

1If we use non-ASCII symbols like "¬" as separator, can it be counted as 1 byte? – Leaky Nun – 2016-08-24T22:39:35.527

5@LeakyNun No, it will be counted as it corresponds depending on the encoding used for the source code, as usual – Luis Mendo – 2016-08-24T22:40:31.503

Is a trailing newline after the last group acceptable? – None – 2016-08-24T23:10:42.463

Is a leading newline of output acceptable? – James – 2016-08-24T23:16:07.843

@DJMcMayhem Sure. That can't be mistaken with any input char – Luis Mendo – 2016-08-24T23:17:08.213

Argh! Im too late to this party. A patch to SILOS was written at 12:00 AM this morning, It now can actually accept multiline string input. but it now would be noncepeting with this feature – Rohan Jhunjhunwala – 2016-08-25T14:16:35.157

@RohanJhunjhunwala Can't you take input as an array of ASCII codes? I included that specially for you! – Luis Mendo – 2016-08-25T14:52:34.257

@LuisMendo ok I will. – Rohan Jhunjhunwala – 2016-08-25T15:06:45.513

Your third and fourth output format examples step from 5 'a's to 4 'a's. – Delioth – 2016-08-25T15:40:05.430

@Delioth Thanks! Corrected – Luis Mendo – 2016-08-25T15:57:13.057

I think the proper term for this is "knolling": https://en.wikipedia.org/wiki/Knoll_(verb)

– Michael Schumacher – 2016-08-25T19:28:23.013

@LuisMendo I'm almost there, One clarification can I output unpaced groups that have no members? Essentially my output is separated with n >= 1 new lines where n is variable – Rohan Jhunjhunwala – 2016-08-25T20:03:39.793

@LuisMendo I did it! – Rohan Jhunjhunwala – 2016-08-25T20:24:23.437

1@RohanJhunjhunwala Well done! :-) Yes, several newlines as separators is fine – Luis Mendo – 2016-08-25T21:35:55.683

Answers

11

Jelly, 5 bytes

ḟ⁶ṢŒg

Try it online!

It does return an array, just that when it is printed to STDOUT, the separator is gone.

This is indeed a function that can be called as such (in Jelly, each line is a function).

ḟ⁶ṢŒg
ḟ⁶      filter out spaces
  Ṣ     sort
   Œg   group

Leaky Nun

Posted 2016-08-24T22:37:12.873

Reputation: 45 011

23

Python 3.5+, 77 46 44 41 bytes

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

Pretty simple. Goes through the unique characters in the string by converting it to a set (using Python 3.5's extended iterable unpacking), then uses a list comprehension to construct the exploded diagrams by counting the number of times each character occurs in the string with str.count. We filter out spaces by removing them from the set.

The order of the output may vary from run to run; sets are unordered, so the order in which their items are processed, and thus this answer outputs, cannot be guaranteed.

This is a lambda expression; to use it, prefix lambda with f=.

Try it on Ideone! Ideone uses Python 3.4, which isn't sufficient.

Usage example:

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

Saved 3 bytes thanks to @shooqie!

Copper

Posted 2016-08-24T22:37:12.873

Reputation: 3 684

3Congrats on 1k! – Luis Mendo – 2016-08-25T00:11:08.980

2In Python >3.5 you can do {*s} for set(s). – shooqie – 2016-08-25T16:44:36.337

11

Retina, 13 bytes

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

The sorting is very easy (it's a builtin), it's separating the letters that takes 9 bytes. Try it online!

The first line sOrts all matches of the regex . (which is every character), giving us !,Aaaaaabbcdhrr.

Match is the default stage for the last line of a program, and ! makes it print a linefeed-separated list of matches of the regex. The regex looks for one or more instances of a non-space character in a row.

NinjaBearMonkey

Posted 2016-08-24T22:37:12.873

Reputation: 9 925

What does the ! Do? – Downgoat – 2016-08-25T01:34:58.857

8

Perl 6, 28 bytes

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

Note that Bag like a Hash or Set is unordered so the order of results is not guaranteed.

Explanation:

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

Brad Gilbert b2gills

Posted 2016-08-24T22:37:12.873

Reputation: 12 713

7

Vim, 50, 46 bytes

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

Explanation/gif will come later.

James

Posted 2016-08-24T22:37:12.873

Reputation: 54 537

1For once, Emacs & vim solutions look alike. – YSC – 2016-08-25T11:26:43.463

7

Pyth, 6

.gk-zd

Try it here or run a Test Suite.

Pretty simple, -zd removes spaces from the input, and .gk groups each remaining element by its value. Unfortunately, I haven't found a way to make use of auto-fill variables. Note that the output is shown as Python strings, so certain characters (read: backslashes) are escaped. If you want it to be more readable, add a j to the beginning of the code.

FryAmTheEggman

Posted 2016-08-24T22:37:12.873

Reputation: 16 206

7

Haskell, 38 bytes

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

Basically nimi's solution, but explicitly checking only letters appearing in the string.

xnor

Posted 2016-08-24T22:37:12.873

Reputation: 115 687

6

Brachylog, 14 7 bytes

7 bytes thanks to Fatalize.

:@Sxo@b

Try it online!

:@Sxo@b
:@Sx     remove spaces
    o    sort
     @b  group

Leaky Nun

Posted 2016-08-24T22:37:12.873

Reputation: 45 011

17 bytes using x to remove @S (space). I believe this output format (list of strings) is valid – Fatalize – 2016-08-25T06:49:34.650

6

JavaScript (ES6), 41 bytes

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

Neil

Posted 2016-08-24T22:37:12.873

Reputation: 95 035

Wouldn't this also cause an entry " " to exist in the returned array, as well? Not sure if that's allowed – Value Ink – 2016-08-24T23:46:23.507

@ValueInk Bah, I thought about that when I started, but promptly forgot. Fixed now. – Neil – 2016-08-25T00:21:23.320

Umm, how is join() being called with those double backkticks ? – Tejas Kale – 2016-08-28T09:01:48.367

1@TejasKale That's an ES6 template string. When you prefix a method to a template string, it passes the template as an array to the method, so in this case, it ends up calling .join(['']). join then converts that to the (empty) string and uses that to join the array elements. Not all methods convert their parameter to string, but this technique is handy on those that do. – Neil – 2016-08-28T09:04:49.140

5

2sable, 7 bytes

Code:

Úð-vyÃ,

Explanation:

Ú       # Uniquify the string, aabbcc would result into abc
 ð-     # Remove spaces
   vy   # For each character...
     Ã  #   Keep those in the string, e.g. 'aabbcc', 'a' would result into 'aa'
      , #   Pop and print with a newline

Uses the CP-1252 encoding. Try it online!

Adnan

Posted 2016-08-24T22:37:12.873

Reputation: 41 965

3That doesn't sound like Dennis at all :-P – Luis Mendo – 2016-08-24T22:57:38.883

5

Haskell, 40 bytes

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

Usage example: f "Ah, abracadabra!"-> ["!",",","A","aaaaa","bb","c","d","h","rr"].

The pattern v:w matches only list with at least one element, so all characters not in the input are ignored.

Also 40 bytes:

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

nimi

Posted 2016-08-24T22:37:12.873

Reputation: 34 639

@ThreeFx: But group is from Data.List, too. Anyway, I think this syntax is ghci only and needs the REPL, so it's a language of it's own. I want to stick with standard Haskell.

– nimi – 2016-08-25T05:59:39.080

4

C# 125 98 Bytes

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

Explanation

//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()));
  • Thanks to @TheLethalCoder who suggested the use of an anonymous function, which also allowed me to remove the ToArray call and just implicitly return an IEnumerable which collectively saves 27 bytes

user19547

Posted 2016-08-24T22:37:12.873

Reputation:

You can save 18 bytes (if I counted correctly) by compiling it to a Func<string, string[]> i.e. s=>s.GroupBy.... – TheLethalCoder – 2016-08-25T10:21:17.380

@TheLethalCoder are you sure that is acceptable in place of a function, I've always been wary of that because it adds quite a bit of extra boilerplate to be able to execute it, and with the argument for requiring the Linq using it just seems... well wrong. – None – 2016-08-25T14:47:17.900

Heres a recent example where I do it... http://codegolf.stackexchange.com/a/91075/38550 it'll remove all your boilerplate, as long as functions are allowed

– TheLethalCoder – 2016-08-25T14:57:55.963

@TheLethalCoder OK thats good enough for me. :) It also allowed me to remove the ToArray call – None – 2016-08-25T17:55:33.433

4

R, 198 189 96 95 bytes

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

Ungolfed :

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

This solution is currently not entirely working, when \ are involved.
Now it is !

Thank a lot you to @JDL for golfing out 102 bytes !

Frédéric

Posted 2016-08-24T22:37:12.873

Reputation: 2 059

@JDL : Please suggest edits in the comments. Your changes are really interesting, but it's kinda rude to change someone else's code like that. – Frédéric – 2016-08-25T09:01:50.250

1apologies for that, but I didn't have 50 reputation at the time and couldn't make comments. Will do in future though! – JDL – 2016-08-26T08:03:43.733

@JDL : Fair enough ! – Frédéric – 2016-08-26T10:15:22.867

Try assigning the variable inside a function: for(i in unique(a=strsplit(gsub(" ","",readline()),"")[[1]]))cat(rep(i,sum(a==i)),"\n",sep="") — saves 2 bytes. – Andreï Kostyrka – 2016-08-26T12:36:51.147

@AndreïKostyrka : It doesn't save bytes in this form because you have to put the whole a=strsplit(...) part between brackets: basically does a -2+2 difference. However, using <- will save 1 byte ! – Frédéric – 2016-08-26T13:19:16.933

Yep, that was my fault; the old a variable was saved in the workspace, causing tha faulty code to work normally. – Andreï Kostyrka – 2016-08-26T13:35:35.597

It works out slightly better to use %in% rather than gsub and rep. You should check out my answer ;)

– Billywob – 2016-09-01T15:10:24.447

4

Ruby, 41 + 1 = 42 bytes

+1 byte for -n flag.

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

Takes input on stdin, e.g.:

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

Jordan

Posted 2016-08-24T22:37:12.873

Reputation: 5 001

4

Swift, 105 91 bytes

Thanks to @NobodyNada for 14 bytes :)

Yeah, I'm pretty new to Swift...

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

Characters within a group are separated by a single newline. Groups are separated by two newlines.

jrich

Posted 2016-08-24T22:37:12.873

Reputation: 3 898

You can save 13 bytes by taking input as a [Character] instead of a String, since the rules say "The input should be a string or an array of chars." Also, print("") can be replaced with just print(). – NobodyNada - Reinstate Monica – 2016-08-26T03:50:37.013

@NobodyNada print without arguments didn't work for some reason but the [Character] suggestion was solid. Thanks! – jrich – 2016-08-26T21:54:13.137

3

Mathematica, 36 bytes

Built-in functions Gather and Characters do most of the work here.

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

Greg Martin

Posted 2016-08-24T22:37:12.873

Reputation: 13 940

3

><>, 49 bytes

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

Very spaciously wasteful in the output, but i assume is still allowed given the lenience of the rules

Explanation:

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

fit some things in pretty tight, even using jumps to get around some functions so i could run the pointer vertically.

Basically this puts each ASCII character on its own newline, and if none of that character exists, the line will be blank

Try it online

Edit: i was wrong there was an error in the code what would cause it to never complete if there was a space in the input

torcado

Posted 2016-08-24T22:37:12.873

Reputation: 550

3

Pyth, 5 bytes

.gksc

Try it here!

Takes input as a Python string (i.e. wrapped in quotes, escaped quotes and slashes as necessary).

Explanation:

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

If you guarantee at least one space in the input, there's a 4-byte solution:

t.gk

Try it here!

Explanation:

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

Steven H.

Posted 2016-08-24T22:37:12.873

Reputation: 2 841

3

Dyalog APL, 11 bytes

Function returning list of strings.

(⊂∩¨∪)~∘' '

(⊂∩¨∪) the intersection of the entirety and its unique characters

~∘' ' except spaces

TryAPL online!

Adám

Posted 2016-08-24T22:37:12.873

Reputation: 37 779

3

PowerShell v2+, 44 bytes

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

Takes input $args[0] as a command-line argument literal string. Casts that as a char-array, and uses the -not equal operator to pull out spaces (ASCII 32). This works because casting has a higher order precedence, and when an array is used as the left-hand operator with a scalar as the right-hand, it acts like a filter.

We pass that array of characters to Group-Object, which does exactly what it says. Note that since we're passing characters, not strings, this properly groups with case-sensitivity.

Now, we've got a custom object(s) that has group names, counts, etc. If we just print that we'll have a host of extraneous output. So, we need to pipe those into a loop |%{...} and each iteration -join the .Group together into a single string. Those resultant strings are left on the pipeline, and output is implicit at program completion.

Example

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

AdmBorkBork

Posted 2016-08-24T22:37:12.873

Reputation: 41 581

2

Processing, 109 bytes

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

Its the brute force approach, sort the array, then loop through it. If it doesn't match the last character printed, print a newline first. If it is whitespace, skip the printing step.

Cody

Posted 2016-08-24T22:37:12.873

Reputation: 447

2

Octave, 61 bytes

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

This is an anoymous function that takes a string as input and outputs a cell arrray of strings.

Try at Ideone.

How it works

  • sort sorts the input string. In particular, spaces will be at the beginning.
  • strtrim removes leading spaces.
  • diff(+y) computes consecutive differences between characters (to detect group boundaries)...
  • ... so diff(find([1 diff(+y) 1]) gives a vector of group sizes.
  • mat2cell then splits the sorted string into chunks with those sizes.

Luis Mendo

Posted 2016-08-24T22:37:12.873

Reputation: 87 464

2

Javascript (using external Library - Enumerable) (78 67 bytes)

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

Link to lib: https://github.com/mvegh1/Enumerable

Code explanation: This is what Enumerable was made to do! Load the string into the library, which converts it to a char array. Filter out the white space entries. Group by char. Write each group to a line, according to the specified predicate. That predicate says to join all the elements of the current group into a string, without a delimiter.

enter image description here

applejacks01

Posted 2016-08-24T22:37:12.873

Reputation: 989

2

Perl6, 48 47 45

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

Thanks to manatwork for the improvements.

bb94

Posted 2016-08-24T22:37:12.873

Reputation: 1 831

1Not a big improvement, but $a.trim seems to do it for the condition. – manatwork – 2017-01-04T18:09:57.827

Seems the logical operators still not need spaces around them, so $^a.trim&&say $a x$^b works. (Sorry for adding the hints byte by byte, but this is my first try on Perl6.) – manatwork – 2017-01-05T09:28:14.293

Little typo, you accidentally removed the opening {. – manatwork – 2017-01-05T13:27:59.613

2

MATL, 7 bytes

Xz!t7XQ

MATL Online Demo

Suever

Posted 2016-08-24T22:37:12.873

Reputation: 10 257

1

Ruby, 35 bytes

->s{(?!..?~).map{|x|s.scan x}-[[]]}

Tried to turn the problem upside down to save some bytes. Instead of starting with the string, start with the possible character set.

G B

Posted 2016-08-24T22:37:12.873

Reputation: 11 099

1

Ruby, 46 bytes

Try it online!

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

My original full program version, 48 bytes after adding the n flag:

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

Value Ink

Posted 2016-08-24T22:37:12.873

Reputation: 10 608

Can you replace .count(c) with .count c ? – Cyoce – 2016-08-26T01:02:21.377

@Cyoce no, because the * operator is present nearby so the parser will complain. – Value Ink – 2016-08-26T01:06:25.107

s.chars-[' ']|[] inside the brackets would avoid the uniq – G B – 2017-01-05T07:56:05.920

@GB It would, but if we're chaining it to map then it needs extra parens, and ((s.chars-[' '])|[]).map has the same number of characters as (s.chars-[' ']).uniq.map. And the other, shorter way to check unique characters (via regex) is already covered by @Jordan in another answer – Value Ink – 2017-01-05T09:20:22.973

It works inside the brackets, you don't need extra brackets because precedence of '-' is higher. – G B – 2017-01-05T09:29:37.840

1

Python, 107

Could be shortened by lambda, but later

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

Destructible Lemon

Posted 2016-08-24T22:37:12.873

Reputation: 5 908

1

CJam, 10 bytes

{S-$e`::*}

An unnamed block that expects the string on top of the stack and replaces it with a list of strings.

Try it online!

Explanation

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.

Martin Ender

Posted 2016-08-24T22:37:12.873

Reputation: 184 808

1

Pyke, 16 9 bytes

d-}F/i*d+

Try it here!

Blue

Posted 2016-08-24T22:37:12.873

Reputation: 26 661

1

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

Ungolfed:

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

Not the most golf friendly language. This could probably be modified to return list of lists instead of printing string.

MatthewRock

Posted 2016-08-24T22:37:12.873

Reputation: 913

1

Emacs, 36 keystrokes

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

Result

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

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

Explanation

  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. Select the input line;
  2. Call sort-regexp-fields with arguments . and .;
    • Argument #1: Regexp scpecifying records to sort
    • Argument #2: Regexp scpecifying key within records
  3. Return at line start;
  4. Apply regexp substitution \(\(.\)\2*\) -> \1\n on all matches.

YSC

Posted 2016-08-24T22:37:12.873

Reputation: 732

1

PHP, 67 bytes

Space as separator

PHP5 using deprecated ereg_replace function.

for(;++$i<128;)echo ereg_replace("[^".chr($i)."]","",$argv[1])." ";

PHP7, 73 bytes

for(;++$i<128;)echo str_repeat($j=chr($i),substr_count($argv[1],$j))." ";

Using built in is worse :(

foreach(array_count_values(str_split($argv[1]))as$a=>$b)echo str_repeat($a,$b)." ";

Crypto

Posted 2016-08-24T22:37:12.873

Reputation: 862

1

Perl, 31 bytes

Includes +1 for -p

Run with input on STDIN:

explode.pl <<< "ab.ceaba.d"

explode.pl:

#!/usr/bin/perl -p
s%.%$&x s/\Q$&//g.$/%eg;y/
//s

If you don't care about spurious newlines inbetween the lines the following 24 bytes version works too:

#!/usr/bin/perl -p
s%.%$&x s/\Q$&//g.$/%eg

Ton Hospel

Posted 2016-08-24T22:37:12.873

Reputation: 14 114

1

Oracle SQL 11.2, 123 bytes

SELECT LISTAGG(c)WITHIN GROUP(ORDER BY 1)FROM(SELECT SUBSTR(:1,LEVEL,1)c FROM DUAL CONNECT BY LEVEL<=LENGTH(:1))GROUP BY c;

Un-golfed

SELECT LISTAGG(c)WITHIN GROUP(ORDER BY 1)
FROM (SELECT SUBSTR(:1,LEVEL,1)c FROM DUAL CONNECT BY LEVEL<=LENGTH(:1))
GROUP BY c

Jeto

Posted 2016-08-24T22:37:12.873

Reputation: 1 601

1

S.I.L.O.S 265

The (non competing) code better input format is at the bottom, feel free to try it online!

def : lbl
loadLine :
a = 256
:a
:s
x = get a
z = x
z - 32
z |
if z u
a + 1
GOTO s
:u
if x c
GOTO e
:c
b = x
b + 512
c = get b
c + 1
set b c
a + 1
if x a
:e
a = 512
b = 768
l = 10
:Z
j = a
j - b
if j z
z = get a
c = a
c - 512
:3
if z C
printChar l
a + 1
GOTO Z
:C
printChar c
z - 1
GOTO 3
:z

Input for the above is a series of command line arguments representing ascii values, terminated with a zero.Try it online!.


For a more reasonable method of input we must up the byte count (and use features that were nonexistent before the writing of this challenge).
For 291 bytes we get the following code.
\
def : lbl
loadLine :
a = 256
:a
:s
x = get a
z = x
z - 32
z |
if z u
a + 1
GOTO s
:u
if x c
GOTO e
:c
b = x
b + 512
c = get b
c + 1
set b c
a + 1
if x a
:e
a = 512
b = 768
l = 10
:Z
j = a
j - b
if j z
z = get a
c = a
c - 512
:3
if z C
printChar l
a + 1
GOTO Z
:C
printChar c
z - 1
GOTO 3
:z

Feel free to test this version online!. The backslash is unnecessary but is there to show the important leading line feed.

Rohan Jhunjhunwala

Posted 2016-08-24T22:37:12.873

Reputation: 2 569

1

ARM machine code on Linux, 60 bytes

Hex Dump:

b590 4c0d f810 2b01 b11a 58a3 3301 50a3 e7f8 6222 2704 2001 f1ad 0101 2201 237f 5ce5 b135 700b df00 3d01 d8fc 250a 700d df00 3b01 d8f4 bd90 000200bc

This function basically creates an array of size 128, and whenever it reads a character from the input string it increment's the value at that characters position. Then it goes back through the array and prints each character array[character] times.

Ungolfed Assembly (GNU syntax):

.syntax unified
.bss @bss is zero-initialized data (doesn't impact code size)
countArray:
    .skip 128 @countArray[x] is the number of occurances of x

.text
.global expStr
.thumb_func
expstr:
    @Input: r0 - a NUL-terminated string.
    @Output: Groups of characters to STDOUT
    push {r4,r7,lr}
    ldr r4,=countArray @Load countArray into r4
    readLoop:
        ldrb r2,[r0],#1 @r2=*r0++
        cbz r2,endReadLoop @If r2==NUL, break
        ldr r3,[r4,r2] @r3=r4[r2]
        adds r3,r3,#1 @r3+=1
        str r3,[r4,r2] @r4[r2]=r3
        b readLoop @while (true)
    endReadLoop:
    @Now countArray[x] is the number of occurances of x.
    @Also, r2 is zero
    str r2,[r4,#' ] @'<character> means the value of <character>
    @What that just did was set the number of spaces found to zero.
    movs r7,#4 @4 is the system call for write
    movs r0,#1 @1 is stdout
    sub r1,sp,#1 @Allocate 1 byte on the stack
    @Also r1 is the char* used for write
    movs r2,#1 @We will print 1 character at a time
    movs r3,#127 @Loop through all the characters
    writeLoop:
        ldrb r5,[r4,r3] @r5=countArray[r3]
        cbz r5,endCharacterLoop @If we're not printing anything, go past the loop
        strb r3,[r1] @We're going to print byte r3, so we store it at *r0
        characterLoop:
            swi #0 @Make system call
            @Return value of write is number of characters printed in r0
            @Since we're printing one character, it should just return 1, which
            @means r0 didn't change.
            subs r5,r5,#1
            bhi characterLoop
        @If we're here then we're done printing our group of characters
        @Thus we just need to print a newline.
        movs r5,#10 @r5='\n' (reusing r5 since we're done using it as a loop counter
        strb r5,[r1]
        swi #0 @Print the character

        endCharacterLoop:
        subs r3,r3,#1
        bhi writeLoop @while (--r3)
    pop {r4,r7,pc}
.ltorg @Store constants here

Testing script (also assembly):

.global _start
_start:
    ldr r0,[sp,#8] @Read argv[1]
    bl expstr @Call function
    movs r7,#1 @1 is the system call for exit
    swi #0 @Make system call

Ian Chew

Posted 2016-08-24T22:37:12.873

Reputation: 171

1

Scala, 53 bytes

def?(s:String)=s.filter(_!=' ').groupBy(identity).map{_._2.mkString}

When run with REPL:

scala> ?("Ah, abracadabra!")
res2: scala.collection.immutable.Iterable[String] = List(!, A, aaaaa, ,, bb, c, h, rr, d)

scala> print(res2.mkString("\n"))
!
A
aaaaa
,
bb
c
h
rr
d

EDIT: Forgot to filter spaces

AmazingDreams

Posted 2016-08-24T22:37:12.873

Reputation: 281

1

Clojure, 46

#(partition-by identity(sort(re-seq #"\S" %)))

Long and descriptive function names for simplest of things, yeah.

Michael M

Posted 2016-08-24T22:37:12.873

Reputation: 101

1

PowerShell, 65

@TimmyD has the shorter answer but I don't have enough rep to comment. Here's my answer in 65 bytes.

I didn't think to use group and I didn't know that you could stick -join in front of something instead of -join"" on the end and save two characters (using that would make my method 63).

([char[]]$args[0]-ne32|sort|%{if($l-ne$_){"`n"};$_;$l=$_})-join""

My method sorts the array, then loops through it and concatenates characters if they match the preceding entry, inserting a newline if they do not.

Chirishman

Posted 2016-08-24T22:37:12.873

Reputation: 389

1

Bash + coreutils, 53 50 45 bytes

sed 's: ::g;s:\(.\)\1*:& :g'<<<`fold -1|sort`

There is no separator between the characters of a group and the groups are separated by space. There is one trailing group separator, but as I understood that's acceptable.

Run:

./explode_view.sh <<< '\o /\ o /\ o k'

Output:

// \\\ k ooo 

seshoumara

Posted 2016-08-24T22:37:12.873

Reputation: 2 878

1

Clojure (55 bytes)

(defn f[s](map(fn[[a b]](repeat b a))(frequencies s)))

Test Cases:

(f "Ah, abracadabra!")
;;=> ((\space) (\!) (\A) (\a \a \a \a \a) (\b \b) (\c) (\d) (\h) (\,) (\r \r))

(f "\\o/\\o/\\o/")
;;=> ((\\ \\ \\) (\o \o \o) (\/ \/ \/))

(f "A man, a plan, a canal: Panama!")
;;=> ((\space \space \space \space \space \space) (\!) (\A) (\a \a \a \a \a \a \a \a \a) (\c) (\, \,) (\l \l) (\m \m) (\n \n \n \n) (\P) (\p) (\:))

(f "\"Show me how you do that trick, the one that makes me scream\" she said")
;;=> ((\space \space \space \space \space \space \space \space \space \space \space \space \space \space) (\a \a \a \a \a) (\" \") (\c \c) (\d \d) (\e \e \e \e \e \e \e) (\h \h \h \h \h \h) (\i \i) (\k \k) (\,) (\m \m \m \m) (\n) (\o \o \o \o \o) (\r \r) (\S) (\s \s \s \s) (\t \t \t \t \t \t) (\u) (\w \w) (\y))

James B.

Posted 2016-08-24T22:37:12.873

Reputation: 51

1

Javascript (ES5): 50 48 bytes

As a function:

function(i){return i.split("").sort().join(" ")}

The important code, replace the empty string with the search string (29 bytes):

"".split("").sort().join(" ")

Paul Schmitz

Posted 2016-08-24T22:37:12.873

Reputation: 1 089

1

Java 8, 121 120 110 103 Bytes

s->s.chars().distinct().filter(c->c!=32)
    .forEach(c->out.println(s.replaceAll("[^\\Q"+(char)c+"\\E]","")))

Above lambda can be consumed with Java-8 Consumer. It fetches distinct characters and replaces other characters of the String to disassemble each character occurrence.

CoderCroc

Posted 2016-08-24T22:37:12.873

Reputation: 337

1

Elixir, 70 bytes

def f(s), do: '#{s}'|>Enum.group_by(&(&1))|>Map.delete(32)|>Map.values

Flow

Posted 2016-08-24T22:37:12.873

Reputation: 39

1

R, 67 bytes

Even though there's already an R-answer by @Frédéric I thought my solution deserves it's own answer because it's conceptually different.

for(i in unique(x<-strsplit(readline(),"")[[1]]))cat(x[x%in%i]," ")

The program prints the ascii characters in order of appearence in the string where groups are separated by two white spaces and chars within groups by one white space. A special case is if the string has whitespaces in itself, then at one specific place in the output there will be 4+number of white spaces in string white spaces separating two groups E.g:

Ah, abracadabra! => A h , a a a a a b b r r c d !

Ungolfed

Split up the code for clarity even though assignment is done within the unique functions and changed to order of evaluation:

x<-strsplit(readline(),"")[[1]]) # Read string from command line and convert into vector

for(i in unique(x){              # For each unique character of the string, create vector 
  cat(x[x%in%i]," ")             # of TRUE/FALSE and return the elements in x for which 
}                                # these are matched

Billywob

Posted 2016-08-24T22:37:12.873

Reputation: 3 363

1

C, 178

#define F for
#define i8 char
#define R return
z(i8*r,i8*e,i8*a){i8*b,c;F(;*a;++a)if(!isspace(c=*a)){F(b=a;*b;++b)if(r>=e)R-1;else if(*b==c)*b=' ',*r++=c;*r++='\n';}*r=0;R 0;}

z(outputArray,LastPointerOkinOutputarray,inputArray) return -1 on error 0 ok Note:Modify its input array too...

#define P printf
main(){char a[]="A, 12aa99dd333aA,,<<", b[256]; z(b,b+255,a);P("r=%s\n", b);}

/*
 178
 r=AA
 ,,,
 1
 2
 aaa
 99
 dd
 333
 <<
 */

RosLuP

Posted 2016-08-24T22:37:12.873

Reputation: 3 036

1

Racket 243 bytes

(let*((l(sort(string->list s)char<?))(g(λ(k i)(list-ref k i))))(let loop((i 1)(ol(list(g l 0))))(cond((= i(length l))
(reverse ol))((equal?(g l(- i 1))(g l i))(loop(+ 1 i)(cons(g l i)ol)))(else(loop(+ 1 i)(cons(g l i)(cons #\newline ol)))))))

Ungolfed:

(define (f s)
  (let*((l (sort (string->list s) char<?))
        (g (λ (k i)(list-ref k i))) )
    (let loop ((i 1)
               (ol (list (g l 0))))
      (cond
        ((= i (length l)) (reverse ol))
        ((equal? (g l (- i 1)) (g l i))
         (loop (+ 1 i) (cons (g l i) ol)))
        (else (loop (+ 1 i) (cons (g l i) (cons #\newline ol))))
        ))))

Testing:

(display (f "Ah, abracadabra!"))

Output:

(  
 ! 
 , 
 A 
 a a a a a 
 b b 
 c 
 d 
 h 
 r r)

rnso

Posted 2016-08-24T22:37:12.873

Reputation: 1 635

0

PowerShell - 86

I imagine I could get this smaller, but I'll work on it later. This assumes that $d contains the string to explode.

$s="";$i=0;[Array]::Sort(($a=$d-split""));$a|%{$s+=$_;if($a[++$i]-cne$_){$s+="`n"}};$s

SomeShinyObject

Posted 2016-08-24T22:37:12.873

Reputation: 953