Défi : recréer les opérateurs de base (+, -, *, %, ...)

Tim -  
 Tim -
Bonjour à tous !

Alors voilà, je me suis lancé le petit défis en C# (mais il peut être fait avec n'importe quel langage) :

Réaliser une classe qui permet de recréer l'ensemble des opérateurs, mais en utilisant le moins d'opérateur possibles !

Exemple pour bien me faire comprendre :

public static class Operateur
{
    public static int soutraction(int a, int b)
    {
        return a - b;
    }

    public static int addition(int a, int b)
    {
        return a - (-b);
    }
}


On a recréer l'opérateur + et -, mais en utilisant uniquement un seul opérateur ! (ici l'opérateur -).

La classe devra ainsi permettre de recréer tous les opérateurs suivant:
+, -, *, /, %, >, <, ~, |, &, ^, >>, <<, ==, !=, &&, ||, !

Tous les opérateur "redondant" ne sont pas nécessaire, comme :
>=, <=, +=, -=, *=, ++, --, etc...

Le seul opérateur ne comptant pas est celui d'affectation =.

Petites règles complémentaires :

Les opérateurs ne sont à recréer que pour les bool et les int, et doivent gérer les cas où ceux-ci sont négatifs.

Les opérateurs recréés doivent avoir EXACTEMENT le même comportement que s'ils étaient simplement utilisés.

L'utilisation d'une méthode externe à la classe est interdit, même avec les classe de base comme string ou int.
(Exemple, pas le droit de faire string.Concat(...))

En revanche, tous les types de bases sont autorisées (int, string, double, char, bool, etc...), ainsi que toutes les instructions (if/else, switch, for, do/while, try/catch, etc...)

Alors voilà, après un peu de temps, j'ai réussi à recréer tous les opérateurs en en utilisant qu'un seul !

(Je met une balise spoiler au cas-où vous voudriez faire l’exercice par vous même)

<label class="ccm_spoiler">Spoiler<input type="checkbox" />

Pour info, l'opérateur que j'ai utilisé est -. :)

public static class Operator
{

    private static readonly int minValue = -2147483648;

    private static bool ToBool(int n1)
    {
        switch (n1)
        {
            case 0:
                return false;
            default:
                return true;
        }
    }

    //Opérateur &&
    public static bool and(bool b1, bool b2)
    {
        if (b1)
        {
            if (b2)
            {
                return true;
            }
        }
        return false;
    }

    //Opérateur ||
    public static bool or(bool b1, bool b2)
    {
        if (b1)
        {
            return true;
        }
        if (b2)
        {
            return true;
        }
        return false;
    }

    //Opérateur !
    public static bool isFalse(bool b)
    {
        if (b)
        {
            return false;
        }
        return true;
    }

    //Opérateur -
    public static int subtract(int n1, int n2)
    {
        return n1 - n2;
    }

    //Opérateur +
    public static int add(int n1, int n2)
    {
        return n1 - (-n2);
    }

    //Opérateur !=
    public static bool nonEquals(int n1, int n2)
    {
        return ToBool(subtract(n1, n2));
    }

    //Opérateur ==
    public static bool equals(int n1, int n2)
    {
        return isFalse(nonEquals(n1, n2));
    }

    //Opérateur ~
    public static int FLIP(int n1)
    {
        return (-n1) - 1;
    }

    private static int opposite(int n1)
    {
        return -n1;
    }

    private static bool isPositive(int n1)
    {
        return or(equals(((int)(n1 - 0.5)) - n1, 0), isFalse(equals(n1, 0)));
    }

    private static bool isNegative(int n1)
    {
        return isFalse(isPositive(n1));
    }

    //Opérateur >
    public static bool superior(int n1, int n2)
    {
        return isPositive(n1 - n2);
    }

    //Opérateur <
    public static bool inferior(int n1, int n2)
    {
        return isNegative(n1 - n2);
    }

    //Opérateur *
    public static int multiplicate(int n1, int n2)
    {
        int result = 0;

        if (isPositive(n2))
        {
            for (int i = 0; inferior(i, n2); i = add(i, 1))
            {
                result = add(result, n1);
            }
        }
        else
        {
            for (int i = n2; inferior(i, 0); i = add(i, 1))
            {
                result = subtract(result, n1);
            }
        }

        return result;
    }

    //Opérateur /
    public static int divide(int n1, int n2)
    {
        int i;
        int sign = 1;

        if ((equals(n2, 0)))
        {
            return 0;
        }

        if (isNegative(n1))
        {
            sign = opposite(sign);
            n1 = opposite(n1);
        }
        if (isNegative(n2))
        {
            sign = opposite(sign);
            n2 = opposite(n2);
        }

        for (i = 0; superior(n1, n2); i = add(i, 1))
        {
            n1 = subtract(n1, n2);
        }

        return multiplicate(i, sign);
    }

    //Opérateur %
    public static int modulo(int n, int modulo)
    {
        int quotient = divide(n, modulo);
        return n - multiplicate(quotient, modulo);
    }

    private static int puissance(int n1, int puissance)
    {
        int result = 1;

        for (int i = 0; inferior(i, puissance); i = add(i, 1))
        {
            result = multiplicate(n1, result);
        }

        return result;
    }

    //Opérateur <<
    public static int DECALE_GAUCHE(int n1, int decale)
    {
        return multiplicate(n1, puissance(2, decale));
    }

    //Opérateur >>
    public static int DECALE_DROITE(int n1, int decale)
    {
        int result;

        result = divide(n1, puissance(2, decale));

        if (and(isNegative(n1), nonEquals(modulo(n1, 2), 0)))
        {
            return result - 1;
        }

        return result;
    }

    //Opérateur &
    public static int AND(int n1, int n2)
    {
        int result = 0;

        for (int i = 0; and(or(nonEquals(n1, 0), nonEquals(n2, 0)), inferior(i, 31)); n1 = DECALE_DROITE(n1, 1), n2 = DECALE_DROITE(n2, 1), i = add(i, 1))
        {
            if (and(nonEquals(modulo(n1, 2), 0), nonEquals(modulo(n2, 2)), 0))
            {
                result = add(result, puissance(2, i));
            }
        }

        if (and(isNegative(n1), isNegative(n2)))
        {
            result = add(result, minValue);
        }

        return result;
    }

    //Opérateur |
    public static int OR(int n1, int n2)
    {
        return add(n1, n2) - AND(n1, n2);
    }

    //Opérateur ^
    public static int XOR(int n1, int n2)
    {
        return OR(n1, n2) - AND(n1, n2);
    }
}

</label>

Ma question est donc la suivante, pensez vous qu'il est possible de réussir ce défi en utilisant un autre opérateur ?
Car j'ai essayez, mais à chaque fois, j'ai l'impression de tomber dans un cul de sac :/

Merci d'avance à tous ceux qui essayeront de répondre à la question !
Et bonne chance à ceux qui essayeront le défi ! :)

2 réponses

yg_be Messages postés 23541 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 586
 
bonjour,
tu te simplifies fortement la vie en considérant que la division ne retourne que la partie entière du résultat.
je pense qu'il est utile de le préciser dans l'énoncé.
0
yg_be Messages postés 23541 Date d'inscription   Statut Contributeur Dernière intervention   1 586
 
par ailleurs, je pense que ta solution ne tient pas compte des différentes représentations utilisées pour les nombres signés.
0
Tim
 
Bonjour, merci pour ta réponse !
Désolé je n'ai peut être pas assez mis l'accent dessus, mais il s'agit de ne gérer que les int, donc pour le C#, que des entiers de 32 bits, avec le 32e bit représentant le signe ! :)
0