Establecer aritmética teórica (+ y *) [cerrado]


10

Establecer aritmética teórica

Premisa

Ya ha habido un par de desafíos que implican la multiplicación sin el operador de multiplicación ( aquí y aquí ) y este desafío está en la misma línea (más similar al segundo enlace).

Este desafío, a diferencia de los anteriores, utilizará una definición teórica establecida de los números naturales ( N ):

ingrese la descripción de la imagen aquí

y

ingrese la descripción de la imagen aquí

por ejemplo,

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

y así.

El reto

Nuestro objetivo es utilizar operaciones de conjuntos (ver abajo), para sumar y multiplicar números naturales. Para este propósito, todas las entradas estarán en el mismo 'idioma establecido' cuyo intérprete está debajo . Esto proporcionará consistencia y una puntuación más fácil.

Este intérprete le permite manipular números naturales como conjuntos. Su tarea será escribir dos cuerpos de programa (ver más abajo), uno de los cuales agrega números naturales y el otro los multiplica.

Notas preliminares sobre conjuntos

Los conjuntos siguen la estructura matemática habitual. Aquí hay algunos puntos importantes:

  • Los conjuntos no están ordenados.
  • Ningún conjunto se contiene a sí mismo
  • Los elementos están en un conjunto o no, esto es booleano. Por lo tanto, los elementos del conjunto no pueden tener multiplicidades (es decir, un elemento no puede estar en un conjunto varias veces).

Intérprete y detalles

Un 'programa' para este desafío está escrito en 'set language' y consta de dos partes: un encabezado y un cuerpo.

Encabezamiento

El encabezado es muy simple. Le dice al intérprete qué programa está resolviendo. El encabezado es la línea de apertura del programa. Comienza con el carácter +o *, seguido de dos enteros, delimitados por espacios. Por ejemplo:

+ 3 5

o

* 19 2

Son encabezados válidos. El primero indica que está tratando de resolver 3+5, lo que significa que su respuesta debería serlo 8. El segundo es similar, excepto con la multiplicación.

Cuerpo

El cuerpo es donde están sus instrucciones reales para el intérprete. Esto es lo que realmente constituye su programa de "suma" o "multiplicación". Su respuesta consistirá en dos cuerpos de programa, uno para cada tarea. Luego cambiará los encabezados para llevar a cabo los casos de prueba.

Sintaxis e Instrucciones

Las instrucciones consisten en un comando seguido de cero o más parámetros. Para los propósitos de las siguientes demostraciones, cualquier carácter del alfabeto es el nombre de una variable. Recuerde que todas las variables son conjuntos. labeles el nombre de una etiqueta (las etiquetas son palabras seguidas de punto y coma (es decir main_loop:), intes un número entero. Las siguientes son las instrucciones válidas:

Control de flujo:
  1. jump labelsaltar incondicionalmente a la etiqueta. Una etiqueta es una 'palabra' seguida de un punto y coma: por ejemplo, main_loop:es una etiqueta.
  2. je A label saltar a la etiqueta si A está vacío
  3. jne A label saltar a la etiqueta si A no está vacío
  4. jic A B label saltar a la etiqueta si A contiene B
  5. jidc A B label saltar a la etiqueta si A no contiene B
Asignación Variable
  1. assign A Bo assign A int ingrese la descripción de la imagen aquío
    donde set(int)es la representación establecida deint
Establecer operaciones
  1. union A B C ingrese la descripción de la imagen aquí
  2. intersect A B C
  3. difference A B C ingrese la descripción de la imagen aquí
  4. add A B ingrese la descripción de la imagen aquí
  5. remove A B ingrese la descripción de la imagen aquí
Depuración
  1. print A imprime el verdadero valor de A, donde {} es el conjunto vacío
  2. printi variable imprime una representación entera de A, si existe, de lo contrario genera un error.
Comentarios
  1. ; El punto y coma indica que el resto de la línea es un comentario y el intérprete lo ignorará.

Informacion adicional

Al inicio del programa, hay tres variables preexistentes. Ellos son set1,set2 y ANSWER. set1toma el valor del primer parámetro de encabezado. set2toma el valor del segundo. ANSWERInicialmente es el conjunto vacío. Al finalizar el programa, el intérprete verifica si ANSWERes la representación entera de la respuesta al problema aritmético definido en el encabezado. Si es así, indica esto con un mensaje para stdout.

El intérprete también muestra el número de operaciones utilizadas. Cada instrucción es una operación. Iniciar una etiqueta también cuesta una operación (las etiquetas solo se pueden iniciar una vez).

Puede tener un máximo de 20 variables (incluidas las 3 variables predefinidas) y 20 etiquetas.

Código de intérprete

NOTAS IMPORTANTES SOBRE ESTE INTÉRPRETE

Las cosas son muy lentas cuando se usan números grandes (> 30) en este intérprete. Voy a describir las razones de esto.

  • Las estructuras de los conjuntos son tales que al aumentar en un número natural, efectivamente se duplica el tamaño de la estructura del conjunto. El n º número natural tiene 2 ^ n conjuntos vacíos dentro de ella (por esto quiero decir que si nos fijamos n como un árbol, hay n conjuntos vacíos. Nota únicos conjuntos vacíos pueden ser hojas.) Esto significa que se trata de 30 es significativamente más costoso que lidiar con 20 o 10 (estás viendo 2 ^ 10 vs 2 ^ 20 vs 2 ^ 30).
  • Los controles de igualdad son recursivos. Dado que los conjuntos supuestamente no están ordenados, esta parecía la forma natural de abordar esto.
  • Hay dos pérdidas de memoria que no pude encontrar cómo solucionar. Soy malo en C / C ++, lo siento. Como solo tratamos con números pequeños y la memoria asignada se libera al final del programa, esto no debería ser un problema. (Antes de que alguien diga nada, sí, lo sé std::vector; estaba haciendo esto como un ejercicio de aprendizaje. Si sabe cómo solucionarlo, avíseme y haré las modificaciones, de lo contrario, ya que funciona, lo dejaré como es.)

Además, observe la ruta de inclusión a set.hen el interpreter.cpparchivo. Sin más preámbulos, el código fuente (C ++):

set.h

using namespace std;

//MEMORY LEAK IN THE ADD_SELF METHOD
class set {

    private:
        long m_size;
        set* m_elements;
        bool m_initialized;
        long m_value;

    public:
        set() {

            m_size =0;
            m_initialized = false;
            m_value=0;
        }

        ~set() {
            if(m_initialized) {
                //delete[] m_elements;
            }
        }

        void init() {
            if(!m_initialized) {
                m_elements = new set[0];

                m_initialized = true;
            }
        }

        void uninit() {
            if(m_initialized) {
                //delete[] m_elements;
            }
        }

        long size() {
            return m_size;
        }

        set* elements() {
            return m_elements;
        }

        bool is_empty() {
            if(m_size ==0) {return true;}
            else {return false;}
        }

        bool is_eq(set otherset) {
            if( (*this).size() != otherset.size() ) {
                return false;
            }
            else if ( (*this).size()==0 && otherset.size()==0 ) { 
                return true;
            }
            else {
                for(int i=0;i<m_size;i++) {
                    bool matched = false;
                    for(int j=0;j<otherset.size();j++) {

                        matched = (*(m_elements+i)).is_eq( *(otherset.elements()+j) );
                        if( matched) {
                            break;
                        }
                    }
                    if(!matched) {
                        return false;
                    }
                }
                return true;
            } 
        }

        bool contains(set set1) {
            for(int i=0;i<m_size;i++) {
                if( (*(m_elements+i)).is_eq(set1) ) {
                    return true;
                }
            }
            return false;
        }

        void add(set element) {
            (*this).init();

            bool alreadythere = false;
            for(int i=0;i<m_size;i++) {
                if( (*(m_elements+i)).is_eq(element) ) { 
                    alreadythere=true;
                }
            }
            if(!alreadythere) {
                set *temp = new set[m_size+1];
                for(int i=0; i<m_size; i++) {
                    *(temp+i)= *(m_elements+i);
                }
                *(temp+m_size)=element;

                m_size++;
                delete[] m_elements;
                m_elements = new set[m_size];

                for(int i=0;i<m_size;i++) {
                    *(m_elements+i) = *(temp+i);
                }
                delete[] temp;
            }
        }

        void add_self() {

            set temp_set;
            for(int i=0;i<m_size;i++) {
                temp_set.add( *(m_elements+i) );
            }
            (*this).add(temp_set);
            temp_set.uninit();
        }

        void remove(set set1) {
            (*this).init();
            for(int i=0;i<m_size;i++) {
                if(  (*(m_elements+i)).is_eq(set1) ) {

                    set* temp = new set[m_size-1];
                    for(int j=0;j<m_size;j++) {

                        if(j<i) {
                            *(temp+j)=*(m_elements+j);
                        }
                        else if(j>i) {
                            *(temp+j-1)=*(m_elements+j);
                        }
                    }
                    delete[] m_elements;
                    m_size--;
                    m_elements = new set[m_size];
                    for(int j=0;j<m_size;j++) {
                        *(m_elements+j)= *(temp+j);
                    }
                    delete[] temp;
                    break;
                }
            }
        }

        void join(set set1) {
            for(int i=0;i<set1.size();i++) {
                (*this).add( *(set1.elements()+i) );
            }
        }

        void diff(set set1) {
            for(int i=0;i<set1.size();i++) {
                (*this).remove( *(set1.elements()+i) );
            }
        }

        void intersect(set set1) {
             for(int i=0;i<m_size;i++) {

                bool keep = false;
                 for(int j=0;j<set1.size();j++) {
                     if(  (*(m_elements+i)).is_eq( *(set1.elements()+j) ) ) {
                         keep = true;
                         break;
                     }
                 }
                 if(!keep) {
                    (*this).remove( *(m_elements+i) );
                 }
             }
         }


        void natural(long number) {
            ////////////////////////// 
            //MEMORY LEAK?
            //delete[] m_elements;
            /////////////////////////
            m_size = 0;
            m_elements = new set[m_size];

            for(long i=1;i<=number;i++) {
                (*this).add_self();
            }
            m_value = number;
        }

        void disp() {
            if( m_size==0) {cout<<"{}";}
            else {
                cout<<"{";
                for(int i=0; i<m_size; i++) {
                    (*(m_elements+i)).disp();
                    if(i<m_size-1) {cout<<", ";}
                    //else{cout<<" ";}
                }
                cout<<"}";
            }
        }

        long value() {
            return m_value;
        }

};
const set EMPTY_SET;

interpreter.cpp

#include<fstream>
#include<iostream>
#include<string>
#include<assert.h>
#include<cmath>
#include "headers/set.h"
using namespace std;
string labels[20];
int jump_points[20];
int label_index=0;
const int max_var = 20;
set* set_ptrs[max_var];
string set_names[max_var];
long OPERATIONS = 0;

void assign_var(string name, set other_set) {
    static int index = 0;
    bool exists = false;
    int i = 0;
    while(i<index) {
        if(name==set_names[i]) {
            exists = true;
            break;
        }
        i++;
    }
    if(exists && index<max_var) {
        *(set_ptrs[i]) = other_set;
    }
    else if(!exists && index<max_var) {
        set_ptrs[index] = new set;
        *(set_ptrs[index]) = other_set;
        set_names[index] = name;
        index++;
    }
}

int getJumpPoint(string str) {
    for(int i=0;i<label_index;i++) {
        //cout<<labels[i]<<"\n";
        if(labels[i]==str) {
            //cout<<jump_points[i];
            return jump_points[i];
        }
    }
    cerr<<"Invalid Label Name: '"<<str<<"'\n";
    //assert(0);
    return -1;
}

long strToLong(string str) { 
    long j=str.size()-1;
    long value = 0;
    for(long i=0;i<str.size();i++) {
        long x = str[i]-48;
        assert(x>=0 && x<=9);  // Crash if there was a non digit character
        value+=x*floor( pow(10,j) );
        j--;
    }
    return value;
}

long getValue(string str) {
    for(int i=0;i<max_var;i++) {
        if(set_names[i]==str) {
            set set1;
            set1.natural( (*(set_ptrs[i])).size() );
            if( set1.is_eq( *(set_ptrs[i]) )   ) {
                return (*(set_ptrs[i])).size();
            }
            else {
                cerr<<"That is not a valid integer construction";
                return 0;
            }
        }
    }
    return strToLong(str);
}

int main(int argc, char** argv){
    if(argc<2){std::cerr<<"No input file given"; return 1;}
    ifstream inf(argv[1]);
    if(!inf){std::cerr<<"File open failed";return 1;}
    assign_var("ANSWER", EMPTY_SET);
    int answer;
    string str;
    inf>>str; 
    if(str=="*") { 
        inf>>str;
        long a = strToLong(str);
        inf>>str;
        long b = strToLong(str);
        answer = a*b;
        set set1; set set2;
        set1.natural(a); set2.natural(b);
        assign_var("set1", set1);
        assign_var("set2",set2);
        //cout<<answer;
    }
    else if(str=="+") {
        inf>>str;
        long a = strToLong(str);
        inf>>str;
        long b = strToLong(str);
        answer = a+b;
        set set1; set set2;
        set1.natural(a); set2.natural(b);
        assign_var("set1", set1);
        assign_var("set2",set2);
        //cout<<answer;
    }
    else{ 
         cerr<<"file must start with '+' or '*'"; 
        return 1;
    }

    // parse for labels
    while(inf) {
        if(inf) {   
            inf>>str;
            if(str[str.size()-1]==':') {
                str.erase(str.size()-1);
                labels[label_index] = str; 
                jump_points[label_index] = inf.tellg();
                //cout<<str<<": "<<jump_points[label_index]<<"\n";
                label_index++;
                OPERATIONS++;
            }
        }
    }

    inf.clear();
    inf.seekg(0,ios::beg);
    // parse for everything else

    while(inf) {
        if(inf) {
            inf>>str;

            if(str==";") {
                getline(inf, str,'\n');
            }

            // jump label
            if(str=="jump") {    
                inf>>str;
                inf.seekg( getJumpPoint(str),ios::beg);
                OPERATIONS++;
            }

            // je set label
            if(str=="je") {        
                inf>>str;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str) {
                        if( (*(set_ptrs[i])).is_eq(EMPTY_SET) ) {
                            inf>>str;
                            inf.seekg( getJumpPoint(str),ios::beg);
                            OPERATIONS++; 
                        }
                        break;
                    }
                }
            }

            // jne set label
            if(str=="jne") {
                inf>>str;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str) {
                        if(! (*(set_ptrs[i])).is_eq(EMPTY_SET) ) {
                            inf>>str;
                            inf.seekg( getJumpPoint(str),ios::beg);
                            OPERATIONS++; 
                        }
                        break;
                    }
                }
            }

            // jic set1 set2 label 
            // jump if set1 contains set2
            if(str=="jic") {
                inf>>str;
                string str2;
                inf>>str2;
                set set1;
                set set2;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str ) {
                        set1 = *(set_ptrs[i]);
                    }
                    if(set_names[i]==str2) {
                        set2 = *(set_ptrs[i]);
                    }
                }
                if( set1.contains(set2) ) {
                    inf>>str;
                    inf.seekg( getJumpPoint(str),ios::beg);
                    OPERATIONS++; 
                }
                else {inf>>str;}
            }

            // jidc set1 set2 label
            // jump if set1 doesn't contain set2
            if(str=="jidc") {
                inf>>str;
                string str2;
                inf>>str2;
                set set1;
                set set2;
                for(int i=0;i<max_var;i++) {
                    if( set_names[i]==str ) {
                        set1 = *(set_ptrs[i]);
                    }
                    if(set_names[i]==str2) {
                        set2 = *(set_ptrs[i]);
                    }
                }
                if( !set1.contains(set2) ) {
                    inf>>str;
                    inf.seekg( getJumpPoint(str),ios::beg);
                    OPERATIONS++; 
                }
                else {inf>>str;}
            }

            // assign variable set/int
            if(str=="assign") {
                inf>>str;
                string str2;
                inf>>str2;
                set set1;
                set1.natural( getValue(str2) );
                assign_var(str,set1);
                OPERATIONS++;

            }

            // union set1 set2 set3
            // set1 = set2 u set3
            if(str=="union") {
                inf>>str;
                int i=0;
                while(i<max_var) {
                    if( set_names[i] == str ) {
                        break;
                    }
                    i++;
                }

                set set1;
                set set2;
                string str1;
                inf>>str1;
                string str2;
                inf>>str2;
                for(int j=0;j<max_var;j++) {
                    if( str1 == set_names[j] ) {
                        set1= *(set_ptrs[j]); 
                    }
                    if( str2 == set_names[j] ) {
                        set2= *(set_ptrs[j]);
                    }
                }
                set1.join(set2);
                if(i==max_var) {
                    assign_var(str,set1);
                }
                else {
                    set_names[i]= str;
                    set_ptrs[i] = new set;
                    *(set_ptrs[i]) = set1;
                }
                OPERATIONS++;

            }

            // intersect set1 set2 set3
            // set1 = set2^set3
            if(str == "intersect") {
                inf>>str;
                int i=0;
                while(i<max_var) {
                    if( set_names[i] == str ) {
                        break;
                    }
                    i++;
                }

                set set1;
                set set2;
                string str1;
                inf>>str1;
                string str2;
                inf>>str2;
                for(int j=0;j<max_var;j++) {
                    if( str1 == set_names[j] ) {
                        set1= *(set_ptrs[j]); 
                    }
                    if( str2 == set_names[j] ) {
                        set2= *(set_ptrs[j]);
                    }
                }
                set1.intersect(set2);
                if(i==max_var) {
                    assign_var(str,set1);
                }
                else {
                    set_names[i]= str;
                    set_ptrs[i] = new set;
                    *(set_ptrs[i]) = set1;
                }
                OPERATIONS++;
            }


            // difference set1 set2 set3
            // set1 = set2\set3
            if(str == "difference") {
                inf>>str;
                int i=0;
                while(i<max_var) {
                    if( set_names[i] == str ) {
                        break;
                    }
                    i++;
                }

                set set1;
                set set2;
                string str1;
                inf>>str1;
                string str2;
                inf>>str2;
                for(int j=0;j<max_var;j++) {
                    if( str1 == set_names[j] ) {
                        set1= *(set_ptrs[j]); 
                    }
                    if( str2 == set_names[j] ) {
                        set2= *(set_ptrs[j]);
                    }
                }
                set1.diff(set2);
                if(i==max_var) {
                    assign_var(str,set1);
                }
                else {
                    set_names[i]= str;
                    set_ptrs[i] = new set;
                    *(set_ptrs[i]) = set1;
                }
                OPERATIONS++;
            }

            // add set1 set2
            // put set2 in set 1
            if(str=="add") {
                inf>>str;
                int i = 0; int j =0;
                while(i<max_var) {
                    if(set_names[i]==str) {
                        break;
                    }
                    i++;
                }
                inf>>str;
                while(j<max_var) {
                    if(set_names[j]==str) {
                    break;
                    }   
                    j++;             
                }
                set set2 = *(set_ptrs[j]);
                if( ! (*(set_ptrs[i])).is_eq(set2) ){
                    (*(set_ptrs[i])).add(set2);
                }
                else {
                    (*(set_ptrs[i])).add_self();
                }
                OPERATIONS++;
            }

            // remove set1 set2
            // remove set2 from set1
            if(str=="remove") {
                inf>>str;
                int i = 0; int j =0;
                while(i<max_var) {
                    if(set_names[i]==str) {
                        break;
                    }
                    i++;
                }
                inf>>str;
                while(j<max_var) {
                    if(set_names[j]==str) {
                    break;
                    }   
                    j++;             
                }
                set set2 = *(set_ptrs[j]);
                (*(set_ptrs[i])).remove(set2);
                OPERATIONS++;
            }

            // print set
            // prints true representation of set
            if(str=="print") {
                inf>>str;
                for(int i=0;i<max_var;i++) {
                    if(set_names[i]==str) {
                        (*(set_ptrs[i])).disp();
                    }
                }
                cout<<"\n";
            }

            // printi set
            // prints integer representation of set, if exists.
            if(str=="printi") {
                inf>>str;
                cout<<getValue(str);
                cout<<"\n";
            }
        }
    }

    cout<<"You used "<<OPERATIONS<<" operations\n";
    set testset;
    testset.natural(answer);
    switch( testset.is_eq( *(set_ptrs[0]) ) ) {
        case 1:
            cout<<"Your answer is correct, the set 'ANSWER' is equivalent "<<answer<<".\n";
            break;
        case 0:
            cout<<"Your answer is incorrect\n";
    }
   // cout<<"\n";
    return 0;
}

Condición ganadora

Ustedes dos escriben dos CUERPOS del programa , uno de los cuales multiplica los números en los encabezados y el otro agrega los números en los encabezados.

Este es un desafío de . Lo más rápido estará determinado por el número de operaciones utilizadas para resolver dos casos de prueba para cada programa. Los casos de prueba son las siguientes líneas de encabezado:

Para la adición:

+ 15 12

y

+ 12 15

y para multiplicar

* 4 5

y

* 5 4

Una puntuación para cada caso es el número de operaciones utilizadas (el intérprete indicará este número al finalizar el programa). El puntaje total es la suma de los puntajes para cada caso de prueba.

Vea mi entrada de ejemplo para ver un ejemplo de una entrada válida.

Una presentación ganadora cumple lo siguiente:

  1. contiene dos cuerpos de programa, uno que se multiplica y otro que agrega
  2. tiene el puntaje total más bajo (suma de puntajes en casos de prueba)
  3. Dado el tiempo y la memoria suficientes, funciona para cualquier número entero que pueda ser manejado por el intérprete (~ 2 ^ 31)
  4. No muestra errores cuando se ejecuta
  5. No usa comandos de depuración
  6. No explota defectos en el intérprete. Esto significa que su programa actual debe ser válido como pseudocódigo y como un programa interpretable en 'set language'.
  7. No explota las lagunas estándar (esto significa que no hay casos de prueba de codificación fija).

Consulte mi ejemplo para la implementación de referencia y el uso de ejemplo del lenguaje


@ Calvin'sHobbies Pensé que era solo mi navegador. ¿Hay un lugar fácil para hacer las fotos?
Liam

@LiamNoronha: me encargué de eso. $$...$$funciona en Meta, pero no en Main. Solía CodeCogs para generar las imágenes.
El'endia Starman

Gracias @ El'endiaStarman por corregir la notación de marcado
Liam

3
no hay suficiente espacio para la optimización
Liam

44
Estoy votando para cerrar esta pregunta como fuera de tema porque no hay suficiente espacio para la optimización
Liam

Respuestas:


1

Ejemplo de respuesta, 1323 operaciones

Tenga en cuenta que este es un ejemplo, no una entrada real.

Cuerpo adicional

Tenga en cuenta que este cuerpo no se ejecutará sin un encabezado.

Los comentarios no son necesarios en una respuesta real, pero están ahí para ayudar a enseñar los conceptos básicos del idioma.

assign ANSWER set2                  ; ANSWER = set2
main:                               ; create label 'main'
    add ANSWER ANSWER               ; Answer union {Answer}, i.e. ANSWER++
    assign looper1 0
    assign looper2 0
    jump dec
    continue:
        intersect set1 set1 looper2 ; set1 = set1 intersect looper2, i.e. set1 = min(set1,looper2)
        jne set1 main
        jump end
dec:
    add looper1 looper1             ; looper1++
    jidc set1 looper1 continue      ; jump if looper >= set1    
    add looper2 looper2             ; looper2++
    jump dec
end:

Para caso de prueba

+ 15 12

usos 440 operationsy para caso de prueba

+ 12 15

usos 299 operations.

Cuerpo de multiplicación

assign mult_loop 0
main:
    jic set1 mult_loop addition    
    jump end

addition:
    assign temp2 set2
    main_add:
        add ANSWER ANSWER
        assign looper1 0
        assign looper2 0
        jump dec
        cont_add:
            intersect temp2 temp2 looper2
            jne temp2 main_add
            jump end_add
    dec:
        add looper1 looper1
        jidc temp2 looper1 cont_add
        add looper2 looper2
        jump dec
    end_add:
        add mult_loop mult_loop
        jump main

end:

Para caso de prueba

* 4 5

usos 305 operationsy para caso de prueba

* 5 4

usos 279 operations.

Por lo tanto, mi puntaje total es440+299+305+279 = 1323


Desafortunadamente, la única mejora que se me ocurre es ordenar las entradas miny maxusarlas uniony intersection, para que las dos adiciones y las dos multiplicaciones obtengan el mismo puntaje (más bajo). Eso no parece una mejora suficiente para estafar el resto de esta solución de referencia. ;)
Martin Ender

@ MartinBüttner Hah Supuse que mis primeros intentos serían bastante horribles. Bueno, si ese es el caso, podríamos cerrar la pregunta entonces
Liam

Eh, solo porque no se me ocurra nada mejor no significa que existan enfoques mucho mejores. Ya veremos ...;)
Martin Ender

@ MartinBüttner Tenía miedo de que algo así pudiera suceder, pero como puse muy poco esfuerzo en las soluciones, supuse que serían fáciles de superar. Le daré una semana más o menos.
Liam
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.