Comptez le hamantaschen ASCII!

18

Aujourd'hui est Pourim sur lequel une coutume est de distribuer des biscuits en forme de triangle avec une garniture appelée hamantaschen (singulier: hamantasch ). Une autre coutume est de boire beaucoup.

Je ne suis pas le boulanger le plus parfait .... J'ai tant de hamantaschen de taille irrégulière à donner et tant d'amis à leur donner! Si je vous ai envoyé une photo de mes cookies, pouvez-vous me dire combien j'ai de quelle taille et de quel remplissage? Mais parce que c'est Pourim et que je suis trop ivre pour lire beaucoup de code, il doit être aussi petit que possible.

Définitions

Taille

Un hamantasch peut être de n'importe quelle taille . Le plus petit hamantasch est de taille 1 et ressemble à ceci:

/\  --
--  \/

Parfois, plusieurs hamantaschen peuvent se chevaucher . La forme ci-dessous compte pour deux hamantaschen (une taille 1, une taille 2):

 /\
/\ \
----

Certains hamantaschen ont du remplissage . Cela sera indiqué en remplissant tous les espaces à l'intérieur avec un caractère. Notez que la taille 1 hamantaschen ne peut pas avoir de remplissage.

Nous allons nommer hamantaschen en fonction de remplissage et la taille. Utilisons le format <filling> <size>et s'il n'est pas rempli, - <size>(vous pouvez utiliser un espace au lieu d'un -, mais le démarque n'aime pas ça).

Voici un . 2, un . 4et un - 3:

          /\
         /./\
 ----   /./  \
 \../  /./    \
  \/   --------

Ce sont a @ 3, a . 2et a - 4:

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------

Voici quelque chose de plus difficile. Voyez comment le & 2remplissage est moins important que prévu à cause de l'inclinaison du chevauchement - 3? Il a un - 1, un & 2a - 3et un & 4:

--------
\   \/&/
 \  /\/
  \/&/
   \/

Contribution

Vous recevrez un fichier texte ou une seule chaîne de hamantaschen (la nouvelle ligne de fin facultative et les espaces de fin facultativement rembourrés pour être pairs).

Limites

  • Vous pouvez vous attendre à ce que la chaîne soit valide - c'est-à-dire que chaque caractère non blanc contribue à un hamantasch délicieusement sucré (pourquoi gaspiller la pâte?).
  • Vous pouvez également vous attendre à être bien rempli ou non - qui est, chaque il sera Oreilles d'Aman entièrement rempli d'un caractère ASCII cohérent - ASCII 32 pour non rempli, ou quoi que ce soit pour 32..127 rempli ( à l' exception /, \et -).
  • Ces hamantaschen ne sont pas empilés en 3 espaces. Tout /et \sera visible. Tous ceux -qui ne sont pas bloqués par /et \seront visibles. Le remplissage vient en dernier.
  • Tous les hamantaschen auront au moins la moitié de leur ligne horizontale (arrondie) visible.
  • Tout bloc de remplissage contigu ne remplit que le plus petit hamantasch qui l'entoure.

Production

Retourne une liste de "noms" de tous les hamantaschen qui répondent aux critères ci-dessus. La sortie peut être sous la forme que vous souhaitez (une chaîne, un hachage, une sortie standard, etc.).

Cas de test

Cas de test # 1

Entrée # 1:

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------
    /\
   /**\
  /*/\*\
 /*/..\*\
 --------

Sortie # 1:

. 2
. 2
- 4
@ 3
* 4

Cas de test # 2

Entrée # 2:

  /\----
 /\/\*\/
/ /\d\/
------

Sortie # 2:

- 3
- 2
d 2
- 1    
* 2
- 1

Test n ° 3

Entrée # 3:

----
\/\/
/\/\  /\
---- /::\
     ----

Résultat n ° 3:

- 1
- 1
- 2
- 1
- 1
- 2
: 2

Test n ° 4

Entrée # 4:

 /\/\
/ /\$\
-/--/\\
 --/--\
  /xxx/\
 /xxx/##\
 ---/----\
   /      \
   -------- 

Sortie # 4:

$ 2
x 4
- 3
- 2
- 4
- 1
- 1
# 2

Cas de test n ° 5 non valide

Contribution:

/\
\/

Production:

Vous n'avez pas besoin de gérer cela.

Pas que Charles
la source
Que diriez-vous d'un cas de test dans lequel les hamentaschen se chevauchent mais n'ont pas la même ligne horizontale? On peut même bloquer la ligne horizontale d'un autre.
fier haskeller
@proudhaskeller Ok, c'est fait. Cependant, et je viens de mettre cela dans le texte, c'est 2 espaces. Nous verrons toujours tout /et \ , et -toujours l'emporterons sur le remplissage.
Pas que Charles
2
@EasterlyIrk Il y a aussi d'autres éléments importants - lire le Livre d'Esther (et huer les méchants), donner aux pauvres - et des choses moins fondamentales comme s'habiller en costume.
Pas que Charles
1
rendu pertinent à nouveau!
downrep_nation
1
Sur la base d'une colonne initiale de zéro, toutes vos colonnes de sommets, sauf (1,0), sont désactivées par +1. Pourtant, je sais ce que vous voulez dire, et je ne suis pas d'accord. Quelle indication y a-t-il qui (2, 2)est le centre supérieur d'un - 2et pas seulement le haut droit et gauche des deux - 1s supérieurs ? Aucun que je puisse voir. Et la même logique s'applique à (3, 2). A moins que vous ne vouliez ajouter une règle pour supposer un maximum de hamantaschen possible ...
Michael Plotke

Réponses:

4

C #, 496 452 octets

Edit: a trouvé un bug avec la vérification des limites ... mais aussi rayé une charge d'octets ayant été forcé de comprendre mon propre code. Dérouler la fonction locale a aidé un peu et a supprimé le code spécifique C # 7. Cette question a été très amusante.

using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,z=0,d,q,c,j,b;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L;var B=new int[H];for(d=W;(d=-d)>0||++z<H*H;)for(c=1,q=z%H;c<=z/H&q%W+c<W&q>=d&q<H+d&&D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47);q-=d+1,c+=2){for(b=0;j>q;)b+=D[--j-d]==45?2:0;for(char h='-',e;c==z/H&b>c;C.WriteLine(h+" "+c/2))for(b=c++;b>1;j=q+=d+1,b-=2)for(;j<q+b;)B[j]=h=B[j]<1&h==45&(e=D[j++])!=47&e!=92&e>32?e:h;}}}

Essayez-le en ligne

Programme complet, attend une entrée remplie d'espace à l'entrée standard, des sorties à la sortie standard. La sortie est une entrée par ligne, avec un saut de ligne de fin. Les cookies sont générés dans un ordre de taille croissant, en haut à gauche en premier. Il m'a fallu un bon moment pour comprendre les règles, mais je pense que cela passe tous les exemples fournis.

Il fonctionne en recherchant à plusieurs reprises sur toute la grille un Hamantaschen valide, en augmentant la taille «autorisée». Pour chaque cellule, il vérifie de haut en bas, en suivant le \et /de chaque côté autant que possible. S'il remarque que la ligne suivante a beaucoup de- et que la taille actuelle est la taille «autorisée», il détermine le remplissage et imprime l'entrée.

Le remplissage se trouve en explorant tout l'espace du cookie, à la recherche d'une cellule «inutilisée». Lorsqu'une cellule inutilisée est trouvée, elle est marquée comme utilisée (puisque nous augmentons la taille autorisée, nous savons que nous sommes le plus petit cookie qui la contient), et nous enregistrons le remplissage.

Code formaté et commenté:

using C=System.Console;

class P
{
    static void Main()
    {
        //   32
        // - 45
        // / 47
        // \ 92
        // range 32..127 (no mod for you)

        string D="", // the whole map
            L; // initally each line of the map, later each line of output

        int W=0, // width
            H=0, // length (width * height)
            z=0, // search tracker
            d, // check direction (this is backwards (1 byte saving!))
            q, // check tracker
            c, // counter (truely, this is the distance from the right to the left)
            //M, // c max (now inlined as z/H)
            j, // horiontal tracker
            b; // - count, and reverse counter

        // read map and width
        for(;(L=C.ReadLine())!=null; // read a line, while we can
                H+=W=L.Length) // record the width, and increment height
            D+=L; // add the line to the map

        var B=new int[H]; // whether this filling has been used already (0 -> false, >0 -> true)

        for(d=W; // init direction
            (d=-d)>0|| // swap direction, else increment z (this allows us to run the check for the same z twice with opposite direction)
            ++z<H*H; // for all M, for all q (z<H -> M=z/H=0 -> no valid cookies, so we can safetly skip them)
            )
            for(//M=z/H, // c allow (now inlined)
                c=1, // reset counter
                q=z%H; // note position
                c<=z/H& // counter check
                // no need for a left check: if we run off the left end, then the right check will necessarily fail
                q%W+c<W& // right check
                q>=d& // high check
                q<H+d&& // low check (short-circuit lookups)
                D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47); // /\ or \/ check, and set j=q+c
                    q-=d+1, // move left tracker
                    c+=2) // increase counter (move right tracker)
            {
                // count the number of '-' into b
                for(b=0; // zero b
                    j>q; // for each element in the row below
                        ) // empty
                    b+=D[--j-d]==45?2:0; // add 2 to b if we tap a '-'

                // j = q

                // check valid before looking up cHaracter (so we don't mark unused stuff as taken)
                // if we are at the current max count, and we have enough -, then we are valid and should be commited
                for( // this runs either one or zero times, we only have a for here (rather than an if) so we can ditch a pair of braces
                    char h='-', // default filling
                         e; // filling we are considering
                    c==z/H&b>c;
                        C.WriteLine(h+" "+c/2)) // print filling and count
                    // continuously compute character
                    for(b=c++; // count b backwards, starting from c (add 1 to c so we can /2 in print)
                        b>1;j=q+=d+1,b-=2) // count q backwards toward z%H (where q came from), and b backwards toward 1 (for each row)
                        for(;j<q+b;) // for each cell in row
                            B[j]= // mark cell as taken (h,e > 0)
                            h= // record filling
                                B[j]<1& // check cell not already used
                                h==45& // '-'
                                (e=D[j++])!=47& // '/'
                                e!=92& // '\'
                                e>32 // ' '
                                ?e:h; // take first filling we can
                    // c runs out after this (exists both loops), so no need to action
            }
    }
}

Sorties pour les 4 cas de test:

testcase #1
. 2
. 2
@ 3
- 4
* 4

testcase #2
- 1
- 1
- 2
d 2
* 2
- 3

testcase #3
- 1
- 1
- 1
- 1
- 2
- 2
: 2

testcase #4
- 1
- 1
- 2
$ 2
# 2
- 3
x 4
- 4
VisualMelon
la source
Je suis étonné de voir à quel point c'est compact en C #! Bien joué!
Pas que Charles
La seule réponse valable! J'ai quelque chose qui est presque fonctionnel, mais qui a quelques erreurs (mais je ne me définirais pas quand même comme gagnant)
Pas que Charles