Parchear el párrafo

32

En el espíritu de Patch the Image , aquí hay un desafío similar pero con texto.

Reto

¡La podredumbre ha afectado tu precioso texto! Dado un párrafo compuesto por caracteres ASCII, con un agujero rectangular en algún lugar, su programa debe intentar completar el agujero con el texto apropiado, de modo que el párrafo se mezcle lo mejor posible.

Definiciones adicionales

  • El agujero siempre será rectangular y puede abarcar varias líneas.
  • Solo habrá un agujero.
  • Tenga en cuenta que el agujero no necesariamente cae en los límites de las palabras (de hecho, generalmente no lo hará).
  • El agujero será como máximo el 25% del párrafo de entrada, pero puede superponerse o extenderse más allá del "final" del texto "normal" (vea los ejemplos de Euclides o Badger a continuación).
  • Dado que encontrar el agujero no es el punto principal de este desafío, estará compuesto únicamente por marcas hash #para permitir una fácil identificación.
  • Ninguna otra ubicación en el párrafo de entrada tendrá una marca hash.
  • Su código no puede usar el texto "normal" en los ejemplos a continuación: solo recibirá y procesará el texto con el agujero.
  • La entrada puede ser como una sola cadena de varias líneas, como una matriz de cadenas (un elemento por línea), como un archivo, etc., su elección de lo que sea más conveniente para su idioma.
  • Si lo desea, se puede tomar una entrada adicional opcional que detalle las coordenadas del agujero (por ejemplo, una tupla de coordenadas o similar).
  • Describa su algoritmo en su envío.

Votación

Se les pide a los votantes que juzguen las entradas en función de qué tan bien el algoritmo llena el agujero de texto. Algunas sugerencias incluyen lo siguiente:

  • ¿El área rellenada coincide con la distribución aproximada de espacios y puntuación como el resto del párrafo?
  • ¿El área rellenada presenta una sintaxis defectuosa? (p. ej., dos espacios seguidos, un punto seguido de un signo de interrogación, una secuencia errónea como , ,, etc.)
  • Si entrecierra los ojos (por lo que en realidad no está leyendo el texto), ¿puede ver dónde solía estar el agujero?
  • Si no hay palabras de CamelCase fuera del agujero, ¿el agujero contiene alguna? Si no hay letras en mayúscula fuera del hoyo, ¿contiene el hoyo? Si hay muchas letras en mayúscula fuera del hoyo, ¿el hoyo contiene una cantidad proporcional?

Criterio de validez

Para que un envío se considere válido, no debe alterar ningún texto del párrafo fuera del agujero (incluidos los espacios finales). Una nueva línea final al final es opcional.

Casos de prueba

El formato es el párrafo original en un bloque de código, seguido del mismo párrafo con un agujero. Los párrafos con el agujero se utilizarán como entrada.

1 (parchear la imagen)

In a popular image editing software there is a feature, that patches (The term
used in image processing is inpainting as @minxomat pointed out.) a selected
area of an image, based on the information outside of that patch. And it does a
quite good job, considering it is just a program. As a human, you can sometimes
see that something is wrong, but if you squeeze your eyes or just take a short
glance, the patch seems to fill in the gap quite well.

In a popular image editing software there is a feature, that patches (The term
used in image processing is inpainting as @minxomat pointed out.) a selected
area of an image, #############information outside of that patch. And it does a
quite good job, co#############is just a program. As a human, you can sometimes
see that something#############t if you squeeze your eyes or just take a short
glance, the patch seems to fill in the gap quite well.

2 (Dirección de Gettysburg)

But, in a larger sense, we can not dedicate, we can not consecrate, we can not
hallow this ground. The brave men, living and dead, who struggled here, have
consecrated it, far above our poor power to add or detract. The world will
little note, nor long remember what we say here, but it can never forget what
they did here. It is for us the living, rather, to be dedicated here to the
unfinished work which they who fought here have thus far so nobly advanced. It
is rather for us to be here dedicated to the great task remaining before us-
that from these honored dead we take increased devotion to that cause for which
they gave the last full measure of devotion-that we here highly resolve that
these dead shall not have died in vain-that this nation, under God, shall have
a new birth of freedom-and that government of the people, by the people, for
the people, shall not perish from the earth.

But, in a larger sense, we can not dedicate, we can not consecrate, we can not
hallow this ground. The brave men, living and dead, who struggled here, have
consecrated it, far above our poor power to add or detract. The world will
little note, nor long remember what we say here, but it can never forget what
they did here. It is for us the living, rather, to be dedicated here to the
unfinished work which they who fought here h######################advanced. It
is rather for us to be here dedicated to the######################before us-
that from these honored dead we take increas######################use for which
they gave the last full measure of devotion-######################solve that
these dead shall not have died in vain-that ######################, shall have
a new birth of freedom-and that government of the people, by the people, for
the people, shall not perish from the earth.

3 (Lorem Ipsum)

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo conse################irure dolor in reprehenderit
in voluptate velit esse cil################giat nulla pariatur. Excepteur
sint occaecat cupidatat non################in culpa qui officia deserunt
mollit anim id est laborum.

4 (Jabberwocky)

'Twas brillig, and the slithy toves
Did gyre and gimble in the wabe;
All mimsy were the borogoves,
And the mome raths outgrabe.

'Twas brillig, and the slithy toves
Did gyre a######### in the wabe;
All mimsy #########borogoves,
And the mome raths outgrabe.

5 (Prueba de Euclides del Teorema de Pitágoras)

1.Let ACB be a right-angled triangle with right angle CAB.
2.On each of the sides BC, AB, and CA, squares are drawn,
CBDE, BAGF, and ACIH, in that order. The construction of
squares requires the immediately preceding theorems in Euclid,
and depends upon the parallel postulate. [footnote 14]
3.From A, draw a line parallel to BD and CE. It will
perpendicularly intersect BC and DE at K and L, respectively.
4.Join CF and AD, to form the triangles BCF and BDA.
5.Angles CAB and BAG are both right angles; therefore C, A,
and G are collinear. Similarly for B, A, and H.
6.Angles CBD and FBA are both right angles; therefore angle ABD
equals angle FBC, since both are the sum of a right angle and angle ABC.
7.Since AB is equal to FB and BD is equal to BC, triangle ABD
must be congruent to triangle FBC.
8.Since A-K-L is a straight line, parallel to BD, then rectangle
BDLK has twice the area of triangle ABD because they share the base
BD and have the same altitude BK, i.e., a line normal to their common
base, connecting the parallel lines BD and AL. (lemma 2)
9.Since C is collinear with A and G, square BAGF must be twice in area
to triangle FBC.
10.Therefore, rectangle BDLK must have the same area as square BAGF = AB^2.
11.Similarly, it can be shown that rectangle CKLE must have the same
area as square ACIH = AC^2.
12.Adding these two results, AB^2 + AC^2 = BD × BK + KL × KC
13.Since BD = KL, BD × BK + KL × KC = BD(BK + KC) = BD × BC
14.Therefore, AB^2 + AC^2 = BC^2, since CBDE is a square.

1.Let ACB be a right-angled triangle with right angle CAB.
2.On each of the sides BC, AB, and CA, squares are drawn,
CBDE, BAGF, and ACIH, in that order. The construction of
squares requires the immediately preceding theorems in Euclid,
and depends upon the parallel postulate. [footnote 14]
3.From A, draw a line parallel to BD and CE. It will
perpendicularly intersect BC and DE at K and L, respectively.
4.Join CF and AD, to form the triangles BCF and BDA.
5.Angles CAB and BAG are both right angles; therefore C, A,
and G are #############milarly for B, A, and H.
6.Angles C#############e both right angles; therefore angle ABD
equals ang############# both are the sum of a right angle and angle ABC.
7.Since AB#############FB and BD is equal to BC, triangle ABD
must be co#############iangle FBC.
8.Since A-#############ight line, parallel to BD, then rectangle
BDLK has t############# of triangle ABD because they share the base
BD and hav#############titude BK, i.e., a line normal to their common
base, conn#############rallel lines BD and AL. (lemma 2)
9.Since C #############with A and G, square BAGF must be twice in area
to triangl#############
10.Therefo############# BDLK must have the same area as square BAGF = AB^2.
11.Similar############# shown that rectangle CKLE must have the same
area as square ACIH = AC^2.
12.Adding these two results, AB^2 + AC^2 = BD × BK + KL × KC
13.Since BD = KL, BD × BK + KL × KC = BD(BK + KC) = BD × BC
14.Therefore, AB^2 + AC^2 = BC^2, since CBDE is a square.

6 (tejón, tejón, tejón por weebl)

Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Mushroom, mushroom, a-
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Mushroom, mushroom, a-
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Mush-mushroom, a
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Argh! Snake, a snake!
Snaaake! A snaaaake, oooh its a snake!

Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Mushroom, mushroom, a-
Badger##################badger, badger,
badger##################badger, badger
Mushro##################
Badger##################badger, badger,
badger##################badger, badger
Mush-mushroom, a
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Argh! Snake, a snake!
Snaaake! A snaaaake, oooh its a snake!
AdmBorkBork
fuente
puedo suponer que el agujero es al menos tres caracteres de ancho
Rohan Jhunjhunwala
@RohanJhunjhunwala Claro. Dado el tamaño del texto, esa es una suposición bastante segura.
AdmBorkBork
El ejemplo de Gettysburg aparentemente contiene guiones de em, que no son simples ascii. Solo señalando eso, ya que dijo en sus comentarios en una de las respuestas que usaría casos de prueba ascii simples.
SuperJedi224
@ SuperJedi224 Gracias - arreglado.
AdmBorkBork

Respuestas:

15

Python 2

Sé que @atlasologist ya publicó una solución en Python 2, pero la forma en que funciona es un poco diferente. Esto funciona yendo a través de todos los agujeros, de arriba a abajo, de izquierda a derecha, mirando a los 5 personajes hacia atrás y al personaje de arriba, y encontrando un personaje donde coincidan. Si se encuentran varios caracteres, elige el más común. En caso de que no se encuentren caracteres, se elimina la restricción de caracteres anteriores. Si aún no se encuentran caracteres, disminuye la cantidad de caracteres que mira hacia atrás y se repite.

def fix(paragraph, holeChar = "#"):
    lines = paragraph.split("\n")
    maxLineWidth = max(map(len, lines))
    lines = [list(line + " " * (maxLineWidth - len(line))) for line in lines]
    holes = filter(lambda pos: lines[pos[0]][pos[1]] == holeChar, [[y, x] for x in range(maxLineWidth) for y in range(len(lines))])

    n = 0
    for hole in holes:
        for i in range(min(hole[1], 5), 0, -1):
            currCh = lines[hole[0]][hole[1]]
            over = lines[hole[0] - 1][hole[1]]
            left = lines[hole[0]][hole[1] - i : hole[1]]

            same = []
            almost = []
            for y, line in enumerate(lines):
                for x, ch in enumerate(line):
                    if ch == holeChar:
                        continue
                    if ch == left[-1] == " ":
                        continue
                    chOver = lines[y - 1][x]
                    chLeft = lines[y][x - i : x]
                    if chOver == over and chLeft == left:
                        same.append(ch)
                    if chLeft == left:
                        almost.append(ch)
            sortFunc = lambda x, lst: lst.count(x) / (paragraph.count(x) + 10) + lst.count(x)
            if same:
                newCh = sorted(same, key=lambda x: sortFunc(x, same))[-1]
            elif almost:
                newCh = sorted(almost, key=lambda x: sortFunc(x, almost))[-1]
            else:
                continue
            lines[hole[0]][hole[1]] = newCh
            break


    return "\n".join(map("".join, lines))

Aquí está el resultado de Badger, Badger, Badger:

Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger 
Mushroom, mushroom, a-                 
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger 
Mushroom, mushroom, a- b               
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger 
Mush-mushroom, a                       
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger 
Argh! Snake, a snake!                  
Snaaake! A snaaaake, oooh its a snake! 

Aquí está el resultado de la prueba:

1.Let ACB be a right-angled triangle with right angle CAB.                 
2.On each of the sides BC, AB, and CA, squares are drawn,                  
CBDE, BAGF, and ACIH, in that order. The construction of                   
squares requires the immediately preceding theorems in Euclid,             
and depends upon the parallel postulate. [footnote 14]                     
3.From A, draw a line parallel to BD and CE. It will                       
perpendicularly intersect BC and DE at K and L, respectively.              
4.Join CF and AD, to form the triangles BCF and BDA.                       
5.Angles CAB and BAG are both right angles; therefore C, A,                
and G are the same areamilarly for B, A, and H.                            
6.Angles CAB and CA, sqe both right angles; therefore angle ABD            
equals angle ABD becaus both are the sum of a right angle and angle ABC.   
7.Since ABD because theFB and BD is equal to BC, triangle ABD              
must be construction ofiangle FBC.                                         
8.Since A-angle ABD becight line, parallel to BD, then rectangle           
BDLK has the same area  of triangle ABD because they share the base        
BD and have the base thtitude BK, i.e., a line normal to their common      
base, conngle and G, sqrallel lines BD and AL. (lemma 2)                   
9.Since C = BD × BK + with A and G, square BAGF must be twice in area     
to triangle FBC. (lemma                                                    
10.Therefore angle and  BDLK must have the same area as square BAGF = AB^2.
11.Similarly for B, A,  shown that rectangle CKLE must have the same       
area as square ACIH = AC^2.                                                
12.Adding these two results, AB^2 + AC^2 = BD × BK + KL × KC             
13.Since BD = KL, BD × BK + KL × KC = BD(BK + KC) = BD × BC             
14.Therefore, AB^2 + AC^2 = BC^2, since CBDE is a square.

Y el resultado de Jabberwocky:

'Twas brillig, and the slithy toves
Did gyre and the mo in the wabe;   
All mimsy toves, anborogoves,      
And the mome raths outgrabe.       
Loovjo
fuente
55
Ese tejón es bastante impresionante, y Jabberwocky parece que podría ser el poema legítimo. Buen trabajo.
AdmBorkBork
6

Python 2

Esta es una solución bastante sencilla. Crea una cadena de muestra compuesta de palabras que se encuentran entre la longitud promedio de las palabras A: ( A/ 2) y A+ (A / 2), luego aplica fragmentos recortados del espacio inicial y final de la muestra al área del parche. No maneja las mayúsculas, y estoy seguro de que hay un caso de prueba de bola curva que lo rompería, pero funciona bien en los ejemplos. Consulte el siguiente enlace para ejecutar todas las pruebas.

También puse un parche en el código por si acaso.

def patch(paragraph):
    sample = [x.split() for x in paragraph if x.count('#') < 1]
    length = max([x.count('#') for x in paragraph if x.find('#')])
    s = sum(####################
    sample,[####################
    ])      ####################
    avg=sum(####################
    len(w)  ####################
    for w in####################
    s)//len(s)
    avg_range = range(avg-(avg//2),avg+(avg//2))
    sample = filter(lambda x:len(x) in avg_range, s)
    height=0
    for line in paragraph:
        if line.find('#'):height+=1
        print line.replace('#'*length,' '.join(sample)[(height-1)*length:height*length].strip())
    print '\n'

Lorem Ipsum, original y luego parcheado:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo conseore dolore magnairure dolor in reprehenderit
in voluptate velit esse cilenim minim quisgiat nulla pariatur. Excepteur
sint occaecat cupidatat nonnisi mollit aniin culpa qui officia deserunt
mollit anim id est laborum.

Intentalo

atlasólogo
fuente
3
Jeje mushroger...
AdmBorkBork
Bueno, no parchea tu código de una manera interesante.
mbomb007
@ mbomb007 eso se debe a los otros #caracteres en el código.
atlasólogo
@atlasologist Incluso si los cambias a otra cosa como @, nada interesante.
mbomb007
4

Java Shakespeare

¿Quién necesita una comprensión de las convenciones inglesas estándar? ¡Solo haz el tuyo! Al igual que al bardo se le permitió inventar sus propias palabras. Este bot no se preocupa demasiado por corregir las palabras cortadas, realmente solo inserta palabras al azar. El resultado es una hermosa poesía. Como característica adicional, el bardo es de un calibre más alto y puede manejar múltiples agujeros siempre que sean del mismo tamaño.


Entrada de muestra

 De las criaturas más bellas que deseamos aumentar,
  Que de ese modo la rosa de la belleza nunca muera,
  Pero como el madrugador debería por tiempo fallecer,
  Su tierna ############ lleva su memoria:
  Pero tú puedes ############ tus propios ojos brillantes,
  Alimente el ############ ame con combustible autosuficiente,
  Haciendo una hambruna donde yace la abundancia,
  Tú mismo tu enemigo, para tu dulce yo demasiado cruel:
  Tú que ahora eres el adorno fresco del mundo,
  Y solo anunciar a la llamativa primavera,
  Dentro de tu propio brote entierras tu contenido,
  Y tierno churl mak'st fue ############ ding:
    Lástima el mundo, o de lo contrario t ############ be,
    Para comer lo que le corresponde al mundo, b ############ y a ti.


                     2
  Cuando cuarenta inviernos asediarán tu frente,
  Y cava trincheras profundas en el campo de tu belleza,
  La orgullosa librea de tu juventud ahora miraba tanto,
  Será una maleza andrajosa de pequeño valor sostenido:  
  Luego, preguntándote dónde está toda tu belleza,
  Donde todo el tesoro de tus días lujuriosos;
  Decir dentro de tus propios ojos hundidos,
  Eran una vergüenza que todo lo come, y un elogio económico.
  Cuánto más alabanza merecía el uso de tu belleza,
  Si pudieras responder 'Este hermoso hijo mío
  Deberé sumar mi cuenta y dar mi vieja excusa
  Demostrando su belleza por sucesión tuya.
    Esto debía hacerse de nuevo cuando seas viejo,
    Y mira tu sangre tibia cuando la sientas fría.


                     3
  Mira en tu vaso y dile a la cara que ves,
  Ahora es el momento en que esa cara debe formar otra,
  Cuya nueva reparación si ahora no renuevas,
  Tú engañas al mundo, liberas a una madre.
  Porque, ¿dónde es ella tan bella cuyo útero no visto?
  ¿Desprecia la labranza de tu cría?
  ¿O quién es tan aficionado será la tumba?
  ¿De su amor propio para detener la posteridad?  
  Tú eres el vaso de tu madre y ella en ti
  Devuelve el hermoso abril de su mejor momento,
  Entonces a través de las ventanas de tu edad verás,
  A pesar de ############ s tu tiempo dorado.
    Pero si ############ no podría ser,
    Die singl ############ imagen muere contigo.

Hermosa salida

 De las criaturas más bellas que deseamos aumentar,
  Que de ese modo la rosa de la belleza nunca muera,
  Pero como el madrugador debería por tiempo fallecer,
  Su tierno debe de llevar su memoria:
  Pero todos has engendrado tus propios ojos brillantes,
  Alimente la prueba o ame con combustible autosuficiente,
  Haciendo una hambruna donde yace la abundancia,
  Tú mismo tu enemigo, para tu dulce yo demasiado cruel:
  Tú que ahora eres el adorno fresco del mundo,
  Y solo anunciar a la llamativa primavera,
  Dentro de tu propio brote entierras tu contenido,
  Y tierno churl mak'st fue él Tú mi ding:
    Lástima del mundo, o de lo contrario t Así que el ser,
    Para comer lo que le corresponde al mundo, así es tú y tú.


                     2
  Cuando cuarenta inviernos asediarán tu frente,
  Y cava trincheras profundas en el campo de tu belleza,
  La orgullosa librea de tu juventud ahora miraba tanto,
  Será una maleza andrajosa de pequeño valor sostenido:  
  Luego, preguntándote dónde está toda tu belleza,
  Donde todo el tesoro de tus días lujuriosos;
  Decir dentro de tus propios ojos hundidos,
  Eran una vergüenza que todo lo come, y un elogio económico.
  Cuánto más alabanza merecía el uso de tu belleza,
  Si pudieras responder 'Este hermoso hijo mío
  Deberé sumar mi cuenta y dar mi vieja excusa
  Demostrando su belleza por sucesión tuya.
    Esto debía hacerse de nuevo cuando seas viejo,
    Y mira tu sangre tibia cuando la sientas fría.


                     3
  Mira en tu vaso y dile a la cara que ves,
  Ahora es el momento en que esa cara debe formar otra,
  Cuya nueva reparación si ahora no renuevas,
  Tú engañas al mundo, liberas a una madre.
  Porque, ¿dónde es ella tan bella cuyo útero no visto?
  ¿Desprecia la labranza de tu cría?
  ¿O quién es tan aficionado será la tumba?
  ¿De su amor propio para detener la posteridad?  
  Tú eres el vaso de tu madre y ella en ti
  Devuelve el hermoso abril de su mejor momento,
  Entonces a través de las ventanas de tu edad verás,
  A pesar de Mira, mira tu tiempo dorado.
    Pero si fuera cuando, no sería,
    Die singl reparar la imagen muere contigo.

Las últimas dos líneas son profundamente poéticas si lo digo yo mismo. Se desempeña sorprendentemente bien en la dirección de Gettysburg también.

But, in a larger sense, we can not dedicate, we can not consecrate, we can not
hallow this ground. The brave men, living and dead, who struggled here, have
consecrated it, far above our poor power to add or detract. The world will
little note, nor long remember what we say here, but it can never forget what
they did here. It is for us the living, rather, to be dedicated here to the
unfinished work which they who fought here h to of rather us of advanced. It
is rather for us to be here dedicated to the who be it, vain who before us 
that from these honored dead we take increas be dead the the what use for which
they gave the last full measure of devotion  dead government The solve that
these dead shall not have died in vain that  the take nor world , shall have
a new birth of freedom and that government of the people, by the people, for
the people, shall not perish from the earth.


Veamos qué hace que Shakespeare funcione. Aquí está el código. Esencialmente se esfuerza por construir una base de vocabulario a partir de la entrada. Luego usa estas palabras y las coloca al azar en el agujero (asegurándose de que encajen bien). Es determinista ya que usa una semilla fija para aleatoriedad.

package stuff;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;

/**
 *
 * @author rohan
 */
public class PatchTheParagraph {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("File Name :");
        String[] text = getWordsFromFile(in.nextLine());
System.out.println("==ORIGINAL==");
        for(String s:text){
    System.out.println(s);
}
                    int lengthOfHole= 0;
        int rows = 0;
            for(String s: text){
                s = s.replaceAll("[^#]", "");

//      System.out.println(s);
                if(s.length()>0){
                    lengthOfHole = s.length();
                rows++;
                }
            }
            ArrayList<String> words = new ArrayList<>();
            words.add("I");
            for(String s:text){
                String[] w = s.replaceAll("#", " ").split(" ");
for(String a :w){
    words.add(a);
            }

            }
                        Iterator<String> j = words.iterator();
            while(j.hasNext()){
                String o;
                if((o = j.next()).equals("")){
                    j.remove();
                }
            }
            System.out.println(words);
            Stack<String> out = new Stack<>();
            String hashRow = "";
            for(int i = 0;i<lengthOfHole;i++){
                hashRow+="#";
            }

        for(int i = 0;i<rows;i++){
            int length = lengthOfHole-1; 
            String outPut = " ";
            while(length>2){
String wordAttempt = words.get(getRandom(words.size()-1));
while(wordAttempt.length()>length-1){
 wordAttempt = words.get(getRandom(words.size()-1));
}           
length -= wordAttempt.length()+1;
            outPut+=wordAttempt;
                outPut+=" ";
            }
        out.push(outPut);
    }
System.out.println("==PATCHED==");
        for(String s : text){
            if(s.contains(hashRow)){
                System.out.println(s.replaceAll(hashRow,out.pop()));
            }else{
                System.out.println(s);
            }
        }
                                    }
public static final Random r = new Random(42);
    public static int getRandom(int max){
    return (int) (max*r.nextDouble());
}
    /**
     *
     * @param fileName is the path to the file or just the name if it is local
     * @return the number of lines in fileName
     */
    public static int getLengthOfFile(String fileName) {
        int length = 0;
        try {
            File textFile = new File(fileName);
            Scanner sc = new Scanner(textFile);
            while (sc.hasNextLine()) {
                sc.nextLine();
                length++;
            }
        } catch (Exception e) {
System.err.println(e);
        }
        return length;
    }

    /**
     *
     * @param fileName is the path to the file or just the name if it is local
     * @return an array of Strings where each string is one line from the file
     * fileName.
     */
    public static String[] getWordsFromFile(String fileName) {
        int lengthOfFile = getLengthOfFile(fileName);
        String[] wordBank = new String[lengthOfFile];
        int i = 0;
        try {
            File textFile = new File(fileName);
            Scanner sc = new Scanner(textFile);
            for (i = 0; i < lengthOfFile; i++) {
                wordBank[i] = sc.nextLine();
            }
            return wordBank;
        } catch (Exception e) {
            System.err.println(e);
            System.exit(55);
        }
        return null;
    }
}


La mayor parte de la poesía de Shakespeare es de dominio público.

Rohan Jhunjhunwala
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Dennis
3

Python 2.7

Otra solución de Python con un enfoque diferente. Mi programa ve el texto como una cadena de Markov , donde cada letra es seguida por otra letra con una cierta probabilidad. Entonces, el primer paso es construir la tabla de probabilidades. El siguiente paso es aplicar esas probabilidades al parche.

El código completo, incluido un texto de ejemplo, se encuentra a continuación. Debido a que un ejemplo usaba caracteres Unicode, incluí una página de códigos explícita (utf-8) para compatibilidad con ese ejemplo.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from collections import defaultdict
import numpy

texts = [
"""'Twas brillig, and the slithy toves
Did gyre a######### in the wabe;
All mimsy #########borogoves,
And the mome raths outgrabe."""
]

class Patcher:
    def __init__(self):
        self.mapper = defaultdict(lambda: defaultdict(int))

    def add_mapping(self, from_value, to_value):
        self.mapper[from_value][to_value] += 1

    def get_patch(self, from_value):
        if from_value in self.mapper:
            sum_freq = sum(self.mapper[from_value].values())
            return numpy.random.choice(
                self.mapper[from_value].keys(),
                p = numpy.array(
                    self.mapper[from_value].values(),dtype=numpy.float64) / sum_freq)
        else:
            return None

def add_text_mappings(text_string, patcher = Patcher(), ignore_characters = ''):
    previous_letter = text_string[0]
    for letter in text_string[1:]:
        if not letter in ignore_characters:
            patcher.add_mapping(previous_letter, letter)
            previous_letter = letter
    patcher.add_mapping(text_string[-1], '\n')

def patch_text(text_string, patcher, patch_characters = '#'):
    result = previous_letter = text_string[0]
    for letter in text_string[1:]:
        if letter in patch_characters:
            result += patcher.get_patch(previous_letter)
        else:
            result += letter
        previous_letter = result[-1]
    return result

def main():
    for text in texts:
        patcher = Patcher()
        add_text_mappings(text, patcher, '#')
        print patch_text(text, patcher, '#')
        print "\n"

if __name__ == '__main__':
    main()

Salida de muestra para Lorem Ipsum:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo conse Exe eut ccadamairure dolor in reprehenderit
in voluptate velit esse cilore indipserexepgiat nulla pariatur. Excepteur
sint occaecat cupidatat non upir alostat adin culpa qui officia deserunt
mollit anim id est laborum.

Una línea poética extra en el Jabberwocky:

'Twas brillig, and the slithy toves
Did gyre and me the in the wabe;
All mimsy was
An inborogoves,
And the mome raths outgrabe.
en cualquier lugar
fuente
¿Qué texto de ejemplo tiene Unicode? Todos deberían ser ASCII rectos. Avísame y lo corregiré.
AdmBorkBork
Python se queja del mınxomaτ en el primer texto, refiriéndose a PEP 263 .
agtoever
Ah, ni siquiera me di cuenta. Lo he editado para que sea ASCII directo. ¡Gracias por hacérmelo saber!
AdmBorkBork
2

C # 5 masivo como siempre

Creé esto, es un poco desordenado, pero produce algunos buenos resultados algunas veces. Es un algoritmo mayormente determinista, pero con cierta aleatoriedad (semilla fija) agregada para evitar que produzca la misma cadena para huecos similares. Es necesario un esfuerzo para tratar de evitar tener columnas de espacios a ambos lados de los espacios.

Funciona mediante la tokenización de la entrada en palabras y puntuación (la puntuación proviene de una lista ingresada manualmente, porque no me molesto en averiguar si Unicode puede hacer esto por mí), para que pueda poner espacios antes de las palabras, y no antes puntuación, porque esto es bastante típico. Se divide en espacios en blanco típicos. En la línea de las cadenas de Markov (creo), cuenta con qué frecuencia cada ficha sigue a la otra ficha, y luego no calcula las probabilidades para esto (me imagino que debido a que los documentos son tan pequeños, sería mejor sesgar las cosas vemos mucho donde podemos). Luego realizamos una búsqueda de amplitud, llenando el espacio dejado por los hashes y las palabras 'parciales' a cada lado, con el costo calculado como -fabness(last, cur) * len(cur_with_space), donde fabnessdevuelve el número de veces que curha seguidolastpara cada token agregado en la cadena generada. Naturalmente, tratamos de minimizar el costo. Debido a que no siempre podemos llenar el vacío con las palabras y los signos de puntuación que se encuentran en el documento, también considera una serie de tokens 'especiales' de ciertos estados, incluidas las cadenas parciales en ambos lados, contra las cuales sesgamos con costos arbitrariamente incrementados.

Si el BFS no logra encontrar una solución, entonces intentamos ingenuamente elegir un adverbio aleatorio, o simplemente insertar espacios para llenar el espacio.

Resultados

Los 6 se pueden encontrar aquí: https://gist.github.com/anonymous/5277db726d3f9bdd950b173b19fec82a

El caso de prueba de Euclides no salió muy bien ...

Parchear la imagen

In a popular image editing software there is a feature, that patches (The term
used in image processing is inpainting as @minxomat pointed out.) a selected
area of an image, that patches information outside of that patch. And it does a
quite good job, co the patch a is just a program. As a human, you can sometimes
see that something In a short it if you squeeze your eyes or just take a short
glance, the patch seems to fill in the gap quite well.

Jabberwocky

'Twas brillig, and the slithy toves
Did gyre and the in in the wabe;
All mimsy the mome borogoves,
And the mome raths outgrabe.

Tejón

Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Mushroom, mushroom, a-
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Mushroom, badger, badger
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Mush-mushroom, a
Badger, badger, badger, badger, badger,
badger, badger, badger, badger, badger
Argh! Snake, a snake!
Snaaake! A snaaaake, oooh its a snake!

_Estoy contento con la forma en que resultó ... es fortuito que "tejón, tejón" encaje, o este no hubiera funcionado tan bien

Código

Ejecútalo con

csc ParaPatch.cs
ParaPatch.exe infile outfile

Hay bastante de eso. El único bit remotamente interesante es el Fillmétodo. Incluyo la implementación del montón, porque .NET no tiene una (¿POR QUÉ MS POR QUÉ?).

using System;
using System.Collections.Generic;
using System.Linq;

namespace ParaPatch
{
    class Program
    {
        private static string[] Filler = new string[] { "may", "will", "maybe", "rather", "perhaps", "reliably", "nineword?", "definitely", "elevenword?", "inexplicably" }; // adverbs
        private static char[] Breaking = new char[] { ' ', '\n', '\r', '\t' };
        private static char[] Punctuation = new char[] { ',', '.', '{', '}', '(', ')', '/', '?', ':', ';', '\'', '\\', '"', ',', '!', '-', '+', '[', ']', '£', '$', '%', '^', '—' };

        private static IEnumerable<string> TokenizeStream(System.IO.StreamReader reader)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            HashSet<char> breaking = new HashSet<char>(Breaking);
            HashSet<char> punctuation = new HashSet<char>(Punctuation);

            while (!reader.EndOfStream)
            {
                int ci = reader.Read();
                if (ci == -1) // sanity
                    break;

                char c = (char)ci;

                if (breaking.Contains(c))
                {
                    if (sb.Length > 0)
                        yield return sb.ToString();
                    sb.Clear();
                }
                else if (punctuation.Contains(c))
                {
                    if (sb.Length > 0)
                        yield return sb.ToString();
                    yield return ""+c;
                    sb.Clear();
                }
                else
                {

                    sb.Append(c);
                }
            }

            if (sb.Length > 0)
                yield return sb.ToString();
        }

        private enum DocTokenTypes
        {
            Known,
            LeftPartial,
            RightPartial,
            Unknown,
        }

        private class DocToken
        {
            public DocTokenTypes TokenType { get; private set; }
            public string StringPart { get; private set; }
            public int Length { get; private set; }

            public DocToken(DocTokenTypes tokenType, string stringPart, int length)
            {
                TokenType = tokenType;
                StringPart = stringPart;
                Length = length;
            }
        }

        private static IEnumerable<DocToken> DocumentTokens(IEnumerable<string> tokens)
        {
            foreach (string token in tokens)
            {
                if (token.Contains("#"))
                {
                    int l = token.IndexOf("#");
                    int r = token.LastIndexOf("#");

                    if (l > 0)
                        yield return new DocToken(DocTokenTypes.LeftPartial, token.Substring(0, l), l);

                    yield return new DocToken(DocTokenTypes.Unknown, null, r - l + 1);

                    if (r < token.Length - 1)
                        yield return new DocToken(DocTokenTypes.RightPartial, token.Substring(r + 1), token.Length - r - 1);
                }
                else
                    yield return new DocToken(DocTokenTypes.Known, token, token.Length);
            }
        }

        private class State : IComparable<State>
        {
            // missing readonly params already... maybe C#6 isn't so bad
            public int Remaining { get; private set; }
            public int Position { get; private set; }
            public State Prev { get; private set; }
            public string Token { get; private set; }
            public double H { get; private set; }
            public double Fabness { get; private set; }
            public string FullFilling { get; private set; }

            public State(int remaining, int position, Program.State prev, double fabness, double h, string token, string toAdd)
            {
                Remaining = remaining;
                Position = position;
                Prev = prev;
                H = h;
                Fabness = fabness;
                Token = token;

                FullFilling = prev != null ? prev.FullFilling + toAdd : toAdd;
            }

            public int CompareTo(State other)
            {
                return H.CompareTo(other.H);
            }
        }

        public static void Main(string[] args)
        {
            if (args.Length < 2)
                args = new string[] { "test.txt", "testout.txt" };

            List<DocToken> document;
            using (System.IO.StreamReader reader = new System.IO.StreamReader(args[0], System.Text.Encoding.UTF8))
            {
                document = DocumentTokens(TokenizeStream(reader)).ToList();
            }

            foreach (DocToken cur in document)
            {
                Console.WriteLine(cur.StringPart + " " + cur.TokenType);
            }

            // these are small docs, don't bother with more than 1 ply
            Dictionary<string, Dictionary<string, int>> FollowCounts = new Dictionary<string, Dictionary<string, int>>();
            Dictionary<string, Dictionary<string, int>> PreceedCounts = new Dictionary<string, Dictionary<string, int>>(); // mirror (might be useful)

            HashSet<string> knowns = new HashSet<string>(); // useful to have lying around

            // build counts
            DocToken last = null;
            foreach (DocToken cur in document)
            {
                if (cur.TokenType == DocTokenTypes.Known)
                {
                    knowns.Add(cur.StringPart);
                }

                if (last != null && last.TokenType == DocTokenTypes.Known && cur.TokenType == DocTokenTypes.Known)
                {
                    {
                        Dictionary<string, int> ltable;
                        if (!FollowCounts.TryGetValue(last.StringPart, out ltable))
                        {
                            FollowCounts.Add(last.StringPart, ltable = new Dictionary<string, int>());
                        }

                        int count;
                        if (!ltable.TryGetValue(cur.StringPart, out count))
                        {
                            count = 0;
                        }
                        ltable[cur.StringPart] = count + 1;
                    }


                    {
                        Dictionary<string, int> ctable;
                        if (!PreceedCounts.TryGetValue(cur.StringPart, out ctable))
                        {
                            PreceedCounts.Add(cur.StringPart, ctable = new Dictionary<string, int>());
                        }

                        int count;
                        if (!ctable.TryGetValue(last.StringPart, out count))
                        {
                            count = 0;
                        }
                        ctable[last.StringPart] = count + 1;
                    }
                }

                last = cur;
            }

            // build probability grid (none of this efficient table filling dynamic programming nonsense, A* all the way!)
            // hmm... can't be bothered
            Dictionary<string, Dictionary<string, double>> fabTable = new Dictionary<string, Dictionary<string, double>>();
            foreach (var k in FollowCounts)
            {
                Dictionary<string, double> t = new Dictionary<string, double>();

                // very naive
                foreach (var k2 in k.Value)
                {
                    t.Add(k2.Key, (double)k2.Value);
                }

                fabTable.Add(k.Key, t);
            }

            string[] knarr = knowns.ToArray();
            Random rnd = new Random("ParaPatch".GetHashCode());

            List<string> fillings = new List<string>();
            for (int i = 0; i < document.Count; i++)
            {
                if (document[i].TokenType == DocTokenTypes.Unknown)
                {
                    // shuffle knarr
                    for (int j = 0; j < knarr.Length; j++)
                    {
                        string t = knarr[j];
                        int o = rnd.Next(knarr.Length);
                        knarr[j] = knarr[o];
                        knarr[o] = t;
                    }

                    fillings.Add(Fill(document, fabTable, knarr, i));
                    Console.WriteLine(fillings.Last());
                }
            }

            string filling = string.Join("", fillings);

            int fi = 0;

            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(args[1]))
            using (System.IO.StreamReader reader = new System.IO.StreamReader(args[0]))
            {
                while (!reader.EndOfStream)
                {
                    int ci = reader.Read();
                    if (ci == -1)
                        break;

                    char c = (char)ci;
                    c = c == '#' ? filling[fi++] : c;

                    writer.Write(c);
                    Console.Write(c);
                }
            }

//            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(args[1], false, System.Text.Encoding.UTF8))
//            using (System.IO.StreamReader reader = new System.IO.StreamReader(args[0]))
//            {
//                foreach (char cc in reader.ReadToEnd())
//                {
//                    char c = cc;
//                    c = c == '#' ? filling[fi++] : c;
//                    
//                    writer.Write(c);
//                    Console.Write(c);
//                }
//            }

            if (args[0] == "test.txt")
                Console.ReadKey(true);
        }

        private static string Fill(List<DocToken> document, Dictionary<string, Dictionary<string, double>> fabTable, string[] knowns, int unknownIndex)
        {
            HashSet<char> breaking = new HashSet<char>(Breaking);
            HashSet<char> punctuation = new HashSet<char>(Punctuation);

            Heap<State> due = new Heap<Program.State>(knowns.Length);

            Func<string, string, double> fabness = (prev, next) =>
            {
                Dictionary<string, double> table;
                if (!fabTable.TryGetValue(prev, out table))
                    return 0; // not fab
                double fab;
                if (!table.TryGetValue(next, out fab))
                    return 0; // not fab
                return fab; // yes fab
            };

            DocToken mostLeft = unknownIndex > 2 ? document[unknownIndex - 2] : null;
            DocToken left = unknownIndex > 1 ? document[unknownIndex - 1] : null;
            DocToken unknown = document[unknownIndex];
            DocToken right = unknownIndex < document.Count - 2 ? document[unknownIndex + 1] : null;
            DocToken mostRight = unknownIndex < document.Count - 3 ? document[unknownIndex + 2] : null;

            // sum of empty space and partials' lengths
            int spaceSize = document[unknownIndex].Length
                + (left != null && left.TokenType == DocTokenTypes.LeftPartial ? left.Length : 0)
                + (right != null && right.TokenType == DocTokenTypes.RightPartial ? right.Length : 0);

            int l = left != null && left.TokenType == DocTokenTypes.LeftPartial ? left.Length : 0;
            int r = l + unknown.Length;

            string defaultPrev =
                left != null && left.TokenType == DocTokenTypes.Known ? left.StringPart :
                mostLeft != null && mostLeft.TokenType == DocTokenTypes.Known ? mostLeft.StringPart :
                "";

            string defaultLast =
                right != null && right.TokenType == DocTokenTypes.Known ? right.StringPart :
                mostRight != null && mostRight.TokenType == DocTokenTypes.Known ? mostRight.StringPart :
                "";

            Func<string, string> topAndTail = str =>
            {
                return str.Substring(l, r - l);
            };

            Func<State, string, double, bool> tryMove = (State prev, string token, double specialFabness) => 
            {
                bool isPunctionuation = token.Length == 1 && punctuation.Contains(token[0]);
                string addStr = isPunctionuation || prev == null ? token : " " + token;
                int addLen = addStr.Length;

                int newRemaining = prev != null ? prev.Remaining - addLen : spaceSize - addLen;
                int oldPosition = prev != null ? prev.Position : 0;
                int newPosition = oldPosition + addLen;

                // check length
                if (newRemaining < 0)
                    return false;

                // check start
                if (oldPosition < l) // implies left is LeftPartial
                {
                    int s = oldPosition;
                    int e = newPosition > l ? l : newPosition;
                    int len = e - s;
                    if (addStr.Substring(0, len) != left.StringPart.Substring(s, len))
                        return false; // doesn't match LeftPartial
                }

                // check end
                if (newPosition > r) // implies right is RightPartial
                {
                    int s = oldPosition > r ? oldPosition : r;
                    int e = newPosition;
                    int len = e - s;
                    if (addStr.Substring(s - oldPosition, len) != right.StringPart.Substring(s - r, len))
                        return false; // doesn't match RightPartial
                }

                if (newRemaining == 0)
                {
                    // could try to do something here (need to change H)
                }

                string prevToken = prev != null ? prev.Token : defaultPrev;
                bool isLastunctionuation = prevToken.Length == 1 && punctuation.Contains(prevToken[0]);

                if (isLastunctionuation && isPunctionuation) // I hate this check, it's too aggresive to be realistic
                    specialFabness -= 50;

                double fab = fabness(prevToken, token);

                if (fab < 1 && (token == prevToken))
                    fab = -1; // bias against unrecognised repeats

                double newFabness = (prev != null ? prev.Fabness : 0.0)
                    - specialFabness // ... whatever this is
                    - fab * addLen; // how probabilistic

                double h = newFabness; // no h for now

                State newState = new Program.State(newRemaining, newPosition, prev, newFabness, h, token, addStr);

//                Console.WriteLine((prev != null ? prev.Fabness : 0) + "\t" + specialFabness);
//                Console.WriteLine(newFabness + "\t" + h + "\t" + due.Count + "\t" + fab + "*" + addLen + "\t" + newState.FullFilling);

                due.Add(newState);
                return true;
            };

            // just try everything everything
            foreach (string t in knowns)
                tryMove(null, t, 0);

            if (left != null && left.TokenType == DocTokenTypes.LeftPartial)
                tryMove(null, left.StringPart, -1);

            while (!due.Empty)
            {
                State next = due.RemoveMin();

                if (next.Remaining == 0)
                {
                    // we have a winner!!
                    return topAndTail(next.FullFilling);
                }

                // just try everything
                foreach (string t in knowns)
                    tryMove(next, t, 0);
                if (right != null && right.TokenType == DocTokenTypes.RightPartial)
                    tryMove(next, right.StringPart, -5); // big bias
            }

            // make this a tad less stupid, non?
            return Filler.FirstOrDefault(f => f.Length == unknown.Length) ?? new String(' ', unknown.Length); // oh dear...
        }
    }

    //
    // Ultilities
    //

    public class Heap<T> : System.Collections.IEnumerable where T : IComparable<T>
    {
        // arr is treated as offset by 1, all idxes stored need to be -1'd to get index in arr
        private T[] arr;
        private int end = 0;

        private void s(int idx, T val)
        {
            arr[idx - 1] = val;
        }

        private T g(int idx)
        {
            return arr[idx - 1];
        }

        public Heap(int isize)
        {
            if (isize < 1)
                throw new ArgumentException("Cannot be less than 1", "isize");

            arr = new T[isize];
        }

        private int up(int idx)
        {
            return idx / 2;
        }

        private int downLeft(int idx)
        {
            return idx * 2;
        }

        private int downRight(int idx)
        {
            return idx * 2 + 1;
        }

        private void swap(int a, int b)
        {
            T t = g(a);
            s(a, g(b));
            s(b, t);
        }

        private void moveUp(int idx, T t)
        {
        again:
            if (idx == 1)
            {
                s(1, t);
                return; // at end
            }

            int nextUp = up(idx);
            T n = g(nextUp);
            if (n.CompareTo(t) > 0)
            {
                s(idx, n);
                idx = nextUp;
                goto again;
            }
            else
            {
                s(idx, t);
            }
        }

        private void moveDown(int idx, T t)
        {
        again:
            int nextLeft = downLeft(idx);
            int nextRight = downRight(idx);

            if (nextLeft > end)
            {
                s(idx, t);
                return; // at end
            }
            else if (nextLeft == end)
            { // only need to check left
                T l = g(nextLeft);

                if (l.CompareTo(t) < 0)
                {
                    s(idx, l);
                    idx = nextLeft;
                    goto again;
                }
                else
                {
                    s(idx, t);
                }
            }
            else
            { // check both
                T l = g(nextLeft);
                T r = g(nextRight);

                if (l.CompareTo(r) < 0)
                { // left smaller (favour going right if we can)
                    if (l.CompareTo(t) < 0)
                    {
                        s(idx, l);
                        idx = nextLeft;
                        goto again;
                    }
                    else
                    {
                        s(idx, t);
                    }
                }
                else
                { // right smaller or same
                    if (r.CompareTo(t) < 0)
                    {
                        s(idx, r);
                        idx = nextRight;
                        goto again;
                    }
                    else
                    {
                        s(idx, t);
                    }
                }
            }
        }

        public void Clear()
        {
            end = 0;
        }

        public void Trim()
        {
            if (end == 0)
                arr = new T[1]; // don't /ever/ make arr len 0
            else
            {
                T[] narr = new T[end];
                for (int i = 0; i < end; i++)
                    narr[i] = arr[i];
                arr = narr;
            }
        }

        private void doubleSize()
        {
            T[] narr = new T[arr.Length * 2];
            for (int i = 0; i < end; i++)
                narr[i] = arr[i];
            arr = narr;
        }

        public void Add(T item)
        {
            if (end == arr.Length)
            {
                // resize
                doubleSize();
            }

            end++;
            moveUp(end, item);
        }

        public T RemoveMin()
        {
            if (end < 1)
                throw new Exception("No items, mate.");

            T min = g(1);

            end--;
            if (end > 0)
                moveDown(1, g(end + 1));

            return min;
        }

        public bool Empty
        {
            get
            {
                return end == 0;
            }
        }

        public int Count
        {
            get
            {
                return end;
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public IEnumerator<T> GetEnumerator()
        {
            return (IEnumerator<T>)arr.GetEnumerator();
        }
    }
}
VisualMelon
fuente