Réduire ascii-art

12

Défi

Étant donné une grille rectangulaire de caractères ascii imprimables sous forme de chaîne ou via une entrée standard, écrivez une fonction ou un programme qui réduit les caractères non spatiaux en une pile en bas.

Les règles:

  • La sortie a les mêmes dimensions et caractères que l'entrée.
  • Un caractère non espace dans (row a,column b)ne peut pas avoir de caractère espace ' 'dans (a-1, b), (a-1,b-1)ou (a-1,b+1), où les lignes sont numérotées à partir du bas. Cela a pour conséquence que tous les pieux verticaux doivent s'effondrer latéralement.
  • Un personnage non spatial peut se déplacer dans la plupart des (initial height - final height)endroits vers la gauche ou la droite (voir Fig. 1).
  • Vous pouvez supposer que l'image a suffisamment d'espace pour se réduire sans que des caractères ne tombent de l'écran.

Figure 1: emplacements finaux possibles pour les caractères @#$représentés par x,y,z, respectivement.

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

L'ordre dans lequel les caractères s'effondrent peut être choisi librement. Les espaces de fin ne sont pas corrects, mais les retours à la ligne de fin le sont.

C'est le , donc la réponse la plus courte en octets l'emporte!

Exemple

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

Une sortie possible:

 
 
 
                --(_
           /----|/|(o_)
          /|/~\---~\\/o)
..."Have*you~mooed~today?"...
Angs
la source
Juste pour clarifier, la façon dont les personnages tombent peut être codée en dur plutôt que générée aléatoirement à chaque fois?
ETHproductions
18
Qu'est-ce que cette vache vous a fait? :(
FlipTack
@ETHproductions c'est correct. Mon exemple le fait de bas en haut, de gauche à droite, mais un ordre aléatoire ou autre chose va bien, tant que les règles sont respectées.
Angs
@ Flp.Tkc Ce n'est qu'un modèle.
Angs
1
@DestructibleWatermelon Si un personnage tombe de l'écran, c'est sa faute, pas la vôtre.
Angs

Réponses:

4

JavaScript (ES6), 100 90 88 octets

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

Exige que la chaîne ait au moins deux lignes et toutes les lignes soient égales à la même longueur. Sortie pour l'image d'exemple:

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

Notez que comme il essaie de déplacer les éléments vers la droite si possible, le *n'est pas tombé entre le Haveet le you.

Edit: Économisez 10% grâce à @ETHproductions. Sauvegardé encore 2 octets grâce à @DanielIndie.

Retina 0.8.2 , 50 octets

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

Essayez-le en ligne! Une approche légèrement différente de ma réponse JavaScript, qui utilise un groupe d'équilibrage pour faire correspondre un espace sous le caractère non-espace; le (?<-1>)?permet l'espace d'être une colonne à gauche tandis que le .?permet l'espace d'être une colonne à droite.

Rétine , 40 octets

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

Essayez-le en ligne! Port de ma réponse JavaScript. L' 0L$étage atomique prend l'entrée et substitue les deux longueurs à la deuxième ligne, ce qui entraîne la commande qui effectue réellement le remplacement, qui est ensuite évaluée sur l'entrée d'origine par l' ~étage composé.

Neil
la source
Ceci est un excellent algorithme! Vous pouvez remplacer \npar un saut de ligne littéral pour le réduire à deux chiffres ;-)
ETHproductions
Aussi, je pense que vous pouvez ainsi l=s.search`\n` économiser quelques octets.
ETHproductions
tio.run/##ZY/… 86 octets
DanielIndie
@DanielIndie Le f=est requis pour la récursivité, mais il me fait encore économiser 2 octets, merci!
Neil
vous avez raison, désolé: P
DanielIndie
3

Python 2, 298 octets

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

Prend l'entrée comme une liste de chaînes (une par ligne)

Exemple: entrée:

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

Production:

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

C, 252 octets

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++]);}

Code de test non 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();
}

Résultat du test:

entrez la description de l'image ici

VolAnd
la source
2

Algodoo (non compétitif)

Entrée - exemple dégénéré utilisé.

Installer

Runnning - gravité par défaut et rebond.

Fonctionnement

Sortie - la précision peut être ajustée via les paramètres Friction et Densité sur les objets.

Production

Algodoo est programmable par logique .

wyldstallyns
la source
Pourquoi est-ce non concurrentiel? La non-concurrence est généralement réservée aux réponses dans des langues plus récentes que le défi.
Ad Hoc Garf Hunter
Bien qu'Algodoo puisse faire une vraie logique, cette simulation équivaut à supprimer une impression déchiquetée de l'entrée sur le sol et à la prendre en photo. Je ne sais pas trop comment capturer même cette sortie de manière programmatique.
wyldstallyns
Et il semblait faux de dire "programme zéro octet! Je gagne!"
wyldstallyns
Je soupçonne que ce n'est pas en fait une réponse à zéro octet. Vous parlez de modifier les paramètres, ce qui semble être l'équivalent de l'écriture de code. Ce pourrait être une bonne idée d'ouvrir une méta-question sur la notation d'Algodoo. Je ne pense pas non plus qu'il y ait quelque chose de mal à avoir un programme à zéro octet.
Ad Hoc Garf Hunter
Je vais ouvrir cette méta.
wyldstallyns
1

JavaScript, 286 octets

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

Exemples

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

Production:

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

Un autre exemple:

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

Production:

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

Fonction non golfée

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
la source
Un moyen court de tester si non vide est c>" "creprésente le personnage que vous testez.
Neil