Recolher ascii-art

12

Desafio

Dada uma grade retangular de caracteres ascii imprimíveis como uma sequência ou através de entrada padrão, escreva uma função ou programa que colecione os caracteres não espaciais em uma pilha na parte inferior.

As regras:

  • A saída possui as mesmas dimensões e caracteres da entrada.
  • Um caractere não espacial em (row a,column b)não pode ter um caractere de espaço ' 'em (a-1, b), (a-1,b-1)ou (a-1,b+1), onde as linhas são numeradas da parte inferior. Isso tem a conseqüência de que todas as pilhas verticais devem entrar em colapso lateralmente.
  • Um caractere não espacial pode viajar na maioria dos (initial height - final height)lugares para a esquerda ou direita (veja a Fig. 1).
  • Você pode assumir que a imagem possui espaço suficiente para recolher sem que caracteres caiam da tela.

Figura 1: possíveis locais finais para os caracteres @#$mostrados como x,y,z, respectivamente.

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

A ordem na qual os caracteres são recolhidos pode ser escolhida livremente. Os espaços à direita não são bons, mas as novas linhas à direita são.

Isso é , então a resposta mais curta em bytes vence!

Exemplo

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

Uma saída possível:

 
 
 
                --(_
           /----|/|(o_)
          /|/~\---~\\/o)
..."Have*you~mooed~today?"...
Angs
fonte
Só para esclarecer, a maneira como os caracteres caem pode ser codificada em vez de gerada aleatoriamente a cada vez?
ETHproductions
18
O que aquela vaca já fez com você? :(
FlipTack 28/11
@ETHproductions está correto. Meu exemplo faz de baixo para cima, da esquerda para a direita, mas a ordem aleatória ou outra coisa é boa, desde que as regras sejam obedecidas.
Angs
@ Flp.Tkc É apenas um modelo.
Angs
1
@DestructibleWatermelon se um personagem cair fora da tela, a culpa é deles, não sua.
Angs

Respostas:

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

Requer que a cadeia tenha pelo menos duas linhas e todas as linhas sejam preenchidas com o mesmo comprimento. Saída para a imagem de exemplo:

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

Observe que, ao tentar mover elementos para a direita, se possível, o *não caiu entre o Havee o you.

Editar: economizou 10% graças a @ETHproductions. Economizou mais 2 bytes graças a @DanielIndie.

Retina 0.8.2 , 50 bytes

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

Experimente online! Uma abordagem ligeiramente diferente da minha resposta JavaScript, isso usa um grupo de equilíbrio para corresponder a um espaço abaixo do caractere não espacial; o (?<-1>)?permite que o espaço para ser uma coluna para a esquerda, enquanto o .?permite que o espaço para ser uma coluna para a direita.

Retina , 40 bytes

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

Experimente online! Porta da minha resposta JavaScript. O 0L$estágio atômico pega a entrada e substitui os dois comprimentos na segunda linha, resultando no comando que realmente executa a substituição, que é então avaliada na entrada original pelo ~estágio composto.

Neil
fonte
Este é um ótimo algoritmo! Você pode substituir \ncom uma nova linha literal para obtê-lo para baixo a dois dígitos ;-)
ETHproductions
Além disso, acho que você pode l=s.search`\n` economizar alguns bytes.
ETHproductions
tio.run/##ZY/… 86 bytes
DanielIndie
@DanielIndie O f=é necessário para a recursão, mas ainda me salva 2 bytes, obrigado!
Neil
você está certo, desculpe: P
DanielIndie 14/04
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()

Recebe entrada como uma lista de strings (uma por linha)

Exemplo: Entrada:

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

Resultado:

              (
            -----/|-(o__
         //|~~\---~\|\/o))
..."Have*you/mooed~today?"...
TFeld
fonte
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 teste ungolfed:

#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 do teste:

insira a descrição da imagem aqui

VolAnd
fonte
2

Algodoo (não concorrente)

Exemplo de entrada - degenerado usado.

Configuração

Runnning - gravidade padrão e salto.

Corrida

A precisão da saída pode ser ajustada através das configurações de Fricção e Densidade nos objetos.

Resultado

Algodoo é lógico programável .

wyldstallyns
fonte
Por que isso não é competitivo? A não concorrência é geralmente reservada para respostas em idiomas mais recentes que o desafio.
Post Rock Garf Hunter
Embora o Algodoo possa fazer lógica real, essa simulação é equivalente a soltar uma impressão triturada da entrada no chão e tirar uma foto dela. Não sei ao certo como capturar essa saída de maneira programática.
Wyldstallyns
E parecia errado dizer "programa de zero bytes! Eu ganho!"
Wyldstallyns
Eu suspeito que essa não seja, de fato, uma resposta de zero byte. Você fala sobre ajustes de configurações que parecem equivaler a escrever código. Pode ser uma boa ideia abrir uma meta questão sobre a pontuação do Algodoo. Também não acho que haja algo errado em ter um programa de zero byte.
Post Rock Garf Hunter
Vou abrir essa 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`')

Exemplos

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

Resultado:

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

Outro exemplo:

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

Resultado:

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

Função ungolfed

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
fonte
Uma maneira curta de testar se não está c>" "em branco é onde crepresenta o personagem que você está testando.
Neil