Vista esplosa di una stringa


39

Non ami quei diagrammi a vista esplosa in cui una macchina o un oggetto viene smontato nei suoi pezzi più piccoli?

inserisci qui la descrizione dell'immagine

Facciamolo con una stringa!

La sfida

Scrivi un programma o una funzione che

  1. inserisce una stringa contenente solo caratteri ASCII stampabili ;
  2. seziona la stringa in gruppi di caratteri uguali non spaziali (i "pezzi" della stringa);
  3. genera quei gruppi in qualsiasi formato conveniente, con qualche separatore tra i gruppi .

Ad esempio, data la stringa

Ah, abracadabra!

l'output sarebbe i seguenti gruppi:

!
,
UN
AAAAA
bb
c
d
h
rr

Ogni gruppo nell'output contiene caratteri uguali, con spazi rimossi. Una nuova riga è stata utilizzata come separatore tra i gruppi. Ulteriori informazioni sui formati consentiti di seguito.

Regole

L' input dovrebbe essere una stringa o una matrice di caratteri. Conterrà solo caratteri ASCII stampabili (l'intervallo compreso dallo spazio alla tilde). Se la tua lingua non lo supporta, puoi prendere l'input sotto forma di numeri che rappresentano i codici ASCII.

Si può presumere che l'input contenga almeno un carattere non spaziale .

L' output deve essere composto da caratteri (anche se l'input avviene tramite codici ASCII). Deve esserci un separatore non ambiguo tra i gruppi , diverso da qualsiasi carattere non spaziale che può apparire nell'input.

Se l'output è tramite il ritorno di funzione, può anche essere una matrice o stringhe o una matrice di matrici di caratteri o una struttura simile. In tal caso la struttura fornisce la separazione necessaria.

Un separatore tra i caratteri di ciascun gruppo è facoltativo . Se ce n'è uno, si applica la stessa regola: non può essere un carattere non spaziale che può apparire nell'input. Inoltre, non può essere lo stesso separatore utilizzato tra i gruppi.

A parte questo, il formato è flessibile. Ecco alcuni esempi:

  • I gruppi possono essere stringhe separate da newline, come mostrato sopra.

  • I gruppi possono essere separati da qualsiasi carattere non ASCII, ad esempio ¬. L'output per l'input sopra sarebbe la stringa:

    !¬,¬A¬aaaaa¬bb¬c¬d¬h¬rr
    
  • I gruppi possono essere separati da n > 1 spazi (anche se n è variabile), con i caratteri tra ogni gruppo separati da un singolo spazio:

    !  ,    A   a a a a a    b b  c       d   h  r r
    
  • L'output può anche essere un array o un elenco di stringhe restituite da una funzione:

    ['!', 'A', 'aaaaa', 'bb', 'c', 'd', 'h', 'rr']
    
  • O una serie di array di caratteri:

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

Esempi di formati non consentiti, secondo le regole:

  • Una virgola non può essere utilizzata come separatore ( !,,,A,a,a,a,a,a,b,b,c,d,h,r,r), poiché l'input può contenere virgole.
  • Non è consentito eliminare il separatore tra gruppi ( !,Aaaaaabbcdhrr) o utilizzare lo stesso separatore tra gruppi e all'interno di gruppi ( ! , A a a a a a b b c d h r r).

I gruppi possono apparire in qualsiasi ordine nell'output. Ad esempio: ordine alfabetico (come negli esempi sopra), ordine di prima apparizione nella stringa, ... L'ordine non deve essere coerente o addirittura deterministico.

Si noti che l'input non può contenere caratteri di nuova riga e Ache asono caratteri diversi (il raggruppamento fa distinzione tra maiuscole e minuscole ).

Vince il codice più breve in byte.

Casi test

In ogni caso di test, viene immessa la prima riga e le restanti righe sono l'output, con ciascun gruppo in una riga diversa.

  • Caso di prova 1:

    Ah, abracadabra!
    !
    ,
    UN
    AAAAA
    bb
    c
    d
    h
    rr
    
  • Caso di prova 2:

    \ O / \ o / \ o /
    ///
    \\\
    ooo
    
  • Caso di prova 3:

    Un uomo, un piano, un canale: Panama!
    !
    ,,
    :
    UN
    P
    aaaaaaaaa
    c
    ll
    mm
    nnnn
    p
    
  • Caso di prova 4:

    "Fammi vedere come fai quel trucco, quello che mi fa urlare" disse
    ""
    ,
    S
    AAAAA
    cc
    dd
    eeeeeee
    hhhhhh
    ii
    kk
    mmmm
    n
    ooooo
    rr
    ssss
    tttttt
    u
    ww
    y
    

1
Se utilizziamo simboli non ASCII come "¬" come separatore, possiamo contare come 1 byte?
Leaky Nun,

5
@LeakyNun No, verrà conteggiato come corrisponde in base alla codifica utilizzata per il codice sorgente, come al solito
Luis Mendo

È accettabile una riga finale dopo l'ultimo gruppo?
JustinM - Ripristina Monica il

È accettabile una nuova linea di produzione leader?
DJMcMayhem

1
@RohanJhunjhunwala Ben fatto! :-) Sì, molte nuove linee come separatori vanno bene
Luis Mendo,

Risposte:


11

Gelatina , 5 byte

ḟ⁶ṢŒg

Provalo online!

Restituisce un array, solo che quando viene stampato su STDOUT, il separatore scompare.

Questa è davvero una funzione che può essere chiamata come tale (in Jelly, ogni riga è una funzione).

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

23

Python 3.5+, 77 46 44 41 byte

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

Abbastanza semplice. Passa attraverso i caratteri univoci nella stringa convertendola in un set (usando la decompressione iterabile estesa di Python 3.5), quindi utilizza una comprensione dell'elenco per costruire i diagrammi esplosi contando il numero di volte in cui ogni carattere si presenta nella stringa str.count. Filtriamo gli spazi rimuovendoli dal set.

L'ordine dell'output può variare da corsa a corsa; gli insiemi non sono ordinati, pertanto l'ordine in cui i loro articoli vengono elaborati e quindi i risultati di questa risposta non possono essere garantiti.

Questa è un'espressione lambda; per usarlo, prefisso lambdacon f=.

Provalo su Ideone! Ideone utilizza Python 3.4, che non è sufficiente.

Esempio di utilizzo:

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

3 byte salvati grazie a @shooqie!


3
Congratulazioni per 1k!
Luis Mendo,

2
In Python> 3.5 puoi farlo {*s}per set(s).
shooqie,

11

Retina, 13 byte

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

L'ordinamento è molto semplice (è incorporato), sta separando le lettere che richiede 9 byte. Provalo online!

La prima riga Oindica tutte le corrispondenze del regex .(che è ogni personaggio), dandoci !,Aaaaaabbcdhrr.

Corrispondenza è la fase predefinita per l'ultima riga di un programma e !consente di stampare un elenco di corrispondenze del regex separate da avanzamento riga. Il regex cerca una o più istanze di un carattere non spaziale in una riga.


Cosa fa il ! Fare?
Downgoat,


8

Perl 6 , 28 byte

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

Nota che Bag come Hash o Set non è ordinato, quindi l'ordine dei risultati non è garantito.

Spiegazione:

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

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

Spiegazione / gif arriverà più tardi.


1
Per una volta, le soluzioni Emacs e vim si assomigliano.
YSC,

7

Pyth, 6

.gk-zd

Provalo qui o esegui una Test Suite .

Abbastanza semplice, -zdrimuove gli spazi dall'input e .gkraggruppa ogni elemento rimanente per il suo valore. Sfortunatamente, non ho trovato il modo di utilizzare le variabili di riempimento automatico. Si noti che l'output viene mostrato come stringhe Python, quindi alcuni caratteri (leggi: barre rovesciate) sono sfuggiti. Se vuoi che sia più leggibile, aggiungi ja all'inizio del codice.


7

Haskell, 38 byte

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

Fondamentalmente la soluzione di nimi , ma controlla esplicitamente solo le lettere che compaiono nella stringa.


6

2 file , 7 byte

Codice:

Úð-vyÃ,

Spiegazione:

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

Utilizza la codifica CP-1252 . Provalo online!


3
Non sembra affatto Dennis :-P
Luis Mendo,

6

JavaScript (ES6), 41 byte

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

Ciò non causerebbe anche l' " "esistenza di una voce nell'array restituito? Non sono sicuro che sia consentito
Value Ink

@ValueInk Bah, ci ho pensato quando ho iniziato, ma ho dimenticato subito. Riparato ora.
Neil,

Umm, come viene join()chiamato con quei doppi backtick?
Tejas Kale,

1
@TejasKale Questa è una stringa modello ES6. Quando si antepone un metodo a una stringa di modello, passa il modello come matrice al metodo, quindi in questo caso finisce per chiamare .join(['']). joinquindi lo converte nella stringa (vuota) e lo utilizza per unire gli elementi dell'array. Non tutti i metodi convertono i loro parametri in stringa, ma questa tecnica è utile per quelli che lo fanno.
Neil,


5

Haskell, 40 byte

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

Esempio di utilizzo: f "Ah, abracadabra!"->["!",",","A","aaaaa","bb","c","d","h","rr"] .

Il modello v:w corrisponde solo all'elenco con almeno un elemento, quindi tutti i caratteri non presenti nell'input vengono ignorati.

Anche 40 byte:

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

@ThreeFx: Ma groupviene anche da Data.List. Comunque, penso che questa sintassi sia ghcisolo e abbia bisogno del REPL, quindi è un linguaggio a sé stante . Voglio rimanere con Haskell standard.
nimi,

4

Rubino, 41 + 1 = 42 byte

+1 byte per -nflag.

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

Accetta input su stdin, ad esempio:

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

4

C # 125 98 byte

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

Spiegazione

//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()));
  • Grazie a @TheLethalCoder che mi ha suggerito l'uso di una funzione anonima, che mi ha anche permesso di rimuovere la ToArraychiamata e restituire implicitamente un IEnumerable che salva collettivamente 27 byte

Puoi salvare 18 byte (se ho contato correttamente) compilandolo in un Func<string, string[]>ies=>s.GroupBy....
TheLethalCoder

@TheLethalCoder sei sicuro che sia accettabile al posto di una funzione, ne sono sempre stato diffidente perché aggiunge un po 'di piastra aggiuntiva per essere in grado di eseguirla, e con l'argomento per richiedere il Linq usando solo sembra ... bene sbagliato.
JustinM - Ripristina Monica il

Ecco un esempio recente in cui lo faccio ... codegolf.stackexchange.com/a/91075/38550 rimuoverà tutta la piastra della caldaia , purché le funzioni siano consentite
TheLethalCoder

@TheLethalCoder OK è abbastanza buono per me. :) Mi ha anche permesso di rimuovere la chiamata ToArray
JustinM - Ripristina Monica il

4

R, 198 189 96 95 byte

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

Questa soluzione al momento non funziona del tutto, quando \sono coinvolti.
Ora è !

Grazie mille a @JDL per aver giocato a golf 102 byte!


@JDL: si prega di suggerire modifiche nei commenti. Le tue modifiche sono davvero interessanti, ma è piuttosto scortese cambiare il codice di qualcun altro in quel modo.
Frédéric,

1
mi scuso per questo, ma al momento non avevo 50 reputazione e non potevo fare commenti. Lo farà in futuro però!
JDL,

@JDL: abbastanza giusto!
Frédéric,

Prova ad assegnare la variabile all'interno di una funzione: for(i in unique(a=strsplit(gsub(" ","",readline()),"")[[1]]))cat(rep(i,sum(a==i)),"\n",sep="")- salva 2 byte.
Andreï Kostyrka,

@ AndreïKostyrka: Non salva i byte in questa forma perché devi mettere l'intera parte a = strsplit (...) tra parentesi: sostanzialmente fa una differenza -2 + 2. Tuttavia, l'utilizzo <-salverà 1 byte!
Frédéric,

4

Swift, 105 91 byte

Grazie a @NobodyNada per 14 byte :)

Sì, sono abbastanza nuovo per Swift ...

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

I personaggi all'interno di un gruppo sono separati da una singola riga. I gruppi sono separati da due nuove righe.


Puoi salvare 13 byte prendendo l'input come [Character]invece che come String, poiché le regole dicono "L'input dovrebbe essere una stringa o una matrice di caratteri". Inoltre, print("")può essere sostituito con solo print().
NobodyNada - Ripristina Monica il

@NobodyNada printsenza argomenti non ha funzionato per qualche motivo, ma il [Character]suggerimento è stato solido. Grazie!
jrich,

3

Ottava , 61 byte

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

Questa è una funzione anaudita che accetta una stringa come input e produce una cella di stringhe.

Prova a Ideone .

Come funziona

  • sortordina la stringa di input. In particolare, gli spazi saranno all'inizio.
  • strtrim rimuove gli spazi iniziali.
  • diff(+y) calcola le differenze consecutive tra i caratteri (per rilevare i confini del gruppo) ...
  • ... quindi diff(find([1 diff(+y) 1])fornisce un vettore di dimensioni di gruppo.
  • mat2cell quindi divide la stringa ordinata in blocchi con quelle dimensioni.

3

Mathematica, 36 byte

Funzioni integrate Gathere Characterssvolgere la maggior parte del lavoro qui.

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

3

> <> , 49 byte

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

Molto dispendioso nell'output, ma suppongo sia ancora consentito, vista la clemenza delle regole

Spiegazione:

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

inserisce alcune cose piuttosto strette, anche usando i salti per aggirare alcune funzioni in modo da poter eseguire il puntatore in verticale.

Fondamentalmente questo mette ogni carattere ASCII sulla sua nuova riga, e se non esiste nessuno di quel carattere, la linea sarà vuota

Provalo online

Modifica: mi sbagliavo c'era un errore nel codice che non lo avrebbe mai completato se ci fosse uno spazio nell'input


3

Pyth, 5 byte

.gksc

Provalo qui!

Accetta l'input come stringa Python (ovvero racchiuso tra virgolette, virgolette di escape e barre se necessario).

Spiegazione:

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

Se garantisci almeno uno spazio nell'input, esiste una soluzione a 4 byte:

t.gk

Provalo qui!

Spiegazione:

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

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

Accetta l'input $args[0]come stringa letterale dell'argomento della riga di comando. Lancia come una charmatrice e usa l' operatore -not equal per estrarre gli spazi (ASCII32 ). Questo perché il casting ha una precedenza di ordine superiore e quando un array viene utilizzato come operatore di sinistra con uno scalare come di destra, si comporta come un filtro.

Passiamo quella serie di personaggi a Group-Object, che fa esattamente quello che dice. Nota che dal momento che stiamo passando personaggi , non stringhe, questo si raggruppa correttamente con la distinzione tra maiuscole e minuscole.

Ora, abbiamo un oggetto / i personalizzato / i che ha nomi di gruppo, conteggi, ecc. Se stampiamo che avremo una serie di output estranei. Quindi, dobbiamo tubo quelle in un ciclo |%{...}e ogni iterazione l'insieme in una singola stringa. Le stringhe risultanti vengono lasciate sulla pipeline e l'output è implicito al completamento del programma.-join.Group

Esempio

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

3

Dyalog APL , 11 byte

Elenco di restituzione di stringhe di funzioni.

(⊂∩¨∪)~∘' '

(⊂∩¨∪) l'intersezione dell'insieme e dei suoi caratteri unici

~∘' ' tranne gli spazi

ProvaAPL online!


2

Elaborazione, 109 byte

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

È l'approccio della forza bruta, ordina l'array, quindi passa attraverso di esso. Se non corrisponde all'ultimo carattere stampato, stampare prima una nuova riga. Se è uno spazio vuoto, saltare la fase di stampa.


2

Javascript (usando la libreria esterna - Enumerabile) ( 78 67 byte)

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

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

Spiegazione del codice: questo è ciò che Enumerable è stato creato per fare! Carica la stringa nella libreria, che la converte in un array di caratteri. Filtra le voci degli spazi bianchi. Raggruppa per carattere. Scrivi ogni gruppo su una riga, in base al predicato specificato. Quel predicato dice di unire tutti gli elementi del gruppo corrente in una stringa, senza un delimitatore.

inserisci qui la descrizione dell'immagine



2

Perl6, 48 47 45

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

Grazie a manatwork per i miglioramenti.


1
Non è un grande miglioramento, ma $a.trimsembra farlo per la condizione.
arte

Sembra che gli operatori logici non abbiano ancora bisogno di spazi attorno a loro, quindi $^a.trim&&say $a x$^bfunziona. (Mi dispiace per aver aggiunto i suggerimenti byte per byte, ma questo è il mio primo tentativo su Perl6.)
manatwork

Piccolo errore di battitura, hai rimosso accidentalmente l'apertura {.
arte

1

Rubino, 46 ​​byte

Provalo online!

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

La mia versione originale del programma completo, 48 byte dopo aver aggiunto il nflag:

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

Puoi sostituirlo .count(c)con .count c?
Cyoce,

@Cyoce no, perché l' *operatore è presente nelle vicinanze, quindi il parser si lamenterà.
Valore inchiostro

s.chars- [''] | [] all'interno delle parentesi eviterebbe uniq
GB

@GB Lo sarebbe, ma se lo stiamo concatenando ha mapbisogno di parentesi extra e ((s.chars-[' '])|[]).mapha lo stesso numero di personaggi di (s.chars-[' ']).uniq.map. E l'altro, il modo più breve per controllare personaggi unici (via regex) è già trattato da @Jordan in un'altra risposta
Value Ink

Funziona tra parentesi, non hai bisogno di parentesi extra perché la precedenza di '-' è maggiore.
GB,

1

Python, 107

Potrebbe essere abbreviato da lambda, ma più tardi

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 byte

{S-$e`::*}

Un blocco senza nome che prevede la stringa in cima allo stack e la sostituisce con un elenco di stringhe.

Provalo online!

Spiegazione

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

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

Non è la lingua più adatta al golf. Questo potrebbe probabilmente essere modificato per restituire un elenco di elenchi invece di stampare una stringa.


1

Emacs, 36 battute

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

Risultato

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

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

Spiegazione

  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. Seleziona la riga di input;
  2. Chiama sort-regexp-fieldscon argomenti .e .;
    • Argomento n. 1: Riscrivi i record di scpecification da ordinare
    • Argomento n. 2: Regexp scpecifying key nei record
  3. Ritorna all'inizio della riga;
  4. Applica la sostituzione regexp \(\(.\)\2*\)-> \1\nsu tutte le partite.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.