Vista despiezada de una cadena


39

¿No te encantan los diagramas de vista explosionada en los que una máquina u objeto se desarma en sus piezas más pequeñas?

ingrese la descripción de la imagen aquí

¡Hagámosle eso a una cuerda!

El reto

Escribir un programa o función que

  1. ingresa una cadena que contiene solo caracteres ASCII imprimibles ;
  2. disecciona la cadena en grupos de caracteres sin espacio (las "piezas" de la cadena);
  3. genera esos grupos en cualquier formato conveniente, con algún separador entre grupos .

Por ejemplo, dada la cadena

Ah, abracadabra!

la salida sería los siguientes grupos:

!
,
UNA
aaaaa
cama y desayuno
do
re
h
rr

Cada grupo en la salida contiene caracteres iguales, con espacios eliminados. Se ha usado una nueva línea como separador entre grupos. Más información sobre los formatos permitidos a continuación.

Reglas

La entrada debe ser una cadena o una matriz de caracteres. Solo contendrá caracteres ASCII imprimibles (el rango inclusivo desde el espacio hasta la tilde). Si su idioma no lo admite, puede tomar la entrada en forma de números que representan códigos ASCII.

Puede suponer que la entrada contiene al menos un carácter no espacial .

La salida debe constar de caracteres (incluso si la entrada se realiza mediante códigos ASCII). Tiene que haber un separador inequívoco entre grupos , diferente de cualquier carácter que no sea espacio que pueda aparecer en la entrada.

Si la salida es a través del retorno de función, también puede ser una matriz o cadenas, o una matriz de matrices de caracteres, o una estructura similar. En ese caso, la estructura proporciona la separación necesaria.

Un separador entre los caracteres de cada grupo es opcional . Si hay uno, se aplica la misma regla: no puede ser un carácter no espacial que pueda aparecer en la entrada. Además, no puede ser el mismo separador que se usa entre grupos.

Aparte de eso, el formato es flexible. Aquí hay unos ejemplos:

  • Los grupos pueden ser cadenas separadas por nuevas líneas, como se muestra arriba.

  • Los grupos pueden estar separados por cualquier carácter no ASCII, como ¬. La salida para la entrada anterior sería la cadena:

    !¬,¬A¬aaaaa¬bb¬c¬d¬h¬rr
    
  • Los grupos pueden estar separados por n > 1 espacios (incluso si n es variable), con caracteres entre cada grupo separados por un solo espacio:

    !  ,    A   a a a a a    b b  c       d   h  r r
    
  • La salida también puede ser una matriz o una lista de cadenas devueltas por una función:

    ['!', 'A', 'aaaaa', 'bb', 'c', 'd', 'h', 'rr']
    
  • O una matriz de matrices de caracteres:

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

Ejemplos de formatos que no están permitidos, de acuerdo con las reglas:

  • Una coma no se puede usar como separador ( !,,,A,a,a,a,a,a,b,b,c,d,h,r,r), porque la entrada puede contener comas.
  • No se acepta soltar el separador entre grupos ( !,Aaaaaabbcdhrr) o usar el mismo separador entre grupos y dentro de grupos ( ! , A a a a a a b b c d h r r).

Los grupos pueden aparecer en cualquier orden en la salida. Por ejemplo: orden alfabético (como en los ejemplos anteriores), orden de la primera aparición en la cadena, ... El orden no tiene por qué ser coherente o incluso determinista.

Tenga en cuenta que la entrada no puede contener caracteres de nueva línea Ay ason caracteres diferentes (la agrupación es sensible a mayúsculas y minúsculas ).

El código más corto en bytes gana.

Casos de prueba

En cada caso de prueba, se ingresa la primera línea y las líneas restantes son la salida, con cada grupo en una línea diferente.

  • Caso de prueba 1:

    Ah, abracadabra!
    !
    ,
    UNA
    aaaaa
    cama y desayuno
    do
    re
    h
    rr
    
  • Caso de prueba 2:

    \ o / \ o / \ o /
    ///
    \\\
    ooo
    
  • Caso de prueba 3:

    Un hombre, un plan, un canal: ¡Panamá!
    !
    ,, ,,
    :
    UNA
    PAGS
    aaaaaaaaa
    do
    ll
    mm
    nnnn
    pags
    
  • Caso de prueba 4:

    "Muéstrame cómo haces ese truco, el que me hace gritar" dijo
    ""
    ,
    S
    aaaaa
    cc
    dd
    eeeeeee
    hhhhhh
    ii
    kk
    mmmm
    norte
    ooooo
    rr
    ssss
    tttttt
    tu
    ww
    y
    

1
Si utilizamos símbolos no ASCII como "¬" como separador, ¿se puede contar como 1 byte?
Leaky Nun

55
@LeakyNun No, se contará según corresponda dependiendo de la codificación utilizada para el código fuente, como de costumbre
Luis Mendo

¿Es aceptable una nueva línea final después del último grupo?
JustinM - Restablece a Mónica el

¿Es aceptable una nueva línea de salida líder?
DJMcMayhem

1
@RohanJhunjhunwala ¡Bien hecho! :-) Sí, varias líneas nuevas como separadores está bien
Luis Mendo

Respuestas:


11

Jalea , 5 bytes

ḟ⁶ṢŒg

Pruébalo en línea!

Devuelve una matriz, solo que cuando se imprime en STDOUT, el separador desaparece.

De hecho, esta es una función que se puede llamar como tal (en Jelly, cada línea es una función).

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

23

Python 3.5+, 77 46 44 41 bytes

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

Bastante simple. Revisa los caracteres únicos en la cadena convirtiéndolo en un conjunto (usando el desempaquetado iterativo extendido de Python 3.5), luego usa una comprensión de la lista para construir los diagramas explotados contando el número de veces que cada carácter aparece en la cadena str.count. Filtramos espacios eliminándolos del conjunto.

El orden de la salida puede variar de una ejecución a otra; los conjuntos no están ordenados, por lo que no se puede garantizar el orden en que se procesan sus elementos y, por lo tanto, esta respuesta.

Esta es una expresión lambda; para usarlo, prefijo lambdacon f=.

Pruébalo en Ideone! Ideone usa Python 3.4, que no es suficiente.

Ejemplo de uso:

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

¡Guardado 3 bytes gracias a @shooqie!


3
¡Felicidades por 1k!
Luis Mendo

2
En Python> 3.5 se puede hacer {*s}para set(s).
shooqie

11

Retina, 13 bytes

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

La clasificación es muy fácil (es una función integrada), separa las letras que toman 9 bytes. Pruébalo en línea!

La primera línea Ocontiene todas las coincidencias de la expresión regular .(que es cada personaje), dándonos !,Aaaaaabbcdhrr.

La coincidencia es la etapa predeterminada para la última línea de un programa, y !hace que imprima una lista de coincidencias separadas por saltos de línea de la expresión regular. La expresión regular busca una o más instancias de un carácter no espacial en una fila.


Lo que hace el ! ¿Hacer?
Downgoat


8

Perl 6 , 28 bytes

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

Tenga en cuenta que Bag like a Hash or Set no está ordenado, por lo que no se garantiza el orden de los resultados.

Explicación:

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

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

Explicación / gif vendrá más tarde.


1
Por una vez, las soluciones de Emacs y vim se parecen.
YSC

7

Pyth, 6

.gk-zd

Pruébelo aquí o ejecute un Test Suite .

Bastante simple, -zdelimina espacios de la entrada y .gkagrupa cada elemento restante por su valor. Desafortunadamente, no he encontrado una manera de hacer uso de las variables de autocompletar. Tenga en cuenta que la salida se muestra como cadenas de Python, por lo que se escapan ciertos caracteres (lectura: barras invertidas). Si desea que sea más legible, agregue un jal principio del código.


7

Haskell, 38 bytes

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

Básicamente, la solución de nimi , pero verificando explícitamente solo las letras que aparecen en la cadena.


6

2sable , 7 bytes

Código:

Úð-vyÃ,

Explicación:

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

Utiliza la codificación CP-1252 . Pruébalo en línea!


3
Eso no suena para nada a Dennis :-P
Luis Mendo

6

JavaScript (ES6), 41 bytes

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

¿No causaría esto también una entrada " "en la matriz devuelta? No estoy seguro si eso está permitido
Value Ink

@ValueInk Bah, pensé en eso cuando comencé, pero rápidamente lo olvidé. Corregido ahora.
Neil

Umm, ¿cómo se join()llama con esos backkticks dobles?
Tejas Kale

1
@TejasKale Esa es una cadena de plantilla ES6. Cuando prefija un método a una cadena de plantilla, pasa la plantilla como una matriz al método, por lo que en este caso, termina llamando .join(['']). joinluego lo convierte a la cadena (vacía) y lo usa para unir los elementos de la matriz. No todos los métodos convierten sus parámetros en cadenas, pero esta técnica es útil para aquellos que lo hacen.
Neil


5

Haskell, 40 bytes

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

Ejemplo de uso: f "Ah, abracadabra!" -> ["!",",","A","aaaaa","bb","c","d","h","rr"].

El patrón v:wsolo coincide con la lista con al menos un elemento, por lo que se ignoran todos los caracteres que no están en la entrada.

También 40 bytes:

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

@ThreeFx: Pero también groupes de Data.List. De todos modos, creo que esta sintaxis es ghciúnica y necesita REPL, por lo que es un lenguaje propio . Quiero seguir con el estándar Haskell.
nimi

4

Ruby, 41 + 1 = 42 bytes

+1 byte para -nbandera.

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

Toma entrada en stdin, por ejemplo:

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

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

Explicación

//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()));
  • Gracias a @TheLethalCoder que sugirió el uso de una función anónima, que también me permitió eliminar el ToArray llamada y devolver implícitamente un IEnumerable que colectivamente ahorra 27 bytes

Puede guardar 18 bytes (si he contado correctamente) compilándolo en un Func<string, string[]>s=>s.GroupBy....
archivo

@TheLethalCoder está seguro de que es aceptable en lugar de una función, siempre he sido cauteloso porque agrega un poco de repetitivo adicional para poder ejecutarlo, y con el argumento de requerir que Linq lo use simplemente parece ... bien mal.
JustinM - Restablece a Monica el

Aquí hay un ejemplo reciente donde lo hago ... codegolf.stackexchange.com/a/91075/38550 eliminará todas sus repeticiones, siempre que las funciones estén permitidas
TheLethalCoder

@TheLethalCoder OK, eso es lo suficientemente bueno para mí. :) También me permitió quitar la llamada ToArray
JustinM - Restablecer Mónica

4

R, 198 189 96 95 bytes

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

Sin golf:

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

Esta solución actualmente no funciona por completo, cuando \están involucrados.
Ahora es !

Gracias mucho que @JDL para jugar al golf a cabo 102 bytes!


@JDL: sugiera modificaciones en los comentarios. Sus cambios son realmente interesantes, pero es un poco grosero cambiar el código de otra persona así.
Frédéric

1
disculpas por eso, pero no tenía 50 reputación en ese momento y no podía hacer comentarios. Lo hará en el futuro sin embargo!
JDL

@JDL: ¡Bastante justo!
Frédéric

Intente asignar la variable dentro de una función: for(i in unique(a=strsplit(gsub(" ","",readline()),"")[[1]]))cat(rep(i,sum(a==i)),"\n",sep="")- ahorra 2 bytes.
Andreï Kostyrka

@ AndreïKostyrka: No guarda bytes en este formulario porque tienes que poner toda la parte a = strsplit (...) entre paréntesis: básicamente hace una diferencia de -2 + 2. Sin embargo, ¡usar <-ahorrará 1 byte!
Frédéric

4

Swift, 105 91 bytes

Gracias a @NobodyNada por 14 bytes :)

Sí, soy bastante nuevo en Swift ...

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

Los caracteres dentro de un grupo están separados por una nueva línea. Los grupos están separados por dos líneas nuevas.


Puede guardar 13 bytes tomando la entrada como en [Character]lugar de a String, ya que las reglas dicen "La entrada debe ser una cadena o una matriz de caracteres". Además, print("")se puede reemplazar por solo print().
NobodyNada - Restablece a Mónica el

@NobodyNada printsin argumentos no funcionó por alguna razón, pero la [Character]sugerencia fue sólida. ¡Gracias!
jrich

3

Octava , 61 bytes

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

Esta es una función anónima que toma una cadena como entrada y genera una matriz de cadenas de celdas.

Prueba en Ideone .

Cómo funciona

  • sortordena la cadena de entrada. En particular, los espacios estarán al principio.
  • strtrim Elimina los espacios iniciales.
  • diff(+y) calcula diferencias consecutivas entre caracteres (para detectar límites de grupo) ...
  • ... asi que diff(find([1 diff(+y) 1]) da un vector de tamaños de grupo.
  • mat2cell luego divide la cadena ordenada en trozos con esos tamaños.

3

Mathematica, 36 bytes

Funciones incorporadas Gathery Charactershacen la mayor parte del trabajo aquí.

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

3

> <> , 49 bytes

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

Un desperdicio muy espacioso en la salida, pero supongo que todavía está permitido dada la indulgencia de las reglas

Explicación:

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

ajusta algunas cosas bastante apretadas, incluso usando saltos para desplazar algunas funciones para que pueda ejecutar el puntero verticalmente.

Básicamente, esto coloca a cada carácter ASCII en su propia nueva línea, y si ninguno de esos caracteres existe, la línea estará en blanco

Pruébalo en línea

Editar: estaba equivocado, había un error en el código que haría que nunca se completara si hubiera un espacio en la entrada


3

Pyth, 5 bytes

.gksc

Pruébalo aquí!

Toma datos como una cadena de Python (es decir, entre comillas, comillas escapadas y barras diagonales según sea necesario).

Explicación:

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

Si garantiza al menos un espacio en la entrada, hay una solución de 4 bytes:

t.gk

Pruébalo aquí!

Explicación:

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

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

Toma la entrada $args[0]como una cadena literal de argumento de línea de comando. Lanza eso como una charmatriz y usa el-ne operador ot qual para extraer espacios (ASCII 32). Esto funciona porque la conversión tiene una prioridad de orden superior, y cuando se usa una matriz como operador de la izquierda con un escalar como la derecha, actúa como un filtro.

Pasamos ese conjunto de caracteres a Group-Object , que hace exactamente lo que dice. Tenga en cuenta que ya que estamos pasando caracteres , no cadenas, esto se agrupa correctamente con mayúsculas y minúsculas.

Ahora, tenemos un objeto u objetos personalizados que tienen nombres de grupos, recuentos, etc. Si imprimimos eso, tendremos una gran cantidad de resultados extraños. Entonces, necesitamos canalizarlos en un bucle|%{...} y cada iteración-join del.Group conjunto en una sola cadena. Esas cadenas resultantes se dejan en la tubería, y la salida está implícita al finalizar el programa.

Ejemplo

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

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

Es el enfoque de la fuerza bruta, ordena la matriz y luego repítela. Si no coincide con el último carácter impreso, imprima primero una nueva línea. Si es un espacio en blanco, omita el paso de impresión.


2

Javascript (usando una biblioteca externa - Enumerable) ( 78 67 bytes)

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

Enlace a lib: https://github.com/mvegh1/Enumerable

Explicación del código: ¡Esto es para lo que se hizo Enumerable! Cargue la cadena en la biblioteca, que la convierte en una matriz de caracteres. Filtre las entradas de espacios en blanco. Agrupar por char. Escriba cada grupo en una línea, de acuerdo con el predicado especificado. Ese predicado dice unir todos los elementos del grupo actual en una cadena, sin un delimitador.

ingrese la descripción de la imagen aquí



2

Perl6, 48 47 45

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

Gracias a manatwork por las mejoras.


1
No es una gran mejora, pero $a.trimparece hacerlo por la condición.
manatwork

Parece que los operadores lógicos aún no necesitan espacios a su alrededor, por lo que $^a.trim&&say $a x$^bfunciona. (Perdón por agregar las sugerencias byte a byte, pero este es mi primer intento en Perl6.)
manatwork

Pequeño error tipográfico, eliminaste accidentalmente la abertura {.
manatwork

1

Ruby, 46 bytes

Pruébalo en línea!

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

Mi versión original del programa completo, 48 bytes después de agregar la nbandera:

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

¿Se puede reemplazar .count(c)con .count c?
Cyoce

@Cyoce no, porque el *operador está presente cerca, por lo que el analizador se quejará.
Value Ink el

s.chars- [''] | [] dentro de los corchetes evitaría el uniq
GB

@GB Lo haría, pero si lo estamos encadenando, mapentonces necesita parens adicionales y ((s.chars-[' '])|[]).maptiene la misma cantidad de caracteres que (s.chars-[' ']).uniq.map. Y la otra forma más corta de verificar caracteres únicos (a través de expresiones regulares) ya está cubierta por @Jordan en otra respuesta
Value Ink el

Funciona dentro de los corchetes, no necesita corchetes adicionales porque la precedencia de '-' es mayor.
GB

1

Python, 107

Podría ser acortado por lambda, pero luego

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 bytes

{S-$e`::*}

Un bloque sin nombre que espera la cadena en la parte superior de la pila y la reemplaza con una lista de cadenas.

Pruébalo en línea!

Explicación

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 común, 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))

Sin golf:

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

No es el lenguaje más amigable para el golf. Esto probablemente podría modificarse para devolver la lista de listas en lugar de imprimir una cadena.


1

Emacs, 36 pulsaciones de teclas

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

Resultado

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

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

Explicación

  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. Seleccione la línea de entrada;
  2. Llamar sort-regexp-fieldscon argumentos .y .;
    • Argumento # 1: expresiones regulares que especifican registros para ordenar
    • Argumento # 2: clave de especificación Regexp dentro de los registros
  3. Regreso al inicio de la línea;
  4. Aplicar la sustitución de expresiones regulares \(\(.\)\2*\)-> \1\nen todas las coincidencias.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.