¡Cuenta el ASCII hamantaschen!

18

Hoy es Purim en el que una costumbre es distribuir galletas en forma de triángulo con relleno llamado hamantaschen (singular: hamantasch ). Otra costumbre es beber mucho.

No soy el panadero más perfecto ... ¡Tengo tantos hamantaschen de tamaño irregular para dar y tantos amigos para darles! Si le envié una foto de mis cookies, ¿puede decirme cuántas tengo de qué tamaño y relleno? Pero debido a que es Purim y estoy demasiado borracho para leer mucho código, debe ser un código tan pequeño como puedas.

Definiciones

Talla

Un hamantasch puede ser de cualquier tamaño . El hamantasch más pequeño es de tamaño 1 y se ve así:

/\  --
--  \/

A veces, múltiples hamantaschen pueden superponerse . La siguiente forma cuenta como dos hamantaschen (una talla 1, una talla 2):

 /\
/\ \
----

Algunos hamantaschen tienen relleno . Esto se indicará rellenando todos los espacios en blanco con un carácter. Tenga en cuenta que el tamaño 1 hamantaschen no puede tener relleno.

Vamos a nombrar hamantaschen basado en el llenado y el tamaño. Usemos el formato <filling> <size>y si no está lleno - <size>(puede usar un espacio en lugar de un -, pero a Markdown no le gusta eso).

Aquí hay a . 2, a . 4y a - 3:

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

Estos son a @ 3, a . 2y a - 4:

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

Aquí hay algo más difícil. ¿Ves cómo & 2tiene menos relleno del que esperas debido a la inclinación de la superposición - 3? Tiene un - 1, un & 2a - 3y un & 4:

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

Entrada

Se le dará un archivo de texto o una sola cadena de hamantaschen (nueva línea final opcional y espacio en blanco final opcionalmente acolchado para que sea par).

Límites

  • Puede esperar que la cadena sea válida , es decir, cada carácter que no sea un espacio en blanco contribuye a un hamantasch deliciosamente dulce (¿por qué desperdiciar masa?).
  • También puede esperar que se llene correctamente o no, es decir, cada hamantasch se llenará por completo con un carácter ASCII consistente: ASCII 32 para sin llenar, o cualquier cosa 32..127 para lleno (excluyendo /, \y -).
  • Estas hamantaschen no se apilan en 3 espacios. Todo /y \será visible. Todos los -que no están bloqueados /y \serán visibles. El relleno es lo último.
  • Todos los hamantaschen tendrán al menos la mitad de su línea horizontal (redondeando hacia arriba) visible.
  • Cualquier bloque contiguo de relleno solo llena el hamantasch más pequeño que lo rodea.

Salida

Devuelva una lista de "nombres" de todos los hamantaschen que se pueden encontrar cumpliendo con los criterios anteriores. El resultado puede estar en la forma que desee (una cadena, un hash, stdout, etc.).

Casos de prueba

Caso de prueba n. ° 1

Entrada # 1:

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

Salida # 1:

. 2
. 2
- 4
@ 3
* 4

Caso de prueba n. ° 2

Entrada # 2:

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

Salida # 2:

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

Prueba n. ° 3

Entrada # 3:

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

Salida # 3:

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

Prueba n. ° 4

Entrada # 4:

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

Salida # 4:

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

Caso de prueba inválido # 5

Entrada:

/\
\/

Salida:

No necesita manejar esto.

No es que Charles
fuente
¿Qué tal un caso de prueba en el que los hamentaschen se superponen pero no tienen la misma línea horizontal? Incluso se puede bloquear la línea horizontal de otro.
orgulloso Haskeller
@proudhaskeller Ok, listo. Sin embargo, y acabo de poner esto en el texto, esto es 2 espacios. Nosotros siempre ver todo /y \ , y -será siempre el llenado de triunfo.
No es que Charles
2
@EasterlyIrk También hay otras partes importantes: leer el Libro de Esther (y abuchear a los malos), dar a los pobres, y cosas menos fundamentales como vestirse con disfraces.
No es que Charles
1
hecho relevante de nuevo!
downrep_nation
1
Basado en una columna inicial de cero, todas sus columnas de vértice, excepto (1,0), están desactivadas por +1. Aún así, sé a qué te refieres, y no estoy de acuerdo. ¿Qué indicación hay de que (2, 2)es el centro superior de a - 2y no solo la parte superior derecha e izquierda de los dos - 1s superiores ? Ninguno que pueda ver. Y la misma lógica se aplica a (3, 2). A menos que desee agregar una regla para asumir el máximo hamantaschen posible ...
Michael Plotke

Respuestas:

4

C #, 496 452 bytes

Editar: encontré un error con comprobación de límites ... pero también eliminé una carga de bytes que se vieron obligados a comprender mi propio código. Desenrollar la función local ayudó un poco y eliminó el código específico de C # 7. Esta pregunta ha sido muy divertida.

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;}}}

Pruébalo en línea

Programa completo, espera entrada rellenada con espacio para entrada estándar, salidas para salida estándar. La salida es una entrada por línea, con avance de línea final. Las cookies se emiten en orden de tamaño creciente, la parte superior izquierda en primer lugar. Me tomó un buen tiempo entender las reglas, pero creo que pasa todos los ejemplos proporcionados.

Funciona buscando repetidamente en toda la cuadrícula Hamantaschen válido, incrementando el tamaño 'permitido'. Para cada celda, verifica hacia arriba y hacia abajo, siguiendo el \y/ a cada lado tanto como sea posible. Si nota que la siguiente fila tiene muchos- , y el tamaño actual es el tamaño 'permitido', entonces determina el relleno e imprime la entrada.

El relleno se encuentra explorando todo el espacio de la cookie, buscando una celda 'no utilizada'. Cuando se encuentra una celda no utilizada, se marca como usada (dado que aumentamos el tamaño permitido, sabemos que somos la cookie más pequeña que la contiene), y registramos el relleno.

Código formateado y comentado:

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

Salidas para los 4 casos de prueba:

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
fuente
¡Estoy sorprendido de lo compacto que es esto en C #! ¡Bien hecho!
No es que Charles
¡La única respuesta válida! Tengo algo que es casi funcional, pero tiene algunos errores (pero de todos modos no me establecería como ganador)
No es que Charles