Convierta exponentes en arte ASCII

28

Tarea

Su tarea es convertir cadenas como esta:

abc^d+ef^g + hijk^l - M^NO^P (Ag^+)

A cuerdas como esta:

   d   g       l    N P    +
abc +ef  + hijk  - M O  (Ag )

Cuál es una aproximación a abc d + ef g + hijk l - M N O P (Ag + )

En palabras, eleva los caracteres directamente al lado de los puntos de atención a la línea superior, un carácter para un punto de referencia.

Especificaciones

  • Se permiten espacios en blanco finales adicionales en la salida.
  • No se darán cuidados encadenados m^n^ocomo entrada.
  • Una caret no será seguida inmediatamente por un espacio o por otra caret.
  • Un cursor no será precedido inmediatamente por un espacio.
  • Todos los cuidados irán precedidos de al menos un carácter y seguidos de al menos un carácter.
  • La cadena de entrada solo contendrá caracteres ASCII imprimibles (U + 0020 - U + 007E)
  • En lugar de dos líneas de salida, puede generar una matriz de dos cadenas.

Para aquellos que hablan expresiones regulares: la cadena de entrada coincidirá con esta expresión regular:

/^(?!.*(\^.\^|\^\^|\^ | \^))(?!\^)[ -~]*(?<!\^)$/

Tabla de clasificación

Monja permeable
fuente
2
@TimmyD "La cadena de entrada solo contendrá caracteres ASCII imprimibles (U + 0020 - U + 007E)"
Leaky Nun
3
¿Por qué detenerse en exponentes? ¡Quiero algo que maneje H_2O!
Neil
1
@Neil Haz tu propio desafío entonces, y puedo cerrar este desafío como un duplicado de ese. :)
Leaky Nun
1
Según su ejemplo, diría que son superindices , no necesariamente exponentes
Luis Mendo
44
Quienes hablan regex provienen de un país muy regular donde la expresión está muy limitada. La principal causa de muerte es el retroceso catastrófico.
David Conrad

Respuestas:

19

V , 15 14 bytes

ÄÒ +òf^xxé kPj

Pruébalo en línea!

Una solución bastante sencilla. ¡El desafío perfecto para V!

Explicación:

Ä                "Duplicate this current line
 Ò               "Replace this line with spaces
   +             "Move to the beginning of the next line
    ò         ò  "Recursively (The second ò is implicit):
     f^          "  Find a caret
       xx        "  Delete two characters. The second will be saved into the main register
         é       "  Insert a space
           k     "  Move up
            P    "  Paste from the main register
             j   "  Move down

Convenientemente, en función de cómo funciona la recursividad, esto se ejecutará una vez por cada cuidado.

DJMcMayhem
fuente
2
vim es el lenguaje perfecto para este desafío. +1
Downgoat
18

Cheddar, 77 72 67 bytes

l->l.chars.vfuse.replace("^\n"," ").lines.map(j->"%-2s"%j).turn(3)

No regex!

Me encanta esta respuesta ya que es una maravillosa demostración de las habilidades de Cheddar. Principalmente gracias a la función de reemplazo agregada por Conor. El PR to dev nunca se realizó, por lo que la función de reemplazo solo existe en esta rama (actualización: hice el PR y ahora está en la última rama beta con la que puede instalar npm install -g cheddar-lang)

He encontrado una forma de jugar al golf, pero desafortunadamente una supervisión resulta en que esto suceda cuando las longitudes de los artículos no son las mismas:

["   denifednud   denifednug       denifednul    denifednuN denifednuP    denifednu+ ", "abcdenifednu +efdenifednu  + hijkdenifednu  - Mdenifednu Odenifednu  (Agdenifednu )"]

Podría haber guardado muchos bytes usando expresiones regulares , y de hecho, acabo de hacer expresiones regulares para Cheddar ... el único problema es que no hay funciones de expresión regular: /

Explicación

l->                    // Function take input as `l`
   l.chars             // Get array of chars in input
   .vfuse              // Join with newlines
   .replace("^\n"," ") // Replace `^\n` with a space globally
   .lines              // Get the lines (see below for more details on what this returns)
   .map(j->            // Loop through each "line" `j` is arg
       "%-2s"          // C-like printf format.
                       // think of as: padRight(j, " ", 2)
                       // see below for more details
        % j            // Pass j as the string to insert
   ).turn(3)           // Turn the string 270 degrees (see below)
   .vfuse              // Vertically fuse to get result (this is not needed as we can output an array of the lines)

Para obtener una mejor comprensión. Esto es lo que .linesvuelve para1^2

["1", " 2"]

el .turncon gire esto:

1
 2

dentro:

 2
1

Otro ejemplo que lo hará más claro:

1
 2
2
 2

se convierte en:

 2 2
1 2

¿Por qué formatear?

Lo que %-2sestá haciendo es bastante simple. %especifica que estamos comenzando un "formato", o que una variable se insertará en esta cadena en este punto. -significa rellenar a la derecha la cadena y 2es la longitud máxima. Por defecto, se rellena con espacios. ssolo especifica que es una cadena. Para ver lo que hace:

"%-2s" % "a"  == "a "
"%-2s" % " a" == " a"
Downgoat
fuente
2
: DI siempre votó cheddar.
DJMcMayhem
@DrGreenEggsandIronMan: D gracias
Downgoat
1
Cheddar tiene un turnmétodo para cuerdas?
TuxCrafting
66
-1 el nombre de este idioma siempre me da hambre.
dejó de girar en contra del reloj
@ TùxCräftîñg solo para matrices 2D, por eso utilicé .lines para obtener las líneas.
Downgoat
10

Perl, 21 + 1 = 22 bytes

say'';s/\^(.)/♥[A\1↓/

Corre con la -pbandera. Reemplace con un ESCbyte sin formato ( 0x1b) y con una pestaña vertical ( 0x0b).

La pestaña vertical es idea de Martin Ender. ¡Ahorró dos bytes! Gracias.

Lynn
fuente
¿No necesitaría mover el cursor hacia abajo una línea al inicio para que los exponentes no se superpongan al último indicador de la consola?
Martin Ender
No estaba seguro de eso, sí. Supuse que tenía todo el espacio que necesitaba, pero tal vez eso sea un poco descarado. (En general, no estoy muy orgulloso de usar los movimientos del cursor para resolver este tipo de problema, pero es lo primero que se me ocurrió ...)
Lynn
2
Creo que es una buena solución, pero el resultado debe ser visualmente indistinguible de imprimir la cadena según lo previsto.
Martin Ender
1
Qué solución tan encantadora
Thomas Weller
7

JavaScript (ES6), 56 55 bytes

s=>[/.(\^(.))?/g,/\^.(())/g].map(r=>s.replace(r,' $2'))

Regexps al rescate por supuesto. El primero reemplaza todos los caracteres con espacios, a menos que encuentre un símbolo de intercalación, en cuyo caso elimina el símbolo de intercalación y mantiene el carácter después de él. (Se garantiza que estos personajes existen). El segundo es el obvio para reemplazar cada símbolo y su siguiente personaje con un espacio.

Editar: se guardó 1 byte gracias a @Lynn que ideó una forma de reutilizar la cadena de reemplazo para el segundo reemplazo permitiendo que el reemplazo se asigne sobre una matriz de expresiones regulares.

Neil
fuente
2
Parece que s=>[/.(\^(.))?/g,/\^.(())/g].map(r=>s.replace(r,' $2'))es un byte más corto.
Lynn
@ Lynn ¡Eso es un truco realmente astuto!
Neil
7

Python 3, 157 101 98 85 83 74 bytes

Esta solución realiza un seguimiento de si el carácter anterior era ^, luego decide si se debe enviar a la primera o segunda línea en función de eso.

Salidas como una matriz de ['firstline', 'secondline'].

a=['']*2
l=0
for c in input():x=c=='^';a[l]+=c*x;a[~l]+=' '*x;l=x
print(a)

¡Guardado 13 15 bytes gracias a @LeakyNun!

¡Guardado 7 bytes gracias a @Joffan!

Cobre
fuente
1
Bonito autómata de estado finito.
Leaky Nun
¿Sería mejor tener a=['','']y concatenar ' 'y cdirectamente en a[l]y a[~l]?
Joffan
6

Python 2, 73 bytes

l=['']*2;p=1
for c in input():b=c!='^';l[p]+=c*b;l[~p]+=' '*b;p=b
print l

Sin expresiones regulares. Recuerda si el carácter anterior era ^, y coloca el carácter actual en la línea superior o inferior en función de eso, y un espacio en el otro.

xnor
fuente
4

Pyth, 17 bytes

CcsmX~Z1j;d;cQ\^2

             Q      input string
            c \^    split on '^'
   m                map for sections d:
    X      ;          insert a space at index:
     ~Z1                the old value of Z (initially 0), before setting Z to 1
                      into:
        j;d             the section joined on spaces
  s                 concatenate
 c              2   chop into groups of 2
C                   transpose

Devuelve una matriz de 2 cadenas. (Prepárese jpara unirlos con una nueva línea).

Pruébalo en línea .

Anders Kaseorg
fuente
1
No puedo dejar de preguntarme cómo se pronuncia tu apellido. : D
Lynn
4

MATL , 18 bytes

94=t1YSt~&vG*cw~Z)

Pruébalo en línea!

94=    % Take input implicitly. Create logical array of the same size that contains
       % true for carets, false otherwise
t      % Push a copy of this array
1YS    % Circularly shift 1 unit to the right. This gives an array that contains true
       % for the elements right after a caret (superindices), and false for the rest 
t~     % Push a copy and negate
&v     % Concatenate vertically. This gives a 2D, 2-row array
G*     % Push the input again, multiply with broadcast. This gives a 2D array in
       % which the first row contains the superindices (characters after a caret)
       % and 0 for the rest; and the second row contains the non-superindices and
       % 0 for the superindices
c      % Convert to char
w      % Swap. Brings to top the array containing true for carets and false otherwise
~      % Negate
Z)     % Use as logical index to remove rows that contain carets. Display implicitly
Luis Mendo
fuente
4

Ruby, 47 + 1 ( -nbandera) = 48 bytes

puts$_.gsub(/\^(.)|./){$1||" "},gsub(/\^./," ")

Ejecútelo así: ruby -ne 'puts$_.gsub(/\^(.)|./){$1||" "},gsub(/\^./," ")'

Tinta de valor
fuente
Creo que puede guardar 1 byte usando $_=$_.gsub(/\^(.)|./){$1||" "}+gsub(/\^./," ")y en -plugar de -n.
Dom Hastings
1
@DomHastings independientemente de si funciona o no, su código no parece tener una nueva línea, y agregar +$/significa que no va a guardar bytes. putslanza la nueva línea automáticamente cuando ,está presente entre argumentos.
Value Ink
Oh ... Lo probé usando, ruby -p ... <<< 'input'pero estoy de acuerdo, si falta la nueva línea, ¡no es bueno! En realidad, podría haber agregado una nueva línea en mis pruebas antes ... ¡Estaba en el trabajo, así que no puedo verificar!
Dom Hastings
@DomHastings Mirándolo de nuevo, supongo que es porque getsincluye la nueva línea final la mayor parte del tiempo, pero si canaliza en un archivo que no contiene la nueva línea final, entonces no aparecerá y la salida será incorrecta . Pruebe su código ruby -p ... inputfileya que Ruby lo redirige getsal archivo si es un argumento de línea de comando.
Value Ink
Lo tengo, tiene mucho sentido. Supongo que una nueva línea final en el archivo también solucionaría el problema. No soy un Rubyista competente de ninguna manera, así que siento que hoy he aprendido un poco más al respecto. ¡Gracias!
Dom Hastings
3

Python (2), 76 68 67 Bytes

-5 Bytes gracias a @LeakyNun

-3 Bytes gracias a @ KevinLau-notKenny

-1 Byte gracias a @ValueInk

-0 bytes gracias a @DrGreenEggsandIronMan

import re
lambda i,s=re.sub:[s("(?<!\^).\^?"," ",i),s("\^."," ",i)]

Esta función Lambda anónima toma la cadena de entrada como su único argumento y devuelve las dos líneas de salida separadas por una nueva línea. Para llamarlo, dale un nombre escribiendo "f =" antes.

Regex bastante simple: la primera parte reemplaza lo siguiente por un espacio: cualquier personaje y un símbolo de zanahoria o solo un char, pero solo si no hay ningún símbolo de interrogatorio antes de ellos. La segunda parte reemplaza cualquier símbolo de intercalación en la cadena y el carácter posterior por un espacio.

KarlKastor
fuente
@LeakyNun: Por alguna razón, me preguntaba si 1. también es válido si importo bibliotecas. Estaba copiando 2. en esta pregunta en este momento cuando vi tu comentario. Gracias a ti y a Kevin!
KarlKastor
Puedes tomar un byte confrom re import*
DJMcMayhem
@DrGreenEggsandIronMan Esto parece usar exactamente el mismo número de bytes. (ver arriba)
KarlKastor
Mantenga la antigua declaración de importación y hágalo lambda i,s=re.sub:[s("(?<!\^).\^?"," ",i),s("\^."," ",i)]por -1 byte
Value Ink el
2

Retina, 16 bytes

S`^
\^(.)
♥[A$1↓

Un puerto de mi respuesta Perl, señalado por Martin Ender. Reemplace por un ESCbyte sin formato ( 0x1b) y con una pestaña vertical ( 0x0b).

Lynn
fuente
2

shell + TeX + catdvi, 51 43 bytes

tex '\empty$'$1'$\end'>n;catdvi *i|head -n2

Usa texpara componer algunas matemáticas hermosas, y luego usa catdvipara hacer una representación de texto. El comando head elimina la basura (numeración de páginas, nuevas líneas finales) que de otro modo estaría presente.

Editar: ¿Por qué hacer lo largo, correcto, y redirigir a /dev/nullcuando puede ignorar los efectos secundarios y escribir en un solo archivo de carta?


Ejemplo

Entrada: abc^d+ef^g + hijk^l - M^NO^P (Ag^+)

Salida de TeX (recortada a la ecuación): ¡Matemáticas "hermosas"! Salida final:

   d   g     l  N P   +
abc +ef +hijk -M O (Ag )

Suposiciones: Comience en un directorio vacío (o específicamente un directorio sin nombre que termine en "i"). La entrada es un argumento único para el script de shell. La entrada no es una cadena vacía.

Alguien me dice si esto es abuso de reglas, especialmente catdvi.

algmyr
fuente
2

Haskell, 74 56 55 bytes

g('^':c:r)=(c,' '):g r
g(c:r)=(' ',c):g r
g x=x
unzip.g

Devuelve un par de cadenas. Ejemplo de uso: unzip.g $ "abc^d+e:qf^g + hijk^l - M^NO^P: (Ag^+)"->(" d g l N P + ","abc +e:qf + hijk - M O : (Ag )")

ghace una lista de pares, donde el primer elemento es el carácter en la línea superior y el segundo elemento es el carácter en la línea inferior. unziplo convierte en un par de listas.

Editar: @xnor sugirió unzipque ahorra 18 bytes. @Laikoni encontró un byte más para guardar. ¡Gracias!

nimi
fuente
Puedes hacer j=unzip.g?
xnor
@xnor: ¡Oh, qué estúpido de mi parte no ver eso yo mismo! ¡Muchas gracias!
nimi
Puede reemplazar g[]=[]con g x=xpara guardar un byte.
Laikoni
@Laikoni: ¡Bien visto! ¡Gracias!
nimi
1

Perl, 35 bytes

Código de 34 bytes + 1 para -p

$_=s/\^(.)|./$1||$"/ger.s/\^./ /gr

Uso

perl -pe '$_=s/\^(.)|./$1||$"/ger.s/\^./ /gr' <<< 'abc^d+ef^g + hijk^l - M^NO^P (Ag^+)'
   d   g       l    N P    + 
abc +ef  + hijk  - M O  (Ag )

Nota: Esto es exactamente lo mismo que la respuesta de Value Ink que espié después. Se eliminará si es necesario, ya que esto realmente no se agrega a la solución Ruby.

Dom Hastings
fuente
1

Java 8 lambda, 132 128 112 caracteres

i->{String[]r={"",""};for(char j=0,c;j<i.length();j++){c=i[j];r[0]+=c==94?i[++j]:32;r[1]+=c==94?32:c;}return r;}

La versión sin golf se ve así:

public class Q86647 {

    static String[] printExponents(char[] input) {
        String[] result = {"",""};
        for (char j = 0, c; j < input.length(); j++) {
            c = input[j];
            result[0] += c == 94 ? input[++j] : 32;
            result[1] += c == 94 ? 32 : c;
        }
        return result;
    }
}

Se muestra como una matriz, simplemente verificando si hay un símbolo de intercalación y, de ser así, el siguiente carácter se colocará en la fila superior, de lo contrario, habrá un espacio.


Actualizaciones

Se reemplazaron los caracteres con sus valores ascii para guardar 4 caracteres.

Gracias a @LeakyLun por señalar el uso de una matriz de caracteres como entrada en su lugar.

También gracias a @KevinCruijssen por cambiar inta charpara guardar algunos personajes más.

Frozn
fuente
Puede intentar ingresar char[]y usar for(char c:i)para ver si se puede reducir el conteo de bytes.
Leaky Nun
Puede reducirlo un poco a 110 bytes usando: i->{String[]r={"",""};for(char j=0,c;j<i.length;j++){c=i[j];r[0]+=c==94?i[++j]:32;r[1]+=c==94?32:c;}return r;}con "abc^d+ef^g + hijk^l - M^NO^P (Ag^+)".toCharArray()como entrada. ( Ideona de estos cambios. )
Kevin Cruijssen
1

Coco , 122114 96 bytes

Editar: 8 26 bytes hacia abajo con la ayuda de Leaky Nun.

def e(s,l)=''==l and s or"^"==l[0]and l[1]+e(s+' ',l[2:])or' '+e(s+l[0],l[1:])
f=print..e$('\n')

Entonces, como aprendí hoy, python tiene un operador condicional ternario, o de hecho dos de ellos: <true_expr> if <condition> else <false_expr>y el <condition> and <true_expr> or <false_expr>último viene con un carácter menos.
Se puede idear una versión conforme a Python .


Primer intento:

def e(s,l):
 case l:
  match['^',c]+r:return c+e(s+' ',r)
  match[c]+r:return' '+e(s+c,r)
 else:return s
f=print..e$('\n')

Llamando con f("abc^d+ef^g + hijk^l - M^NO^P (Ag^+)")huellas

   d   g       l    N P    +
abc +ef  + hijk  - M O  (Ag )

¿Alguien ha intentado jugar al golf en coco todavía? Enriquece a Python con conceptos de programación más funcionales como la coincidencia de patrones y la concatenación de funciones (con ..) utilizadas anteriormente. Como este es mi primer intento con coco, cualquier consejo sería apreciado.

Esto definitivamente podría acortarse ya que cualquier código válido de Python también es válido y se han publicado respuestas más cortas de Python, sin embargo, intenté encontrar una solución puramente funcional.

Laikoni
fuente
Creo que puede usar operadores ternarios ( x and y or z) para reemplazar el case.
Leaky Nun
Incluso puedes usar en s[0]=="^"lugar dematch['^',c]+r in l
Leaky Nun
@LeakyNun Cuando lo reemplazo match['^',c]+rcon s[0]=="^", entonces cy rya no estoy vinculado. ¿Cómo ayudaría esto?
Laikoni
Puede usar s[1]para reemplazar cy s[2:]para reemplazar r.
Leaky Nun
entonces puedes usar ternary ahora.
Leaky Nun
0

Dyalog APL, 34 bytes

{(0 1=⊂b/¯1⌽b){⍺\⍺/⍵}¨⊂⍵/⍨b←⍵≠'∧'}

Devuelve un vector de dos elementos con las dos líneas.

Ejecución de muestra (la uparrow en frente es formatear el vector de dos el. Para consumo humano):

      ↑{(0 1=⊂b/¯1⌽b){⍺\⍺/⍵}¨⊂⍵/⍨b←⍵≠'∧'}'abc∧d+ef∧g + hijk∧l - M∧NO∧P (Ag∧+)'
   d   g       l    N P    + 
abc +ef  + hijk  - M O  (Ag )
lstefano
fuente
A tu comentario sobre mi pregunta sobre el código que no hace nada: sí, ese código que pones cuenta.
haykam
0

PowerShell v2 +, 88 83 bytes

-join([char[]]$args[0]|%{if($c){$_;$b+=' '}elseif($_-94){$b+=$_;' '}$c=$_-eq94});$b

Un poco más largo que los otros, pero muestra un poco de magia de PowerShell y una lógica un poco diferente.

Esencialmente, el mismo concepto que las respuestas de Python: iteramos sobre la entrada carácter por carácter, recordamos si el anterior era un símbolo de intercalación ( $c) y colocamos el carácter actual en el lugar apropiado. Sin embargo, la lógica y el método para determinar dónde emitir se manejan de manera un poco diferente, y sin una tupla o variables separadas: probamos si el carácter anterior era un símbolo de intercalación, y si es así, emite el carácter a la tubería y concatena un espacio en $b. De lo contrario, verificamos si el carácter actual es un símbolo de intercalación elseif($_-94)y, siempre que no lo sea, concatenamos el carácter actual $by enviamos un espacio a la tubería. Finalmente, establecemos si el personaje actual es un símbolo para la próxima ronda.

Recopilamos esos caracteres de la tubería en parens, los encapsulamos en una -joinque los convierte en una cadena y los dejamos junto con $bla tubería. La salida al final está implícita con una nueva línea intermedia.

A modo de comparación, aquí hay un puerto directo de la respuesta Python de @ xnor , a 85 bytes :

$a=,''*2;[char[]]$args[($l=0)]|%{$a[!$l]+="$_"*($c=$_-ne94);$a[$l]+=' '*$c;$l=!$c};$a
AdmBorkBork
fuente
0

Gema, 42 41 caracteres

\^?=?@set{s;$s }
?=\ @append{s;?}
\Z=\n$s

Gema procesa la entrada como flujo, por lo que debe resolverla de una sola vez: la primera línea se escribe inmediatamente como procesada, la segunda línea se recopila en la variable $ s y luego la salida al final.

Ejecución de muestra:

bash-4.3$ gema '\^?=?@set{s;$s };?=\ @append{s;?};\Z=\n$s' <<< 'abc^d+ef^g + hijk^l - M^NO^P (Ag^+)'
   d   g       l    N P    +  
abc +ef  + hijk  - M O  (Ag )
hombre trabajando
fuente
0

Chicle de canela, 21 bytes

0000000: 5306 6533 bd92 d1db 8899 8381 a2f8 8f8c  S.e3............
0000010: 1230 249e a1                             .0$..

No competidor Pruébalo en línea.

Explicación

No soy un gran golfista de expresiones regulares, por lo que probablemente haya una mejor manera de hacerlo.

La cadena se descomprime a:

S(?<!\^)[^^]& &\^&`S\^.& 

(tenga en cuenta el espacio final)

La primera Setapa recibe información y usa una mirada hacia atrás negativa para reemplazar todos los caracteres que no sean trazos sin un trazo anterior con un espacio, luego elimina todos los trazos. Luego emite inmediatamente la cadena de entrada modificada con una nueva línea y elimina esa Setapa. Dado que STDIN ahora está agotado y la etapa anterior no proporcionó ninguna entrada, la siguiente Setapa recibe la última línea de STDIN nuevamente y luego reemplaza todos los caracteres seguidos por cualquier carácter con un espacio y lo genera.

En el código psuedo de Perl:

$first_stage_sub_1 = ($input =~ s/(?<!\^)[^^]/ /gr);
$first_stage_sub_2 = ($first_stage_sub_1 =~ s/\^//gr);
print $first_stage_sub_2, "\n";

$second_stage_sub = ($input =~ s/\^./ /gr);
print $second_stage_sub, "\n";
un espagueti
fuente
0

J , 28 27 bytes

0|:t#]{."0~_1-_1|.t=.'^'~:]

Pruébalo en línea!

                  t=.'^'~:]    0 for ^, 1 for the rest, define t
              _1|.             Shift right, now zeroes are for superscripts         
     ]{."0~_1-                 Prepend that many spaces to each character
   t#                          Remove the rows with carets
0|:                            Transpose

Tiene que haber una mejor manera...

FrownyFrog
fuente