Pissenlits ASCII

17

Ce sont des pissenlits ASCII:

   \|/      \ /          |      
   /|\       |    \|/    |      
    |        |     |   _\|/_
    |        |     |    /|\

Les pissenlits ASCII ont trois paramètres: Longueur de la tige (nombre positif entre 1 et 256, nombre de graines (nombre positif entre 0 et 7) et orientation (^ ou v). Les pissenlits ci-dessus ont pour longueur, graines et orientation, ( 3,5, ^), (3,2, ^), (2,3, ^) et (3,7, v) respectivement.

Les graines sont remplies dans l'ordre suivant (retourné à l'envers pour les pissenlits tête en bas), illustré sur un pissenlit de longueur 2:

seeds:  0    1    2    3    4    5     6      7

             |   \ /  \|/  \ /  \|/  _\ /_  _\|/_
        |    |    |    |   /|\  /|\   /|\    /|\
        |    |    |    |    |    |     |      |

Le défi:

Écrivez un programme / une fonction qui, lorsqu'il reçoit un pissenlit ASCII en entrée, renvoie sa longueur, son nombre de graines et son orientation formatés de la même manière que dans les exemples ci-dessus et lorsque des paramètres donnés dans ce format renvoient un pissenlit ASCII avec ces paramètres. Vous pouvez ignorer les parenthèses et supposer que l'entrée / sortie sera un nombre, une virgule, un nombre, une virgule et soit ^ou v. Vous pouvez remplacer d'autres caractères par ^/ vtant qu'ils peuvent toujours être facilement interprétés comme «haut» / «bas» (par exemple, u/ d). Vous n'avez pas besoin de distinguer les pissenlits qui se ressemblent, tels que (2,1, ^) et (3,0, ^) ou (2,1, ^) et (2,1, v). Étant donné l'art ASCII, l'un ou l'autre ensemble de paramètres serait une sortie acceptable, et les deux ensembles de paramètres peuvent donner le même art ASCII.

C'est le , donc le code le plus court en octets l'emporte.


Un exemple de programme en C # (pas même légèrement golfé):

    string Dandelion(string s)
    {
        if (s.Contains(','))
        {
            //got parameters as input
            string[] p = s.Split(',');
            //depth and width (number of seeds)
            int d = int.Parse(p[0]);
            int w = int.Parse(p[1]);
            //draw stem
            string art = "  |";
            while (d > 2)
            {
                d--;
                art += "\n  |";
            }
            //draw head
            string uhead = (w % 2 == 1 ? "|" : " ");
            string dhead = uhead;
            if (w > 1)
            {
                uhead = "\\" + uhead + "/";
                dhead = "/" + dhead + "\\";
                if (w > 5)
                {
                    uhead = "_" + uhead + "_\n /|\\";
                    dhead = "_\\|/_\n " + dhead;
                }
                else if (w > 3)
                {
                    uhead = " " + uhead + " \n /|\\";
                    dhead = " \\|/ \n " + dhead;
                }
                else
                {
                    uhead = " " + uhead + " \n  |";
                    dhead = "  |\n " + dhead;
                }
            }
            else
            {
                uhead = "  " + uhead + "\n  |";
                dhead = "  |\n  " + dhead;
            }
            //add head to body
            if (p[2] == "^")
            {
                return uhead + "\n" + art;
            }
            return art + "\n" + dhead;
        }
        else
        {
            //ASCII input
            string[] p = s.Split('\n');
            int l = p.Length - 1;
            int offset = 0;
            //find first non-' ' character in art
            while (p[0][offset] == ' ')
            {
                offset++;
            }
            int w = 0;
            if (p[0][offset] == '|')
            {
                //if '|', either head-down or no head.
                if (offset == 0 || p[l][offset - 1] == ' ')
                {
                    //if no space for a head to the left or no head at the bottom, no head.
                    return l.ToString() + ",1,^";
                }
                //head must have at least size 2, or else indistinguishable from no head case 
                w = 6;
                if (p[l][offset] == '|')
                {
                    //odd sized head
                    w = 7;
                }
                if (offset == 1 || p[l - 1][offset - 2] == ' ')
                {
                    //not size 6 or 7
                    w -= 2;
                    if (p[l - 1][offset - 1] == ' ')
                    {
                        //not size 4 or 5
                        w -= 2;
                    }
                }
                return l.ToString() + "," + w.ToString() + ",v";
            }
            else if (p[0][offset] == '\\')
            {
                //head at least size 2 and not 6/7, or indistinguishable from no head.
                w = 4;
                if (p[0][offset + 1] == '|')
                {
                    w = 5;
                }
                if (p[1][offset] == ' ')
                {
                    w -= 2;
                }
            }
            else
            {
                w = 6;
                if (p[0][offset + 2] == '|')
                {
                    w = 7;
                }
            }
            return l.ToString() + "," + w.ToString() + ",^";
        }
    }
P ...
la source
Pouvons-nous prendre d'autres symboles distincts au lieu de ^et v?
Kritixi Lithos du
@KritixiLithos Tant qu'ils peuvent être facilement interprétés comme «haut» et «bas», bien sûr.
P ...
3
Comment trouvez-vous la différence entre une graine 1 de longueur 2 et une graine 0 de longueur 3 pissenlit? Pour les graines 0 et 1, il est également impossible de dire si elles sont retournées ...
Luke
@Luke Vous n'avez pas besoin de distinguer les arbres qui se ressemblent. Vous devez renvoyer le même art ASCII dans le cas de la graine 1 de longueur 2 que dans la graine 0 de longueur 3, et vous pouvez renvoyer la graine 1 de longueur 2 ou la graine 0 de longueur 3 lorsque cette art est en entrée.
P ...
1
Sauf erreur, il semble que nous ayons une réponse qui se traduit des paramètres en ASCII et une autre réponse qui se traduit des ASCII en paramètres. Mais nous sommes censés prendre en charge les deux tâches, non?
Arnauld

Réponses:

6

Bean , 321 octets

Accepte l'entrée en tant que chaîne unique dans stdin sans retour à la ligne. Les paramètres seront pris de la même manière, mais formatés comme

length (1-256)
orientation (u or d)
seeds (0-7)

Les paramètres de sortie du programme lorsque l'entrée est un pissenlit seront au même format que ci-dessus.

Hexdump:

00000000 26 52 ca c1 20 5d d3 d0 80 d5 cd a0 5e 80 4c cc  &RÊÁ ]ÓÐ.ÕÍ ^.LÌ
00000010 a0 45 86 25 3e 88 4d a0 6b 80 4c a0 5e 80 23 60   E.%>.M k.L ^.#`
00000020 cd a0 63 80 43 cd a0 5f 80 50 84 a3 81 00 20 5e  Í c.CÍ _.P.£.. ^
00000030 d0 84 a3 81 01 4d a0 60 80 4a c1 4c a0 45 86 25  Ð.£..M `.JÁL E.%
00000040 3a d0 84 a3 81 02 4c a0 45 92 25 3a d0 84 a3 81  :Ð.£..L E.%:Ð.£.
00000050 03 20 60 a0 5f a3 81 04 cd a0 61 80 50 84 a3 81  . ` _£..Í a.P.£.
00000060 05 20 5e cf 52 cc a0 45 86 25 3c a3 81 06 23 81  . ^ÏRÌ E.%<£..#.
00000070 07 a0 61 cf 53 d0 80 a3 81 08 20 80 b5 4c a0 43  . aÏSÐ.£.. .µL C
00000080 8c 25 3a 00 52 a0 6b d3 50 80 a0 63 20 80 7e 20  .%:.R kÓP. c .~ 
00000090 63 20 80 7b 23 00 53 d0 80 c3 cc d0 80 a0 78 20  c .{#.SÐ.ÃÌÐ. x 
000000a0 80 01 8c 25 3a d2 ce cc a0 5d 80 23 81 09 80 4c  ...%:ÒÎÌ ].#...L
000000b0 d0 84 a0 5e 25 3b 81 23 81 0a ce d3 50 80 a0 78  Ð. ^%;.#..ÎÓP. x
000000c0 20 80 7e 81 23 60 23 71 cc d2 cc d0 84 d0 84 a0   .~.#`#qÌÒÌÐ.Ð. 
000000d0 78 25 3a 25 3a 81 23 81 0b cc a5 3d 8b 4c cc d0  x%:%:.#..Ì¥=.LÌÐ
000000e0 84 d0 84 a0 78 25 39 25 39 81 50 84 d0 84 a0 78  .Ð. x%9%9.P.Ð. x
000000f0 25 3a 25 39 8d 25 3b 4c cc d0 84 d0 84 a0 78 25  %:%9.%;LÌÐ.Ð. x%
00000100 39 25 3c 81 23 81 0b 8d 25 3b 8b 4c d0 84 d0 84  9%<.#...%;.LÐ.Ð.
00000110 a0 78 25 39 25 3b 81 23 81 0b 00 20 80 7b 23 81   x%9%;.#... .{#.
00000120 04 a0 df 20 a0 5c a0 7c a0 2f 0a a0 a0 5f af fc  . ß  \ | /.  _¯ü
00000130 5c a0 fc 20 8a a0 a0 fc a0 20 a0 a0 fc a0 20 7c  \ ü .  ü    ü  |
00000140 20                                                
00000141

JavaScript équivalent:

+a?                               // if input is parameters
  (
    b=(C>5)<<(o=b=="d"),          // encoding if seeds > 5 and if orientation is down
    g=[                           // storing dandelion as array of characters
      c=" _ "[b],                 // "_" if seeds > 5 and orientation is up, else " "
      " \\"[d=+(C>1)],            // "\" if seeds > 1, else " "
      " |"[C&1],                  // "|" if seeds is odd, else " "
      " /"[d],
      c,                          // "_" if seeds > 5 and orientation is up, else " "
      "\n",
      e="  _"[b],                 // "_" if seeds > 5 and orientation is down, else " "
      ...(                        // spread characters for .reverse() to be correct
        C>3?                      // if seeds > 3 "/|\" else " | "
          "/|\\":
          " | "
      ),
      e,                          // "_" if seeds > 5 and orientation is down, else " "
      ..."\n  |  ".repeat(A-1)    // repeat stem length - 1 times
    ],
    o?                            // if orientation is down, reverse
      g.reverse():
      g
  ).join(""):                     // join array of characters
  [                               // else if input is dandelion
    _.length-1,                   // length of stem is number of rows - 1
    a=="  |  "||b[2]!="|"?        // test orientation of dandelion
      _.reverse()&&"d":           // reverse rows if necessary and return "d" for down
      "u"                         // else return "u" for up
    ,
    (
      _[1][1]!=" "?               // if 1,1 is not " ", seeds is 4 or more
        4+(_[0][0]!=_[1][0])*2:   // if 0,0 or 1,0 is "_", seeds is 6 or 7
        (_[0][3]!=" ")*2          // if 0,3 is not " ", seeds is 2 or 3
    )+
    (_[0][2]!=" ")                // if 0,2 is not " ", seeds is odd
  ].join("\n")                    // join parameters with newline to match input format

Prend implicitement stdin comme un tableau de chaînes non formatées séparées par des sauts de ligne et génère _implicitement les paramètres sous forme de triplet. Suite de tests ci-dessous et démonstration ici :

const js = String.raw`
+a?                               // if input is parameters
  (
    b=(C>5)<<(o=b=="d"),          // encoding if seeds > 5 and if orientation is down
    g=[                           // storing dandelion as array of characters
      c=" _ "[b],                 // "_" if seeds > 5 and orientation is up, else " "
      " \\"[d=+(C>1)],            // "\" if seeds > 1, else " "
      " |"[C&1],                  // "|" if seeds is odd, else " "
      " /"[d],
      c,                          // "_" if seeds > 5 and orientation is up, else " "
      "\n",
      e="  _"[b],                 // "_" if seeds > 5 and orientation is down, else " "
      ...(                        // spread characters for .reverse() to be correct
        C>3?                      // if seeds > 3 "/|\" else " | "
          "/|\\":
          " | "
      ),
      e,                          // "_" if seeds > 5 and orientation is down, else " "
      ..."\n  |  ".repeat(A-1)    // repeat stem length - 1 times
    ],
    o?                            // if orientation is down, reverse
      g.reverse():
      g
  ).join(""):                     // join array of characters
  [                               // else if input is dandelion
    _.length-1,                   // length of stem is number of rows - 1
    a=="  |  "||b[2]!="|"?        // test orientation of dandelion
      _.reverse()&&"d":           // reverse rows if necessary and return "d" for down
      "u"                         // else return "u" for up
    ,
    (
      _[1][1]!=" "?               // if 1,1 is not " ", seeds is 4 or more
        4+(_[0][0]!=_[1][0])*2:   // if 0,0 or 1,0 is "_", seeds is 6 or 7
        (_[0][3]!=" ")*2          // if 0,3 is not " ", seeds is 2 or 3
    )+
    (_[0][2]!=" ")                // if 0,2 is not " ", seeds is odd
  ].join("\n")                    // join parameters with newline to match input format`;

// bean binary
const bin = bean.compile(js);

// program as function
const prog = bean.program(bin);

(document.body.onchange = function () {
  const parameters = stem.value + '\n' + orientation.value + '\n' + seeds.value;
  dandelion.textContent = prog(parameters);
  params.value = prog(dandelion.textContent);
})();
textarea {
  resize: none;
}
<script src="https://cdn.rawgit.com/patrickroberts/bean/master/dst/bean.min.js"></script>
<input id=stem type=number min=1 max=256 value=5>
<select id=orientation>
  <option value="u">u</option>
  <option value="d">d</option>
</select>
<input id=seeds type=number min=0 max=7 value=5>
<p>Dandelion (output from program given parameters)</p>
<pre id=dandelion></pre>
<p>Parameters (output from program given dandelion)</p>
<textarea id=params rows=3></textarea>

Patrick Roberts
la source
2

Javascript 513 391 379 355 octets

Merci à @Neil pour avoir aidé le golf sur 134 octets et @Kritixi Lithos pour avoir aidé le golf sur 13 octets. Ce programme suppose que tous les pissenlits ASCII qu'il essaie d'identifier ont une largeur de ligne de 5 pour toutes les lignes de la chaîne. soit: la tige est de 2 espaces, la ligne verticale puis encore 2 espaces. (Il ne peut pas classer les pissenlits qu'il crée en raison de ce problème)

(x,y,z)=>{a=Array(x+1).fill(1);if(x.length>1){a=x.split`
`;h=a.length-1;t=b=i=0;for(;i<(h>1)+1;i++)for(j=0;j<5;a[h-i][j++]!=' '&&b++)a[i][j]!=' '&&t++;return[h,(t>b?t:b)-(h>1),t>b?'^':'v']}z<'v'?(a[0]=y&4?y-2:y,a[1]=y&4?7:1):(a[x-1]=1+(y>4)*2+(y>4)*(y&2),a[x]=y&1+(y>2)*6);return a.map(n=>',  |, \\ /, \\|/,_\\ /_,_\\|/_, / \\, /|\\'.split`,`[n]).join`
`}

Comment ça fonctionne

La fonction vérifie si le premier argument qui lui est donné a une longueur> 1 (est une chaîne). Si le premier argument est une chaîne, il identifie les détails du pissenlit ASCII.

Pour obtenir la hauteur du pissenlit, il divise la chaîne autour des caractères de nouvelle ligne et compte le nombre d'éléments - 1. Pour obtenir le nombre de graines, il compte le nombre de caractères non spatiaux sur les deux lignes du haut et du bas. s'il y a plus de caractères en haut, il est déclaré vertical et il utilise le décompte supérieur-1, sinon il est déclaré à l'envers et utilise le décompte inférieur-1. Si la hauteur totale n'est que de 2, elle détermine la droiture en vérifiant les nombres de chaque ligne individuellement et en choisissant le côté avec plus de caractères non espace.

Sinon, la fonction utilise des mathématiques au niveau du bit afin d'affecter des valeurs de 0 à 7 en fonction de la forme de chaque niveau du pissenlit à dessiner avant de convertir chaque niveau dans la chaîne appropriée.

0:  
1:  |  
2: \\ /  
3: \\|/  
4:_\\ /_  
5:_\\|/_  
6: / \\  
7: /|\\

Essayez-le en ligne

fəˈnɛtɪk
la source
1
@JonathanAllan l'a corrigé afin qu'il catégorise désormais une entrée de pissenlit
fəˈnɛtɪk
1
En prenant juste votre créateur de pissenlit, j'ai pu jouer au golf à 125 octets. Mon code ne peut pas être collé directement dans votre solution, mais vous pouvez peut-être incorporer certaines des économies:(x,y,z,a=[...Array(x+1)].fill(1))=>a.map(n=>', |, \\ /, \\|/,_\\ //,_\\|/_, / \\, /|\\'.split`,`[n],z<'v'?(a[0]=y&4?y-2:y,a[1]=y&4?7:1):(a[x-1]=1+(y>4)*2+(y>4)*(y&2),a[x]=y&1+(y>2)*6)).join`\n`
Neil
1
Vous pouvez supprimer le elsecar vous revenez ifquand même dans la pièce. De plus, pendant que je suis ici, je voulais simplement souligner que certaines fonctions telles que splitet joinn'ont pas besoin des ()s lorsque vous les invoquez sur `des littéraux de chaîne entre guillemets, c'est pourquoi je ne les ai pas incluses dans mon commentaire précédent.
Neil
1
Vous devez utiliser le bon type de guillemets, cela ne fonctionne qu'avec `s, pas 's ou "s.
Neil
1
Vous pouvez modifier le \ndans join`\n`une nouvelle ligne (comme dans le caractère). Vous pouvez également changer le (h>2?1:0)en juste h>2et le (h>2?2:1)en (h>2)+1. tio.run/#IRiKF
Kritixi Lithos
1

Python 3.6, 476 453 448 413 394 octets

Solution :

def h(i):
 l,s,o=i.split(",");s=int(s);z=["  |  "];q=(int(l)-1)*z;b,d,f,h,g,c,a=["  ","\\/"][s>1]+["  ","\\/"][s>3]+["| ","||"][s%2==1]+[" ","_"][s>5]
 if"d"==o:b,d,h,f,c,g=f,h,d,b,g,c
 r=[[a+b+c+d+a]+[" "+h+g+f+" "],z][s==0];return"\n".join([q+r,r+q]["u"==o])
def j(i):
 if","in i:print(h(i))
 else:[print(f"{m},{j},{k}")for m in range(257)for j in range(8)for k in"ud"if i==h(f"{m},{j},{k}")]

Résultat

>>> j("6,5,u")
 \|/
 /|\
  |
  |
  |
  |
  |
>>> j("5,2,d")
  |
  |
  |
  |
  |
 / \
>>> j("3,2,u")
 \ /
  |
  |
  |
>>> j("_\|/_\n /|\ \n  |  \n  |  \n  |  \n  |  \n  |  ")
6,7,u
>>> j(" \|/ \n /|\ \n  |  \n  |  \n  |  \n  |  ")
5,5,u
>>> j("  |  \n  |  \n  |  \n  |  \n  |  ")
4,1,u
4,1,d
5,0,u
5,0,d

Se dérouler

def g(i):
    def h(i):                       # this function draw dandelion
        l, s, o = i.split(",")      # split argument 
        s = int(s)

        # Calcul the string in the flower for up case 
        #   _\|/_   --> abcdb  --> when s=7 we have a=_ b=\ c=| d=/ h=/ g=| f=\ 
        #    /|\    -->  hgf  
        a = "_" if s > 5 else " "
        b = "\\" if s > 1 else " "
        d = "/" if s > 1 else " "
        h = "/" if s > 3 else " "
        f = "\\" if s > 3 else " "
        c = "|" if s%2 == 1 else " "
        g = "|" if s%2 == 1 else "|"

        # Shuffle a bit if the position is down 
        if"d"==o:
            b,d,h,f,c,g=f,h,d,b,g,c

        # treate the case to remove the line with ony white space
        if s==0:
            res=["  |  "]
        else:
            # assemble all piece of the flower
            res += [a+b+c+d+a]
            res += [" "+h+g+f+" "]

        # add stem up or down
        if o=="u":
            res = res + (int(l)-1) * ["  |  "]
        else:
            res = (int(l)-1) * ["  |  "] + res
        return "\n".join(res)

    if "," in i:
        print(h(i))
    else:
        # search in all flower posibility if we can recreate the input
        [print(m,j,k) for m in range(1, 257) for j in range(0, 8)for k in "ud"if i == h(f"{m},{j},{k}")]
Erwan
la source