Contraer ascii-art

12

Desafío

Dada una cuadrícula rectangular de caracteres ascii imprimibles como una cadena o mediante una entrada estándar, escriba una función o programa que contraiga los caracteres no espaciales en una pila en la parte inferior.

Las normas:

  • La salida tiene las mismas dimensiones y caracteres que la entrada.
  • Un carácter no espacial en (row a,column b)no puede tener un carácter espacial ' 'en (a-1, b), (a-1,b-1)o (a-1,b+1), donde las filas están numeradas desde la parte inferior. Esto tiene la consecuencia de que todas las pilas verticales deberían colapsar de lado.
  • Un personaje no espacial puede viajar en la mayoría de los (initial height - final height)lugares hacia la izquierda o hacia la derecha (ver Fig. 1).
  • Puede suponer que la imagen tiene suficiente espacio para colapsar sin que los caracteres se caigan de la pantalla.

Figura 1: posibles ubicaciones finales para los caracteres @#$mostrados como x,y,z, respectivamente.

..............
...@..........
..xxx.........
.xxxxx...#....
xxxxxxx.yyy.$.

El orden en que colapsan los personajes se puede elegir libremente. Los espacios finales no están bien, pero las nuevas líneas finales sí.

Este es el , por lo que gana la respuesta más corta en bytes.

Ejemplo

                 (__)
                 (oo)
           /------\/
          / |    ||
         *  /\---/\
            ~~   ~~
..."Have you mooed today?"...

Una salida posible:

 
 
 
                --(_
           /----|/|(o_)
          /|/~\---~\\/o)
..."Have*you~mooed~today?"...
Angs
fuente
Solo para aclarar, ¿la forma en que caen los personajes puede codificarse en lugar de generarse al azar cada vez?
ETHproductions
18
¿Qué te hizo esa vaca? :(
FlipTack
@ETHproductions eso es correcto. Mi ejemplo lo hace de abajo hacia arriba, de izquierda a derecha, pero el orden aleatorio u otra cosa está bien, siempre que se cumplan las reglas.
Angs
@ Flp.Tkc Es solo un modelo.
Angs
1
@DestructibleWatermelon si un personaje se cae de la pantalla, es su culpa, no la tuya.
Angs

Respuestas:

4

JavaScript (ES6), 100 90 88 bytes

f=s=>s==(l=s.search`
`,s=s.replace(eval(`/(\\S)([^]{${l-1},${l+1}}) /`),` $2$1`))?s:f(s)
s=`                 (__)        
                 (oo)        
           /------\\/         
          / |    ||          
         *  /\\---/\\          
            ~~   ~~          
..."Have you mooed today?"...`
console.log(s)
console.log(f(s))

Requiere que la cadena tenga al menos dos líneas y todas las líneas rellenadas a la misma longitud. Salida para la imagen de ejemplo:

              ( --           
            /|---/|-(o__     
          */~~\---~\|\/o))   
..."Have you/mooed~today?"...

Tenga en cuenta que si trata de mover elementos hacia la derecha si es posible, *no cayó entre el Havey el you.

Editar: ahorrado 10% gracias a @ETHproductions. Ahorró otros 2 bytes gracias a @DanielIndie.

Retina 0.8.2 , 50 bytes

+`(?<=(.)*)(\S)(.*¶(?<-1>)?(?>(?<-1>.)*).?) 
 $3$2

Pruébalo en línea! Un enfoque ligeramente diferente a mi respuesta de JavaScript, utiliza un grupo de equilibrio para que coincida con un espacio debajo del carácter no espacial; el (?<-1>)?permite que el espacio sea una columna a la izquierda, mientras que el .?permite que el espacio sea una columna a la derecha.

Retina , 40 bytes

~0L$`.(.*)¶
+s`(\S)(.{$.1,$.&}) ¶ $$2$$1

Pruébalo en línea! Puerto de mi respuesta de JavaScript. La 0L$etapa atómica toma la entrada y sustituye las dos longitudes en la segunda línea, lo que da como resultado el comando que realmente realiza el reemplazo, que luego se evalúa en la entrada original por la ~etapa compuesta.

Neil
fuente
Este es un gran algoritmo! Puede reemplazarlo \ncon una nueva línea literal para
reducirlo
Además, creo que puede hacerlo l=s.search`\n` para ahorrar unos pocos bytes.
ETHproductions
tio.run/##ZY/… 86 bytes
DanielIndie
@DanielIndie Se f=requiere para la recursión, pero aún me ahorra 2 bytes, ¡gracias!
Neil
tienes razón, lo siento: P
DanielIndie
3

Python 2, 298 bytes

a=input()
L=len(a);s=' '
a=[list(s*L+l.ljust(L+max(map(len,a))))for l in a]
t=1
while t:
 t=0
 for y in range(L-1):
  for x in range(len(a[y])):
   c=a[y][x];C=a[y+1][x-1:x+2]
   if s!=c and s in C:t=1;a[y][x]=s;a[y+1][[[x+1,x][C[1]==s],x-1][C[0]==s]]=c
for l in map(''.join,a):print l[L:].rstrip()

Toma la entrada como una lista de cadenas (una por línea)

Ejemplo: Entrada:

['                 (__)',
'                 (oo)',
'           /------\/',
'          / |    ||',
'         *  /\---/\ ',
'            ~~   ~~',
'..."Have you mooed today?"...']

Salida:

              (
            -----/|-(o__
         //|~~\---~\|\/o))
..."Have*you/mooed~today?"...
TFeld
fuente
3

C, 252 bytes

e=1,l,c,i,j,p,r,w,a[999];f(){while((i=getchar())>0)a[w++]=i,i<16?l++:0,l?0:c++;while(e)for(i=e=0;i<c;i++)for(j=l;j>=0;j--)e=(r=a[p=j*(c+1)+i]-32?a[r=p+c+1]-32?a[r=p+c]-32?a[r=p+c+2]-32?0:r:r:r:0)?l=a[p],a[p]=a[r],a[r]=l:e;for(i=0;i<w;)putchar(a[i++]);}

Código de prueba sin golf:

#include <stdio.h>

e=1,l,c,i,j,p,r,w,a[999];
f()
{
    // counting lines and columns
    while ((i = getchar())>0)a[w++] = i, i<16 ? l++ : 0, l ? 0 : c++;
    // main shaking loop
    while (e) // repeat while collapsing
        for (i = e = 0; i < c; i++) // columns loop
            for (j = l; j >= 0; j--) // lines loop
                e = ( // remember that collapsing was
                     r = // find place to collapse
                         a[p = j*(c + 1) + i] - 32 ? // if not space
                             a[r = p + c + 1] - 32 ? // if char under the current is not a space
                                 a[r = p + c] - 32 ? // see one position left
                                    a[r = p + c + 2] - 32 ? 0 // then one position right
                                                          : r
                                    : r
                                 : r
                             : 0
                         ) ? // and if place was found
                           l=a[p],a[p]=a[r],a[r]=l // replace values in positions p and r
                           : e;
    //print resulting picture
    for(i=0;i<w;)putchar(a[i++]);
}

int main(void)
{
    int cnt;
    FILE * testf = fopen("caw.txt","w");
    char testd[][31] = {
        "                 (__)        \n",
        "                 (oo)        \n", 
        "           /------\\/         \n", 
        "          / |    ||          \n", 
        "         *  /\\---/\\          \n", 
        "            ~~   ~~          \n", 
        "...\"Have you mooed today ? \"...",
        "" };
    // prepare data for test
    printf("Initial data:\n");
    for(cnt = 0; cnt < 7; cnt++)
    {
        printf("%s", testd[cnt]);
        fprintf(testf, testd[cnt]);
    }
    fclose(testf);
    // redirect standard input
    freopen("caw.txt", "r", stdin);
    printf("\n\nResult:\n");
    // start test
    f();
}

Resultado de la prueba:

ingrese la descripción de la imagen aquí

VolAnd
fuente
2

Algodoo (no competidor)

Entrada: ejemplo degenerado utilizado.

Preparar

Runnning: gravedad y rebote predeterminados.

Corriendo

Salida: la precisión se puede ajustar a través de la configuración de Fricción y Densidad de los objetos.

Salida

Algodoo es lógico programable .

wyldstallyns
fuente
¿Por qué esto no es competitivo? La no competencia generalmente se reserva para respuestas en idiomas más nuevos que el desafío.
Ad Hoc Garf Hunter
Aunque Algodoo puede hacer una lógica real, esta simulación es equivalente a dejar caer una copia impresa de la entrada en el piso y tomarle una foto. No estoy seguro de cómo capturar esa salida de manera programática.
wyldstallyns
Y parecía incorrecto decir "¡programa de cero bytes! ¡Yo gano!"
wyldstallyns
Sospecho que esto no es, de hecho, una respuesta de cero bytes. Hablas de ajustes de ajustes que parecen ser el equivalente a escribir código. Puede ser una buena idea abrir una meta pregunta sobre la puntuación de Algodoo. Tampoco creo que haya nada de malo en tener un programa de cero bytes.
Ad Hoc Garf Hunter
Abriré ese meta.
wyldstallyns
1

JavaScript, 286 bytes

b=>eval('f=b=>b==null||" "==b;b=b.split`\n`.map(b=>[...b]);a:for(;;){for(c=0;c<b.length-1;c++)for(g=b[c],d=0;d<g.length;d++){h=g[d];if(!f(h)){e=0;f(b[c+1][d])?e=2:f(b[c+1][d-1])?e=1:f(b[c+1][d+1])&&(e=3);if(e){b[c+1][d+e-2]=h;b[c][d]=" ";continue a}}}break}b.map(b=>b.join``).join`\n`')

Ejemplos

// Here I assume that you've assigned the above function to `fall`
console.log(fall(`
                 (__)
                 (oo)
           /------\/
          / |    ||
         *  /\---/\\
            ~~   ~~
..."Have you mooed today?"...`))

Salida:

                -       
            /--(-\--(__  
          /|~~---/~||/oo))
..."Have*you/mooed~today?"...

Otro ejemplo:

console.log(fall(`
 (\__/)  .~    ~. ))
 /O O  ./      .'
{O__,   \    {
  / .  . )    \\
  |-| '-' \    }
 .(   _(   )_.'
'---.~_ _ _&`))

Salida:

    _ , /            
  OO/__'_.. .         
 {.(|-|.(O'))/.~{      
/('---.~___-_&)_.'}\~.'))

Función sin golf

function fall(input) {
  let move = true
  let lines = input.split("\n").map(line => line.split(""))
  let isSpace = c => c == null || c == " "
  loop: for (;;) {
    for (let y = 0; y < lines.length - 1; y++) {
      let line = lines[y]
      for (let x = 0; x < line.length; x++) {
        let ch = line[x]
        if (!isSpace(ch)) {
          let dx = 0
          if (isSpace(lines[y+1][x])) { dx = 2 }
          else if (isSpace(lines[y+1][x-1])) { dx = 1 }
          else if (isSpace(lines[y+1][x+1])) { dx = 3 }
          if (dx) {
            lines[y + 1][x + dx - 2] = ch
            lines[y][x] = " "
            continue loop
          }
        }
      }
    }
    break
  }
  return lines.map(line => line.join("")).join("\n")
}
Florent
fuente
Una forma corta de probar no en blanco es c>" "donde crepresenta el personaje que está probando.
Neil