# Exploded view of a string

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

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

• If we use non-ASCII symbols like "¬" as separator, can it be counted as 1 byte? – Leaky Nun Aug 24 '16 at 22:39
• @LeakyNun No, it will be counted as it corresponds depending on the encoding used for the source code, as usual – Luis Mendo Aug 24 '16 at 22:40
• Is a trailing newline after the last group acceptable? – Phaeze Aug 24 '16 at 23:10
• Is a leading newline of output acceptable? – DJMcMayhem Aug 24 '16 at 23:16
• @RohanJhunjhunwala Well done! :-) Yes, several newlines as separators is fine – Luis Mendo Aug 25 '16 at 21:35

## Pyke, 16 9 bytes

d-}F/i*d+


Try it here!

# 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)." ";  # 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  # 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  # 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. ## 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  # 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 ## Clojure, 46 #(partition-by identity(sort(re-seq #"\S" %)))  Long and descriptive function names for simplest of things, yeah. # 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. # 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))  # 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(" ")  # Java 8, 121120110 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. # Elixir, 70 bytes def f(s), do: '#{s}'|>Enum.group_by(&(&1))|>Map.delete(32)|>Map.values  ## 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  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 << */  ## Bash + coreutils, 5350 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  ## 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)  ## 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. # 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